Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > и снова о правах доступа


Автор: PunkRat 12.1.2008, 13:32
блин у меня от этого секьюрити уже голова отстегивается напрочь. скажите, пожалуйста, почему может не работать такой код. вот я устанавливаю право на чтение для пользователя таким макаром:

Код


    char *path = "C:\\Dir";
    char *usr  = "Den";
    
    DWORD dwRes = 0;
    PACL pOldDACL = NULL, pNewDACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea;

    //    Получаем указатель на существующий 
    //    список контроля доступа объекта

    dwRes = GetNamedSecurityInfo(
        path,
        SE_FILE_OBJECT,      //  объект - файл или папка
          DACL_SECURITY_INFORMATION,
          NULL, 
          NULL, 
          &pOldDACL, 
          NULL, 
          &pSD);


    if (ERROR_SUCCESS != dwRes) {
        printf( "GetNamedSecurityInfo Error %u\n", dwRes );
        goto Cleanup; 
    }

    // Инициализируем структуру для нового элемента
    //    списка контроля доступа

    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = GENERIC_WRITE; // только чтение
    ea.grfAccessMode = GRANT_ACCESS;
    ea.grfInheritance= CONTAINER_INHERIT_ACE;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME; // указывает тип элемента ptstrName
    ea.Trustee.ptstrName = usr;  // для кого устанавливается доступ ( здесь можно указать имя или SID)

    //    создаём новый список контроля доступа, в который будет входить новый элемент
    //    с установленными разрешениями.

    dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
    if (ERROR_SUCCESS != dwRes)  {
        printf( "SetEntriesInAcl Error %u\n", dwRes );
        goto Cleanup; 
    }  


    //    Соединяем новый список с существующим списком объекта

    dwRes = SetNamedSecurityInfo(path, SE_FILE_OBJECT, 
          DACL_SECURITY_INFORMATION,
          NULL, NULL, pNewDACL, NULL);
    if (ERROR_SUCCESS != dwRes)  {
        printf( "SetNamedSecurityInfo Error %u\n", dwRes );
        goto Cleanup; 
    }  



Cleanup:
   if(pSD != NULL) 
        LocalFree((HLOCAL) pSD); 
    if(pNewDACL != NULL) 
        LocalFree((HLOCAL) pNewDACL); 

    getch();
    return 0; //благодарю Pulse69!
}



все отлично устанавливается что и видно в диалоге прав. почему тогда, когда я пытаюсь получить права у меня бит GENERIC_WRITE - пустой. получаю вот так:

Код

char *path = "C:\\test.txt";
    char *usr  = "PUNKRAT\\CyberGod";
    
    DWORD dwRes = 0;
    PACL pOldDACL = NULL, pNewDACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea;

    dwRes = GetNamedSecurityInfo(
        path,
        SE_FILE_OBJECT,     
          DACL_SECURITY_INFORMATION,
          NULL, 
          NULL, 
          &pOldDACL, 
          NULL, 
          &pSD);


    if (ERROR_SUCCESS != dwRes)
        AfxMessageBox("Ошибка!");

    PTRUSTEE pTrustee = new TRUSTEE();
    BuildTrusteeWithName(pTrustee, usr);
    
    ACCESS_MASK mask;
    DWORD dwRetVal = GetEffectiveRightsFromAcl(pOldDACL, pTrustee, &mask);

    if(mask & GENERIC_WRITE)
    {
        AfxMessageBox("Есть!");
    }




