[SERVICES]

- Create a default service security descriptor.
- RCreateServiceW: Assign the default security descriptor to new services on service creation and store it in the registry.
- RQueryServiceObjectSecurity: Return the services security descriptor to the caller.

svn path=/trunk/; revision=71603
This commit is contained in:
Eric Kohl 2016-06-09 21:30:48 +00:00
parent 998a832892
commit 5a180609eb
6 changed files with 453 additions and 9 deletions

View file

@ -14,6 +14,7 @@ list(APPEND SOURCE
groupdb.c
lock.c
rpcserver.c
security.c
services.c
services.h
${CMAKE_CURRENT_BINARY_DIR}/svcctl_s.c)

View file

@ -498,4 +498,154 @@ done:
return dwError;
}
DWORD
ScmWriteSecurityDescriptor(
_In_ HKEY hServiceKey,
_In_ PSECURITY_DESCRIPTOR pSecurityDescriptor)
{
PSECURITY_DESCRIPTOR pRelativeSD = NULL;
HKEY hSecurityKey = NULL;
DWORD dwBufferLength = 0;
DWORD dwDisposition;
DWORD dwError;
NTSTATUS Status;
DPRINT1("ScmWriteSecurityDescriptor(%p %p)\n", hServiceKey, pSecurityDescriptor);
Status = RtlAbsoluteToSelfRelativeSD(pSecurityDescriptor,
NULL,
&dwBufferLength);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
DPRINT1("\n");
return RtlNtStatusToDosError(Status);
}
DPRINT1("BufferLength %lu\n", dwBufferLength);
pRelativeSD = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
dwBufferLength);
if (pRelativeSD == NULL)
{
DPRINT1("\n");
return ERROR_OUTOFMEMORY;
}
DPRINT1("\n");
Status = RtlAbsoluteToSelfRelativeSD(pSecurityDescriptor,
pRelativeSD,
&dwBufferLength);
if (!NT_SUCCESS(Status))
{
DPRINT1("\n");
dwError = RtlNtStatusToDosError(Status);
goto done;
}
DPRINT1("\n");
dwError = RegCreateKeyExW(hServiceKey,
L"Security",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE,
NULL,
&hSecurityKey,
&dwDisposition);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("\n");
goto done;
}
DPRINT1("\n");
dwError = RegSetValueExW(hSecurityKey,
L"Security",
0,
REG_BINARY,
(LPBYTE)pRelativeSD,
dwBufferLength);
DPRINT1("\n");
done:
if (hSecurityKey != NULL)
RegCloseKey(hSecurityKey);
if (pRelativeSD != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, pRelativeSD);
return dwError;
}
DWORD
ScmReadSecurityDescriptor(
_In_ HKEY hServiceKey,
_Out_ PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
{
PSECURITY_DESCRIPTOR pRelativeSD = NULL;
HKEY hSecurityKey = NULL;
DWORD dwBufferLength = 0;
DWORD dwType;
DWORD dwError;
dwError = RegOpenKeyExW(hServiceKey,
L"Security",
0,
KEY_QUERY_VALUE,
&hSecurityKey);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("\n");
goto done;
}
dwError = RegQueryValueExW(hSecurityKey,
L"Security",
0,
&dwType,
NULL,
&dwBufferLength);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("\n");
goto done;
}
pRelativeSD = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
dwBufferLength);
if (pRelativeSD == NULL)
{
DPRINT1("\n");
return ERROR_OUTOFMEMORY;
}
dwError = RegQueryValueExW(hSecurityKey,
L"Security",
0,
&dwType,
(LPBYTE)pRelativeSD,
&dwBufferLength);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("\n");
goto done;
}
done:
if (pRelativeSD != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, pRelativeSD);
if (hSecurityKey != NULL)
RegCloseKey(hSecurityKey);
return dwError;
}
/* EOF */

View file

