I am using a code similar to below to check the access to the folders/files. Source
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;
}
This code is failing on the customer machines (where our app runs) and returning answer as false for local users which are not in the Windows Domains as well as for users which have Samba based network shares.
One of our in house Windows experts have commented that perhaps in the situation above, user SID returned by the network filer does NOT match the SID querying for permissions in the AccessCheck function. He then mentioned that perhaps, to achieve such thing, we would have to correctly create a logged-on token of some kind and then impersonate it to get the correct access.
How do I impersonate the domain user (or some user that network filer permits) so that network filer can allow my code to get the correct access info ?
Any help will be appreciated.
AccessCheck
not always returns true, it returns false if the security descriptor not allows the requested access rights to the client identified by the access token.
If you want to impersonate a domain user that network filer permits, use LogonUser
function(not suitable for remote computer) to get the token of this domain user, then ImpersonateLoggedOnUser
, lets the calling thread impersonate the security context of this domain user.