Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

how to get whether directory has read/write access

Posted on 2008-10-14
7
Medium Priority
?
808 Views
Last Modified: 2012-05-05
Hi,
I am writing a function which will take a parameter as a path to a folder (remote/local) and if the program has write access to the folder, it wil return true else false.
For this i am using
      LPWSTR lpFilePahtW = strFilePath.GetBuffer(0);
      PSECURITY_DESCRIPTOR psd = NULL;
      DWORD dwReturn;
      dwReturn = GetNamedSecurityInfo(lpFilePahtW, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION, NULL, NULL, NULL ,NULL, &psd);
      if(dwReturn == ERROR_SUCCESS)
      {
            LPBOOL lpbDaclPresent;
            PACL pDacl;
            LPBOOL lpbDaclDefaulted;
            if(GetSecurityDescriptorDacl(psd,lpbDaclPresent, &pDacl,lpbDaclDefaulted)
            {
                  if(lpbDaclPresent == TRUE)
                  {
                        if(pDacl != NULL)
                        {
                                                                                          //donno how to process pDacl
                        }
                  }

            }
      }
      else
      {

      }

first of all is this method correct.
If yes, i am not sure how to do i get the pDacl to read the values.
Also do i need to assign values to psd or somewhere else?
I donno how the memory assignment is done?
0
Comment
Question by:LearningCpp
  • 4
  • 2
7 Comments
 
LVL 6

Expert Comment

by:ChristianWimmer
ID: 22716105
Use the AccessCheck function to check what access is possible to a resource:
http://www.experts-exchange.com/Programming/Languages/CPP/Q_10236213.html?sfQueryTermInfo=1+accesscheck

BTW: Remote files are access checked by the remote client only. Checking access using the local AccessCheck may differ from the remote check because the SIDs can be different.
Short: If local AccessCheck grants access to an resource there is no guarantee that you will get really access to the resource.
0
 

Author Comment

by:LearningCpp
ID: 22716384
I dont understand why do i need to call get the thread and use accesscheck.
If i can get the the ACE with GetAce
cast the LPVoid pAce to ACCESS_ALLOWED_ACE and then read the mask

for(WORD i=0; i < pDacl->AceCount; i++)
{
      LPVOID pAce;
      bSuccess = GetAce(pDacl, i, &pAce);
      ACCESS_ALLOWED_ACE* pAllowed = (ACCESS_ALLOWED_ACE*)pAce;
      DWORD dwmask = pAllowed->Mask;
}

Some pointer in this direction?
0
 

Author Comment

by:LearningCpp
ID: 22717009
I tried the accesscheck method but i get access denied after OpenThreadToken?
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 6

Expert Comment

by:ChristianWimmer
ID: 22718992
AccessCheck is the standard method to check for access to resources. You could do it yourself but it is a little bit complicated because of ACL structure.

You need to retrieve the token of the user who runs your program. A token is always assigned to a process but is optional for a thread. Try OpenProcessToken instead. If this also fails with 5, an already assigned thread token prevents access to your own token (strange!!) you should try RevertToSelf (removes thread tokenn) and try again.
I know that AccessCheck looks complicated but the previous link contains everything you need. I should mention that the generic mask mapping is intended for translating GENERIC_ALL and co to specific access masks like FILE_ALL_ACCESS. You should map the generic rights to their corresponding specific file/folder rights.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22719485
I tried the same a few years before and after spending some hours on trying to understand these weird functions (security by obscurity), I ended with code like

   time_t tt = time(NULL);
   std::ostringstream oss;
   oss << folderToTestForWrite << "\\test" << tt << std::endl;
   std::ofstream ofs(oss.str().c_str());
   bool writeAccess = false;
   if (ofs)
   {
       ofs.close();
       writeAccess = true;
       remove(oss.str().c_str());
   }
0
 
LVL 6

Accepted Solution

by:
ChristianWimmer earned 1500 total points
ID: 22752598
I've created this code to show how AccessCheck works for files without removing an existing threadtoken (if USE_IMPERSONATESELF is not set).
#include "windows.h"
 
//#define USE_IMPERSONATESELF
 
GENERIC_MAPPING GenericFileMapping = {
    FILE_GENERIC_READ,
    FILE_GENERIC_WRITE,
    FILE_GENERIC_EXECUTE,
    FILE_ALL_ACCESS
};
 
bool CheckAccessToFile(DWORD DesiredAccess, 
					   LPTSTR FileName,
					   bool OpenAsSelf = true)
{
  DWORD LengthNeeded;
  PSECURITY_DESCRIPTOR SecurityDescriptor;
  HANDLE TempToken, 
	     Token;
  DWORD AccessMask;
  PRIVILEGE_SET PrivilegeSet;
  DWORD PrivilegeSetLength,
        GrantedAccess;
  BOOL  AccessStatus;
 
  ::SetLastError(0);
 
  //get size of security descriptor
  //AccessCheck needs owner and group!
  if (!::GetFileSecurity(FileName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, NULL, 0,
    &LengthNeeded) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
    return false;
 
  SecurityDescriptor = (PSECURITY_DESCRIPTOR) ::LocalAlloc(LPTR, LengthNeeded);
 
  __try //try statement http://msdn.microsoft.com/en-us/library/s58ftw19(VS.80).aspx
  {
    if (!::GetFileSecurity(FileName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
      SecurityDescriptor, LengthNeeded, &LengthNeeded))
	{
        return false;
	}
 
#ifdef USE_IMPERSONATESELF
	// Some examples use this way to impersonate the thread token
	// In this way we can just use OpenThreadToken without a second
	// call to OpenProcessToken if the thread does not have a token.
	// However the one who calls this function may lose his own thread token!
	if (!::ImpersonateSelf(SecurityImpersonation))
		return false;
 
	__try
	{
#endif //USE_IMPERSONATESELF
 
		//first try token assigned to the current thread
		if (!::OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, 
			  OpenAsSelf, &Token)) 
		{
		  //otherwise use process token
		  if ((::GetLastError() == ERROR_NO_TOKEN) &&
			 (!::OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, 
				 &Token))) 
			 return false;
 
		  TempToken = INVALID_HANDLE_VALUE;
		  __try {
			//convert to thread token.
			if (!::DuplicateToken(Token, SecurityImpersonation, &TempToken))
			  return false;
		  }
		  __finally  {
			//close process token and switch them for further processing
			::CloseHandle(Token);
		  }
 
		  Token = TempToken;
		}
 
		AccessMask = DesiredAccess;
		::MapGenericMask(&AccessMask, &GenericFileMapping);
		PrivilegeSetLength = sizeof(PrivilegeSet);
 
		
		__try {
		  if (::AccessCheck(SecurityDescriptor, Token, AccessMask,
				&GenericFileMapping, &PrivilegeSet, &PrivilegeSetLength, &GrantedAccess,
				&AccessStatus))
			return (AccessStatus != FALSE);
		  //if AccessStatus is FALSE AccessCheck sets last error to 5 (Access Denied)
		  else
		  {
			  return false;
		  }
		}
		__finally  {
		  ::CloseHandle(Token);
		}
#ifdef USE_IMPERSONATESELF
	}
	__finally {
		::RevertToSelf();
	}
#endif //USE_IMPERSONATESELF
 
	
  }
  __finally
  {
	  ::LocalFree((HLOCAL)SecurityDescriptor);
  }
}
 
int _tmain(int argc, _TCHAR* argv[])
{
 
	if (!CheckAccessToFile(GENERIC_READ, _T("C:\\Windows\\")))
	{
		if (::GetLastError() != 0) //BUG: 1 == TRUE == invalid function
			return ::GetLastError(); //returns 5 (Access denied) if CheckAccessToFile returns false
		else
			return FALSE;
	}
	else
		return TRUE;
}

Open in new window

0
 
LVL 6

Expert Comment

by:ChristianWimmer
ID: 22887331
Could you please point out why you didn't give an A grade? In this way I could improve my answers.
0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
Suggested Courses

885 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question