Модификация DACL для службы


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

 

Назад в оглавление
На главную страницу

Hosted by uCoz