Автор: PunkRat 12.1.2008, 18:47
блин, ну почему же mask возвращается равным 2032127, т.е. все старшие биты - нулевые. в то время как я устанавливаю файлу GENERIC_WRITE перед этим, т.е. 31 бит и в свойствах файла это видно отлично ( (

Автор: Pulse69 13.1.2008, 03:47
В маске будут содержаться т.н Specific Rights для файловых объектов. Вам же именно они нужны. GENERIC_READ и GENERIC_WRITE вполне могут и не возвращатсься  (точно не знаю, но, скорее всего, так и есть). 
Та маска, что вы получаете (2032127) как раз содержит в себе все доступные для файловых объектов операции.

Вот, на всякий случай, их список.
Код

FILE_READ_DATA                     -- File Specific Access Right (0x0001)
FILE_WRITE_DATA                    -- File Specific Access Right (0x0002)
FILE_APPEND_DATA                   -- File Specific Access Right (0x0004)
FILE_READ_EA                       -- File Specific Access Right (0x0008)
FILE_WRITE_EA                      -- File Specific Access Right (0x0010)
FILE_EXECUTE                       -- File Specific Access Right (0x0020)
FILE_DELETE_CHILD                  -- File Specific Access Right (0x0040)
FILE_READ_ATTRIBUTES               -- File Specific Access Right (0x0080)
FILE_WRITE_ATTRIBUTES              -- File Specific Access Right (0x0100)


Если нужно проверить, есть ли право на запись в файл, необходимо использовать следующий код:
Код

    if(mask & FILE_WRITE_DATA )
    {
        AfxMessageBox("Есть!");
    }

Вот и всё :-)


Автор: PunkRat 13.1.2008, 04:12
Pulse69, голова! ) таким образом получается, что полностью ваш код, большое вам спасибо. я бы не подумал, что это младшие биты в описании ACCESS_MASK в мсдн нет их расшифровки :\ хотя видел ведь, что число меняется... ой, кажется я все-таки успеваю все дописать  smile  сейчас попробуем.

Автор: PunkRat 13.1.2008, 14:37
блин, вот теперь запретив какое то из свойств из программы я не могу его вновь разрешить, только из диалога свойств файла ... нипонятна, что с этим делать. сначала я думал это потому, что я, например запретив право на чтение или запись для текущего пользователя пытаюсь потом что, то менять. но когда меняю права для другой записи - все то же самое. стоит что-то запретить, как потом ничего обратно программно не вернуть. через свойства файла - пожалуйста. в этих свойствах кстати для записи присутствует два элемента, в одном проставлено разрешение для дейстивя, а в другом - запрет.

Автор: PunkRat 13.1.2008, 19:55
сделал вот как. теперь работает! правда все равно нифига не понимаю как. мне кажется, что и в том варианте реализации можно было что-то подправить, чтоб работало. 

Код

    LPTSTR lpFileName = "c:\\hard.txt";
    LPTSTR lpUserName = "kooperativ";
    PSECURITY_DESCRIPTOR psd;
    SECURITY_DESCRIPTOR sd;
    EXPLICIT_ACCESS ea;
    PACL OldAcl;
    PACL NewAcl;
    BOOL bDaclPresent;
    BOOL bDaclDefaulted;

    DWORD dwSize = 0;
    GetFileSecurity(lpFileName, DACL_SECURITY_INFORMATION, 0, 0, &dwSize);

    psd = HeapAlloc(GetProcessHeap(), 8, dwSize);
    BuildExplicitAccessWithName(&ea, lpUserName, FILE_READ_DATA,
        DENY_ACCESS, SUB_CONTAINERS_AND_OBJECTS_INHERIT);

    GetFileSecurity(lpFileName, DACL_SECURITY_INFORMATION,
        psd, dwSize, &dwSize);
    GetSecurityDescriptorDacl(psd, &bDaclPresent, &OldAcl, &bDaclDefaulted);
    SetEntriesInAcl(1, &ea, OldAcl, &NewAcl);
    InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, TRUE, NewAcl, FALSE);
    SetFileSecurity(lpFileName, DACL_SECURITY_INFORMATION, &sd);

Автор: Pulse69 14.1.2008, 01:13
Быть может, дело в том, что приоритет запрещения выше, чем разрешения, и если запретить какое-либо действие над файлом, его разрешение уже не даст эффекта. Для этого надо сначала удалить DENY_ACCESS-записи из ACL, а потом добавлять GRANT_ACCESS.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)