windows-nt/Source/XPSP1/NT/ds/security/ntmarta/newsrc/service.cxx
2020-09-26 16:20:57 +08:00

474 lines
15 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1996.
//
// File: service.cxx
//
// Contents: Service support functions
//
// History: 8/94 davemont Created
//
//----------------------------------------------------------------------------
#include <aclpch.hxx>
#pragma hdrstop
//+---------------------------------------------------------------------------
//
// Function: OpenServiceObject
//
// Synopsis: Opens the specified service object
//
// Arguments: [IN pwszService] -- The name of the service to
// open
// [IN AccessMask] -- Flags indicating if the object
// is to be opened to read or write
// the DACL
// [OUT pHandle] -- Where the open handle is
// returned
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
// ERROR_INVALID_PARAMETER -- A bad name was given
//
//----------------------------------------------------------------------------
DWORD
OpenServiceObject(IN LPWSTR pwszService,
IN ACCESS_MASK AccessMask,
OUT SC_HANDLE *pHandle)
{
acDebugOut((DEB_TRACE, "in OpenServiceObject \n"));
DWORD dwErr;
//
// Make sure the service functions are loaded
//
dwErr = LoadDLLFuncTable();
if(dwErr != ERROR_SUCCESS)
{
return(dwErr);
}
if(pwszService != NULL)
{
WCHAR wszName[MAX_PATH + 1];
PWSTR pwszName;
//
// save the object since we must crack it to go to remote machines
//
dwErr = AccGetBufferOfSizeW(pwszService,
wszName,
&pwszName);
if(dwErr == ERROR_SUCCESS)
{
PWSTR pwszSvcName, pwszMachine;
//
// Separate the names
//
dwErr = ParseName(pwszName,
&pwszMachine,
&pwszSvcName);
//
// Go ahead and open the service control manager
//
if(dwErr == ERROR_SUCCESS)
{
SC_HANDLE hSC = OpenSCManager(pwszMachine,
NULL,
GENERIC_READ);
if(hSC == NULL)
{
dwErr = GetLastError();
}
else
{
//
// Open the service
//
*pHandle = OpenService(hSC,
pwszSvcName,
AccessMask);
if(*pHandle == NULL)
{
dwErr = GetLastError();
}
//
// Close the handle to the scm
//
CloseServiceHandle(hSC);
}
}
//
// Free our buffer
//
AccFreeBufferOfSizeW(wszName, pwszName);
}
}
else
{
dwErr = ERROR_INVALID_PARAMETER;
}
acDebugOut((DEB_TRACE, "Out OpenServiceObject: %lu\n", dwErr));
return(dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: ReadServicePropertyRights
//
// Synopsis: Gets the specified security info for the specified service
// object
//
// Arguments: [IN pwszService] -- The service to get the rights
// for
// [IN pRightsList] -- SecurityInfo to read based
// on properties
// [IN cRights] -- Number of items in rights list
// [IN AccessList] -- Access List to fill in
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_INVALID_PARAMETER -- A bad property was encountered
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
//
//----------------------------------------------------------------------------
DWORD
ReadServicePropertyRights(IN LPWSTR pwszService,
IN PACTRL_RIGHTS_INFO pRightsList,
IN ULONG cRights,
IN CAccessList& AccessList)
{
acDebugOut((DEB_TRACE, "in ReadServicePropertyRights\n"));
DWORD dwErr = ERROR_SUCCESS;
SC_HANDLE hSvc;
//
// For the moment, there is only service property itself...
//
ASSERT(cRights == 1 && pRightsList[0].pwszProperty == NULL);
if(cRights != 1 || pRightsList[0].pwszProperty != NULL)
{
return(ERROR_INVALID_PARAMETER);
}
//
// Open the service
//
dwErr = OpenServiceObject(pwszService,
GetDesiredAccess(READ_ACCESS_RIGHTS,
pRightsList[0].SeInfo),
&hSvc);
if(dwErr == ERROR_SUCCESS)
{
dwErr = ReadServiceRights(hSvc,
pRightsList,
cRights,
AccessList);
//
// Close the object handle
//
CloseServiceHandle(hSvc);
}
acDebugOut((DEB_TRACE, "Out ReadServicePropertyRights: %lu\n", dwErr));
return(dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: ReadServiceRights
//
// Synopsis: Gets the specified security info for the specified service
// object
//
// Arguments: [IN hSvc] -- Handle to the open service
// [IN pRightsList] -- SecurityInfo to read based
// on properties
// [IN cRights] -- Number of items in rights list
// [IN AccessList] -- Access List to fill in
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_INVALID_PARAMETER -- A bad property was encountered
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
//
//----------------------------------------------------------------------------
DWORD
ReadServiceRights(IN SC_HANDLE hSvc,
IN PACTRL_RIGHTS_INFO pRightsList,
IN ULONG cRights,
IN CAccessList& AccessList)
{
acDebugOut((DEB_TRACE, "in ReadServiceRights\n"));
DWORD dwErr = ERROR_SUCCESS;
//
// For the moment, there is only service property itself...
//
ASSERT(cRights == 1 && pRightsList[0].pwszProperty == NULL);
if(cRights != 1 || pRightsList[0].pwszProperty != NULL)
{
return(ERROR_INVALID_PARAMETER);
}
//
// Get the service security...
//
UCHAR SDBuff[PSD_BASE_LENGTH];
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SDBuff;
ULONG cSize = 0;
//
// Get the size of the security descriptor from the service
//
if(QueryServiceObjectSecurity(hSvc,
pRightsList[0].SeInfo,
pSD,
PSD_BASE_LENGTH,
&cSize) == FALSE)
{
dwErr = GetLastError();
if(dwErr == ERROR_INSUFFICIENT_BUFFER)
{
dwErr = ERROR_SUCCESS;
pSD = (PISECURITY_DESCRIPTOR)AccAlloc(cSize);
if(pSD == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
}
else
{
if(QueryServiceObjectSecurity(hSvc,
pRightsList[0].SeInfo,
pSD,
cSize,
&cSize) == FALSE)
{
dwErr = GetLastError();
}
}
}
}
//
// If all that worked, we'll add our SD
//
if(dwErr == ERROR_SUCCESS)
{
dwErr = AccessList.AddSD(pSD,
pRightsList->SeInfo,
pRightsList->pwszProperty);
}
//
// Free our memory if we allocated...
//
if(cSize > PSD_BASE_LENGTH)
{
AccFree(pSD);
}
acDebugOut((DEB_TRACE, "Out ReadServiceRights: %lu\n", dwErr));
return(dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: GetServiceParentRights
//
// Synopsis: Determines who the parent is, and gets the access rights
// for it. It is used to aid in determining what the approriate
// inheritance bits are.
//
// This operation does not make sense for kernel objects
//
// Arguments: [IN pwszService] -- The service to get the parent
// for
// [IN pRightsList] -- The properties to get the
// rights for
// [IN cRights] -- Number of items in rights list
// [OUT ppDAcl] -- Where the DACL is returned
// [OUT ppSAcl] -- Where the SACL is returned
// [OUT ppSD] -- Where the Security Descriptor
// is returned
//
// Returns: ERROR_INVALID_FUNCTION -- Call doesn't make sense here
//
//----------------------------------------------------------------------------
DWORD
GetServiceParentRights(IN LPWSTR pwszService,
IN PACTRL_RIGHTS_INFO pRightsList,
IN ULONG cRights,
OUT PACL *ppDAcl,
OUT PACL *ppSAcl,
OUT PSECURITY_DESCRIPTOR *ppSD)
{
//
// This doesn't currently make sense for kernel objects, so simply
// return an error
//
return(ERROR_INVALID_FUNCTION);
}
//+---------------------------------------------------------------------------
//
// Function: SetServiceSecurityInfo
//
// Synopsis: Sets the specified security info on the specified service
// object
//
// Arguments: [IN hService] -- The handle of the object
// [IN SeInfo] -- Flag indicating what security
// info to set
// [IN pwszProperty] -- The property on the object to
// set
// For kernel objects, this MBZ
// [IN pSD] -- The security descriptor to set
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_INVALID_PARAMETER -- A bad property was given
//
//----------------------------------------------------------------------------
DWORD
SetServiceSecurityInfo(IN SC_HANDLE hService,
IN SECURITY_INFORMATION SeInfo,
IN PWSTR pwszProperty,
IN PSECURITY_DESCRIPTOR pSD)
{
acDebugOut((DEB_TRACE, "in SetServiceSecurityInfo\n"));
DWORD dwErr = ERROR_SUCCESS;
//
// Service don't have properties
//
if(pwszProperty != NULL)
{
dwErr = ERROR_INVALID_PARAMETER;
}
else
{
if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION)) {
((PISECURITY_DESCRIPTOR)pSD)->Control |= SE_DACL_AUTO_INHERIT_REQ;
}
if(FLAG_ON(SeInfo, SACL_SECURITY_INFORMATION)) {
((PISECURITY_DESCRIPTOR)pSD)->Control |= SE_SACL_AUTO_INHERIT_REQ;
}
//
// set the security descriptor on the service
//
if(SetServiceObjectSecurity(hService,
SeInfo,
pSD) == FALSE)
{
dwErr = GetLastError();
}
}
acDebugOut((DEB_TRACE, "Out SetServiceSecurityInfo: %lu\n", dwErr));
return(dwErr);
}
#if 0
//+---------------------------------------------------------------------------
//
// Function : GetServiceAccessMaskFromProviderIndependentRights
//
// Synopsis : translates the specified provider independent access rights into
// an access mask for a service
//
// Arguments: IN [AccessRights] - the input access rights
// OUT [AccessMask] - the returned NT access mask
//
//----------------------------------------------------------------------------
void GetServiceAccessMaskFromProviderIndependentRights(ULONG AccessRights,
ACCESS_MASK *AccessMask)
{
if (PROV_OBJECT_READ & AccessRights)
{
*AccessMask |= SERVICE_READ;
}
if (PROV_OBJECT_WRITE & AccessRights)
{
*AccessMask |= SERVICE_WRITE;
}
if (PROV_OBJECT_EXECUTE & AccessRights)
{
*AccessMask |= SERVICE_EXECUTE;
}
}
//+---------------------------------------------------------------------------
//
// Function : GetServiceProviderIndependentRightsFromAccessMask
//
// Synopsis : translates a service access mask into provider independent
// access rights
//
// Arguments: IN OUT [AccessMask] - the input NT access mask (modified)
// OUT [AccessRights] - the returned access rights
//
//----------------------------------------------------------------------------
ACCESS_RIGHTS GetServiceProviderIndependentRightsFromAccessMask( ACCESS_MASK AccessMask)
{
ACCESS_RIGHTS accessrights = 0;
if (GENERIC_ALL & AccessMask)
{
accessrights = PROV_ALL_ACCESS;
} else
{
if (KEY_ALL_ACCESS == (KEY_ALL_ACCESS & AccessMask))
{
accessrights = PROV_ALL_ACCESS;
} else
{
if (WRITE_DAC & AccessMask)
{
accessrights |= PROV_EDIT_ACCESSRIGHTS;
}
if (SERVICE_READ == (SERVICE_READ & AccessMask))
{
accessrights |= PROV_OBJECT_READ;
}
if (SERVICE_WRITE == (SERVICE_WRITE & AccessMask))
{
accessrights |= PROV_OBJECT_WRITE;
}
if (SERVICE_EXECUTE == (SERVICE_EXECUTE & AccessMask) )
{
accessrights |= PROV_OBJECT_EXECUTE;
}
}
}
return(accessrights);
}
#endif