.NET Forum / .NET Framework / Interop / November 2003
Using GetEffectiveRightsFromAcl in CSharp
|
|
Thread rating:  |
Katrin Bibas - 13 Nov 2003 21:39 GMT Hello,
how can I use GetEffectiveRightsFromAcl in C#? I don't know how to transform the parameters to the corresponding C# structs.
DWORD GetEffectiveRightsFromAcl( PACL pacl, PTRUSTEE pTrustee, PACCESS_MASK pAccessRights );
I hope this function will be more efficient than iterating through all the ACEs manually.
Thanks in advance, Katrin
Mattias Sj?gren - 13 Nov 2003 22:11 GMT Katrin,
Try this
enum MULTIPLE_TRUSTEE_OPERATION { NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_IMPERSONATE }
enum TRUSTEE_FORM { TRUSTEE_IS_SID, TRUSTEE_IS_NAME, TRUSTEE_BAD_FORM, TRUSTEE_IS_OBJECTS_AND_SID, TRUSTEE_IS_OBJECTS_AND_NAME }
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 }
struct TRUSTEE { public IntPtr pMultipleTrustee; public MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation; public TRUSTEE_FORM TrusteeForm; public TRUSTEE_TYPE TrusteeType; public IntPtr ptstrName; }
[DllImport("advapi32.dll")] static extern uint GetEffectiveRightsFromAcl(IntPtr pacl, ref TRUSTEE pTrustee, out uint pAccessRights);
Mattias
 Signature Mattias Sjögren [MVP] mattias @ mvps.org http://www.msjogren.net/dotnet/ Please reply only to the newsgroup.
Katrin Bibas - 14 Nov 2003 09:58 GMT Thank you for your quick response. I have not worked with IntPtr yet, so may you tell me how to convert IADsAccessControlList to an IntPtr?
I want to use the distinguishedName of the trustee, so I converted it with System.Runtime.InteropServices.Marshal.StringToCoTaskMemAnsi to an IntPtr and set TrusteeForm to TRUSTEE_IS_NAME. Is this the right way to do it?
Thank you. Katrin
Mattias Sj?gren - 15 Nov 2003 01:58 GMT Katrin,
>Thank you for your quick response. I have not worked with IntPtr yet, >so may you tell me how to convert IADsAccessControlList to an IntPtr? IntPtr is just the most generic type that can hold any kind of pointer sized value. If you know that it'll always be an IADsAccessControlList interface reference, you can probably change the type from IntPtr to IADsAccessControlList.
>I want to use the distinguishedName of the trustee, so I converted it >with System.Runtime.InteropServices.Marshal.StringToCoTaskMemAnsi to >an IntPtr and set TrusteeForm to TRUSTEE_IS_NAME. Is this the right >way to do it? I don't know, what do you do with the string pointer after that? It's possible that you also here can just change the data type from the generic IntPtr to a string, if that's what you always will use it for, and the runtime will then take care of the rest.
Mattias
 Signature Mattias Sjögren [MVP] mattias @ mvps.org http://www.msjogren.net/dotnet/ Please reply only to the newsgroup.
