Ben J
Ben J

Reputation: 1387

Another winapi file permissions C head-scratcher. Why isn't my method working?

I'm really scratching my head over how to correctly use the windows api to determine file permissions. I have seen so many posts on this, but I just can't seem to get it right. Specifically, I would like to examine whether a user has read or write permissions for a given file. These are my steps:

(1) Access fully qualified username of the calling client (inc. domain name) with GetUserNameEx; (returns 0 error; user name appears to print out correctly using a cout debug message).

(2) Access the user's SID using LookupAccountName. (I do this twice, the first time for setting the SID and domain buffer sizes -- Returns 122 error on first call and 0 error on second (to be expected)). I assume the SID buffer is correctly set.

(3) Build a trustee with the obtained sid:

        TRUSTEE t;
        PTRUSTEE tptr = &t;
        BuildTrusteeWithSid(tptr,&sid[0]);

(4) Obtain the DACL:

 // following are freed up later using LocalFree (maybe I should use delete?)
 PACL ppDacl = new ACL;
 PSECURITY_DESCRIPTOR ppSecurityDescriptor = new SECURITY_DESCRIPTOR;
 std::vector<TCHAR> v(pathString.begin(), pathString.end());
 GetNamedSecurityInfo(&v[0],
                      SE_FILE_OBJECT,
                      READ_CONTROL,
                      NULL,
                      NULL,
                      &ppDacl,
                      NULL,
                      &ppSecurityDescriptor);

A simple call

 std::cout<<"ACE count: "<<ppDacl->AceCount<<std::endl;

then indicates that there are 58 ACEs leading me to assume that the DACL struct is being correctly instantiated (I am further assuming that there are 58 ACEs although I'm not sure how to manually verify this; I'm really not a windows person). However, printing GetLastError() after the GetNamedSecurityInfo call gives me a 122 (i.e. ERROR_INSUFFICIENT_BUFFER) so it appears something is going wrong at this step.

Note that initializing the PACL and PSECURITY_DESCRIPTOR as follows:

 ACL dacl;
 PACL ppDacl = &dacl;
 SECURITY_DESCRIPTOR sd;
 PSECURITY_DESCRIPTO = &sd;

rather than new-ing them doesn't seem to correctly fill the DACL (at least the call

  std::cout<<"ACE count: "<<ppDacl->AceCount<<std::endl;

reports 0 rather than 58). I'm not sure why.

(5) Finally, I attempt to get the file's access mask given the created trustee and dacl:

 ACCESS_MASK access;
 GetEffectiveRightsFromAcl(ppDacl, tptr, &access);

Which indicates no access rights when I do:

 ((access & GENERIC_WRITE)==GENERIC_WRITE)

or

 ((access & GENERIC_READ)==GENERIC_READ)

I hope one of you can shed some light on this

Cheers,

Ben.

Upvotes: 1

Views: 562

Answers (1)

alk
alk

Reputation: 70981

The call to GetNamedSecurityInfo() shall have DACL_SECURITY_INFORMATION set in the set of flags being passed as 3rd parameter. Only then the data being referenced by the value returned in the 6th parameter will be valid after the call returned.

Verbatim from GetNamedSecurityInfo()'s documentation on MSDN:

ppDacl [out, optional]

... The returned pointer is valid only if you set the DACL_SECURITY_INFORMATION flag.


Also as a side note: There is no need to initialise ppDacl and ppSecurityDescriptor as this is done by GetNamedSecurityInfo(). If you dynamically allocate memory to those this causes a memory leak, as by the call to GetNamedSecurityInfo() you lose the references to what you allocated.

Upvotes: 2

Related Questions