Solved

how to get whether directory has read/write access

Posted on 2008-10-14
7
758 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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 500 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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
c++ array loading from DB inheriting previous data when empty 5 59
C++ assignment question 7 165
ASP.net build a IF/Then Walkthrough Guide 1 191
How to split this in C++ 4 94
Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

911 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now