tags:

views:

368

answers:

3

I’m attempting to check the rights on a particular file for a specific trustee and am using the win32 API GetEffectiveRightsFromAcl(). When the file is accessible by a domain group, the function returns 5 (Access Denied) when a local account (admin or other) is used to execute the function.

These three statements summarize the behavior I am seeing with GetEffectiveRightsFromAcl():

  • When domain group has rights to the file and the program runs under a local account: Access Denied.
  • When domain group has rights to the file and the program runs under a domain account or Local System: Success
  • When domain group doesn't have rights to the file and the program runs under any account: Success

Does anyone know the reason behind this? It looks to me like this is related to Active Directory security. What settings could affect this and what would be a good way to debug this?

Also, I've heard that GetEffectiveRightsFromAcl() may be generally problematic and to use AccessCheck() instead. However I need to be able to take an arbitrary SID and check it's access against a file and since AccessCheck() requires an impersonation token I don't know how I could greate a token out of an arbitrary SID... Any ideas? Thanks

Bob

+2  A: 
  • if domain group have right to the file, this function has to access the active directory to enumerate the group membership of the trustee ( at least if it is a domain user ). If your program is running under local account, then this account don't have right to access the active directory, hence the error return code.
  • domain account and Local System have access to the active directory. Local system is the computer account in the active directory( computers are like users in AD).
  • If no domain group has access to the file, the function don't have to check with the active directory. So local users succeed too.
Igal Serban
+1  A: 

Hi.

I have in C# used and it works well for me.

using System; using System.Runtime.InteropServices; using System.Security.Principal; using System.Security.AccessControl;

namespace DACL { class Class1 { private enum MULTIPLE_TRUSTEE_OPERATION { NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_IMPERSONATE }

    private enum TRUSTEE_FORM
    {
        TRUSTEE_IS_SID,
        TRUSTEE_IS_NAME,
        TRUSTEE_BAD_FORM,
        TRUSTEE_IS_OBJECTS_AND_SID,
        TRUSTEE_IS_OBJECTS_AND_NAME
    }

    private enum TRUSTEE_TYPE
    {
        TRUSTEE_IS_UNKNOWN,
        TRUSTEE_IS_USER,
        TRUSTEE_IS_GROUP,
        TRUSTEE_IS_DOMAIN,
        TRUSTEE_IS_ALIAS,
        TRUSTEE_IS_WELL_KNOWN_GROUP,
        TRUSTEE_IS_DELETED,
        TRUSTEE_IS_INVALID,
        TRUSTEE_IS_COMPUTER
    }

    private struct TRUSTEE
    {
        public IntPtr pMultipleTrustee;
        public MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation;
        public TRUSTEE_FORM TrusteeForm;
        public TRUSTEE_TYPE TrusteeType;
        public IntPtr ptstrName;
    }

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern void BuildTrusteeWithSid(
        ref TRUSTEE pTrustee,
        byte[] sid
    );

    [DllImport("advapi32.dll")]
    private static extern uint GetEffectiveRightsFromAcl(byte[] pacl, ref TRUSTEE
    pTrustee, ref uint pAccessRights);

    public bool HasAccess(SecurityIdentifier sid)
    {

        DiscretionaryAcl dacl = <DACL from somewhere>;

        byte[] daclBuffer = new byte[dacl.BinaryLength];
        dacl.GetBinaryForm(daclBuffer, 0);

        byte[] sidBuffer = new byte[sid.BinaryLength];
        sid.GetBinaryForm(sidBuffer, 0);

        TRUSTEE t = new TRUSTEE();
        BuildTrusteeWithSid(ref t, sidBuffer);

        uint access = 0;
        uint hr = GetEffectiveRightsFromAcl(daclBuffer, ref t, ref access);

        int i = Marshal.Release(t.ptstrName);

        return ((access | <Desired Access>) == <Desired Access>) ? true : false;
    }
}

}

A: 

Correction on return statement

return ((access | ) == ) ? true : false;

Should be

return ((access & ) == );

return ((access