Приложение может создать или модифицировать DACL, связанный с объектом службы, чтобы управлять доступом. Чтобы извлечь DACL, связанный с объектом службы, используйте функцию QueryServiceObjectSecurity. Чтобы установить DACL, используйте функцию SetServiceObjectSecurity. Любые изменения, сделанные в SECURITY_DESCRIPTOR, связанным с объектом службы постоянны до тех пор, пока служба не будет удалена из системы.
Нижеследующий типовой код создает и устанавливает новый DACL службы заданной командной строкой. Типовой код объединяет Элемент списка контроля доступа (ACE) с существующим DACL службы. Новый ACE предоставляет указанной службе запуск, останов, удаление учетной записи Guest и доступ READ_CONTROL. Доступ службе может быть модифицирован параметром AccessPermissions, который передают функции BuildExplicitAccessWithName.
#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); // Показываем на экране строку. _tprintf(TEXT("ERROR: API = %s.\n"), pszAPI); _tprintf(TEXT(" error code = %u.\n"), dwError); _tprintf(TEXT(" message = %s.\n"), (LPTSTR)lpvMessageBuffer); // Освобождаем буфер назначенный системой. 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; } // Получим дескриптор Диспетчера службы. schManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (schManager == NULL) DisplayError(GetLastError(), TEXT("OpenSCManager")); // Получим дескриптор службы. schService = OpenService(schManager, argv[1], READ_CONTROL | WRITE_DAC); if (schService == NULL) DisplayError(GetLastError(), TEXT("OpenService")); // Получим текущий дескриптор безопасности. 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")); // Обратите внимание на то, что HeapAlloc не поддерживает GetLastError() } if (!QueryServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, psd, dwSize, &dwSize)) DisplayError(GetLastError(), TEXT("QueryServiceObjectSecurity")); } else DisplayError(GetLastError(), TEXT("QueryServiceObjectSecurity")); } // Получим DACL. if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, &bDaclDefaulted)) DisplayError(GetLastError(), TEXT("GetSecurityDescriptorDacl")); // Создадим 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")); // Инициализируем НОВЫЙ дескриптор безопасности. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) DisplayError(GetLastError(), TEXT("InitializeSecurityDescriptor")); // Установим новый DACL в Дескриптор безопасности. if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE)) DisplayError(GetLastError(), TEXT("SetSecurityDescriptorDacl")); // Установим новый DACL объекта службы. if (!SetServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, &sd)) DisplayError(GetLastError(), TEXT("SetServiceObjectSecurity")); // Закроем дескрипторы. if (!CloseServiceHandle(schManager)) DisplayError(GetLastError(), TEXT("CloseServiceHandle")); if (!CloseServiceHandle(schService)) DisplayError(GetLastError(), TEXT("CloseServiceHandle")); // Освободим буферы. LocalFree((HLOCAL)pNewAcl); HeapFree(GetProcessHeap(), 0, (LPVOID)psd); } |