Я неправильно использую SetNamedSecurityInfo? ACL моего файла, похоже, не изменяется должным образом

Я пытаюсь включить и отключить определенные права доступа к файлу. Я понял, что для этого нужно возиться с DACL. Я использую следующий код для изменения файла DACL:

 void set_DACL_for_object(const char *object, SE_OBJECT_TYPE object_type,
                          int access_perms, int access_mode) {

      PACL pDACL = NULL, pOldDACL = NULL;
      PSECURITY_DESCRIPTOR pSD = NULL;
      EXPLICIT_ACCESS ea;

      GetNamedSecurityInfo((LPTSTR)object, object_type,
                            DACL_SECURITY_INFORMATION, NULL, NULL,
                            &pOldDACL, NULL, &pSD);

      ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));

      ea.grfAccessPermissions = access_perms;
      ea.grfAccessMode = access_mode;
      ea.grfInheritance = NO_INHERITANCE;
      ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
      ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
      ea.Trustee.ptstrName = _T("ADMINISTRATORS");

      SetEntriesInAcl(1, &ea, pOldDACL, &pDACL);

      SetNamedSecurityInfo((LPTSTR)object, object_type,
                            DACL_SECURITY_INFORMATION, NULL, NULL, pDACL, NULL);
 }

Итак, сначала я создаю файл с помощью fopen(), создаю ACL для предоставления всего доступа группе "Администраторы", а затем отказываю в доступе на запись группе "Администраторы":

 set_DACL_for_object("C:\\file.txt", SE_FILE_OBJECT, GENERIC_ALL, SET_ACCESS);
 set_DACL_for_object("C:\\file.txt", SE_FILE_OBJECT, GENERIC_WRITE, DENY_ACCESS);

Однако после этих звонков у меня нет доступа на чтение к файлу. Если я не звоню, у меня есть доступ на чтение / запись (как и следовало ожидать).

Я должен отметить, что я работаю под учетной записью администратора, и функции возвращаются как успешные. Я также попытался изменить ACL для конкретного ограниченного пользователя, но происходит то же самое... пользователю отказано в доступе на чтение, а не на запись, как я хотел.

Я попробовал несколько разных комбинаций вызовов set_DACL_for_object(), например, заменил DENY_ACCESS на REVOKE_ACCESS, SET_ACCESS на GRANT_ACCESS, не делал никаких вызовов SET_ACCESS и т. Д., И т. Д., Но ничего не получалось.

Я должен отметить, что большая часть кода была взята из этого примера MSDN, поэтому я думаю, что он должен работать. Что именно я делаю не так?

2 ответа

Решение

Открыть и прочитать в какой программе? ACL был установлен на то, что я ожидал, но FILE_GENERIC_WRITE может быть слишком общим для ваших целей; похоже, это также устанавливает "специальное" разрешение, которое влияет на атрибуты чтения.

из winnt.h:

#define FILE_GENERIC_WRITE        (STANDARD_RIGHTS_WRITE    |\
                                   FILE_WRITE_DATA          |\
                                   FILE_WRITE_ATTRIBUTES    |\
                                   FILE_WRITE_EA            |\
                                   FILE_APPEND_DATA         |\
                                   SYNCHRONIZE)

если я звоню с более ограниченным набором флагов, тестовый файл теперь можно открыть и прочитать, по крайней мере, в блокноте, но администратор не может сохранить документ:

DWORD dwCustomWrite = FILE_WRITE_DATA       | 
                      FILE_WRITE_ATTRIBUTES | 
                      FILE_WRITE_EA         | 
                      FILE_APPEND_DATA;
set_DACL_for_object(..., SE_FILE_OBJECT, dwCustomWrite, DENY_ACCESS);

в списке расширенных разрешений на вкладке "Безопасность" в файле при указанном выше вызове только следующие помечаются как "запрещенные" для группы "администраторы":

"Создание файлов / запись данных", "создание папок / добавление данных", "Запись атрибутов", "Запись расширенных атрибутов"

Обладая этими знаниями, вы сможете выбрать именно тот набор флагов, который вам нужен.

Я думаю set_DACL_for_object звонки должны указывать FILE_ALL_ACCESS а также FILE_GENERIC_WRITEне GENERIC_ALL а также GENERIC_WRITE, я скомпилировал ваш фрагмент кода с этими изменениями, и он работал как вы ожидаете.

Как примечание стороны, LPTSTR Метод cast запрещает компилятору определить, что этот код является Ansi, если вам когда-либо придется скомпилировать его как Unicode, поэтому в этом случае код не будет работать во время выполнения.

Вы должны использовать _T("ADMINISTRATORS") вместо.

Другие вопросы по тегам