1

さまざまなユーザーグループが共通のデータディレクトリ(c:\ ProgramData \ xyzなど)からファイルを読み書きできるという問題に直面しています。

データはさまざまなソースから書き込まれます。たとえば、サービスはデータにファイルを書き込み、ユーザーは後でそのコンテンツを変更できるようにする必要があります。

現在の問題は、これが機能するのは、「全員」がそのディレクトリ(およびサブディレクトリ)内のファイルの読み取り/書き込み/変更を許可されている場合のみであるということです。

インストーラーでチェックしたいのは、すべてのユーザーがそうすることを許可されているかどうかです。「すべてのユーザー」グループ(またはドイツ語では「Jeder」グループ)がアクセスリストに含まれているかどうかを確認します。私はACLに関する基本的な知識しか持っておらず、エクスプローラーでそれを変更できますが、正しい方向に進むための数行のコードが必要になります(Delphiの場合)。

マイクに感謝します

4

2 に答える 2

1

DelphiではなくWinAPIの質問だと思います。Delphiには、これを簡単にAFAIKにするための特別な機能はありません。

ACLから情報を取得すると、開いているハンドルでGetSecurityInfoを実行してから、取得したACLでGetEffectiveRightsFromACLを実行する必要があります。

トラスティを指定します。これは名前で指定できますが、SIDを使用することをお勧めします。「Everyone」の名前は変更できますが、どのPCでも有効な特別なSIDがあります。グーグルで検索してください。さて、ここにあります:「(S-1–1–0)」。または、CreateWellKnownSidを使用してWinWorldSidを指定すると、同じSIDを取得できます(より適切ですが、より長い方法です)。

5分間のグーグルからのすべてなので、間違いに注意してください。

了解しました。ここにいくつかのコードがあります。

function ConvertStringSidToSid(StringSid: PWideChar; var Sid: PSID): boolean; stdcall; external advapi32 name 'ConvertStringSidToSidW';

function AclGetEffectiveRights(const path, sid: string): cardinal;
var h: THandle; //handle to our directory
  err: integer;
  dacl: PACL; //access control list for the object
  secdesc: pointer;
  tr: TRUSTEE;
  bsid: PSid;
begin
  Result := 0;
 //Open directory
  h := CreateFile(PChar(path), GENERIC_READ, FILE_SHARE_READ, nil,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_BACKUP_SEMANTICS, 0);
    //we need FILE_FLAG_BACKUP_SEMANTICS to open a directory
  if h=INVALID_HANDLE_VALUE then RaiseLastOsError();
  try

    bsid := nil;
   //Query access control list for a directory -- the list you see in the properties box
    err := GetSecurityInfo(h, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
      nil, nil, @dacl, nil, secdesc);
      //GetSecurityInfo can return many things but we only need DACL,
      //and we are required to also get a security descriptor
    if err<>ERROR_SUCCESS then
      raise Exception.CreateFmt('Cannot retrieve DACL: error %d',[err]);
    try
     //Convert string sid to binary sid
      if not ConvertStringSidToSid(PChar(sid), bsid) then
        RaiseLastOsError();

     //Query effective rights for a trustee
      BuildTrusteeWithSid(@tr, bsid);
      err := GetEffectiveRightsFromAcl(dacl^, tr, Result);
      if err<>ERROR_SUCCESS then
        raise Exception.CreateFmt('Cannot calculate effective rights: error %d',[err]);
    finally
     //Documentation says to free some resources this way when we're done with it.
      LocalFree(NativeUint(bsid));
      LocalFree(NativeUint(secdesc));
    end;
  finally
    CloseHandle(h);
  end;
end;

これは次のように使用されます:

var rights,test: cardinal;
rights := AclGetEffectiveRights('C:\My\Folder','S-1-1-0');
//List rights you want tested
test := FILE_LIST_DIRECTORY + FILE_ADD_FILE + FILE_ADD_SUBDIRECTORY
  + FILE_READ_EA + FILE_WRITE_EA + FILE_TRAVERSE + FILE_DELETE_CHILD;
Result := (rights and test) = test;

動作しない可能性があります。私のPCでACCESS_DENIEDを与えますが、それはおそらく私の複雑なドメインの状況が原因です。とにかく、それは最初の何かです。

于 2013-03-27T13:25:01.103 に答える
0

したがって、上記のバージョンは機能しました... Windows Update 1903が私を襲い、GetEffectiveRightsFromAclが常にエラーERROR_NO_SUCH_DOMAIN(ここにはドメインが含まれていないため、あいまいです)が発生するまで。したがって、次の手順に切り替える必要がありました。

