2

I have a need to manage Kerberos Resource Based Delegation in C# (I know it's easier in Powershell but that is not the requirement). The attribute on the user/computer/service accounts is msDS-AllowedToActOnBehalfOfOtherIdentity, but this seems to be some COM object which I can't seem to deal with in C#:

static void Main(string[] args)
{
    string ou = @"OU=some,OU=ou,DC=corp,DC=com";
    string cn = @"someaccount";

    DirectoryEntry de = new DirectoryEntry();

    de.Username = @"CORP\userwithOUrights";
    de.Password = @"password";
    de.AuthenticationType = AuthenticationTypes.Secure;
    de.Path = $"LDAP://CN={cn},{ou}";
    Object a = de.Properties["msDS-AllowedToActOnBehalfOfOtherIdentity"];
}

After this, a doesn't seem to be anything I can do much with, unlike other properties. It is some COM object and I need to get the accounts which are in there. Powershell reports that this property returns a System.DirectoryServices.ActiveDirectorySecurity object and I see useful methods in this class for decoding the binary format which is stored in AD etc. But this does not seem to be the return type from the property call in C#.

CSDev
  • 3,177
  • 6
  • 19
  • 37
PLK
  • 389
  • 2
  • 13

1 Answers1

2

Update: All of this is now better documented in an article on my website: Handling NT Security Descriptor attributes


According to this the "attribute syntax" for that attribute is 2.5.5.15. According to this, that means it's a "String(NT-Sec-Desc)". According to this, that means it's a IADsSecurityDescriptor COM object.

You can add a COM reference in your project to "Active DS Type library" and cast it directly to IADsSecurityDescriptor, like this:

var act = (ActiveDs.IADsSecurityDescriptor)
              de.Properties["msDS-AllowedToActOnBehalfOfOtherIdentity"].Value;
Console.WriteLine(act.Owner);

The Owner property gives you a DOMAIN\Username.

According to this random code I found, it seems you can also use the RawSecurityDescriptor class to interact with it. There is a constructor that takes a plain string, but you also can't seem to get the raw string from the attribute from DirectoryEntry.

But I did remember that sometimes DirectorySearcher will give you values in a different type than DirectoryEntry (doesn't make sense, but it's true). That appears to be true here. DirectorySearcher gives this attribute to you as a byte[], and RawSecurityDescriptor does have a constructor that takes a byte[].

So it seems you can do something like this:

string ou = @"OU=some,OU=ou,DC=corp,DC=com";
string cn = @"someaccount";

var search = new DirectorySearcher(new DirectoryEntry($"LDAP://{ou}"), $"(cn={cn})");
search.PropertiesToLoad.Add("msDS-AllowedToActOnBehalfOfOtherIdentity");

var result = search.FindOne();

var act = new RawSecurityDescriptor(
    (byte[]) result.Properties["msDS-AllowedToActOnBehalfOfOtherIdentity"][0], 0);

Console.WriteLine(act.Owner);

//make changes to act.DiscretionaryAcl

byte[] descriptor_buffer = new byte[act.BinaryLength];
act.GetBinaryForm(descriptor_buffer, 0);

var de = result.GetDirectoryEntry();
de.Properties["msDS-AllowedToActOnBehalfOfOtherIdentity"].Value = descriptor_buffer;
de.CommitChanges();

In this, act.Owner is an account SID.

Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
  • Very helpful, thanks - with the DirectorySearcher, I was able to replicate the powershell results and so this should be possible now. – PLK Jul 24 '19 at 08:58
  • No problem. It was an interesting issue. I hadn't dealt with that attribute before. – Gabriel Luci Jul 24 '19 at 12:20
  • I took another try at it this morning, and you can actually cast it to an `IADsSecurityDescriptor` object if you include a reference in your project to `activeds.dll`. – Gabriel Luci Jul 24 '19 at 12:52
  • Hmm, I could also do that but it wasn't clear how useful the resulting object was. I need to be able to write to this property too though so I might have to look again as the searcher results are naturally not writable back to AD. – PLK Jul 24 '19 at 14:46
  • If you can modify the `RawSecurityDescriptor` object the way you need, you can write it back as a `byte[]` using the [`GetBinaryForm`](https://learn.microsoft.com/en-us/dotnet/api/system.security.accesscontrol.genericsecuritydescriptor.getbinaryform) method, like [this](https://github.com/pkb1s/SharpAllowedToAct/blob/master/SharpAllowedToAct/Program.cs#L93) (see lines 93-96) – Gabriel Luci Jul 24 '19 at 14:59
  • I should clarify, what I need is to read and set the DiscretionaryAcl properties in this. I could access them using the `DirectorySearcher` and a new `RawSecurityDescriptor` but I also need to change them ... – PLK Jul 24 '19 at 15:00
  • Right. So once you get a `RawSecurityDescriptor` object, it has a [`DiscretionaryAcl`](https://learn.microsoft.com/en-us/dotnet/api/system.security.accesscontrol.rawsecuritydescriptor.discretionaryacl) property you can change, then you can use `GetBinaryForm` to get a `byte[]` that you can write back to AD. – Gabriel Luci Jul 24 '19 at 15:02
  • Right - it's the "writing back to AD" part that's a bit tricky ... I got as far as the `GetBinaryForm` but then it's not clear what to do with this ... – PLK Jul 24 '19 at 15:07
  • Just `de.Properties["msDS-AllowedToActOnBehalfOfOtherIdentity"].Value = myByteArray;` then `de.CommitChanges();` – Gabriel Luci Jul 24 '19 at 15:10
  • To get a `DirectoryEntry` from the `SearchResult`, you can use [`result.GetDirectoryEntry()`](https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.searchresult.getdirectoryentry). – Gabriel Luci Jul 24 '19 at 15:11
  • Ah, of course, many thanks - I will try to put all the pieces together now - you have been very helpful indeed. – PLK Jul 24 '19 at 15:19
  • No problem. I updated my answer with that bit of code. – Gabriel Luci Jul 24 '19 at 15:20
  • 1
    I just finished implementing this exactly as you have done and it works perfectly. Very much appreciated - this is the only example of managing the Resource Based Kerberos Delegation properties in C# online currently I think! – PLK Jul 24 '19 at 15:26
  • I ended up documenting this a bit better on my website: [Handling NT Security Descriptor attributes](https://www.gabescode.com/active-directory/2019/07/25/nt-security-descriptors.html) – Gabriel Luci Jul 30 '19 at 02:15