@ -1364,9 +1364,6 @@ DWORD RQueryServiceObjectSecurity(
DWORD dwBytesNeeded;
DWORD dwError;
SECURITY_DESCRIPTOR ObjectDescriptor;
DPRINT("RQueryServiceObjectSecurity() called\n");
hSvc = ScmGetServiceFromHandle(hService);
@ -1401,11 +1398,8 @@ DWORD RQueryServiceObjectSecurity(
/* Lock the service database */
ScmLockDatabaseShared();
/* hack */
Status = RtlCreateSecurityDescriptor(&ObjectDescriptor, SECURITY_DESCRIPTOR_REVISION);
Status = RtlQuerySecurityObject(&ObjectDescriptor /* lpService->lpSecurityDescriptor */,
/* Retrieve the security descriptor */
Status = RtlQuerySecurityObject(lpService->pSecurityDescriptor,
dwSecurityInformation,
(PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
cbBufSize,
@ -2258,6 +2252,12 @@ DWORD RCreateServiceW(
goto done;
}
/* Assign the default security descriptor */
if (dwServiceType & SERVICE_WIN32)
{
lpService->pSecurityDescriptor = pDefaultServiceSD;
}
/* Write service data to the registry */
/* Create the service key */
dwError = ScmCreateServiceKey(lpServiceName,
@ -2391,6 +2391,13 @@ DWORD RCreateServiceW(
if (dwError != ERROR_SUCCESS)
goto done;
}
DPRINT1("\n");
/* Write the security descriptor */
dwError = ScmWriteSecurityDescriptor(hServiceKey,
lpService->pSecurityDescriptor);
if (dwError != ERROR_SUCCESS)
goto done;
}
dwError = ScmCreateServiceHandle(lpService,

View file

@ -0,0 +1,268 @@
/*
* PROJECT: ReactOS Service Control Manager
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/system/services/security.c
* PURPOSE: Security functions
* COPYRIGHT: Eric Kohl
*/
/* INCLUDES *****************************************************************/
#include "services.h"
#define NDEBUG
#include <debug.h>
PSECURITY_DESCRIPTOR pDefaultServiceSD = NULL;
static PSID pNullSid = NULL;
static PSID pLocalSystemSid = NULL;
static PSID pAuthenticatedUserSid = NULL;
static PSID pAliasAdminsSid = NULL;
/* FUNCTIONS ****************************************************************/
static
VOID
ScmFreeSids(VOID)
{
if (pNullSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, pNullSid);
if (pLocalSystemSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, pLocalSystemSid);
if (pAuthenticatedUserSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, pAuthenticatedUserSid);
if (pAliasAdminsSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, pAliasAdminsSid);
}
static
DWORD
ScmCreateSids(VOID)
{
SID_IDENTIFIER_AUTHORITY NullAuthority = {SECURITY_NULL_SID_AUTHORITY};
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
PULONG pSubAuthority;
ULONG ulLength1 = RtlLengthRequiredSid(1);
ULONG ulLength2 = RtlLengthRequiredSid(2);
/* Create the Null SID */
pNullSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, ulLength1);
if (pNullSid == NULL)
{
return ERROR_OUTOFMEMORY;
}
RtlInitializeSid(pNullSid, &NullAuthority, 1);
pSubAuthority = RtlSubAuthoritySid(pNullSid, 0);
*pSubAuthority = SECURITY_NULL_RID;
/* Create the LocalSystem SID */
pLocalSystemSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, ulLength1);
if (pLocalSystemSid == NULL)
{
return ERROR_OUTOFMEMORY;
}
RtlInitializeSid(pLocalSystemSid, &NtAuthority, 1);
pSubAuthority = RtlSubAuthoritySid(pLocalSystemSid, 0);
*pSubAuthority = SECURITY_LOCAL_SYSTEM_RID;
/* Create the AuthenticatedUser SID */
pAuthenticatedUserSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, ulLength1);
if (pAuthenticatedUserSid == NULL)
{
return ERROR_OUTOFMEMORY;
}
RtlInitializeSid(pAuthenticatedUserSid, &NtAuthority, 1);
pSubAuthority = RtlSubAuthoritySid(pAuthenticatedUserSid, 0);
*pSubAuthority = SECURITY_AUTHENTICATED_USER_RID;
/* Create the AliasAdmins SID */
pAliasAdminsSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, ulLength2);
if (pAliasAdminsSid == NULL)
{
return ERROR_OUTOFMEMORY;
}
RtlInitializeSid(pAliasAdminsSid, &NtAuthority, 2);
pSubAuthority = RtlSubAuthoritySid(pAliasAdminsSid, 0);
*pSubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
pSubAuthority = RtlSubAuthoritySid(pAliasAdminsSid, 1);
*pSubAuthority = DOMAIN_ALIAS_RID_ADMINS;
return ERROR_SUCCESS;
}
static
DWORD
ScmCreateDefaultServiceSD(VOID)
{
PSECURITY_DESCRIPTOR pServiceSD = NULL;
PACL pDacl = NULL;
PACL pSacl = NULL;
ULONG ulLength;
NTSTATUS Status;
DWORD dwError = ERROR_SUCCESS;
/* Create DACL */
ulLength = sizeof(ACL) +
(sizeof(ACE) + RtlLengthSid(pLocalSystemSid)) +
(sizeof(ACE) + RtlLengthSid(pAliasAdminsSid)) +
(sizeof(ACE) + RtlLengthSid(pAuthenticatedUserSid));
pDacl = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, ulLength);
if (pDacl == NULL)
{
dwError = ERROR_OUTOFMEMORY;
goto done;
}
RtlCreateAcl(pDacl, ulLength, ACL_REVISION);
RtlAddAccessAllowedAce(pDacl,
ACL_REVISION,
READ_CONTROL | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_INTERROGATE |
SERVICE_PAUSE_CONTINUE | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS |
SERVICE_START | SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL,
pLocalSystemSid);
RtlAddAccessAllowedAce(pDacl,
ACL_REVISION,
SERVICE_ALL_ACCESS,
pAliasAdminsSid);
RtlAddAccessAllowedAce(pDacl,
ACL_REVISION,
READ_CONTROL | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_INTERROGATE |
SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_USER_DEFINED_CONTROL,
pAuthenticatedUserSid);
/* Create SACL */
ulLength = sizeof(ACL) +
(sizeof(ACE) + RtlLengthSid(pNullSid));
pSacl = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, ulLength);
if (pSacl == NULL)
{
dwError = ERROR_OUTOFMEMORY;
goto done;
}
RtlCreateAcl(pSacl, ulLength, ACL_REVISION);
RtlAddAuditAccessAce(pSacl,
ACL_REVISION,
SERVICE_ALL_ACCESS,
pNullSid,
FALSE,
TRUE);
pServiceSD = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SECURITY_DESCRIPTOR));
if (pServiceSD == NULL)
{
dwError = ERROR_OUTOFMEMORY;
goto done;
}
DPRINT1("pServiceSD %p\n", pServiceSD);
Status = RtlCreateSecurityDescriptor(pServiceSD,
SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
goto done;
}
Status = RtlSetOwnerSecurityDescriptor(pServiceSD,
pLocalSystemSid,
FALSE);
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
goto done;
}
Status = RtlSetGroupSecurityDescriptor(pServiceSD,
pLocalSystemSid,
FALSE);
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
goto done;
}
Status = RtlSetDaclSecurityDescriptor(pServiceSD,
TRUE,
pDacl,
FALSE);
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
goto done;
}
Status = RtlSetSaclSecurityDescriptor(pServiceSD,
TRUE,
pSacl,
FALSE);
if (!NT_SUCCESS(Status))
{
dwError = RtlNtStatusToDosError(Status);
goto done;
}
pDefaultServiceSD = pServiceSD;
DPRINT1("pDefaultServiceSD %p\n", pDefaultServiceSD);
done:
if (dwError != ERROR_SUCCESS)
{
if (pDacl != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, pDacl);
if (pSacl != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, pSacl);
if (pServiceSD != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, pServiceSD);
}
return dwError;
}
DWORD
ScmInitializeSecurity(VOID)
{
DWORD dwError;
dwError = ScmCreateSids();
if (dwError != ERROR_SUCCESS)
return dwError;
dwError = ScmCreateDefaultServiceSD();
if (dwError != ERROR_SUCCESS)
return dwError;
return ERROR_SUCCESS;
}
VOID
ScmShutdownSecurity(VOID)
{
ScmFreeSids();
}
/* EOF */

