тельство, что для того, чтобы сформировать список ACL, вы должны вычис-
лить его точный размер. Список ACL должен обладать размером, достаточным
для того, чтобы вместить в себя все АСЕ. Однако разные записи АСЕ могут
включать в себя разное количество байт. Таким образом, задача вычисления
размера ACL может оказаться непростой.
Размер записи АСЕ зависит от ее типа и длины SID, который в ней содер-
жится. Для записей АСЕ, разрешающих доступ, длина записи составляет:
L = sizeof(ACCESS_ALLOWED_ACE) – sizeof
(ACCESS_ALLOWED_ACE.SidStart) + GetLengthSid((PSID) ace.SidStart);…
Как видно, к длине заголовка (за вычетом длины первой части SID) добавляет-
ся длина SID. Таким образом, размер ACL равняется размеру структуры ACL плюс
сумма размеров всех АСЕ, входящих в список. Зачастую возникает соблазн не тра-
тить время на расчеты, а просто зарезервировать достаточно большой буфер в памя-
ти и предположить, что выделенного места должно хватить для размещения всего
списка. В общем случае такой подход не запрещается – ACL может обладать разме-
ром большим, чем размер, достаточный для хранения всех его записей.
Когда вы получили достаточно объемный буфер, вы должны инициализи-
ровать ACL при помощи вызова InitializeAcl(). После этого можно добавлять в
список записи АСЕ. Для этого служат функции AddAccessDeniedAce() и Ad-
dAccessAllowedAce(). Каждая из этих функций принимает в качестве аргумен-
тов указатель на буфер ACL, константу ACL_REVISION, права, которые вы
намерены предоставить или отменить, а также указатель на SID. Этот SID
идентифицирует пользователя или группу, которым соответствует АСЕ. Полу-
чить SID можно при помощи вызова LookupAccountName().
Помните, что записи АСЕ, запрещающие доступ, следует добавлять в список
в первую очередь, в противном случае Windows NT 4.0 и более ранние версии NT
будут некорректно обрабатывать взаимоисключающие АСЕ. Чтобы пояснить си-
туацию, рассмотрим следующий простой пример. Допустим, вы являетесь членом
группы ТЕСН, а также членом группы USERS. Допустим также, что в списке ACL
содержится запись, запрещающая группе USERS доступ к файлу. Другая запись
разрешает группе ТЕСН доступ к файлу. В этой ситуации вы лишены возможно-
сти прочитать файл, так как принадлежите к группе, для которой доступ к файлу
явно запрещен. Если вы не разместите все АСЕ, запрещающие доступ, в самом на-
чале списка ACL, в некоторых, версиях NT такая комбинация взаимоисключаю-
щих АСЕ будет обработана некорректно.
Когда ACL сформирован, его необходимо установить в рамках структуры
SECURITY_DESCRIPTOR. Для этого служит вызов SetSecurityDescriptorDacl().
Затем указатели на дескриптор безопасности, содержащий ACL, необходимо раз-
местить в структуре SECURITY_ATTRIBUTES, которую в свою очередь можно
передать любой API-функции, элементом которой является данная структура.
7.3. API-функции для обеспечения безопасности в ОС Windows
98