WINAPI Читать все права доступа для пользовательского файла или папки - PullRequest
0 голосов
/ 21 октября 2019

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

1) Использовать функцию GetNamedSecurityInfo (), например: GetNamedSecurityInfo (путь, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, & a, NULL и & pSD)

2) Далее, используйте SID для получения прав: используйте эти функции для получения SID: GetAclInformation (), затем GetAce ().

3) Теперь вы можете использовать функцию LookupAccountSid () иЕсли это было успешно, сравните pACE-> Mask со всеми константами, например, «GENERIC_ALL, GENERIC_READ, GENERIC_WRITE, GENERIC_EXECUTE для файлов и т. д.»отображение прав доступа.

И как я пытался реализовать этот алгоритм: // Сначала получаем SID процесса

PSID g_pSID;
BOOL GetCurrentProcessSID()
{
    DWORD dwSize = 0, dwError, dwResult = 0;
    HANDLE hToken;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
    {
        printf("OpenProcessToken Error %u\n", GetLastError());
        return FALSE;
    }

    // Call GetTokenInformation to get the buffer size.
    TOKEN_USER tU;
    if (!GetTokenInformation(hToken, TokenUser, &tU, 0, &dwSize))
    {
        dwError = GetLastError();
        if (dwError != ERROR_INSUFFICIENT_BUFFER)
        {
            std::cout << "GetTokenInformation failed, error " << dwError;
            CloseHandle(hToken);
            return 0;
        }
    }

    PTOKEN_OWNER to = (PTOKEN_OWNER)LocalAlloc(LPTR, dwSize);
    if (!to)
    {
        dwError = GetLastError();
        std::cout << "LocalAlloc failed, error " << dwError;
        CloseHandle(hToken);
        return 0;
    }

    if (!GetTokenInformation(hToken, TokenOwner, to, dwSize, &dwSize))
    {
        dwError = GetLastError();
        std::cout << "GetTokenInformation failed, error " << dwError;
        LocalFree(to);
        CloseHandle(hToken);
        return 0;
    }

    g_pSID = to->Owner;
    return TRUE;
}

// Затем я использовал итерацию по списку ACL:

std::stringstream g_TestSecurityResult;
void TestSecurity( wchar_t* path )
{
    g_TestSecurityResult = std::stringstream();
    GetCurrentProcessSID();
    PACL pDacl; 
    PSECURITY_DESCRIPTOR pSD;
    GetNamedSecurityInfoW(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &pSD);

    ACL_SIZE_INFORMATION aclSizeInfo = { sizeof(ACL) };

    BOOL fResult = GetAclInformation( pDacl, &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), ACL_INFORMATION_CLASS::AclSizeInformation );

    if (fResult)
    {
        for (DWORD dwIndex = 0; dwIndex < aclSizeInfo.AceCount; ++dwIndex)
        {
            LPVOID pTempAce = nullptr;

            fResult = ::GetAce(pDacl, dwIndex, &pTempAce);
            if (fResult)
            {
                PSID pSid = &((ACCESS_ALLOWED_ACE*)pTempAce)->SidStart;

                if (EqualSid(pSid, &g_pSID))
                {
                    g_TestSecurityResult << "User: " << userNameFromSid(&g_pSID) << std::endl;
                    g_TestSecurityResult << "\tAccess mode: " << ((EXPLICIT_ACCESS*)pTempAce)->grfAccessMode << "\n";
                    g_TestSecurityResult << "\tAccess permissions: " << ((EXPLICIT_ACCESS*)pTempAce)->grfAccessPermissions << "\n";
                    g_TestSecurityResult << "\tInheritance: " << ((EXPLICIT_ACCESS*)pTempAce)->grfInheritance << "\n";
                    g_TestSecurityResult << std::endl;
                }
            }
            else
            {
                g_TestSecurityResult << "GetAce() failed." << GetLastError();
                break;
            }
        }
    } else {
        g_TestSecurityResult << "Error in GetAclInformation(): " << GetLastError();
    }
}

std::string userNameFromSid(PSID userSid)
{
    char buffName[MAX_BUFF_SIZE];
    DWORD buffNameSize = MAX_BUFF_SIZE;
    char buffDomain[MAX_BUFF_SIZE];
    DWORD buffDomainSize = MAX_BUFF_SIZE;
    SID_NAME_USE SidType;

    if (LookupAccountSid(NULL, userSid, buffName, &buffNameSize, buffDomain, &buffDomainSize, &SidType)) {
        return buffName;
    } else {
        DWORD dwResult = GetLastError();
        printf("GetTokenInformation Error %u\n", dwResult);
    }

    /*Here some code to print error in a Message box*/
    return "";
}

Проблема: Код работает, но в строке if (EqualSid (pSid, & g_pSID)) отладчик проходит и пропускает SID, который яполучил от моего процесса. Другими словами, я не могу получить какую-либо информацию из списка ACL, несмотря на то, что я запускаю процесс и Visual Studio под учетной записью администратора (не использую «Запуск от имени администратора», и я попробую, но все же .. Полученный SID действителен, и я могу получить имя владельца процесса, используя вышеуказанную функцию. Что может быть здесь не так?

Источники кода: https://gist.github.com/m4x1m1l14n/37f39c5d25855c2b1d3a6334851f7549 Как получить SID вошедшего в систему пользователя в Windows GetTokenInformation, TOKEN_OWNER и LookupAccountSidA

1 Ответ

0 голосов
/ 22 октября 2019

Благодаря комментарию @ (Рита Хан - MSFT) я забыл удалить метку амперсанда из сравнения pSID

EqualSid(pSid, g_pSID);

вместо

EqualSid(pSid, &g_pSID);

И это правильноработает сейчас

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