View file

@ -354,6 +354,8 @@ wWinMain(HINSTANCE hInstance,
// ScmInitThreadManager();
ScmInitializeSecurity();
/* FIXME: more initialization */
/* Read the control set values */
@ -432,6 +434,8 @@ wWinMain(HINSTANCE hInstance,
WaitForSingleObject(hScmShutdownEvent, INFINITE);
done:
ScmShutdownSecurity();
/* Delete our communication named pipe's critical section */
if (bCanDeleteNamedPipeCriticalSection == TRUE)
ScmDeleteNamedPipeCriticalSection();

View file

@ -72,7 +72,7 @@ typedef struct _SERVICE
ULONG Flags;
PSECURITY_DESCRIPTOR lpSecurityDescriptor;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
BOOLEAN ServiceVisited;
@ -98,6 +98,8 @@ extern LIST_ENTRY ImageListHead;
extern BOOL ScmInitialize;
extern BOOL ScmShutdown;
extern PSECURITY_DESCRIPTOR pDefaultServiceSD;
/* FUNCTIONS ***************************************************************/
@ -132,6 +134,12 @@ ScmSetServicePassword(
IN PCWSTR pszServiceName,
IN PCWSTR pszPassword);
DWORD
ScmWriteSecurityDescriptor(
_In_ HKEY hServiceKey,
_In_ PSECURITY_DESCRIPTOR pSecurityDescriptor);
/* controlset.c */
BOOL ScmGetControlSetValues(VOID);
@ -197,6 +205,12 @@ VOID ScmQueryServiceLockStatusA(OUT LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus);
VOID ScmStartRpcServer(VOID);
/* security.c */
DWORD ScmInitializeSecurity(VOID);
VOID ScmShutdownSecurity(VOID);
/* services.c */
VOID PrintString(LPCSTR fmt, ...);