Проверка доступа к файлу в удаленном месте - PullRequest
0 голосов
/ 06 июня 2019

Я использую код, подобный приведенному ниже, чтобы проверить доступ к папкам / файлам. Источник

bool CanAccessFolder( LPCTSTR folderName, DWORD genericAccessRights )
{
    bool bRet = false;
    DWORD length = 0;
    if (!::GetFileSecurity( folderName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION 
            | DACL_SECURITY_INFORMATION, NULL, NULL, &length ) && 
            ERROR_INSUFFICIENT_BUFFER == ::GetLastError()) {
        PSECURITY_DESCRIPTOR security = static_cast< PSECURITY_DESCRIPTOR >( ::malloc( length ) );
        if (security && ::GetFileSecurity( folderName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
                            | DACL_SECURITY_INFORMATION, security, length, &length )) {
            HANDLE hToken = NULL;
            if (::OpenProcessToken( ::GetCurrentProcess(), TOKEN_IMPERSONATE | TOKEN_QUERY | 
                    TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, &hToken )) {
                HANDLE hImpersonatedToken = NULL;
                if (::DuplicateToken( hToken, SecurityImpersonation, &hImpersonatedToken )) {
                    GENERIC_MAPPING mapping = { 0xFFFFFFFF };
                    PRIVILEGE_SET privileges = { 0 };
                    DWORD grantedAccess = 0, privilegesLength = sizeof( privileges );
                    BOOL result = FALSE;

                    mapping.GenericRead = FILE_GENERIC_READ;
                    mapping.GenericWrite = FILE_GENERIC_WRITE;
                    mapping.GenericExecute = FILE_GENERIC_EXECUTE;
                    mapping.GenericAll = FILE_ALL_ACCESS;

                    ::MapGenericMask( &genericAccessRights, &mapping );
                    if (::AccessCheck( security, hImpersonatedToken, genericAccessRights, 
                            &mapping, &privileges, &privilegesLength, &grantedAccess, &result )) {
                        bRet = (result == TRUE);
                    }
                    ::CloseHandle( hImpersonatedToken );
                }
                ::CloseHandle( hToken );
            }
            ::free( security );
        }
    }

    return bRet;
}

Этот код не работает на клиентских компьютерах (где работает наше приложение) и возвращает ответ как ложный для локальных пользователей, которых нет в доменах Windows, а также для пользователейкоторые имеют общие сетевые ресурсы на основе Samba.

Один из наших экспертов по Windows прокомментировал, что, возможно, в описанной выше ситуации SID пользователя, возвращаемый сетевым файлером, НЕ совпадает с SID, запрашивающим разрешения в функции AccessCheck.Затем он упомянул, что, возможно, для достижения этой цели нам нужно будет правильно создать какой-либо токен для входа в систему, а затем выдать себя за него, чтобы получить правильный доступ.

Как выдать себя за пользователя домена (иликакой-то пользователь, которому разрешает сетевой файлер), чтобы сетевой файлер мог позволить моему коду получить правильную информацию о доступе?

Любая помощь будет принята.

1 Ответ

1 голос
/ 07 июня 2019

AccessCheck не всегда возвращает true, возвращается false, если дескриптор безопасности не позволяет запрошенные права доступа клиенту, идентифицированному токеном доступа.

Если вы хотите выдать себя за пользователя домена, который разрешает сетевой файлер, используйте функцию LogonUser (не подходит для удаленного компьютера), чтобы получить токен этого пользователя домена, тогда ImpersonateLoggedOnUser , позволяет вызывающему потоку олицетворять контекст безопасности этого пользователя домена.

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