Modificando a DACL para um serviço
Um programa de controle de serviço pode criar ou modificar a DACL associada a um serviço para controlar o acesso. Para recuperar a DACL associada a um objeto de serviço, use a função QueryServiceObjectSecurity . Para definir a DACL, use a função SetServiceObjectSecurity . Todas as alterações feitas no SECURITY_DESCRIPTOR associadas ao objeto de serviço são persistentes até que o serviço seja removido do sistema.
O exemplo a seguir cria e define uma nova DACL para o serviço. O código mescla uma ACE (entrada de controle de acesso) à DACL existente para o serviço. A nova ACE concede acesso de início, parada, exclusão e READ_CONTROL da conta convidada ao serviço especificado. O acesso ao serviço pode ser modificado pelo parâmetro AccessPermissions passado para a função BuildExplicitAccessWithName .
A variável szSvcName é uma variável global que contém o nome do serviço. Para obter o exemplo completo que define essa variável, consulte SvcControl.cpp.
//
// Purpose:
// Updates the service DACL to grant start, stop, delete, and read
// control access to the Guest account.
//
// Parameters:
// None
//
// Return value:
// None
//
VOID __stdcall DoUpdateSvcDacl()
{
EXPLICIT_ACCESS ea;
SECURITY_DESCRIPTOR sd;
PSECURITY_DESCRIPTOR psd = NULL;
PACL pacl = NULL;
PACL pNewAcl = NULL;
BOOL bDaclPresent = FALSE;
BOOL bDaclDefaulted = FALSE;
DWORD dwError = 0;
DWORD dwSize = 0;
DWORD dwBytesNeeded = 0;
// Get a handle to the SCM database.
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}
// Get a handle to the service
schService = OpenService(
schSCManager, // SCManager database
szSvcName, // name of service
READ_CONTROL | WRITE_DAC); // access
if (schService == NULL)
{
printf("OpenService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}
// Get the current security descriptor.
if (!QueryServiceObjectSecurity(schService,
DACL_SECURITY_INFORMATION,
&psd, // using NULL does not work on all versions
0,
&dwBytesNeeded))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
dwSize = dwBytesNeeded;
psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, dwSize);
if (psd == NULL)
{
// Note: HeapAlloc does not support GetLastError.
printf("HeapAlloc failed\n");
goto dacl_cleanup;
}
if (!QueryServiceObjectSecurity(schService,
DACL_SECURITY_INFORMATION, psd, dwSize, &dwBytesNeeded))
{
printf("QueryServiceObjectSecurity failed (%d)\n", GetLastError());
goto dacl_cleanup;
}
}
else
{
printf("QueryServiceObjectSecurity failed (%d)\n", GetLastError());
goto dacl_cleanup;
}
}
// Get the DACL.
if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl,
&bDaclDefaulted))
{
printf("GetSecurityDescriptorDacl failed(%d)\n", GetLastError());
goto dacl_cleanup;
}
// 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)
{
printf("SetEntriesInAcl failed(%d)\n", dwError);
goto dacl_cleanup;
}
// Initialize a new security descriptor.
if (!InitializeSecurityDescriptor(&sd,
SECURITY_DESCRIPTOR_REVISION))
{
printf("InitializeSecurityDescriptor failed(%d)\n", GetLastError());
goto dacl_cleanup;
}
// Set the new DACL in the security descriptor.
if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE))
{
printf("SetSecurityDescriptorDacl failed(%d)\n", GetLastError());
goto dacl_cleanup;
}
// Set the new DACL for the service object.
if (!SetServiceObjectSecurity(schService,
DACL_SECURITY_INFORMATION, &sd))
{
printf("SetServiceObjectSecurity failed(%d)\n", GetLastError());
goto dacl_cleanup;
}
else printf("Service DACL updated successfully\n");
dacl_cleanup:
CloseServiceHandle(schSCManager);
CloseServiceHandle(schService);
if(NULL != pNewAcl)
LocalFree((HLOCAL)pNewAcl);
if(NULL != psd)
HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
}
Tópicos relacionados