Как проверить, есть ли у пользователя права доступа к файлу с Windows API - PullRequest
1 голос
/ 28 января 2009

Я пытаюсь написать простую функцию для окон, которая отвечает на следующий вопрос.

Имеет ли пользователь (U) права (R) на файл (F)?
Где,
R - это некоторая комбинация (GENERIC_READ, GENERIC_WRITE, GENERIC_EXECUTE)
Вы не должны входить в систему или олицетворять

Код, который я написал, показан ниже. Приложение вызывает первую отображаемую UserHasPermission.

Права доступа, возвращаемые GetEffectiveRightsFromAcl, одинаковы для всех протестированных мной комбинаций пользователь / файл ($ 001200A9). Я дважды проверил, и $ 001200A9 - это не просто указатель на место, где фактически хранятся права доступа.

У меня двоякий вопрос:
1. Есть ли лучший способ сделать это?
2. Может кто-нибудь сказать мне, где я иду не так?

function UserHasPermission(APermission: Longword; out HasPermission: Boolean; AFileName: WideString; AUserName: String; ADomainName: String): Boolean;
    var
      SID: PSID;
      ACL: PACL;
    begin
      SID := nil;
      ACL := nil;
      try
        Result := GetUserSID(SID, AUserNAme, ADomainName);
        Result := Result and GetFileDACL(AFileName, ACL);
        Result := Result and UserHasPermission(APermission, HasPermission, ACL, SID);
      finally
        Dispose(SID);
      end;
    end;

    function UserHasPermission(APermission: Longword; out HasPermission: Boolean; AACL: PACL; AUserSID: PSID): Boolean;
    var
      T: TRUSTEE;
      Rights: ACCESS_MASK;
    begin
      BuildTrusteeWithSid(@T, AUserSID);
      Result := GetEffectiveRightsFromAcl(AACL, @T, @Rights) = ERROR_SUCCESS;
      HasPermission := (Rights and APermission) = APermission;
    end;

    function GetUserSID(out ASID: PSID; AUserName: WideString; const ADomainName: WideString): Boolean;
    var
      NSID, NDomain: Longword;
      Use: SID_NAME_USE;
      DomainName: WideString;
    begin
      Result := False;
      if Length(AUserName) > 0 then
        begin
          if Length(ADomainName) > 0 then
            AUserName := ADomainName + '\' + AUserName;

          // determine memory requirements
          NSID := 0;
          NDomain := 0;
          LookupAccountNameW(nil, PWideChar(AUserName), nil, NSID, nil, NDomain, Use);

          // allocate memory
          GetMem(ASID, NSID);
          SetLength(DomainName, NDomain);

          Result := LookupAccountNameW(nil, PWideChar(AUserName), ASID, NSID, PWideChar(DomainName), NDomain, Use);
        end;
    end;

    function GetFileDACL(AFileName: WideString; out AACL: PACL): Boolean;
    var
      SD: PSecurityDescriptor;
      NSD, NNeeded: Longword;
      Present, Defualted: Longbool;
    begin
      GetFileSecurityW(PWideChar(AFileName), DACL_SECURITY_INFORMATION, nil, 0, NNeeded);
      GetMem(SD, NNeeded);
      try
        NSD := NNeeded;
        Result := GetFileSecurityW(PWideChar(AFileName), DACL_SECURITY_INFORMATION, SD, NSD, NNeeded);
        Result := Result and GetSecurityDescriptorDacl(SD, Present, AACL, Defualted);
        Result := Result and Present;
      finally
        Dispose(SD);
      end;
    end;

1 Ответ

2 голосов
/ 21 марта 2009

GetEffectiveRightsFromAcl одинаковы для всех протестированных мной комбинаций пользователь / файл ($ 001200A9).

Все зависит от ACL, например, если каждому предоставлен полный контроль, то любое использование будет иметь полный контроль.

Код выглядит разумно, и вы используете один из API-интерфейсов безопасности Win32 (GetEffectiveRightsFromAcl) для выполнения тяжелой работы.

Предложение. Создайте очень специфичные списки ACL для проверки своего кода ( SDDL делает это проще), начиная с того, который не предоставляет грантов, затем с тем, что включает только другого пользователя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...