Мы реализовали службу Windows, которая работает как пользователь SYSTEM и имеет права администратора. Если нашим клиентом управляет пользователь с правами администратора, он может без проблем запускать процессы через службу от имени администратора. Служба олицетворяет пользователя и запускает процесс с правами администратора.
Но теперь нам нужно сделать то же самое для пользователя без прав администратора. Я не смог найти никакой документации.
Код, который мы используем:
Получаем текущий токен
MyHandle Impersonator::getCurrentProcessToken() const
{
MyHandle currentProcessToken;
const auto returnCode = ::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, currentProcessToken);
if (returnCode == 0 || *currentProcessToken == nullptr)
throw EXCEPTION_STATIC(Exceptions::Windows::Impersonation, "Could not get token of current process", ::GetLastError());
return currentProcessToken;
}
Устанавливаем токен привилегии
void Impersonator::enableTcbPrivilege() const
{
MyHandle currentProcessToken = getCurrentProcessToken();
TOKEN_PRIVILEGES tokenPrivilege;
tokenPrivilege.PrivilegeCount = 1;
tokenPrivilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!::LookupPrivilegeValueW(nullptr, SE_TCB_NAME, &tokenPrivilege.Privileges[0].Luid))
throw EXCEPTION(Exceptions::Windows::Elevation, "Could not lookup TCB privilege UID", ::GetLastError());
/* Documentation for AdjustTokenPrivileges() can be found in the internet archive:
* https://web.archive.org/web/20161009182045/https://msdn.microsoft.com/en-us/library/aa375202(v=vs.85).aspx
*/
if (!::AdjustTokenPrivileges(*currentProcessToken, FALSE, &tokenPrivilege, 0, nullptr, nullptr))
throw EXCEPTION(Exceptions::Windows::Elevation, "Could not enable TCB privilege", ::GetLastError());
}
Мы получаем связанный токен:
MyHandle UserImpersonator::getLinkedToken(MyHandle token) const
{
TOKEN_LINKED_TOKEN linkedTokenStruct;
DWORD returnLength = 0;
const auto returnCode = ::GetTokenInformation(*token, TokenLinkedToken, &linkedTokenStruct, sizeof(linkedTokenStruct), &returnLength);
MyHandle linkedToken(linkedTokenStruct.LinkedToken);
if (returnCode == 0)
throw EXCEPTION(Exceptions::Windows::Elevation, QString("Could not get admin token for user - error: %1").arg(QString::number(::GetLastError())), ::GetLastError());
return linkedToken;
}
::GetTokenInformation
завершается с ERROR_NO_SUCH_LOGON_SESSION
Я хотел бы знать, возможно ли то, что мы пытаемся достичь, и документировано ли это где-нибудь. Или любой намек на наш код, который может что-то упустить или ошибиться.