mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[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.
This commit is contained in:
parent
8571c26a71
commit
0625eb3746
4 changed files with 139 additions and 55 deletions
|
@ -40,61 +40,89 @@ static DWORD PipeTimeout = 30000; /* 30 Seconds */
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
static
|
||||||
|
BOOL
|
||||||
|
ScmIsSecurityService(
|
||||||
|
_In_ PSERVICE_IMAGE pServiceImage)
|
||||||
|
{
|
||||||
|
return (wcsstr(pServiceImage->pszImagePath, L"\\system32\\lsass.exe") != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static DWORD
|
static DWORD
|
||||||
ScmCreateNewControlPipe(PSERVICE_IMAGE pServiceImage)
|
ScmCreateNewControlPipe(
|
||||||
|
_In_ PSERVICE_IMAGE pServiceImage,
|
||||||
|
_In_ BOOL bSecurityServiceProcess)
|
||||||
{
|
{
|
||||||
WCHAR szControlPipeName[MAX_PATH + 1];
|
WCHAR szControlPipeName[MAX_PATH + 1];
|
||||||
SECURITY_ATTRIBUTES SecurityAttributes;
|
SECURITY_ATTRIBUTES SecurityAttributes;
|
||||||
HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE;
|
HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE;
|
||||||
DWORD ServiceCurrent = 0;
|
DWORD dwServiceCurrent = 1;
|
||||||
DWORD KeyDisposition;
|
DWORD dwKeyDisposition;
|
||||||
DWORD dwKeySize;
|
DWORD dwKeySize;
|
||||||
DWORD dwError;
|
DWORD dwError;
|
||||||
|
|
||||||
/* Get the service number */
|
/* Get the service number */
|
||||||
/* TODO: Create registry entry with correct write access */
|
if (bSecurityServiceProcess == FALSE)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError);
|
/* TODO: Create registry entry with correct write access */
|
||||||
return dwError;
|
dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
|
||||||
}
|
L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent",
|
||||||
|
0,
|
||||||
if (KeyDisposition == REG_OPENED_EXISTING_KEY)
|
NULL,
|
||||||
{
|
REG_OPTION_VOLATILE,
|
||||||
dwKeySize = sizeof(DWORD);
|
KEY_WRITE | KEY_READ,
|
||||||
dwError = RegQueryValueExW(hServiceCurrentKey,
|
NULL,
|
||||||
L"", 0, NULL, (BYTE*)&ServiceCurrent, &dwKeySize);
|
&hServiceCurrentKey,
|
||||||
|
&dwKeyDisposition);
|
||||||
if (dwError != ERROR_SUCCESS)
|
if (dwError != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
RegCloseKey(hServiceCurrentKey);
|
DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError);
|
||||||
DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError);
|
|
||||||
return 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
dwServiceCurrent++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dwError = RegSetValueExW(hServiceCurrentKey,
|
||||||
|
L"",
|
||||||
|
0,
|
||||||
|
REG_DWORD,
|
||||||
|
(BYTE*)&dwServiceCurrent,
|
||||||
|
sizeof(dwServiceCurrent));
|
||||||
|
|
||||||
|
RegCloseKey(hServiceCurrentKey);
|
||||||
|
|
||||||
|
if (dwError != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError);
|
||||||
|
return dwError;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
dwError = RegSetValueExW(hServiceCurrentKey, L"", 0, REG_DWORD, (BYTE*)&ServiceCurrent, sizeof(ServiceCurrent));
|
|
||||||
|
|
||||||
RegCloseKey(hServiceCurrentKey);
|
|
||||||
|
|
||||||
if (dwError != ERROR_SUCCESS)
|
|
||||||
{
|
{
|
||||||
DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError);
|
dwServiceCurrent = 0;
|
||||||
return dwError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create '\\.\pipe\net\NtControlPipeXXX' instance */
|
/* Create '\\.\pipe\net\NtControlPipeXXX' instance */
|
||||||
StringCchPrintfW(szControlPipeName, ARRAYSIZE(szControlPipeName),
|
StringCchPrintfW(szControlPipeName, ARRAYSIZE(szControlPipeName),
|
||||||
L"\\\\.\\pipe\\net\\NtControlPipe%lu", ServiceCurrent);
|
L"\\\\.\\pipe\\net\\NtControlPipe%lu", dwServiceCurrent);
|
||||||
|
|
||||||
DPRINT("PipeName: %S\n", szControlPipeName);
|
DPRINT("PipeName: %S\n", szControlPipeName);
|
||||||
|
|
||||||
|
@ -437,6 +465,7 @@ ScmCreateOrReferenceServiceImage(PSERVICE pService)
|
||||||
DWORD dwError = ERROR_SUCCESS;
|
DWORD dwError = ERROR_SUCCESS;
|
||||||
DWORD dwRecordSize;
|
DWORD dwRecordSize;
|
||||||
LPWSTR pString;
|
LPWSTR pString;
|
||||||
|
BOOL bSecurityService;
|
||||||
|
|
||||||
DPRINT("ScmCreateOrReferenceServiceImage(%p)\n", pService);
|
DPRINT("ScmCreateOrReferenceServiceImage(%p)\n", pService);
|
||||||
|
|
||||||
|
@ -518,8 +547,11 @@ ScmCreateOrReferenceServiceImage(PSERVICE pService)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bSecurityService = ScmIsSecurityService(pServiceImage);
|
||||||
|
|
||||||
/* Create the control pipe */
|
/* Create the control pipe */
|
||||||
dwError = ScmCreateNewControlPipe(pServiceImage);
|
dwError = ScmCreateNewControlPipe(pServiceImage,
|
||||||
|
bSecurityService);
|
||||||
if (dwError != ERROR_SUCCESS)
|
if (dwError != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
DPRINT1("ScmCreateNewControlPipe() failed (Error %lu)\n", dwError);
|
DPRINT1("ScmCreateNewControlPipe() failed (Error %lu)\n", dwError);
|
||||||
|
@ -542,6 +574,11 @@ ScmCreateOrReferenceServiceImage(PSERVICE pService)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bSecurityService)
|
||||||
|
{
|
||||||
|
SetSecurityServicesEvent();
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: Add more initialization code here */
|
/* 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
|
#if 0
|
||||||
_ultow(Service->lpImage->dwProcessId, szBuffer1, 10);
|
_ultow(Service->lpImage->dwProcessId, szBuffer1, 10);
|
||||||
|
@ -1916,7 +1954,7 @@ ScmStartUserModeService(PSERVICE Service,
|
||||||
StartupInfo.lpDesktop = L"WinSta0\\Default";
|
StartupInfo.lpDesktop = L"WinSta0\\Default";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wcsstr(Service->lpImage->pszImagePath, L"\\system32\\lsass.exe") == NULL)
|
if (!ScmIsSecurityService(Service->lpImage))
|
||||||
{
|
{
|
||||||
Result = CreateProcessW(NULL,
|
Result = CreateProcessW(NULL,
|
||||||
Service->lpImage->pszImagePath,
|
Service->lpImage->pszImagePath,
|
||||||
|
|
|
@ -28,6 +28,7 @@ int WINAPI RegisterServicesProcess(DWORD ServicesProcessId);
|
||||||
BOOL ScmInitialize = FALSE;
|
BOOL ScmInitialize = FALSE;
|
||||||
BOOL ScmShutdown = FALSE;
|
BOOL ScmShutdown = FALSE;
|
||||||
static HANDLE hScmShutdownEvent = NULL;
|
static HANDLE hScmShutdownEvent = NULL;
|
||||||
|
static HANDLE hScmSecurityServicesEvent = NULL;
|
||||||
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* 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
|
VOID
|
||||||
ScmLogEvent(DWORD dwEventId,
|
ScmLogEvent(DWORD dwEventId,
|
||||||
WORD wType,
|
WORD wType,
|
||||||
|
@ -258,6 +291,9 @@ done:
|
||||||
if (bCanDeleteNamedPipeCriticalSection != FALSE)
|
if (bCanDeleteNamedPipeCriticalSection != FALSE)
|
||||||
ScmDeleteNamedPipeCriticalSection();
|
ScmDeleteNamedPipeCriticalSection();
|
||||||
|
|
||||||
|
if (hScmSecurityServicesEvent != NULL)
|
||||||
|
CloseHandle(hScmSecurityServicesEvent);
|
||||||
|
|
||||||
/* Close the shutdown event */
|
/* Close the shutdown event */
|
||||||
if (hScmShutdownEvent != NULL)
|
if (hScmShutdownEvent != NULL)
|
||||||
CloseHandle(hScmShutdownEvent);
|
CloseHandle(hScmShutdownEvent);
|
||||||
|
|
|
@ -256,6 +256,7 @@ ScmCreateDefaultServiceSD(
|
||||||
/* services.c */
|
/* services.c */
|
||||||
|
|
||||||
VOID PrintString(LPCSTR fmt, ...);
|
VOID PrintString(LPCSTR fmt, ...);
|
||||||
|
DWORD SetSecurityServicesEvent(VOID);
|
||||||
VOID ScmLogEvent(DWORD dwEventId,
|
VOID ScmLogEvent(DWORD dwEventId,
|
||||||
WORD wType,
|
WORD wType,
|
||||||
WORD wStrings,
|
WORD wStrings,
|
||||||
|
|
|
@ -58,6 +58,7 @@ typedef struct _ACTIVE_SERVICE
|
||||||
static DWORD dwActiveServiceCount = 0;
|
static DWORD dwActiveServiceCount = 0;
|
||||||
static PACTIVE_SERVICE lpActiveServices = NULL;
|
static PACTIVE_SERVICE lpActiveServices = NULL;
|
||||||
static handle_t hStatusBinding = NULL;
|
static handle_t hStatusBinding = NULL;
|
||||||
|
static BOOL bSecurityServiceProcess = FALSE;
|
||||||
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
@ -227,7 +228,7 @@ ScConnectControlPipe(HANDLE *hPipe)
|
||||||
{
|
{
|
||||||
DWORD dwBytesWritten;
|
DWORD dwBytesWritten;
|
||||||
DWORD dwState;
|
DWORD dwState;
|
||||||
DWORD dwServiceCurrent = 0;
|
DWORD dwServiceCurrent = 1;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
WCHAR NtControlPipeName[MAX_PATH + 1];
|
WCHAR NtControlPipeName[MAX_PATH + 1];
|
||||||
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
||||||
|
@ -237,25 +238,32 @@ ScConnectControlPipe(HANDLE *hPipe)
|
||||||
hPipe);
|
hPipe);
|
||||||
|
|
||||||
/* Get the service number and create the named pipe */
|
/* Get the service number and create the named pipe */
|
||||||
RtlZeroMemory(&QueryTable,
|
if (bSecurityServiceProcess == FALSE)
|
||||||
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);
|
RtlZeroMemory(&QueryTable, sizeof(QueryTable));
|
||||||
return RtlNtStatusToDosError(Status);
|
|
||||||
|
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);
|
swprintf(NtControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent);
|
||||||
|
TRACE("PipeName: %S\n", NtControlPipeName);
|
||||||
|
|
||||||
if (!WaitNamedPipeW(NtControlPipeName, 30000))
|
if (!WaitNamedPipeW(NtControlPipeName, 30000))
|
||||||
{
|
{
|
||||||
|
@ -836,13 +844,14 @@ RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
|
||||||
*
|
*
|
||||||
* Undocumented
|
* Undocumented
|
||||||
*
|
*
|
||||||
* @unimplemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
I_ScIsSecurityProcess(VOID)
|
I_ScIsSecurityProcess(VOID)
|
||||||
{
|
{
|
||||||
FIXME("I_ScIsSecurityProcess()\n");
|
TRACE("I_ScIsSecurityProcess()\n");
|
||||||
|
bSecurityServiceProcess = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue