DACL

Поделись знанием:
Перейти к: навигация, поиск


DACL, англ. Discretionary Access Control List — список избирательного управления доступом, контролируемый владельцем объекта и регламентирующий права пользователей и групп на действия с объектом (чтение, запись, удаление и т. д.). [1] Состоит из набора ACE'ов. Пример добавления элементов в список DACL файла или каталога[2]:

#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>
#include <lm.h>

int main()
{
  wchar_t wchDirName[248];       // имя каталога
  wchar_t wchUserName[UNLEN];    // имя пользователя
  
  ACL *lpOldDacl;    // указатель на старый DACL
  ACL *lpNewDacl;    // указатель на новый DACL
  LPVOID lpAce;      // указатель на элемент ACE
  
  DWORD dwDaclLength = 0;        // длина DACL
  DWORD dwSdLength = 0;          // длина SD
  DWORD dwSidLength = 0;         // длина SID
  DWORD dwLengthOfDomainName = 0;    // длина имени домена
  
  PSID lpSid = NULL;             // указатель на разрешающий SID
  LPTSTR lpDomainName = NULL;    // указатель на имя домена
  
  SID_NAME_USE typeOfSid;        // тип учетной записи
  
  SECURITY_DESCRIPTOR *lpSd = NULL;  // адрес дескриптора безопасности
  SECURITY_DESCRIPTOR sdAbsoluteSd;  // абсолютный формат SD
  BOOL bDaclPresent;             // признак присутствия списка DACL
  BOOL bDaclDefaulted;           // признак списка DACL по умолчанию
  
  DWORD dwRetCode;   // код возврата

  // читаем имя файла или каталога
  printf("Input a file or directory name: ");
  _getws(wchDirName);
  
  // получаем длину дескриптора безопасности
  if (!GetFileSecurity(
    wchDirName,    // имя файла
    DACL_SECURITY_INFORMATION,   // получаем DACL
    lpSd,          // адрес дескриптора безопасности
    0,             // определяем длину буфера
    &dwSdLength))  // адрес для требуемой длины
  {
    dwRetCode = GetLastError();
    
    if (dwRetCode == ERROR_INSUFFICIENT_BUFFER)
      // распределяем память для буфера
      lpSd = (SECURITY_DESCRIPTOR*) new char[dwSdLength];
    else
    {
      // выходим из программы
      printf("Get file security failed.\n");
      printf("Error code: %d\n", dwRetCode);
      
      return dwRetCode;
    }
  }

  // читаем дескриптор безопасности
  if (!GetFileSecurity(
    wchDirName,    // имя файла
    DACL_SECURITY_INFORMATION,   // получаем DACL
    lpSd,          // адрес дескриптора безопасности
    dwSdLength,    // длину буфера
    &dwSdLength))  // адрес для требуемой длины
  {
    dwRetCode = GetLastError();
    printf("Get file security failed.\n");
    printf("Error code: %d\n", dwRetCode);
    
    return dwRetCode;
  }
  
  // вводим имя пользователя, которого добавляем в DACL
  printf("Input a user name: ");
  _getws(wchUserName);
  
  // определяем длину SID пользователя
  if (!LookupAccountName(
    NULL,          // ищем имя на локальном компьютере
    wchUserName,   // имя пользователя
    NULL,          // определяем длину SID
    &dwSidLength,  // длина SID
    NULL,          // определяем имя домена
    &dwLengthOfDomainName,     // длина имени домена
    &typeOfSid))   // тип учетной записи
  {
    dwRetCode = GetLastError();
    
    if (dwRetCode == ERROR_INSUFFICIENT_BUFFER)
    {
      // распределяем память для SID
      lpSid = (SID*) new char[dwSidLength];
      lpDomainName = (LPTSTR) new wchar_t[dwLengthOfDomainName];
    }
    else
    {
      // выходим из программы
      printf("Lookup account name failed.\n");
      printf("Error code: %d\n", dwRetCode);
      
      return dwRetCode;
    }
  }
  
  // определяем SID
  if(!LookupAccountName(
    NULL,          // ищем имя на локальном компьютере
    wchUserName,   // имя пользователя
    lpSid,         // указатель на SID
    &dwSidLength,  // длина SID
    lpDomainName,  // указатель на имя домена
    &dwLengthOfDomainName,   // длина имени домена
    &typeOfSid))   // тип учетной записи
  {
    dwRetCode = GetLastError();
    
    printf("Lookup account name failed.\n");
    printf("Error code: %d\n", dwRetCode);
    
    return dwRetCode;
  }

  // получаем список DACL из дескриптора безопасности
  if (!GetSecurityDescriptorDacl(
    lpSd,              // адрес дескриптора безопасности
    &bDaclPresent,     // признак присутствия списка DACL
    &lpOldDacl,        // адрес указателя на DACL
    &bDaclDefaulted))  // признак списка DACL по умолчанию
  {
    dwRetCode = GetLastError();
    printf("Get security descriptor DACL failed.\n");
    printf("Error code: %d\n", dwRetCode);
    
    return dwRetCode;
  }

  // определяем длину нового DACL
  dwDaclLength = lpOldDacl->AclSize + 
    sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + dwSidLength;

  // распределяем память под новый DACL
  lpNewDacl = (ACL*)new char[dwDaclLength];

  // инициализируем новый DACL
  if (!InitializeAcl(
    lpNewDacl,       // адрес DACL
    dwDaclLength,    // длина DACL
    ACL_REVISION))   // версия DACL
  {
    dwRetCode = GetLastError();
    
    printf("Lookup account name failed.\n");
    printf("Error code: %d\n", dwRetCode);
    
    return dwRetCode;
  }

  // добавляем нового элемент в новый DACL
  if (!AddAccessDeniedAce(
    lpNewDacl,       // адрес DACL
    ACL_REVISION,    // версия DACL
    FILE_WRITE_ATTRIBUTES,  // запрещаем писать атрибуты
    lpSid))          // адрес SID
  {
    dwRetCode = GetLastError();
    perror("Add access allowed ace failed.\n");
    printf("The last error code: %u\n", dwRetCode);
    
    return dwRetCode;
  }

  // получаем адрес первого ACE в старом списке DACL
  if (!GetAce(
    lpOldDacl,     // адрес старого DACL
    0,             // ищем первый элемент
    &lpAce))       // адрес первого элемента
  {
    dwRetCode = GetLastError();
    
    printf("Get ace failed.\n");
    printf("Error code: %d\n", dwRetCode);
    
    return dwRetCode;
  }

  // переписываем элементы из старого DACL в новый DACL
  if (bDaclPresent)
  {
    if (!AddAce(
      lpNewDacl,       // адрес нового DACL
      ACL_REVISION,    // версия DACL
      MAXDWORD,        // добавляем в конец списка
      lpAce,           // адрес старого DACL
      lpOldDacl->AclSize - sizeof(ACL)))  // длина старого DACL
    {
      dwRetCode = GetLastError();
      perror("Add access allowed ace failed.\n");
      printf("The last error code: %u\n", dwRetCode);
      
      return dwRetCode;
    }
  }

  // проверяем достоверность DACL
  if (!IsValidAcl(lpNewDacl))
  {
    dwRetCode = GetLastError();
    perror("The new ACL is invalid.\n");
    printf("The last error code: %u\n", dwRetCode);
    
    return dwRetCode;
  }

  // создаем новый дескриптор безопасности в абсолютной форме
  if (!InitializeSecurityDescriptor(
    &sdAbsoluteSd,       // адрес структуры SD
    SECURITY_DESCRIPTOR_REVISION))
  {
    dwRetCode = GetLastError();
    perror("Initialize security descriptor failed.\n");
    printf("The last error code: %u\n", dwRetCode);
    
    return dwRetCode;
  }

  // устанавливаем DACL  в новый дескриптор безопасности
  if (!SetSecurityDescriptorDacl(
    &sdAbsoluteSd,   // адрес дескриптора безопасности
    TRUE,            // DACL присутствует
    lpNewDacl,       // указатель на DACL
    FALSE))          // DACL не задан по умолчанию
  {
    dwRetCode = GetLastError();
    perror("Set security descriptor DACL failed.\n");
    printf("The last error code: %u\n", dwRetCode);
    
    return dwRetCode;
  }
  
  // проверяем структуру дескриптора безопасности
  if (!IsValidSecurityDescriptor(&sdAbsoluteSd))
  {
    dwRetCode = GetLastError();
    perror("Security descriptor is invalid.\n");
    printf("The last error code: %u\n", dwRetCode);
    
    return dwRetCode;
  }
  // устанавливаем новый дескриптор безопасности
  if (!SetFileSecurity(
    wchDirName,        // имя файла
    DACL_SECURITY_INFORMATION,     // устанавливаем DACL
    &sdAbsoluteSd))    // адрес дескриптора безопасности
  {
    dwRetCode = GetLastError();
    printf("Set file security failed.\n");
    printf("Error code: %d\n", dwRetCode);
    
    return dwRetCode;
  }
  
  // освобождаем память
  delete[] lpSd;
  delete[] lpSid;
  delete[] lpDomainName;
  delete[] lpNewDacl;

  return 0;
}