Katrin Bibas - 17 Nov 2003 10:20 GMT Mattias,
I always get the return value 1336, something's wrong with the ACL structure. I tried to use IADsAccessControlList and the string directly, and also the conversion to the IntPtr with System.Runtime.InteropServices.Marshal... . Always with the same result. Here is a snippet of code:
// get the security descriptor descriptor = entry.Properties["ntSecurityDescriptor"][0] as ADsSecurityDescriptor; if(descriptor != null) { // get DiscretionaryAcl dacl = descriptor.DiscretionaryAcl as IADsAccessControlList;
TRUSTEE pTrustee = new TRUSTEE(); pTrustee.MultipleTrusteeOperation = MULTIPLE_TRUSTEE_OPERATION.NO_MULTIPLE_TRUSTEE; pTrustee.pMultipleTrustee = IntPtr.Zero; pTrustee.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_NAME; pTrustee.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_USER; pTrustee.strName = userDN;
uint pAccessRights; uint result = GetEffectiveRightsFromAcl(dacl, ref pTrustee, out pAccessRights); }
Thanks in advance. Katrin
Stephen Martin - 17 Nov 2003 13:26 GMT Hi Katrin,
The problem is that the dacl parameter to GetEffectiveRightsFromACL is a pointer to an ACL structure but you are trying to pass it an IADsAccessControlList interface pointer. One is a C-style struct the other is a COM object, they are not interchangeable nor can one be marshalled to the other.
The AD object does not expose an underlying access control list pointer for the DACL. In order to use GetEffectiveRightsFromACL you will need to use the underlying API GetNamedSecurityInfo to retrieve a pointer to a DACL.
> Mattias, > [quoted text clipped - 29 lines] > Thanks in advance. > Katrin Katrin Bibas - 17 Nov 2003 19:09 GMT Hi Stephen, I thought it must be something like this. Now I use GetNamedSecurityInfo and the return value is 0 (for GetNamedSecurityInfo and GetEffectiveRightsFromAcl), so it should work. But the AccessMask is always 0. Am I still doing something wrong? I want to get the AccessMask for a user (userDN) on another DirectoryEntry (entryDN). Here is a new snippet of code:
IntPtr psd = IntPtr.Zero; IntPtr pZero = IntPtr.Zero; IntPtr pDacl = IntPtr.Zero; IntPtr pDacl2 = IntPtr.Zero;
int errorReturn = GetNamedSecurityInfo(entryDN, (int)SE_OBJECT_TYPE.SE_DS_OBJECT, DACL_SECURITY_INFORMATION, out pZero, out pZero, out pDacl, out pZero, out pZero);
errorReturn = GetNamedSecurityInfo(userDN, (int)SE_OBJECT_TYPE.SE_DS_OBJECT, DACL_SECURITY_INFORMATION, out pZero, out pZero, out pDacl2, out pZero, out psd);
TRUSTEE pTrustee = new TRUSTEE(); pTrustee.pMultipleTrustee = IntPtr.Zero; pTrustee.MultipleTrusteeOperation = MULTIPLE_TRUSTEE_OPERATION.NO_MULTIPLE_TRUSTEE; pTrustee.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_SID; pTrustee.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_USER; pTrustee.pName = psd; // this is an IntPtr
uint pAccessRights; uint result = GetEffectiveRightsFromAcl(pDacl, ref pTrustee, out pAccessRights);
Thanks in advance, Katrin
Stephen Martin - 18 Nov 2003 13:38 GMT Hi Katrin,
You have a couple of problems with your code that I can see.
In your first call to GetNamedSecurityInfo you are ignoring the security descriptor pointer, you can't do this. This pointer must be freed when you are done. In your second call to GetNamedSecurityInfo you are retrieving the security information for the Active Directory object that represents the user, you are not retrieving information about that user. In particular, the psd is not a pointer to that user's SID.
You need to use your original TRUSTEE code, modify the GetNamedSecurityInfo call slightly and add code at the end to free the memory allocated for the security descriptor. Something like this should work(not tested):
IntPtr psd = IntPtr.Zero; IntPtr pOwner = IntPtr.Zero; IntPtr pGroup = IntPtr.Zero; IntPtr pDacl = IntPtr.Zero; IntPtr pSacl = IntPtr.Zero;
int errorReturn = GetNamedSecurityInfo(entryDN, (int)SE_OBJECT_TYPE.SE_DS_OBJECT, DACL_SECURITY_INFORMATION, out pOwner, out pGroup, out pDacl, out pSacl, out psd);
TRUSTEE pTrustee = new TRUSTEE(); pTrustee.pMultipleTrustee = IntPtr.Zero; pTrustee.MultipleTrusteeOperation = MULTIPLE_TRUSTEE_OPERATION.NO_MULTIPLE_TRUSTEE; pTrustee.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_NAME; pTrustee.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_USER; pTrustee.strName = userDN;
uint pAccessRights; uint result = GetEffectiveRightsFromAcl(pDacl, ref pTrustee, out pAccessRights);
//The security descriptor pointer must always be freed //when you are done with it. System.Runtime.InteropServices.Marshal.FreeHGlobal(psd);
> Hi Stephen, > I thought it must be something like this. Now I use [quoted text clipped - 33 lines] > Thanks in advance, > Katrin Katrin Bibas - 18 Nov 2003 20:02 GMT Hi Stephen,
thank you for help. I think I did it now. At first I had a problem with errorcode 1332. I thought I could use the distinguishedName of the user, but obviously this did not work. But then I translated it to the NT4-style name, and now it works.
Katrin
> Hi Katrin, > [quoted text clipped - 75 lines] > > Thanks in advance, > > Katrin Katrin Bibas - 27 Nov 2003 18:54 GMT Hi,
is it possible, that GetEffectiveRightsFromAcl returns wrong values? I get access masks with rights I didn't expect. This function returns the rights the trustee really has, not the denied rights, doesn't it? So for example if I do
if((accessmask & 0x10000) == 0x10000) // check for standard rights - DELETE { ... }
I should get true if the accessmask for the trustee contains this right. But as far as I know the trustee I am testing does not have this right in the active directory. I haven't work with those things that often yet. Is there anything else I have to pay attention for when using this function? Do some rights override others?
Thanks in advance. Katrin
Stephen Martin - 29 Nov 2003 13:25 GMT Hi Katrin,
Are you sure that the trustee does not have the requested access through some group membership (possibly indirect such as belonging to a group that belongs to a group that has the access). I usually don't recommend using GetEffectiveRightsFromAcl because its results are often incorrect but sometimes there is no alternative. But GetEffectiveRightsFromAcl usually errs on the side of giving false negatives (i.e. reporting that a trustee does not have a certain access when in fact they do have it). I can't say that I remember it ever giving a false positive.
> Hi, > [quoted text clipped - 17 lines] > Thanks in advance. > Katrin Katrin Bibas - 29 Nov 2003 15:06 GMT Hi Stephen,
I used the admin tools to check the effective rights too, and there was the same result. Lots of rights were checked although the user does not have those rights. I have read the article http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com: 80/support/kb/articles/q262/2/78.asp&NoWebContent=1. There is written that sometimes GetEffectiveRightsFromAcl does not return the correct rights. So I started a new thread about using AccessCheck. Maybe you can help me with this, too :-) IsAccessCheck the right way to solve my problem?
Thanks a lot for any help. Katrin
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|