xref: /reactos/base/services/rpcss/setup.c (revision 7abc8be1)
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 
22 WINE_DEFAULT_DEBUG_CHANNEL(rpcss);
23 
24 /* FUNCTIONS ****************************************************************/
25 
26 static BOOL
27 SetupIsActive(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 
52 static BOOL
53 RunningAsSYSTEM(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 
86 Quit:
87     CloseHandle(hToken);
88     return bRet;
89 }
90 
91 static VOID
92 RpcSsConfigureAsNetworkService(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 
132 static VOID
133 AddImpersonatePrivilege(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 
163 VOID 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 }
180