Напишите отзыв о статье "DACL"



Литература

Побегайло А. П. Системное программирование в Windows. — СПб.: БХВ-Петербург, 2006. — 1056 с: ил.

Примечания

  1. [msdn.microsoft.com/en-us/library/ms721573(VS.85).aspx#_security_discretionary_access_control_list_gly D (Windows)]
  2. Побегайло А. П. Системное программирование в Windows. — СПб.: БХВ-Петербург, 2006. — 1056 с: ил.


Отрывок, характеризующий DACL

– De Bal macheve! – сказал король (своей решительностью превозмогая трудность, представлявшуюся полковнику), – charme de faire votre connaissance, general, [очень приятно познакомиться с вами, генерал] – прибавил он с королевски милостивым жестом. Как только король начал говорить громко и быстро, все королевское достоинство мгновенно оставило его, и он, сам не замечая, перешел в свойственный ему тон добродушной фамильярности. Он положил свою руку на холку лошади Балашева.
– Eh, bien, general, tout est a la guerre, a ce qu'il parait, [Ну что ж, генерал, дело, кажется, идет к войне,] – сказал он, как будто сожалея об обстоятельстве, о котором он не мог судить.
– Sire, – отвечал Балашев. – l'Empereur mon maitre ne desire point la guerre, et comme Votre Majeste le voit, – говорил Балашев, во всех падежах употребляя Votre Majeste, [Государь император русский не желает ее, как ваше величество изволите видеть… ваше величество.] с неизбежной аффектацией учащения титула, обращаясь к лицу, для которого титул этот еще новость.
Лицо Мюрата сияло глупым довольством в то время, как он слушал monsieur de Balachoff. Но royaute oblige: [королевское звание имеет свои обязанности:] он чувствовал необходимость переговорить с посланником Александра о государственных делах, как король и союзник. Он слез с лошади и, взяв под руку Балашева и отойдя на несколько шагов от почтительно дожидавшейся свиты, стал ходить с ним взад и вперед, стараясь говорить значительно. Он упомянул о том, что император Наполеон оскорблен требованиями вывода войск из Пруссии, в особенности теперь, когда это требование сделалось всем известно и когда этим оскорблено достоинство Франции. Балашев сказал, что в требовании этом нет ничего оскорбительного, потому что… Мюрат перебил его:
– Так вы считаете зачинщиком не императора Александра? – сказал он неожиданно с добродушно глупой улыбкой.
Балашев сказал, почему он действительно полагал, что начинателем войны был Наполеон.
– Eh, mon cher general, – опять перебил его Мюрат, – je desire de tout mon c?ur que les Empereurs s'arrangent entre eux, et que la guerre commencee malgre moi se termine le plutot possible, [Ах, любезный генерал, я желаю от всей души, чтобы императоры покончили дело между собою и чтобы война, начатая против моей воли, окончилась как можно скорее.] – сказал он тоном разговора слуг, которые желают остаться добрыми приятелями, несмотря на ссору между господами. И он перешел к расспросам о великом князе, о его здоровье и о воспоминаниях весело и забавно проведенного с ним времени в Неаполе. Потом, как будто вдруг вспомнив о своем королевском достоинстве, Мюрат торжественно выпрямился, стал в ту же позу, в которой он стоял на коронации, и, помахивая правой рукой, сказал: – Je ne vous retiens plus, general; je souhaite le succes de vorte mission, [Я вас не задерживаю более, генерал; желаю успеха вашему посольству,] – и, развеваясь красной шитой мантией и перьями и блестя драгоценностями, он пошел к свите, почтительно ожидавшей его.
Балашев поехал дальше, по словам Мюрата предполагая весьма скоро быть представленным самому Наполеону. Но вместо скорой встречи с Наполеоном, часовые пехотного корпуса Даву опять так же задержали его у следующего селения, как и в передовой цепи, и вызванный адъютант командира корпуса проводил его в деревню к маршалу Даву.


Даву был Аракчеев императора Наполеона – Аракчеев не трус, но столь же исправный, жестокий и не умеющий выражать свою преданность иначе как жестокостью.
В механизме государственного организма нужны эти люди, как нужны волки в организме природы, и они всегда есть, всегда являются и держатся, как ни несообразно кажется их присутствие и близость к главе правительства. Только этой необходимостью можно объяснить то, как мог жестокий, лично выдиравший усы гренадерам и не могший по слабости нерв переносить опасность, необразованный, непридворный Аракчеев держаться в такой силе при рыцарски благородном и нежном характере Александра.
Балашев застал маршала Даву в сарае крестьянскои избы, сидящего на бочонке и занятого письменными работами (он поверял счеты). Адъютант стоял подле него. Возможно было найти лучшее помещение, но маршал Даву был один из тех людей, которые нарочно ставят себя в самые мрачные условия жизни, для того чтобы иметь право быть мрачными. Они для того же всегда поспешно и упорно заняты. «Где тут думать о счастливой стороне человеческой жизни, когда, вы видите, я на бочке сижу в грязном сарае и работаю», – говорило выражение его лица. Главное удовольствие и потребность этих людей состоит в том, чтобы, встретив оживление жизни, бросить этому оживлению в глаза спою мрачную, упорную деятельность. Это удовольствие доставил себе Даву, когда к нему ввели Балашева. Он еще более углубился в свою работу, когда вошел русский генерал, и, взглянув через очки на оживленное, под впечатлением прекрасного утра и беседы с Мюратом, лицо Балашева, не встал, не пошевелился даже, а еще больше нахмурился и злобно усмехнулся.
Заметив на лице Балашева произведенное этим приемом неприятное впечатление, Даву поднял голову и холодно спросил, что ему нужно.
Предполагая, что такой прием мог быть сделан ему только потому, что Даву не знает, что он генерал адъютант императора Александра и даже представитель его перед Наполеоном, Балашев поспешил сообщить свое звание и назначение. В противность ожидания его, Даву, выслушав Балашева, стал еще суровее и грубее.
– Где же ваш пакет? – сказал он. – Donnez le moi, ije l'enverrai a l'Empereur. [Дайте мне его, я пошлю императору.]