Home > front end >  Why DACL entries of a file printed via win32 API is not matching up with DACL information in the fil
Why DACL entries of a file printed via win32 API is not matching up with DACL information in the fil

Time:07-29

Here is the minimal code for reference

 ULONG result = GetSecurityInfo(Hfile
        , SE_FILE_OBJECT
        , OWNER_SECURITY_INFORMATION |GROUP_SECURITY_INFORMATION| DACL_SECURITY_INFORMATION 
        , &sidowner
        , &sidgroup
        , &pdacl
        , NULL
        , &psd);

This is how I extracted the access control entries from DACL

BOOL b = GetAce(pdacl, i, (LPVOID*)&ace); 
        if (((ACCESS_ALLOWED_ACE*)ace)->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) {

            sid = (PSID)&((ACCESS_ALLOWED_ACE*)ace)->SidStart;

            LookupAccountSid(NULL, sid, oname, &namelen, doname, &domainnamelen, &peUse);
            wcout << "domianName/AccoutName : " << doname << "/" << oname << endl;

            mask = ((ACCESS_ALLOWED_ACE*)ace)->Mask;
            cout << "Allowed" << endl;
        }

output:

domianName/AccoutName : BUILTIN/Administrators
Allowed
 

    DELETE
     FILE_GENERIC_READ
     FILE_GENERIC_WRITE
     FILE_GENERIC_EXECUTE
     READ_CONTROL
     WRITE_DAC
     WRITE_OWNER
     SYNCHRONIZE
    
    domianName/AccoutName : BUILTIN/Administrators
    Allowed
     DELETE
     FILE_GENERIC_READ
     FILE_GENERIC_WRITE
     FILE_GENERIC_EXECUTE
     READ_CONTROL
     WRITE_DAC
     WRITE_OWNER
     SYNCHRONIZE
    
    domianName/AccoutName : BUILTIN/Administrators
    Allowed
     DELETE
     FILE_GENERIC_READ
     FILE_GENERIC_WRITE
     FILE_GENERIC_EXECUTE
     READ_CONTROL
     SYNCHRONIZE
    
    domianName/AccoutName : BUILTIN/Users
    Allowed
     FILE_GENERIC_READ
     FILE_GENERIC_WRITE
     FILE_GENERIC_EXECUTE
     READ_CONTROL
     SYNCHRONIZE

As we can see from the above output Administrators have multiple entries and ACE of "System" and "Authenticated users" are not found. "Users" only have read rights in file properties but in the output, it is printed that the "Users" have "Write access" as well.

I did a lot of research and read through many books but nothing seems to give a clear-cut answer

edit: Here's the output using the CACLS command.

C:\Users\Administrator>cacls e:/hello.txt
e:\hello.txt BUILTIN\Administrators:F
             NT AUTHORITY\SYSTEM:F
             NT AUTHORITY\Authenticated Users:C
             BUILTIN\Users:R

CodePudding user response:

The first part of the question:

The reason why the program prints the name same account name repeatedly is because the LookupAccountSid function does not have enough data area. since the namelen and domainlen are IN\OUT arguments the function returns the size of the domain name and account name every time after execution. So to solve this the namelen and domainlen have to be reassigned every time.

LookupAccountSid(NULL, sid, oname, &namelen, doname, &domainnamelen, &peUse);
wcout << "domianName/AccoutName : " << doname << "/" << oname << endl;
namelen = 100; domainnamelen = 100; //This should solve the problem

Here is the link to the docs for the LookupAccountSid function

The second part of the question

The reason why the output from the program shows the users have FILE_GENERIC_WRITE permission even though the CACLS seem to show that users only have read and execute permission to the given file path is that in the program the code that checks if the users have the write permissions is done by the following.

if (FILE_GENERIC_WRITE & ace->Mask) {
    wcout << " FILE_GENERIC_WRITE" << "\n";
}

The problem is the FILE_GENERIC_WRITE consists of multiple permissions like STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE and when the code is written like this (FILE_GENERIC_WRITE & ace->Mask) it only checks if at least one of the permissions is present or not.

A special thanks to @user253751 and @Werner Henze for patiently explaining the solution

  • Related