From: Eric Kohl Date: Sat, 31 Aug 2019 15:24:47 +0000 (+0200) Subject: [SERVICES][ADVAPI32] Support the security process aka lsass.exe X-Git-Tag: 0.4.14-dev~200 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=0625eb374634510238dc3f36761f63428733190c;hp=8571c26a719ae05a32bbb19f2d42b5d49e84188e [SERVICES][ADVAPI32] Support the security process aka lsass.exe - Reserve the pipe NtControlPipe0 for the security process. - Count regular service control pipes from 1. - Use I_ScIsSecurityProcess to identify the security process. - Services.exe uses the SECURITY_SERVICES_STARTED event to notify the security process that NtControlPipe0 is ready for use. --- diff --git a/base/system/services/database.c b/base/system/services/database.c index 622bdf0c847..fc3d673c347 100644 --- a/base/system/services/database.c +++ b/base/system/services/database.c @@ -40,61 +40,89 @@ static DWORD PipeTimeout = 30000; /* 30 Seconds */ /* FUNCTIONS *****************************************************************/ +static +BOOL +ScmIsSecurityService( + _In_ PSERVICE_IMAGE pServiceImage) +{ + return (wcsstr(pServiceImage->pszImagePath, L"\\system32\\lsass.exe") != NULL); +} + + static DWORD -ScmCreateNewControlPipe(PSERVICE_IMAGE pServiceImage) +ScmCreateNewControlPipe( + _In_ PSERVICE_IMAGE pServiceImage, + _In_ BOOL bSecurityServiceProcess) { WCHAR szControlPipeName[MAX_PATH + 1]; SECURITY_ATTRIBUTES SecurityAttributes; HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE; - DWORD ServiceCurrent = 0; - DWORD KeyDisposition; + DWORD dwServiceCurrent = 1; + DWORD dwKeyDisposition; DWORD dwKeySize; DWORD dwError; /* Get the service number */ - /* TODO: Create registry entry with correct write access */ - dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE, - L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent", 0, NULL, - REG_OPTION_VOLATILE, - KEY_WRITE | KEY_READ, - NULL, - &hServiceCurrentKey, - &KeyDisposition); - if (dwError != ERROR_SUCCESS) + if (bSecurityServiceProcess == FALSE) { - DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError); - return dwError; - } - - if (KeyDisposition == REG_OPENED_EXISTING_KEY) - { - dwKeySize = sizeof(DWORD); - dwError = RegQueryValueExW(hServiceCurrentKey, - L"", 0, NULL, (BYTE*)&ServiceCurrent, &dwKeySize); - + /* TODO: Create registry entry with correct write access */ + dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent", + 0, + NULL, + REG_OPTION_VOLATILE, + KEY_WRITE | KEY_READ, + NULL, + &hServiceCurrentKey, + &dwKeyDisposition); if (dwError != ERROR_SUCCESS) { - RegCloseKey(hServiceCurrentKey); - DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError); + DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError); return dwError; } - ServiceCurrent++; - } + if (dwKeyDisposition == REG_OPENED_EXISTING_KEY) + { + dwKeySize = sizeof(DWORD); + dwError = RegQueryValueExW(hServiceCurrentKey, + L"", + 0, + NULL, + (BYTE*)&dwServiceCurrent, + &dwKeySize); + if (dwError != ERROR_SUCCESS) + { + RegCloseKey(hServiceCurrentKey); + DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError); + return dwError; + } - dwError = RegSetValueExW(hServiceCurrentKey, L"", 0, REG_DWORD, (BYTE*)&ServiceCurrent, sizeof(ServiceCurrent)); + dwServiceCurrent++; + } - RegCloseKey(hServiceCurrentKey); + dwError = RegSetValueExW(hServiceCurrentKey, + L"", + 0, + REG_DWORD, + (BYTE*)&dwServiceCurrent, + sizeof(dwServiceCurrent)); - if (dwError != ERROR_SUCCESS) + RegCloseKey(hServiceCurrentKey); + + if (dwError != ERROR_SUCCESS) + { + DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError); + return dwError; + } + } + else { - DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError); - return dwError; + dwServiceCurrent = 0; } /* Create '\\.\pipe\net\NtControlPipeXXX' instance */ StringCchPrintfW(szControlPipeName, ARRAYSIZE(szControlPipeName), - L"\\\\.\\pipe\\net\\NtControlPipe%lu", ServiceCurrent); + L"\\\\.\\pipe\\net\\NtControlPipe%lu", dwServiceCurrent); DPRINT("PipeName: %S\n", szControlPipeName); @@ -437,6 +465,7 @@ ScmCreateOrReferenceServiceImage(PSERVICE pService) DWORD dwError = ERROR_SUCCESS; DWORD dwRecordSize; LPWSTR pString; + BOOL bSecurityService; DPRINT("ScmCreateOrReferenceServiceImage(%p)\n", pService); @@ -518,8 +547,11 @@ ScmCreateOrReferenceServiceImage(PSERVICE pService) goto done; } + bSecurityService = ScmIsSecurityService(pServiceImage); + /* Create the control pipe */ - dwError = ScmCreateNewControlPipe(pServiceImage); + dwError = ScmCreateNewControlPipe(pServiceImage, + bSecurityService); if (dwError != ERROR_SUCCESS) { DPRINT1("ScmCreateNewControlPipe() failed (Error %lu)\n", dwError); @@ -542,6 +574,11 @@ ScmCreateOrReferenceServiceImage(PSERVICE pService) goto done; } + if (bSecurityService) + { + SetSecurityServicesEvent(); + } + /* FIXME: Add more initialization code here */ @@ -1806,7 +1843,8 @@ ScmWaitForServiceConnect(PSERVICE Service) } } - if (dwProcessId != Service->lpImage->dwProcessId) + if ((ScmIsSecurityService(Service->lpImage) == FALSE)&& + (dwProcessId != Service->lpImage->dwProcessId)) { #if 0 _ultow(Service->lpImage->dwProcessId, szBuffer1, 10); @@ -1916,7 +1954,7 @@ ScmStartUserModeService(PSERVICE Service, StartupInfo.lpDesktop = L"WinSta0\\Default"; } - if (wcsstr(Service->lpImage->pszImagePath, L"\\system32\\lsass.exe") == NULL) + if (!ScmIsSecurityService(Service->lpImage)) { Result = CreateProcessW(NULL, Service->lpImage->pszImagePath, diff --git a/base/system/services/services.c b/base/system/services/services.c index 75bfeeb195e..81725260253 100644 --- a/base/system/services/services.c +++ b/base/system/services/services.c @@ -28,6 +28,7 @@ int WINAPI RegisterServicesProcess(DWORD ServicesProcessId); BOOL ScmInitialize = FALSE; BOOL ScmShutdown = FALSE; static HANDLE hScmShutdownEvent = NULL; +static HANDLE hScmSecurityServicesEvent = NULL; /* FUNCTIONS *****************************************************************/ @@ -48,6 +49,38 @@ PrintString(LPCSTR fmt, ...) } +DWORD +SetSecurityServicesEvent(VOID) +{ + DWORD dwError; + + if (hScmSecurityServicesEvent != NULL) + return ERROR_SUCCESS; + + /* Create or open the SECURITY_SERVICES_STARTED event */ + hScmSecurityServicesEvent = CreateEventW(NULL, + TRUE, + FALSE, + L"SECURITY_SERVICES_STARTED"); + if (hScmSecurityServicesEvent == NULL) + { + dwError = GetLastError(); + if (dwError != ERROR_ALREADY_EXISTS) + return dwError; + + hScmSecurityServicesEvent = OpenEventW(EVENT_MODIFY_STATE, + FALSE, + L"SECURITY_SERVICES_STARTED"); + if (hScmSecurityServicesEvent == NULL) + return GetLastError(); + } + + SetEvent(hScmSecurityServicesEvent); + + return ERROR_SUCCESS; +} + + VOID ScmLogEvent(DWORD dwEventId, WORD wType, @@ -258,6 +291,9 @@ done: if (bCanDeleteNamedPipeCriticalSection != FALSE) ScmDeleteNamedPipeCriticalSection(); + if (hScmSecurityServicesEvent != NULL) + CloseHandle(hScmSecurityServicesEvent); + /* Close the shutdown event */ if (hScmShutdownEvent != NULL) CloseHandle(hScmShutdownEvent); diff --git a/base/system/services/services.h b/base/system/services/services.h index 6e3ca20e11b..845ea020da1 100644 --- a/base/system/services/services.h +++ b/base/system/services/services.h @@ -256,6 +256,7 @@ ScmCreateDefaultServiceSD( /* services.c */ VOID PrintString(LPCSTR fmt, ...); +DWORD SetSecurityServicesEvent(VOID); VOID ScmLogEvent(DWORD dwEventId, WORD wType, WORD wStrings, diff --git a/dll/win32/advapi32/service/sctrl.c b/dll/win32/advapi32/service/sctrl.c index 68ec2a6ac63..c0cf0f42288 100644 --- a/dll/win32/advapi32/service/sctrl.c +++ b/dll/win32/advapi32/service/sctrl.c @@ -58,6 +58,7 @@ typedef struct _ACTIVE_SERVICE static DWORD dwActiveServiceCount = 0; static PACTIVE_SERVICE lpActiveServices = NULL; static handle_t hStatusBinding = NULL; +static BOOL bSecurityServiceProcess = FALSE; /* FUNCTIONS *****************************************************************/ @@ -227,7 +228,7 @@ ScConnectControlPipe(HANDLE *hPipe) { DWORD dwBytesWritten; DWORD dwState; - DWORD dwServiceCurrent = 0; + DWORD dwServiceCurrent = 1; NTSTATUS Status; WCHAR NtControlPipeName[MAX_PATH + 1]; RTL_QUERY_REGISTRY_TABLE QueryTable[2]; @@ -237,25 +238,32 @@ ScConnectControlPipe(HANDLE *hPipe) hPipe); /* Get the service number and create the named pipe */ - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].Name = L""; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[0].EntryContext = &dwServiceCurrent; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, - L"ServiceCurrent", - QueryTable, - NULL, - NULL); - if (!NT_SUCCESS(Status)) + if (bSecurityServiceProcess == FALSE) { - ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status); - return RtlNtStatusToDosError(Status); + RtlZeroMemory(&QueryTable, sizeof(QueryTable)); + + QueryTable[0].Name = L""; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[0].EntryContext = &dwServiceCurrent; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"ServiceCurrent", + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status); + return RtlNtStatusToDosError(Status); + } + } + else + { + dwServiceCurrent = 0; } swprintf(NtControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent); + TRACE("PipeName: %S\n", NtControlPipeName); if (!WaitNamedPipeW(NtControlPipeName, 30000)) { @@ -836,13 +844,14 @@ RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName, * * Undocumented * - * @unimplemented + * @implemented */ VOID WINAPI I_ScIsSecurityProcess(VOID) { - FIXME("I_ScIsSecurityProcess()\n"); + TRACE("I_ScIsSecurityProcess()\n"); + bSecurityServiceProcess = TRUE; }