Как програмно сотворить то, что мутит dcomcnfg
От: x2003 Россия www.mportal.narod.ru
Дата: 24.07.03 07:42
Оценка:
У меня возникла проблемка . Мне необходимо настройить для моего сервиса свойство RunAs, чтобы он крутился под аккаунтом конкретного пользователя. Причем сделать енто надо без использования dcomcnfg.exe .
Re: Как програмно сотворить то, что мутит dcomcnfg
От: SergH Россия  
Дата: 24.07.03 07:45
Оценка:
Здравствуйте, x2003, Вы писали:

X>У меня возникла проблемка . Мне необходимо настройить для моего сервиса свойство RunAs, чтобы он крутился под аккаунтом конкретного пользователя. Причем сделать енто надо без использования dcomcnfg.exe .


Почитай статьи Alexa Fedotova про упавление системными службами. В Статьи\Базовые сервисы\..
Делай что должно, и будь что будет
Re[2]: Как програмно сотворить то, что мутит dcomcnfg
От: x2003 Россия www.mportal.narod.ru
Дата: 24.07.03 07:56
Оценка:
Здравствуйте, SergH, Вы писали:

SH>Здравствуйте, x2003, Вы писали:


X>>У меня возникла проблемка . Мне необходимо настройить для моего сервиса свойство RunAs, чтобы он крутился под аккаунтом конкретного пользователя. Причем сделать енто надо без использования dcomcnfg.exe .


SH>Почитай статьи Alexa Fedotova про упавление системными службами. В Статьи\Базовые сервисы\..


Да. Я вроде как этими функциями и пользуюсь. Конкретно:

DWORD
SetAccountRights (
LPTSTR User,
LPTSTR Privilege
)
{
LSA_HANDLE policyHandle;
LSA_OBJECT_ATTRIBUTES objectAttributes;
PSID principalSID;
LSA_UNICODE_STRING lsaPrivilegeString;
WCHAR widePrivilege [256];

#ifdef _UNICODE
lstrcpy (widePrivilege, Privilege);
#else
STR2UNI (widePrivilege, Privilege);
#endif

memset (&objectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
if (LsaOpenPolicy (NULL,
&objectAttributes,
POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
&policyHandle) != ERROR_SUCCESS)
{
return GetLastError();
}

GetPrincipalSID (User, &principalSID);

lsaPrivilegeString.Length = (USHORT) (wcslen (widePrivilege) * sizeof (WCHAR));
lsaPrivilegeString.MaximumLength = (USHORT) (lsaPrivilegeString.Length + sizeof (WCHAR));
lsaPrivilegeString.Buffer = widePrivilege;

if (LsaAddAccountRights (policyHandle,
principalSID,
&lsaPrivilegeString,
1) != ERROR_SUCCESS)
{
free (principalSID);
LsaClose (policyHandle);
return GetLastError();
}

free (principalSID);
LsaClose (policyHandle);

return ERROR_SUCCESS;
}

Причем как привилегию беру SeBatchLogonRight.

Когда хочу пустить сервис мне говорят. Logon failure.
Re[2]: Как програмно сотворить то, что мутит dcomcnfg
От: Alex Fedotov США  
Дата: 24.07.03 08:01
Оценка:
Здравствуйте, SergH, Вы писали:

SH>Здравствуйте, x2003, Вы писали:


X>>У меня возникла проблемка . Мне необходимо настройить для моего сервиса свойство RunAs, чтобы он крутился под аккаунтом конкретного пользователя. Причем сделать енто надо без использования dcomcnfg.exe .


SH>Почитай статьи Alexa Fedotova про упавление системными службами. В Статьи\Базовые сервисы\..


Это если действительно сервис. Если это COM-сервер, не являющийся сервисом, то надо под его AppID прописать значение RunAs: http://msdn.microsoft.com/library/en-us/com/htm/reg_7nar.asp.
-- Alex Fedotov
Re[3]: Как програмно сотворить то, что мутит dcomcnfg
От: SergH Россия  
Дата: 24.07.03 08:03
Оценка: 1 (1)
Здравствуйте, x2003, Вы писали:

X>Да. Я вроде как этими функциями и пользуюсь. Конкретно:


X>DWORD

X>SetAccountRights (
X> LPTSTR User,
X> LPTSTR Privilege
X> )
X>{
X> LSA_HANDLE policyHandle;
X> LSA_OBJECT_ATTRIBUTES objectAttributes;
X> PSID principalSID;
X> LSA_UNICODE_STRING lsaPrivilegeString;
X> WCHAR widePrivilege [256];

X>#ifdef _UNICODE

X> lstrcpy (widePrivilege, Privilege);
X>#else
X> STR2UNI (widePrivilege, Privilege);
X>#endif

X> memset (&objectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));

X> if (LsaOpenPolicy (NULL,
X> &objectAttributes,
X> POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
X> &policyHandle) != ERROR_SUCCESS)
X> {
X> return GetLastError();
X> }

X> GetPrincipalSID (User, &principalSID);


X> lsaPrivilegeString.Length = (USHORT) (wcslen (widePrivilege) * sizeof (WCHAR));

X> lsaPrivilegeString.MaximumLength = (USHORT) (lsaPrivilegeString.Length + sizeof (WCHAR));
X> lsaPrivilegeString.Buffer = widePrivilege;

X> if (LsaAddAccountRights (policyHandle,

X> principalSID,
X> &lsaPrivilegeString,
X> 1) != ERROR_SUCCESS)
X> {
X> free (principalSID);
X> LsaClose (policyHandle);
X> return GetLastError();
X> }

X> free (principalSID);

X> LsaClose (policyHandle);

X> return ERROR_SUCCESS;

X>}

