Reactos
1/*
2 * PROJECT: ReactOS RPC Subsystem Service
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: One-time service setup configuration.
5 * COPYRIGHT: Copyright 2018 Hermes Belusca-Maito
6 */
7
8/* INCLUDES *****************************************************************/
9
10/* PSDK/NDK Headers */
11#define WIN32_NO_STATUS
12#include <windef.h>
13#include <winbase.h>
14#include <winreg.h>
15#include <winsvc.h>
16
17#include <ndk/rtlfuncs.h>
18#include <ntsecapi.h>
19
20#include "wine/debug.h"
21
22WINE_DEFAULT_DEBUG_CHANNEL(rpcss);
23
24/* FUNCTIONS ****************************************************************/
25
26static BOOL
27SetupIsActive(VOID)
28{
29 LONG lResult;
30 HKEY hKey;
31 DWORD dwData = 0;
32 DWORD cbData = sizeof(dwData);
33 DWORD dwType = REG_NONE;
34
35 lResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
36 if (lResult != ERROR_SUCCESS)
37 return FALSE;
38
39 lResult = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL,
40 &dwType, (LPBYTE)&dwData, &cbData);
41 RegCloseKey(hKey);
42
43 if ((lResult == ERROR_SUCCESS) && (dwType == REG_DWORD) &&
44 (cbData == sizeof(dwData)) && (dwData == 1))
45 {
46 return TRUE;
47 }
48
49 return FALSE;
50}
51
52static BOOL
53RunningAsSYSTEM(VOID)
54{
55 /* S-1-5-18 -- Local System */
56 static SID SystemSid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } };
57
58 BOOL bRet = FALSE;
59 PTOKEN_USER pTokenUser;
60 HANDLE hToken;
61 DWORD cbTokenBuffer = 0;
62
63 /* Get the process token */
64 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
65 return FALSE;
66
67 /* Retrieve token's information */
68 if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbTokenBuffer) ||
69 GetLastError() != ERROR_INSUFFICIENT_BUFFER)
70 {
71 goto Quit;
72 }
73
74 pTokenUser = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbTokenBuffer);
75 if (!pTokenUser)
76 goto Quit;
77
78 if (GetTokenInformation(hToken, TokenUser, pTokenUser, cbTokenBuffer, &cbTokenBuffer))
79 {
80 /* Compare with SYSTEM SID */
81 bRet = EqualSid(pTokenUser->User.Sid, &SystemSid);
82 }
83
84 HeapFree(GetProcessHeap(), 0, pTokenUser);
85
86Quit:
87 CloseHandle(hToken);
88 return bRet;
89}
90
91static VOID
92RpcSsConfigureAsNetworkService(VOID)
93{
94 SC_HANDLE hSCManager, hService;
95
96 /* Open the service controller */
97 hSCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
98 if (!hSCManager)
99 {
100 ERR("OpenSCManager() failed with error 0x%lx\n", GetLastError());
101 return;
102 }
103
104 /* Open the RPCSS service */
105 hService = OpenServiceW(hSCManager, L"RPCSS", SERVICE_CHANGE_CONFIG);
106 if (!hService)
107 ERR("OpenService(\"RPCSS\") failed with error 0x%lx\n", GetLastError());
108 if (hService)
109 {
110 /* Use the NetworkService account */
111 if (!ChangeServiceConfigW(hService,
112 SERVICE_NO_CHANGE,
113 SERVICE_NO_CHANGE,
114 SERVICE_NO_CHANGE,
115 NULL,
116 NULL,
117 NULL,
118 NULL,
119 L"NT AUTHORITY\\NetworkService",
120 L"",
121 NULL))
122 {
123 ERR("ChangeServiceConfig(\"RPCSS\") failed with error 0x%lx\n", GetLastError());
124 }
125
126 CloseServiceHandle(hService);
127 }
128
129 CloseServiceHandle(hSCManager);
130}
131
132static VOID
133AddImpersonatePrivilege(VOID)
134{
135 /* S-1-5-6 -- "Service" group */
136 static SID ServiceSid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } };
137
138 NTSTATUS Status;
139 LSA_HANDLE PolicyHandle;
140 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
141 LSA_UNICODE_STRING RightString;
142
143 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
144 Status = LsaOpenPolicy(NULL, &ObjectAttributes,
145 POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
146 &PolicyHandle);
147 if (!NT_SUCCESS(Status))
148 {
149 ERR("LsaOpenPolicy() failed with Status 0x%08lx\n", Status);
150 return;
151 }
152
153 RtlInitUnicodeString(&RightString, L"SeImpersonatePrivilege");
154 Status = LsaAddAccountRights(PolicyHandle, &ServiceSid, &RightString, 1);
155 if (!NT_SUCCESS(Status))
156 {
157 ERR("LsaAddAccountRights(\"S-1-5-6\", \"%wZ\") failed with Status 0x%08lx\n", Status, &RightString);
158 }
159
160 LsaClose(PolicyHandle);
161}
162
163VOID DoRpcSsSetupConfiguration(VOID)
164{
165 /*
166 * On first run during the setup phase, the RPCSS service runs under
167 * the LocalSystem account. RPCSS then re-configures itself to run
168 * under the NetworkService account and adds the Impersonate privilege
169 * to the "Service" group.
170 * This is done in this way, because the NetworkService account does not
171 * initially exist when the setup phase is running and the RPCSS service
172 * is started, but this account is created later during the setup phase.
173 */
174 if (SetupIsActive() && RunningAsSYSTEM())
175 {
176 RpcSsConfigureAsNetworkService();
177 AddImpersonatePrivilege();
178 }
179}