Приложение может создать или модифицировать 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);
} |