Похоже на правду.

X>Причем как привилегию беру SeBatchLogonRight.


А разьве не SeServiceLogonRight?

X>Когда хочу пустить сервис мне говорят. Logon failure.


А Event Log чего-нибудь говорит?
Делай что должно, и будь что будет
Re[3]: Как програмно сотворить то, что мутит dcomcnfg
От: Alex Fedotov США  
Дата: 24.07.03 08:03
Оценка:
Здравствуйте, x2003, Вы писали:

X>Когда хочу пустить сервис мне говорят. Logon failure.


Включи аудит logon/logoff events. Посмотри, что там пишут когда ты пытаешься запустить сервис.
-- Alex Fedotov
Re[4]: Как програмно сотворить то, что мутит dcomcnfg
От: Alex Fedotov США  
Дата: 24.07.03 08:05
Оценка:
Здравствуйте, SergH, Вы писали:

SH>А разьве не SeServiceLogonRight?

SH>А Event Log чего-нибудь говорит?

Все, больше не мешаю, пациент ваш
-- Alex Fedotov
Re[3]: Как програмно сотворить то, что мутит dcomcnfg
От: x2003 Россия www.mportal.narod.ru
Дата: 24.07.03 08:19
Оценка:
Здравствуйте, Alex Fedotov, Вы писали:

AF>Здравствуйте, SergH, Вы писали:


SH>>Здравствуйте, x2003, Вы писали:


X>>>У меня возникла проблемка . Мне необходимо настройить для моего сервиса свойство RunAs, чтобы он крутился под аккаунтом конкретного пользователя. Причем сделать енто надо без использования dcomcnfg.exe .


SH>>Почитай статьи Alexa Fedotova про упавление системными службами. В Статьи\Базовые сервисы\..


AF>Это если действительно сервис. Если это COM-сервер, не являющийся сервисом, то надо под его AppID прописать значение RunAs: http://msdn.microsoft.com/library/en-us/com/htm/reg_7nar.asp.


Это реальный ATL-ный сервис. В нем есть один COM объект.
Для установки прав на запуск я делаю следующее:

1) Вызов с APPID и Principal

DWORD
SetRunAsPrincipal
(
LPTSTR AppID,
LPTSTR Principal
)
{
DWORD returnValue;
HKEY registryKey;
TCHAR appid [256];
TCHAR keyName [256];

if (AppID[0] == '{')
wsprintf (appid, TEXT("%s"), AppID);
else
wsprintf (appid, TEXT("{%s}"), AppID);

wsprintf (keyName, TEXT("APPID\\%s"), appid);

returnValue = RegOpenKeyEx (HKEY_CLASSES_ROOT, keyName, 0, KEY_ALL_ACCESS, &registryKey);
if (returnValue != ERROR_SUCCESS)
return returnValue;
//Error (TEXT("ERROR: Cannot open AppID registry key."), returnValue);
LPSTR s;
PDWORD a;
DWORD type;
returnValue = RegSetValueEx (registryKey, TEXT("RunAs"), 0, REG_SZ, (LPBYTE) Principal, _tcslen (Principal) * sizeof (TCHAR));
if (returnValue != ERROR_SUCCESS)
return returnValue;

RegCloseKey (registryKey);
return returnValue;
}

2) После вызова следующего я получаю, что dcomcnfg.exe показывает в меню
This User — имя Principal.

DWORD
SetRunAsPrincipalX
(
LPTSTR Service,
LPTSTR Principal
)
{
DWORD returnValue;
HKEY registryKey;
TCHAR appid [256];
TCHAR keyName [256];

wsprintf (appid, TEXT("%s"), Service);

wsprintf (keyName, TEXT("System\\CurrentControlSet\\Services\\%s"), appid);

returnValue = RegOpenKeyEx (HKEY_LOCAL_MACHINE, keyName, 0, KEY_ALL_ACCESS, &registryKey);
if (returnValue != ERROR_SUCCESS)
return returnValue;
//Error (TEXT("ERROR: Cannot open AppID registry key."), returnValue);
LPSTR s;
PDWORD a;
DWORD type;
returnValue = RegSetValueEx (registryKey, TEXT("ObjectName"), 0, REG_SZ, (LPBYTE) Principal, _tcslen (Principal) * sizeof (TCHAR));
if (returnValue != ERROR_SUCCESS)
return returnValue;
// Error (TEXT("ERROR: Cannot set RunAs registry value."), returnValue);

RegCloseKey (registryKey);
return returnValue;
}

3) Даю этому Principal CeBatchLogonRight и юзерский пароль устанавливаю при помощи

