Пытаюсь запустить консольный процесс на текущей машине под "безопасным" пользователем, отличным от Администратора. Создаю этого пользователя (имя dyn1) и исключаю его из всех групп, чтобы он был с максимально низкими правами в системе. Проверяю через runas: runas /user:dyn1 process.exe Все запускается нормально. Теперь делаю то же самое на WINAPI: LogonUser(user, ".", password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken); Результат: логон проходит, но попытка вызова CreateProcessAsUser(hToken, 0, (LPSTR)cmd, 0, 0, FALSE, NORMAL_PRIORITY_CLASS, 0, 0, &si, pi); дает (GetLastError/FormatMessage): A required privilege is not held by the client. Что это за "привилегии" такие, интересно, которые он хочет затребовать? Если же попробовать LOGON32_LOGON_BATCH: LogonUser(user, 0, password, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &hToken); получаю сразу же после этого вызова: Logon failure: the user has not been granted the requested logon type at this computer. Вопрос: как же тогда, черт возьми, работает runas? Ведь работает же, запускает процесс...
может какой нибудь Debug-privilege нужен? Код (Text): #define SE_CREATE_TOKEN_NAME TEXT("SeCreateTokenPrivilege") #define SE_ASSIGNPRIMARYTOKEN_NAME TEXT("SeAssignPrimaryTokenPrivilege") #define SE_LOCK_MEMORY_NAME TEXT("SeLockMemoryPrivilege") #define SE_INCREASE_QUOTA_NAME TEXT("SeIncreaseQuotaPrivilege") #define SE_UNSOLICITED_INPUT_NAME TEXT("SeUnsolicitedInputPrivilege") #define SE_MACHINE_ACCOUNT_NAME TEXT("SeMachineAccountPrivilege") #define SE_TCB_NAME TEXT("SeTcbPrivilege") #define SE_SECURITY_NAME TEXT("SeSecurityPrivilege") #define SE_TAKE_OWNERSHIP_NAME TEXT("SeTakeOwnershipPrivilege") #define SE_LOAD_DRIVER_NAME TEXT("SeLoadDriverPrivilege") #define SE_SYSTEM_PROFILE_NAME TEXT("SeSystemProfilePrivilege") #define SE_SYSTEMTIME_NAME TEXT("SeSystemtimePrivilege") #define SE_PROF_SINGLE_PROCESS_NAME TEXT("SeProfileSingleProcessPrivilege") #define SE_INC_BASE_PRIORITY_NAME TEXT("SeIncreaseBasePriorityPrivilege") #define SE_CREATE_PAGEFILE_NAME TEXT("SeCreatePagefilePrivilege") #define SE_CREATE_PERMANENT_NAME TEXT("SeCreatePermanentPrivilege") #define SE_BACKUP_NAME TEXT("SeBackupPrivilege") #define SE_RESTORE_NAME TEXT("SeRestorePrivilege") #define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege") #define SE_DEBUG_NAME TEXT("SeDebugPrivilege") #define SE_AUDIT_NAME TEXT("SeAuditPrivilege") #define SE_SYSTEM_ENVIRONMENT_NAME TEXT("SeSystemEnvironmentPrivilege") #define SE_CHANGE_NOTIFY_NAME TEXT("SeChangeNotifyPrivilege") #define SE_REMOTE_SHUTDOWN_NAME TEXT("SeRemoteShutdownPrivilege")
А как это использовать в данной задаче? И не совсем понятно, при чем тут Debug-привилегия? Я ж ничего не отлаживаю, а просто процесс запускаю, так же, как это делает runas...
Короче, похоже, что все понятно. http://www.codeguru.com/Cpp/misc/misc/system/article.php/c3805 (совсем немножко!) http://www.microsoft.com/msj/0200/logon/logon.aspx http://www.codeguru.com/Cpp/W-P/win32/cursors/article.php/c6745/ Оказывается, этот код можно выполнять только из сервисов. В обычной сессии нет нужный привилегий, а чтобы их выставить, требуется перелогиниваться минимум, что неприемлемо.
Как-то только это все нелогично малек. Мало того, что нужно знать plaintext-пароль (!) для запуска процесса под другим юзером из-под Администратора (в Unix, например, пароль знать не нужно, что весьма логично). Так еще и у Администратора по умолчанию нет прав на запуск чужих процессов, и приходится извращаться с сервисами! В общем, усложнено все, что только можно было усложить.
Должна помочь функция CreateProcessWithLogonW - именно ей пользуется runas. Сам еще не пробовал - все руки не доходят.
Да, CreateProcessWithLogonW прокатила: Код (Text): STARTUPINFOW si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); PROCESS_INFORMATION pi; memset(&pi, 0, sizeof(pi)); WCHAR wuser[128], wpassword[128], wcmd[4096]; MultiByteToWideChar(CP_ACP, 0, user, strlen(user)+1, wuser, sizeof(wuser)/sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, password, strlen(password)+1, wpassword, sizeof(wpassword)/sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, cmd, strlen(cmd)+1, wcmd, sizeof(wcmd)/sizeof(WCHAR)); bool result = CreateProcessWithLogonW( wuser, L".", wpassword, 0, 0, wcmd, CREATE_NEW_PROCESS_GROUP, 0, 0, &si, &pi );