Modifying the DACL for a Service
An application can create or modify the DACL associated with a Service object in order to control access. To retrieve the DACL associated with a service object, use the QueryServiceObjectSecurity function. To set the DACL, use the SetServiceObjectSecurity function. Any changes made to the SECURITY_DESCRIPTOR associated with the service object are persistent until the service is removed from the system.
The following sample code creates and sets a new DACL for the service specified on the command line. The sample code merges one Access Control Entry (ACE) to the existing DACL for the service. The new ACE grants the Guest account start, stop, delete, and READ_CONTROL access to the specified service. Access to the service can be modified by the AccessPermissions parameter passed to the BuildExplicitAccessWithName function.
#include <windows.h>
#include <aclapi.h>
#include <stdio.h>
#include <tchar.h>
void DisplayError(DWORD dwError, LPTSTR pszAPI)
{
LPVOID lpvMessageBuffer;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpvMessageBuffer, 0, NULL);
// Display the string.
_tprintf(TEXT("ERROR: API = %s./n"), pszAPI);
_tprintf(TEXT(" error code = %u./n"), dwError);
_tprintf(TEXT(" message = %s./n"),
(LPTSTR)lpvMessageBuffer);
// Free the buffer allocated by the system.
LocalFree(lpvMessageBuffer);
ExitProcess(dwError);
}
void _tmain(int argc, TCHAR *argv[])
{
BOOL bDaclPresent = FALSE;
BOOL bDaclDefaulted = FALSE;
DWORD dwError = 0;
DWORD dwSize = 0;
EXPLICIT_ACCESS ea;
PACL pacl = NULL;
PACL pNewAcl = NULL;
PSECURITY_DESCRIPTOR psd;
SC_HANDLE schManager = NULL;
SC_HANDLE schService = NULL;
SECURITY_DESCRIPTOR sd;
if (argc != 2)
{
_tprintf(TEXT("Usage: %s [service name]/n"), argv[0]);
return;
}
// Obtain a handle to the Service Controller.
schManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (schManager == NULL)
DisplayError(GetLastError(), TEXT("OpenSCManager"));
// Obtain a handle to the service.
schService = OpenService(schManager, argv[1],
READ_CONTROL | WRITE_DAC);
if (schService == NULL)
DisplayError(GetLastError(), TEXT("OpenService"));
// Get the current security descriptor.
if (!QueryServiceObjectSecurity(schService,
DACL_SECURITY_INFORMATION, psd, 0, &dwSize))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, dwSize);
if (psd == NULL)
{
DisplayError(0, TEXT("HeapAlloc"));
// note HeapAlloc does not support GetLastError()
}
if (!QueryServiceObjectSecurity(schService,
DACL_SECURITY_INFORMATION, psd, dwSize, &dwSize))
DisplayError(GetLastError(),
TEXT("QueryServiceObjectSecurity"));
}
else
DisplayError(GetLastError(),
TEXT("QueryServiceObjectSecurity"));
}
// Get the DACL.
if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl,
&bDaclDefaulted))
DisplayError(GetLastError(), TEXT("GetSecurityDescriptorDacl"));
// Build the ACE.
BuildExplicitAccessWithName(&ea, TEXT("GUEST"),
SERVICE_START | SERVICE_STOP | READ_CONTROL | DELETE,
SET_ACCESS, NO_INHERITANCE);
dwError = SetEntriesInAcl(1, &ea, pacl, &pNewAcl);
if (dwError != ERROR_SUCCESS)
DisplayError(dwError, TEXT("SetEntriesInAcl"));
// Initialize a NEW Security Descriptor.
if (!InitializeSecurityDescriptor(&sd,
SECURITY_DESCRIPTOR_REVISION))
DisplayError(GetLastError(),
TEXT("InitializeSecurityDescriptor"));
// Set the new DACL in the Security Descriptor.
if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE))
DisplayError(GetLastError(), TEXT("SetSecurityDescriptorDacl"));
// Set the new DACL for the service object.
if (!SetServiceObjectSecurity(schService,
DACL_SECURITY_INFORMATION, &sd))
DisplayError(GetLastError(), TEXT("SetServiceObjectSecurity"));
// Close the handles.
if (!CloseServiceHandle(schManager))
DisplayError(GetLastError(), TEXT("CloseServiceHandle"));
if (!CloseServiceHandle(schService))
DisplayError(GetLastError(), TEXT("CloseServiceHandle"));
// Free buffers.
LocalFree((HLOCAL)pNewAcl);
HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
}
应用程序可创建或修改与服务对象关联的DACL来控制访问。可使用QueryServiceObjectSecurity函数检索DACL,用SetServiceObjectSecurity函数设置。对服务对象关联的SECURITY_DESCRIPTOR所做更改在服务从系统移除前一直有效。还给出了创建和设置新DACL的示例代码。
879

被折叠的 条评论
为什么被折叠?