DWORD SetRunAsPassword (
LPTSTR AppID,
LPTSTR Principal,
LPTSTR Password
)
{
LSA_OBJECT_ATTRIBUTES objectAttributes;
HANDLE policyHandle = NULL;
LSA_UNICODE_STRING lsaKeyString;
LSA_UNICODE_STRING lsaPasswordString;
WCHAR key [4 + GUIDSTR_MAX + 1];
WCHAR wideAppID [GUIDSTR_MAX + 1];
WCHAR widePassword [256];
DWORD returnValue;

#ifndef UNICODE
STR2UNI (wideAppID, AppID);
STR2UNI (widePassword, Password);
#else
wcscpy (wideAppID, AppID);
wcscpy (widePassword, Password);
#endif

wcscpy (key, L"SCM:");
wcscat (key, wideAppID);

lsaKeyString.Length = (USHORT) ((wcslen (key) + 1) * sizeof (WCHAR));
lsaKeyString.MaximumLength = (GUIDSTR_MAX + 5) * sizeof (WCHAR);
lsaKeyString.Buffer = key;

USES_CONVERSION;
MessageBox(0,"",OLE2A(key),0);

lsaPasswordString.Length = (USHORT) ((wcslen (widePassword) + 1) * sizeof (WCHAR));
lsaPasswordString.Buffer = widePassword;
lsaPasswordString.MaximumLength = lsaPasswordString.Length;

//
// Open the local security policy
//

memset (&objectAttributes, 0x00, sizeof (LSA_OBJECT_ATTRIBUTES));
objectAttributes.Length = sizeof (LSA_OBJECT_ATTRIBUTES);

returnValue = LsaOpenPolicy (NULL,
&objectAttributes,
POLICY_CREATE_SECRET,
&policyHandle);

if (returnValue != ERROR_SUCCESS)
return returnValue;

//
// Store the user's password
//

returnValue = LsaStorePrivateData (policyHandle,
&lsaKeyString,
&lsaPasswordString);

if (returnValue != ERROR_SUCCESS)
{
LsaClose (policyHandle);
return returnValue;
}

LsaClose (policyHandle);

returnValue = SetAccountRights (Principal, TEXT("SeBatchLogonRight"));
if (returnValue != ERROR_SUCCESS)
return returnValue;

return ERROR_SUCCESS;
}

В результате получаю Logon Failure.

Долго копался и в конце концов сделал следующее:
Сохранил реестр до регистрации сервиса (в файл).
Зарегистрировал сервис.
Запустил свою програмку.
Сохранил реестр в файл.
Отрегистрил сервис.
Опять зарегистрил.
Воспользовался dcomcnfg.exe
Сохранил реестр в файл.
Сравнил файлы и выявил, что моя программка не создает в реестре ключ

HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets\_SC_<имя сервиса>
В этом ключе каких-то бинарных данных до черта. Похоже что это security.
Грохнул ключик и вот оно — Logon failure.

Что я делаю неправильно при регистрации.
Re[4]: Как програмно сотворить то, что мутит dcomcnfg
От: SergH Россия  
Дата: 24.07.03 08:27
Оценка:
Здравствуйте, x2003, Вы писали:

X>Это реальный ATL-ный сервис. В нем есть один COM объект.

X>Для установки прав на запуск я делаю следующее:

X>3) Даю этому Principal CeBatchLogonRight и юзерский пароль устанавливаю при помощи


[skip]

Зачем так сложно? Попробуй для установки пароля/логина использовать ChangeServiceConfig.
Делай что должно, и будь что будет
Re[4]: Как програмно сотворить то, что мутит dcomcnfg
От: Alex Fedotov США  
Дата: 24.07.03 08:28
Оценка:
Здравствуйте, x2003, Вы писали:

Прости, я код без форматирования долго читать не могу, избаловался.

Там в ссылочке, которую я дал, написано:

The RunAs value is not used for servers configured to be run as services. COM services that need to run under an identity other than LocalSystem should set the appropriate user name and password using the services control panel applet or the service controller functions. (For more information about these functions, see the Services section of the Windows Base Services documentation in the Platform SDK.)

Поэтому все твои манипуляции с ключом RunAs не имеют смысла. Что нужно сделать, это:
1. Создать под ключом AppID значение LocalService, содержащее имя твоего сервиса;
2. Вызвать ChangeServiceConfig, чтобы установить имя пользователя и пароль к сервису;
3. Установить тот же самый пароль пользователю с помощью NetUserChangePassword (пароль при этом может быть случайным и сообщать его кому-либо вовсе не обязательно);
4. Дать пользователю SeServiceLogonRight.
-- Alex Fedotov
Re[4]: Как програмно сотворить то, что мутит dcomcnfg
От: x2003 Россия www.mportal.narod.ru
Дата: 24.07.03 08:28
Оценка:
Thanks.
Попробую SeServiceLogonRight
Re[5]: Как програмно сотворить то, что мутит dcomcnfg
От: x2003 Россия www.mportal.narod.ru
Дата: 24.07.03 09:15
Оценка:
Реальную вы мне вешь подсказали. Спасибо. Все заработало.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.