Groups | Blog | Home
all groups > dotnet security > february 2006 >

dotnet security : .net 2.0: exception getting DirectorySecurity on a particular directory


Michael D'Angelo
2/17/2006 12:39:20 PM
I'm trying to enumerate the acls on various directories, and on a couple of
them, I get a System.ArgumentException stating
"The binary form of an ACE object is invalid.
Parameter name: binaryForm"

All I'm doing is the following:
DirectorySecurity sec = new DirectorySecurity(path,
AccessControlSections.Access);

If I look at the directory in Windows Explorer, there are some SIDs which do
not translate to named accounts, but I am still able to view it fine. Is
there some way I can get the SDDL or binary representation within .net 2.0,
or do I have to resort to native methods?

Nicole Calinoiu
2/19/2006 10:57:52 AM
SIDs do not appear to be mapped to names during the ACE binary form
validation, so I suspect that this isn't what is causing your particular
problem. It's likely that it may be necessary for your exact ACE entries to
be examined to determine the cause, so you might want to consider reporting
this as a bug at http://lab.msdn.microsoft.com/productfeedback/. In the
meantime, it sounds like using p/invoke to the underlying APIs might be your
safest bet...



[quoted text, click to view]

Michael D'Angelo
3/1/2006 11:31:19 AM
I have a .net 1.1 library I got from GotDotNet which p/invokes into the
Win32 API. On the directories I get that exception in .net 2.0, the 1.1
library complains that the SID's length is 36, when it is supposed to be 24.
So it appears there is something wrong with the ACLs on these directories.

[quoted text, click to view]

Joe Kaplan (MVP - ADSI)
3/1/2006 2:59:47 PM
SIDs should be even multiples of 4 bytes, so 36 should be ok. That would
be a SID with 7 sub authorities, which is a lot, but still a legal value. I
thought 15 was the max. According to WinNT.h:

#define SID_MAX_SUB_AUTHORITIES (15)

Perhaps it is a bug in the library?

Joe K.


[quoted text, click to view]

Joe Kaplan (MVP - ADSI)
3/1/2006 3:45:36 PM
This I'm not sure about. I thought it was in reference to a SID by itself,
but it looks like the SID is in another structure here.

If you can, maybe you can get an SDDL dump of the SD for the objects in
question and send them to PSS. It seems uncool that the .NET 2.0 libraries
would crash on an SD that you actually have, even if it is goofed up
somehow.

There is probably some cool tool to get the SDDL of an SD easily, but I'm
not sure what it is.

Joe K.

[quoted text, click to view]

Michael D'Angelo
3/1/2006 4:27:43 PM
Maybe, but then why would the .net 2.0 library from MS crash on the same
directories? Unless they both have the same bug...
The code in the 1.1 library that fails looks like this:

/// <summary>

/// Sanety check of the state of our members.

/// We don't want to make this method Debug-only, because we are dealing
with

/// security objects!

/// </summary>

protected unsafe void CheckInvariant()

{

int headerSize = _header.AceSize;

int compSize = OffsetOfSid() + _sid.Size;

if (headerSize != compSize)

{

string msg = string.Format(

"Invariant of Ace is not verified (size is {0} instead of {1})",

headerSize, compSize);

throw new InvalidOperationException(msg);

}

if (_sid == null)

throw new InvalidOperationException(

"Invariant of Ace is not verified: sid member is null");

}

The _header field is of type ACE_HEADER. OffsetOfSid() returns
ACCESS_ALLOWED_ACE.SidOffset. I don't really know the Win32 api for acls,
but I think those are native structs.
Perhaps the size from the header does not match the actual size of the SID.
Either way it appears the folder's ACLs are borked somehow...

[quoted text, click to view]

Michael D'Angelo
3/1/2006 4:37:52 PM
Here are the definitions for the structs in the library...
[StructLayout(LayoutKind.Sequential)]

public struct ACE_HEADER

{

public static readonly int SizeOf = Marshal.SizeOf(typeof(ACE_HEADER));

public AceType AceType;

public AceFlags AceFlags;

public WORD AceSize;

}



[StructLayout(LayoutKind.Sequential)]

public struct ACCESS_ALLOWED_ACE

{

public static readonly int SizeOf =
Marshal.SizeOf(typeof(ACCESS_ALLOWED_ACE));

public static readonly int SidOffset =
Marshal.OffsetOf(typeof(ACCESS_ALLOWED_ACE), "SidStart").ToInt32();

public ACE_HEADER Header;

public ACCESS_MASK Mask;

public DWORD SidStart;

}

So I'm guessing it's expecting the AceSize to match the offset of the
SidStart field. Could be a bug in the library....


[quoted text, click to view]

Michael D'Angelo
3/1/2006 5:09:26 PM
I can use cacls /s to get the SDDL string, but that doesn't seem to bother
the .net 2.0 classes. I'm trying to figure out if I can get the binary form
since that seems to be what is tripping things up.

[quoted text, click to view]

Joe Kaplan (MVP - ADSI)
3/1/2006 8:26:56 PM
If you use .NET to convert the SDDL back to binary, does it crash and are
the bytes the same? Maybe there is a wierd canonicalization issue with the
binary format?

Joe K.

[quoted text, click to view]

Joe Kaplan (MVP - ADSI)
3/2/2006 12:30:18 PM
There are a bunch of conversion functions like
ConvertSecurityDescriptorToStringSecurityDescriptor and
ConvertStringSecurityDescriptorToSecurityDescriptor. They have many friends
as well. :) You could try doing P/Invoke on those.

Joe K.

[quoted text, click to view]

Michael D'Angelo
3/2/2006 12:52:36 PM
I can't seem to figure out how to access the bytes that get passed to
RawAcl. It's all hidden within some undocumented classes within the class
library as far as I can see. Converting the string to binary form and back
doesn't appear to matter...

I don't suppose you know how one might do it via the Win32 api? I don't
deal with native much at all...

[quoted text, click to view]

AddThis Social Bookmark Button