mirror of
https://github.com/reactos/reactos.git
synced 2024-10-29 19:13:58 +00:00
98bbe8358c
The first call to GetTokenInformation is used to determine the size of a TokenInformation buffer. It should fail and return ERROR_INSUFFICIENT_BUFFER
180 lines
5.1 KiB
C
180 lines
5.1 KiB
C
/*
|
|
* PROJECT: ReactOS RPC Subsystem Service
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: One-time service setup configuration.
|
|
* COPYRIGHT: Copyright 2018 Hermes Belusca-Maito
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
/* PSDK/NDK Headers */
|
|
#define WIN32_NO_STATUS
|
|
#include <windef.h>
|
|
#include <winbase.h>
|
|
#include <winreg.h>
|
|
#include <winsvc.h>
|
|
|
|
#include <ndk/rtlfuncs.h>
|
|
#include <ntsecapi.h>
|
|
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(rpcss);
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
static BOOL
|
|
SetupIsActive(VOID)
|
|
{
|
|
LONG lResult;
|
|
HKEY hKey;
|
|
DWORD dwData = 0;
|
|
DWORD cbData = sizeof(dwData);
|
|
DWORD dwType = REG_NONE;
|
|
|
|
lResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
|
|
if (lResult != ERROR_SUCCESS)
|
|
return FALSE;
|
|
|
|
lResult = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL,
|
|
&dwType, (LPBYTE)&dwData, &cbData);
|
|
RegCloseKey(hKey);
|
|
|
|
if ((lResult == ERROR_SUCCESS) && (dwType == REG_DWORD) &&
|
|
(cbData == sizeof(dwData)) && (dwData == 1))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL
|
|
RunningAsSYSTEM(VOID)
|
|
{
|
|
/* S-1-5-18 -- Local System */
|
|
static SID SystemSid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } };
|
|
|
|
BOOL bRet = FALSE;
|
|
PTOKEN_USER pTokenUser;
|
|
HANDLE hToken;
|
|
DWORD cbTokenBuffer = 0;
|
|
|
|
/* Get the process token */
|
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
|
|
return FALSE;
|
|
|
|
/* Retrieve token's information */
|
|
if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbTokenBuffer) ||
|
|
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
goto Quit;
|
|
}
|
|
|
|
pTokenUser = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbTokenBuffer);
|
|
if (!pTokenUser)
|
|
goto Quit;
|
|
|
|
if (GetTokenInformation(hToken, TokenUser, pTokenUser, cbTokenBuffer, &cbTokenBuffer))
|
|
{
|
|
/* Compare with SYSTEM SID */
|
|
bRet = EqualSid(pTokenUser->User.Sid, &SystemSid);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, pTokenUser);
|
|
|
|
Quit:
|
|
CloseHandle(hToken);
|
|
return bRet;
|
|
}
|
|
|
|
static VOID
|
|
RpcSsConfigureAsNetworkService(VOID)
|
|
{
|
|
SC_HANDLE hSCManager, hService;
|
|
|
|
/* Open the service controller */
|
|
hSCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
|
|
if (!hSCManager)
|
|
{
|
|
ERR("OpenSCManager() failed with error 0x%lx\n", GetLastError());
|
|
return;
|
|
}
|
|
|
|
/* Open the RPCSS service */
|
|
hService = OpenServiceW(hSCManager, L"RPCSS", SERVICE_CHANGE_CONFIG);
|
|
if (!hService)
|
|
ERR("OpenService(\"RPCSS\") failed with error 0x%lx\n", GetLastError());
|
|
if (hService)
|
|
{
|
|
/* Use the NetworkService account */
|
|
if (!ChangeServiceConfigW(hService,
|
|
SERVICE_NO_CHANGE,
|
|
SERVICE_NO_CHANGE,
|
|
SERVICE_NO_CHANGE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
L"NT AUTHORITY\\NetworkService",
|
|
L"",
|
|
NULL))
|
|
{
|
|
ERR("ChangeServiceConfig(\"RPCSS\") failed with error 0x%lx\n", GetLastError());
|
|
}
|
|
|
|
CloseServiceHandle(hService);
|
|
}
|
|
|
|
CloseServiceHandle(hSCManager);
|
|
}
|
|
|
|
static VOID
|
|
AddImpersonatePrivilege(VOID)
|
|
{
|
|
/* S-1-5-6 -- "Service" group */
|
|
static SID ServiceSid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } };
|
|
|
|
NTSTATUS Status;
|
|
LSA_HANDLE PolicyHandle;
|
|
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
|
|
LSA_UNICODE_STRING RightString;
|
|
|
|
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
|
|
Status = LsaOpenPolicy(NULL, &ObjectAttributes,
|
|
POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
|
|
&PolicyHandle);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsaOpenPolicy() failed with Status 0x%08lx\n", Status);
|
|
return;
|
|
}
|
|
|
|
RtlInitUnicodeString(&RightString, L"SeImpersonatePrivilege");
|
|
Status = LsaAddAccountRights(PolicyHandle, &ServiceSid, &RightString, 1);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsaAddAccountRights(\"S-1-5-6\", \"%wZ\") failed with Status 0x%08lx\n", Status, &RightString);
|
|
}
|
|
|
|
LsaClose(PolicyHandle);
|
|
}
|
|
|
|
VOID DoRpcSsSetupConfiguration(VOID)
|
|
{
|
|
/*
|
|
* On first run during the setup phase, the RPCSS service runs under
|
|
* the LocalSystem account. RPCSS then re-configures itself to run
|
|
* under the NetworkService account and adds the Impersonate privilege
|
|
* to the "Service" group.
|
|
* This is done in this way, because the NetworkService account does not
|
|
* initially exist when the setup phase is running and the RPCSS service
|
|
* is started, but this account is created later during the setup phase.
|
|
*/
|
|
if (SetupIsActive() && RunningAsSYSTEM())
|
|
{
|
|
RpcSsConfigureAsNetworkService();
|
|
AddImpersonatePrivilege();
|
|
}
|
|
}
|