修改服務的 DACL
服務控制程式可以建立或修改與服務相關聯的 DACL 來控制存取。 若要擷取與服務物件相關聯的 DACL,請使用 QueryServiceObjectSecurity 函式。 若要設定 DACL,請使用 SetServiceObjectSecurity 函式。 對與服務物件相關聯的 SECURITY_DESCRIPTOR 所做的任何變更都會持續發生,直到服務從系統中移除為止。
下列範例會建立並設定服務的新 DACL。 程式碼會將一個存取控制專案 (ACE) 合併至服務的現有 DACL。 新的 ACE 會授與來賓帳戶對指定服務的啟動、停止、刪除和READ_CONTROL存取權。 傳遞至BuildExplicitAccessWithName函式的AccessPermissions參數可以修改服務的存取權。
szSvcName 變數是包含服務名稱的全域變數。 如需設定此變數的完整範例,請參閱 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);
}
相關主題