// ###########################################
// ### translated and extended from https://docs.microsoft.com/de-de/windows/win32/api/aclapi/nf-aclapi-geteffectiverightsfromacla

procedure DisplayAccessMask(Mask : ACCESS_MASK );
begin
{
      // This evaluation of the ACCESS_MASK is an example. 
      // Applications should evaluate the ACCESS_MASK as necessary.

}
   if (((Mask and GENERIC_ALL) = GENERIC_ALL)
      or ((Mask and FILE_ALL_ACCESS) = FILE_ALL_ACCESS)) 
   then
   begin
        OutputDebugString( 'Full control');
        exit;
   end;

   if (((Mask and GENERIC_READ) = GENERIC_READ)
      or ((Mask and FILE_GENERIC_READ) = FILE_GENERIC_READ)) 
   then
       OutputDebugString( 'Read');

   if (((Mask and GENERIC_WRITE) = GENERIC_WRITE)
      or ((Mask and FILE_GENERIC_WRITE) = FILE_GENERIC_WRITE))
   then
         OutputDebugString('Write');

   if (((Mask and GENERIC_EXECUTE) = GENERIC_EXECUTE)
      or ((Mask and FILE_GENERIC_EXECUTE) = FILE_GENERIC_EXECUTE))
   then
       OutputDebugString('Execute');

end;

function CheckMask( MASK : ACCESS_MASK; refMask : ACCESS_MASK ) : boolean;
var msk : ACCESS_MASK;
begin
     msk := 0;

     if (((Mask and GENERIC_READ) = GENERIC_READ)
      or ((Mask and FILE_GENERIC_READ) = FILE_GENERIC_READ)) 
     then
         msk := msk or FILE_GENERIC_READ;

   if (((Mask and GENERIC_WRITE) = GENERIC_WRITE)
      or ((Mask and FILE_GENERIC_WRITE) = FILE_GENERIC_WRITE))
   then
       msk := msk or FILE_GENERIC_WRITE;

   if (((Mask and GENERIC_EXECUTE) = GENERIC_EXECUTE)
      or ((Mask and FILE_GENERIC_EXECUTE) = FILE_GENERIC_EXECUTE))
   then
       msk := msk or FILE_GENERIC_EXECUTE;

   Result := (msk and refMask) = refMask;
end;

function GetAccess(hAuthzClient :AUTHZ_CLIENT_CONTEXT_HANDLE; psd : PSECURITY_DESCRIPTOR) : BOOL;
var AccessRequest : AUTHZ_ACCESS_REQUEST;
    AccessReply : AUTHZ_ACCESS_REPLY;
    buffer : Array[0..1023] of Byte;
begin
     FillChar(AccessRequest, sizeof(AccessRequest), 0);
     FillChar(AccessReply, sizeof(AccessReply), 0);
     FillChar(buffer, sizeof(buffer), 0);

     AccessRequest.DesiredAccess := MAXIMUM_ALLOWED;
     AccessRequest.PrincipalSelfSid := nil;
     AccessRequest.ObjectTypeList := nil;
     AccessRequest.ObjectTypeListLength := 0;
     AccessRequest.OptionalArguments := nil;

     AccessReply.ResultListLength := 1;
     AccessReply.GrantedAccessMask := PACCESS_MASK( LongWord(@Buffer[0])); 
     AccessReply.Error := PDWORD( LongWord( AccessReply.GrantedAccessMask ) + sizeof(Access_Mask));

     Result := AuthzAccessCheck( 0,
                          hAuthzClient,
                          @AccessRequest,
                          0,
                          psd,
                          nil,
                          0,
                          @AccessReply,
                          nil);

     if Result then
     begin
          DisplayAccessMask( AccessReply.GrantedAccessMask^ );
          Result := CheckMask( AccessReply.GrantedAccessMask^, FILE_GENERIC_WRITE or FILE_GENERIC_READ );
     end
     else
         RaiseLastOSError;
end;

function ConvertStringSidToSid(StringSid: PWideChar; var Sid: PSID): boolean; stdcall; external advapi32 name 'ConvertStringSidToSidW';

function ConvertNameToBinarySid(pAccountName : PCHAR): PSID ;
var pDomainName : PChar;
    dwDomainNameSize : DWord;
    aSID : PSID;
    dwSIDSIZE : DWORD;
    sidType : SID_NAME_USE;
