AccessCheck() and MoveFileEx() doesn't work with network mapped driver

Bo Zhou 1 Reputation point
2020-08-27T07:32:10.23+00:00

Hi

We have a NAS installed locally and mapped a folder as local driver letter, such W .

Here uses credential from NAS to establish the mapping from NAS folder to local driver letter, not from Windows Active Directory. And user account is local. Any operation from Explorer works as usual.

By using AccessChk tools, it prints the SID starts with S-1-5-21, it means SECURITY_NT_NON_UNIQUE

Accesschk v6.12 - Reports effective permissions for securable objects
Copyright (C) 2006-2017 Mark Russinovich
Sysinternals - www.sysinternals.com

W:\temp
RW S-1-5-21-825604914-2373088077-4039564966-1203
RW S-1-5-21-825604914-2373088077-4039564966-3052
RW S-1-5-21-825604914-2373088077-4039564966-3048

Print current user's SID

USER INFORMATION

User Name SID
========= =============================================
3fasd6sf\user S-1-5-21-3089250728-987539432-1982516474-1001

Now we have a program needs to check if current process has permission to read/write/execute a file under an existed folder such as W:\temp, by API AccessCheck and MoveFileEx always return 5 = ACCESS_DENIED. Here is simple program to re-produce.

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;
}


int main(int argc, char *argv[])
{
    bool can = CanAccessFolder(argv[1], FILE_GENERIC_WRITE);
    if (can) {
        printf("OK");
    } else {
        printf("BAD");
    }

     return 0;

}

Any idea on this ? Thanks a lot !

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,498 questions
{count} votes