Конференция "WinAPI" » Файловая безопасность в NTFS [WinXP]
 
  • roughneck (23.10.07 15:25) [0]
    Как получить и изменить безопасность файлов?
    Я делаю следующее но работает очень долго:
    1. GetFileSecurity
    2. GetSecurityDescriptorDACL
    3. GetACECount
    4. цикл по всем acount-ам
        а. LookupAccountSid
        б. GetUserFullName
        в. GetFileGenericSecurity

    5. полученный список обрабатываю (это быстро)
    6. применяю обработанный список (это почти также как получать только Set-функции)

    Может есть какой-то другой способ попроше, главно чтоб побыстрее.
    Спасибо.
  • Ins © (23.10.07 15:39) [1]

    > Как получить и изменить безопасность файлов?

    1. GetNamedSecurityInfo - сразу же получаем DACL, имея только имя файла, 2. SetEntriesInAcl - устанавливаем новые элементы в DACL,
    3. SetNamedSecurityInfo - новый DACL

    Ваш п.4. я вообще не понял. Что нужно то?
  • roughneck (24.10.07 07:50) [2]
    п.4. и получается еще п.3. нужны чтоб из DACL получить ACE (GetACE) а из него PSID, а по SID-у получаем имя пользователя. Также из ACE получаем маску галочек доступа.
  • Ins © (24.10.07 09:44) [3]

    > а по SID-у получаем имя пользователя.

    Зачем? Что вам нужно, объясните подробнее плз...
  • roughneck (24.10.07 13:12) [4]
    Нужно получить список пользователей и их права (14 галочек). Затем изменить этот список и применить. Прям как в винде.

    Проведя некий анализ выявил что долго выполняются функции: LookupAccountSid и LookupAccountName. Причем если работать по сети (сервер, домен и все такое), то долго, а на локальной машине побыстрее выполняется.
  • Ins © (24.10.07 13:20) [5]

    > Нужно получить список пользователей

    Тех пользователей и групп, которые присутствуют в ACL? Тогда да, пройдитесь в цикле по всем элементам списка, запомнить где-либо уникальные SID и получить по ним имя аккаунта.


    > и их права (14 галочек)

    GetEffectiveRightsFromAcl - как раз то, что вам нужно.


    > Затем изменить этот список и применить.

    Об этом уже сказал.


    > Проведя некий анализ выявил что долго выполняются функции:
    >  LookupAccountSid и LookupAccountName. Причем если работать
    > по сети (сервер, домен и все такое), то долго, а на локальной
    > машине побыстрее выполняется.

    Ничего удивительного.
  • roughneck (24.10.07 13:40) [6]

    > > Проведя некий анализ выявил что долго выполняются функции:
    >
    > >  LookupAccountSid и LookupAccountName. Причем если работать
    >
    > > по сети (сервер, домен и все такое), то долго, а на локальной
    >
    > > машине побыстрее выполняется.
    >
    > Ничего удивительного.

    а по быстрее нет функций?
  • Ins © (24.10.07 13:42) [7]

    > и их права (14 галочек)

    А вообще-то, по хорошему, тут уточнить нужно бы. Дело в том, что есть два алгоритма определения прав учетной записи. По первому работает функция GetEffectiveRightsFromAcl. По второму - AccessCheck. Для формирования "списка галочек как в винде" используется первая, а для проверки прав доступа при открытии объекта - вторая. Галочка еще не гарантирует разрешение доступа, так как он может быть запрещен для группы, в которую входит аккаунт. Проще говоря, GetEffectiveRightsFromAcl возвращает маску прав, разрешенных в DACL, именно для данного SID, не учитывая группы, в которые аккаунт может входить. Т.е. она работает только с ACL. AccessCheck же еще извлекает из маркера доступа SID-ы групп и учитывает их. Т.е. она работает не только с ACL, но и с Access Token вызывающего потока.
  • Ins © (24.10.07 14:24) [8]

    > а по быстрее нет функций?

    Я думаю, дело не в плохой функции, а в том, что для выполнения этой операции требуется обатиться к удаленному компьютеру.
  • roughneck (24.10.07 14:29) [9]

    > уточнить нужно бы

    Пока мне нужно получать "галочки как в винде" и изменять их. Вообще смысл проги в том, чтобы устанавливать права по расписанию. Например, дать доступ юзеру на чтение-запись на такую-то папку/файл с такого-то по такое-то время. Весь "интерфейс безопасности" примерно как в винде.
  • BiN © (24.10.07 17:29) [10]

    > roughneck   (24.10.07 14:29) [9]
    >
    >
    > > уточнить нужно бы
    >
    > Пока мне нужно получать "галочки как в винде" и изменять
    > их. Вообще смысл проги в том, чтобы устанавливать права
    > по расписанию. Например, дать доступ юзеру на чтение-запись
    > на такую-то папку/файл с такого-то по такое-то время. Весь
    > "интерфейс безопасности" примерно как в винде.


    пример использования стандартного диалога редактирования настроек безопасности (ISecurityInformation) есть у Рихтера-Кларка.. прямая ссылка на примеры с исходниками (с++):
    http://irazin.ru/downloads/booksamples/Richter_Clark.zip
  • Eraser © (24.10.07 17:47) [11]

    > roughneck   (24.10.07 14:29) [9]

    дать пример работы с ISecurityInformation на delphi?
  • vpbar © (24.10.07 20:37) [12]
    >>BiN ©   (24.10.07 17:29) [10]
    О! Спасибо. Мне как раз нужно права в XP Home настроить.  Уже почти собрался File Security Manager покупать, а тут такое да еще в исходниках. Супер!!
  • roughneck (25.10.07 05:59) [13]

    > дать пример работы с ISecurityInformation на delphi?

    Очень хорошо бы
  • Eraser © (27.10.07 01:13) [14]
    > [13] roughneck   (25.10.07 05:59)

    примерно так
    unit SecurityPage;

    interface

    uses
     Classes, SysUtils, Dialogs, JwaWinNT, JwaAclApi, JwaAccCtrl, JwaWinBase,
     JwaAclUI, JwaWinType, JwaWinError;

    type
     TAccessControl = class
     private
       FAccessData: TStream;
       function GetACL: PACL;
       function GetOwnerSID: PSID;
       function StoreACL(ApACL: PACL): Boolean;
       procedure FreeSD(pSD: PSECURITY_DESCRIPTOR);
     public
       constructor Create(AccessInfo: TStream); reintroduce; overload;

       function GetSD: PSECURITY_DESCRIPTOR;
       function SetSD(pSD: PSECURITY_DESCRIPTOR): Boolean;
     end;

     TSecurityInfo = class(TInterfacedObject, ISecurityInformation)
     private
       FAccessControl: TAccessControl;
     protected
       function GetObjectInformation(out pObjectInfo: SI_OBJECT_INFO): HRESULT; stdcall;
       function GetSecurity(RequestedInformation: SECURITY_INFORMATION;
         out ppSecurityDescriptor: PSECURITY_DESCRIPTOR; fDefault: BOOL): HRESULT; stdcall;
       function SetSecurity(SecurityInformation: SECURITY_INFORMATION;
         pSecurityDescriptor: PSECURITY_DESCRIPTOR): HRESULT; stdcall;
       function GetAccessRights(pguidObjectType: LPGUID; dwFlags: DWORD;
         out ppAccess: PSI_ACCESS; out pcAccesses, piDefaultAccess: ULONG): HRESULT; stdcall;
       function MapGeneric(pguidObjectType: LPGUID; pAceFlags: PUCHAR;
         pMask: PACCESS_MASK): HRESULT; stdcall;
       function GetInheritTypes(out ppInheritTypes: PSI_INHERIT_TYPE;
         out pcInheritTypes: ULONG): HRESULT; stdcall;
       function PropertySheetPageCallback(hwnd: HWND; uMsg: UINT;
         uPage: SI_PAGE_TYPE): HRESULT; stdcall;
     public
       constructor Create(AccessInfo: TStream); reintroduce; overload;
       destructor Destroy; override;
     end;

    const
     GUID_NULL: TGUID = '{00000000-0000-0000-0000-000000000000}';
     
     AccessMap: array[0..1] of SI_ACCESS = (
       (
       pguid: @GUID_NULL;
       mask: $01;
       pszName: 'Full Control';
       dwFlags: SI_ACCESS_GENERAL
       ),
       (  // We do not use it in this version!
       pguid: @GUID_NULL;
       mask: $02;
       pszName: 'View only';
       dwFlags: SI_ACCESS_GENERAL
       )
       );
    var
     AccessMasks: GENERIC_MAPPING = (
       GenericRead: STANDARD_RIGHTS_READ;
       GenericWrite: STANDARD_RIGHTS_WRITE;
       GenericExecute: STANDARD_RIGHTS_EXECUTE;
       GenericAll: {STANDARD_RIGHTS_REQUIRED or }
         STANDARD_RIGHTS_READ or
         STANDARD_RIGHTS_WRITE or
         STANDARD_RIGHTS_EXECUTE;
       );

    implementation

    { TSecurityInfo }

    constructor TSecurityInfo.Create(AccessInfo: TStream);
    begin
     inherited Create;
     FAccessControl := TAccessControl.Create(AccessInfo);
    end;

    destructor TSecurityInfo.Destroy;
    begin
     FAccessControl.Free;
     inherited Destroy;
    end;

    function TSecurityInfo.GetAccessRights(pguidObjectType: LPGUID; dwFlags: DWORD;
     out ppAccess: PSI_ACCESS; out pcAccesses, piDefaultAccess: ULONG): HRESULT;
    begin
     ppAccess := @AccessMap[0];
     pcAccesses := 1;
     piDefaultAccess := 0;
     Result := S_OK;
    end;

    function TSecurityInfo.GetInheritTypes(out ppInheritTypes: PSI_INHERIT_TYPE;
     out pcInheritTypes: ULONG): HRESULT;
    begin
     ppInheritTypes := nil;
     pcInheritTypes := 0;
     Result := S_OK;
    end;

    function TSecurityInfo.GetObjectInformation(
     out pObjectInfo: SI_OBJECT_INFO): HRESULT;
    begin
     pObjectInfo.dwFlags := SI_EDIT_PERMS or SI_NO_ACL_PROTECT
       or SI_PAGE_TITLE;
     pObjectInfo.hInstance := SysInit.HInstance;
     pObjectInfo.pszServerName := nil;
     pObjectInfo.pszObjectName := 'My object name';
     Result := S_OK;
    end;

    function TSecurityInfo.GetSecurity(RequestedInformation: SECURITY_INFORMATION;
     out ppSecurityDescriptor: PSECURITY_DESCRIPTOR; fDefault: BOOL): HRESULT;
    begin
     ppSecurityDescriptor := FAccessControl.GetSD;
     if ppSecurityDescriptor <> nil then
       Result := S_OK
     else
       Result := E_FAIL;
    end;

    function TSecurityInfo.MapGeneric(pguidObjectType: LPGUID; pAceFlags: PUCHAR;
     pMask: PACCESS_MASK): HRESULT;
    begin
     MapGenericMask(pMask^, AccessMasks);
     Result := S_OK;
    end;

    function TSecurityInfo.PropertySheetPageCallback(hwnd: HWND; uMsg: UINT;
     uPage: SI_PAGE_TYPE): HRESULT;
    begin
     Result := S_OK;
    end;

    function TSecurityInfo.SetSecurity(SecurityInformation: SECURITY_INFORMATION;
     pSecurityDescriptor: PSECURITY_DESCRIPTOR): HRESULT;
    begin
     if FAccessControl.SetSD(pSecurityDescriptor) then
       Result := S_OK
     else
       Result := E_FAIL;
    end;

    { TAccessControl }

    constructor TAccessControl.Create(AccessInfo: TStream);
    begin
     inherited Create;
     FAccessData := AccessInfo;
    end;

    procedure TAccessControl.FreeSD(pSD: PSECURITY_DESCRIPTOR);
    var
     pOwnerSID, pGroupSID: PSID;
     pDACL, pSACL: PACL;
     bOwnerDefaulted, bGroupDefaulted, bDaclPresent, bSaclDefaulted: Bool;
     bDaclDefaulted, bSaclPresent: LongBool;
    begin
     if pSD <> nil then
     begin
       pOwnerSID := nil;
       pGroupSID := nil;
       if GetSecurityDescriptorOwner(pSD, pOwnerSID, @bOwnerDefaulted) then
       begin
         try
           HeapFree(GetProcessHeap, 0, pOwnerSID);
         except
         end;
       end;
       if GetSecurityDescriptorGroup(pSD, pGroupSID, @bGroupDefaulted) then
       begin
         try
           HeapFree(GetProcessHeap, 0, pGroupSID);
         except
         end;
       end;
       GetSecurityDescriptorDacl(pSD, bDaclPresent, pDACL, bDaclDefaulted);
     GetSecurityDescriptorSacl(pSD, bSaclPresent, pSACL, bSaclDefaulted);
     end;
     try
       if pSD <> nil then
         FreeMem(pSD);
       if bDaclPresent and (pDACL <> nil) then
         FreeMem(pDACL);
       if bSaclPresent and (pSACL <> nil) then
         FreeMem(pSACL);
     except
     end;
    end;

    function TAccessControl.GetACL: PACL;
    begin
     Result := nil;
     try
       if FAccessData.Size < SizeOf(ACL) then
         exit;
       FAccessData.Position := 0;
       GetMem(Result, FAccessData.size);
       FAccessData.Read(Result^, FAccessData.size);
     except
     end;
    end;

    function TAccessControl.GetOwnerSID: PSID;
    var
     pAdminSid: PSid;
     SIDAuth: SID_IDENTIFIER_AUTHORITY;
    begin
     pAdminSid := nil;
     SIDAuth := SECURITY_NT_AUTHORITY;
     AllocateAndInitializeSid(@SIDAuth,
       2,
       SECURITY_BUILTIN_DOMAIN_RID,
       DOMAIN_ALIAS_RID_ADMINS,
       0, 0, 0, 0, 0, 0,
       pAdminSid);
     Result := pAdminSid;
    end;

  • Eraser © (27.10.07 01:14) [15]
    function TAccessControl.GetSD: PSECURITY_DESCRIPTOR;
    var
     pntAcl: PACL;
     pSD, pSelfRelativeSD: PSECURITY_DESCRIPTOR;
     BufferLength: Cardinal;
    begin
     Result := nil;
     BufferLength := 0;
     try
       pntAcl := GetACL;
       if (pntAcl = nil) or (not IsValidAcl(pntAcl)) then
       begin
         GetMem(pntAcl, SizeOf(ACL));
         if not InitializeAcl(pntAcl, SizeOf(ACL), ACL_REVISION) then
           Exit;
       end;
       GetMem(pSD, SECURITY_DESCRIPTOR_MIN_LENGTH);
       if not InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION) then
         exit;
       if not SetSecurityDescriptorDacl(pSD, true, pntAcl, false) then
         exit;
       if not SetSecurityDescriptorOwner(pSD, GetOwnerSID, false) then
         exit;
       if not SetSecurityDescriptorGroup(pSD, GetOwnerSID, false) then
         exit;
       MakeSelfRelativeSD(pSD, nil, BufferLength);
       pSelfRelativeSD := PSECURITY_DESCRIPTOR(
         LocalAlloc(0, BufferLength));
       if not MakeSelfRelativeSD(pSD, pSelfRelativeSD, BufferLength) then
         Exit;
       FreeSD(pSD);
       Result := pSelfRelativeSD;
     finally

     end;
    end;

    function TAccessControl.SetSD(pSD: PSECURITY_DESCRIPTOR): Boolean;
    var
     bDaclPresent, bDaclDefaulted: BOOL;
     pDACL: PACL;
    begin
     pDACL := nil;
     Result := false;
     GetSecurityDescriptorDacl(pSD, bDaclPresent, pDACL, bDaclDefaulted);
     if bDaclPresent and (pDACL <> nil) and IsValidAcl(pDACL) and StoreACL(pDACL) then
       Result := true;
    end;

    function TAccessControl.StoreACL(ApACL: PACL): Boolean;
    var
     AclInfo: ACL_SIZE_INFORMATION;
     nAclInformationLength: Cardinal;
    begin
     Result := false;
     FAccessData.Size := 0;
     FAccessData.Position := 0;
     if ApACL = nil then
       Exit;
     try
       nAclInformationLength := SizeOf(ACL_SIZE_INFORMATION);
       GetAclInformation(ApACL, @AclInfo, nAclInformationLength,
         AclSizeInformation);
       FAccessData.Write(ApACL^, AclInfo.AclBytesInUse);
       FAccessData.Position := 0;
       Result := true;
     except

     end;
    end;

    end.

  • Eraser © (27.10.07 01:16) [16]
    пример из реального проекта, поэтому без даработки может не заработать.

    PS необходимы заголовочный файлы winAPI от jedi, см. ftp://ftp.delphi-jedi.org/api/win32api.zip
 
Конференция "WinAPI" » Файловая безопасность в NTFS [WinXP]
Есть новые Нет новых   [134431   +10][b:0][p:0.004]