begin
     pDomainName := nil;
     dwDomainNameSize := 0;
     aSID := nil;

     LookupAccountName( nil, pAccountName, aSID, dwSIDSIZE, pDomainName, dwDomainNameSize, sidType);
     aSid := Pointer( LocalAlloc( LPTR, dwSIDSIZE*sizeof(char)) );
     pDomainName := Pointer( LocalAlloc(LPTR, dwDomainNameSize*sizeof(char)) );
     if not LookupAccountName( nil, pAccountName, aSID, dwSIDSIZE, pDomainName, dwDomainNameSize, sidType) then
     begin
          LocalFree( Cardinal(aSID) );
          Result := nil;
     end
     else
     begin
          Result := aSid;
     end;

     LocalFree( Cardinal(pDomainName) );
end;

function GetEffectiveRightsForSID(hManager :AUTHZ_RESOURCE_MANAGER_HANDLE;
                                   psd : PSECURITY_DESCRIPTOR; 
                                   sid : PChar) : BOOL;
var asid : PSID;
    bResult : BOOL;
    unusedID : LUID;
    hAuthzClientContext : AUTHZ_CLIENT_CONTEXT_HANDLE;
begin
     Result := False;
     asid := nil;
     hAuthzClientContext := 0;
     FillChar(unusedID, sizeof(unusedID), 0);

     if not ConvertStringSidToSid(sid, asid) then
        RaiseLastOsError();
//     asid := ConvertNameToBinarySid('rabatscher');

     if asid = nil then
        RaiseLastOSError;
     try
        if asid <> nil then
        begin
             bResult := AuthzInitializeContextFromSid( 0, aSid, hManager, nil, unusedId, nil, @hAuthzClientContext );
             try
                if bResult then
                   Result := GetAccess(hAuthzClientContext, psd);
             finally
                    if hAuthzClientContext <> 0 then
                       AuthzFreeContext(hAuthzClientContext);
             end;
        end;
     finally
            if asid <> nil then
               LocalFree(LongWord(asid));
     end;
end;

function UseAuthzSolution( psd : PSECURITY_DESCRIPTOR; const sid : string = 'S-1-1-0') : boolean;
var hManager : AUTHZ_RESOURCE_MANAGER_HANDLE;
    bResult : BOOL;
    pSid : PChar;
begin
     bResult := AuthzInitializeResourceManager(AUTHZ_RM_FLAG_NO_AUDIT,
                nil, nil, nil, nil, @hManager);
     if bResult then
     begin
          pSid := PChar(sid);
          bResult := GetEffectiveRightsForSID(hManager, psd, psid);
          AuthzFreeResourceManager(hManager);
     end;

     Result := bResult;
end;

function GetSecurityInfo(handle: THandle; ObjectType: SE_OBJECT_TYPE;
         SecurityInfo: SECURITY_INFORMATION; ppsidOwner, ppsidGroup: PPSID; ppDacl, ppSacl: PACL;
         var pSecurityDescriptor: PSECURITY_DESCRIPTOR): DWORD; stdcall; external 'ADVAPI32.DLL' name 'GetSecurityInfo'; {use localfree to release ppSecurityDescriptor}


function CheckDirectoryAccess( path : string ) : boolean;
var dw : DWORD;
    apacl : PACL;
    psd : PSECURITY_DESCRIPTOR;
    apSID : PSID;
    h : THandle;    
begin
     try
        apSID := nil;

        //Open directory
        h := CreateFile(PChar(path), GENERIC_READ, FILE_SHARE_READ, nil,
                     OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_BACKUP_SEMANTICS, 0);

        //we need FILE_FLAG_BACKUP_SEMANTICS to open a directory
        if h = INVALID_HANDLE_VALUE then 
           RaiseLastOsError();
        try
           //Query access control list for a directory -- the list you see in the properties box
           dw := GetSecurityInfo(h, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION or OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION,
                                  nil, nil, @apacl, nil, psd);

           if dw <> ERROR_SUCCESS then
              RaiseLastOSError;

           try
              Result := UseAuthzSolution(psd);
           finally
                  if apSID <> nil then
                     LocalFree(NativeUint(apSID));

                  LocalFree(NativeUint(psd));
           end;
        finally
               CloseHandle(h);
        end;
     except
           on E : Exception do
           begin
                Result := False;
           end;
     end;
end;

手順が機能するようにいくつかの変更があることに注意してください。GetSecurityInfo(上記の手順から)にはパラメータDACL_SECURITY_INFORMATIONまたはOWNER_SECURITY_INFORMATIONまたはGROUP_SECURITY_INFORMATION(DACL_SECURITY_INFORMATIONだけでなく)が必要です。

さらに、jediライブラリからJWAヘッダーをチェックアウトする必要があります。

それが他の人にも役立つことを願っています。

于 2019-07-04T10:10:08.263 に答える