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