Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there better (easier) ways to get a specific domain's SID?

I've been assigned to modify a WinForms application to basically check that the logged on user belongs to a specific domain. This is what I've come up with so far:

byte[] domainSid;

var directoryContext =
    new DirectoryContext(DirectoryContextType.Domain, "domain.se");

using (var domain = Domain.GetDomain(directoryContext))
using (var directoryEntry = domain.GetDirectoryEntry())
    domainSid = (byte[])directoryEntry.Properties["objectSid"].Value;

var sid = new SecurityIdentifier(domainSid, 0);
bool validUser = UserPrincipal.Current.Sid.IsEqualDomainSid(sid);

Is there a better/easier way to do this? To me it seems like the domainSid would be accessible in some way using the PrincipalContext or some other class in System.Security.Principal.

I've considered using a hardcoded SID-string, but I don't know how "correct" that would be.

like image 257
jovnas Avatar asked Oct 11 '11 12:10

jovnas


3 Answers

What you're doing looks like the best option to me. Hardcoding strings is definetely not a good idea.

like image 187
Brian Desmond Avatar answered Oct 28 '22 17:10

Brian Desmond


Each domain has a build in account domainName\administrator, so you can create an account with this name, translate it to the SecurityIdentifier and read the AccountDomainSid property.

An example of this way is:

public static class SecurityEx
{
    public static SecurityIdentifier DomainSId
    {
        get
        {               
            var administratorAcount = new NTAccount(GetDomainName(), "administrator");
            var administratorSId = (SecurityIdentifier) administratorAcount.Translate(typeof (SecurityIdentifier));
            return administratorSId.AccountDomainSid;
        }
    }

    internal static string GetDomainName()
    {
        //could be other way to get the domain name through Environment.UserDomainName etc...
        return IPGlobalProperties.GetIPGlobalProperties().DomainName;
    }
}

Also you can find other solutions to achieve the same result via WMI or Lsa. This one seems the most elegant way for me.

like image 38
Yuriy Shinbuev Avatar answered Oct 28 '22 15:10

Yuriy Shinbuev


Here's a slightly different approach to the accepted answer:

C#

using System.Security.Principal; 
using System.DirectoryServices;  

//...

void Main()
{
    var sidHelp = new SecurityIdentifierHelper();
    Console.WriteLine(sidHelp.GetDomainSecurityIdentifier("MyDomain"));
}

//...

public class SecurityIdentifierHelper
{
    const int OffsetBinaryFormStartingIndex = 0; // just to avoid magic numbers; though this is still a bit magic.  Documentation says "The byte offset to use as the starting index in binaryForm", whatever that means.
                                                 // https://referencesource.microsoft.com/#mscorlib/system/security/principal/sid.cs,d06a8d5ee0c7a26d,references
                                                 // https://docs.microsoft.com/en-us/dotnet/api/system.security.principal.securityidentifier.-ctor?view=netframework-4.8#System_Security_Principal_SecurityIdentifier__ctor_System_Byte___System_Int32_
    public SecurityIdentifier GetDomainSecurityIdentifier(string domain)
    {
        var ldapPath = $"LDAP://{domain}";
        var domainAdsi = new DirectoryEntry(ldapPath);
        var domainSidByteArray = (byte[])domainAdsi.Properties["objectSid"].Value;
        return new SecurityIdentifier(domainSidByteArray, OffsetBinaryFormStartingIndex);
    }
}

C# One Liner

Console.WriteLine(new System.Security.Principal.SecurityIdentifier(((byte[])new System.DirectoryServices.DirectoryEntry("LDAP://MyDomain").Properties["objectSid"].Value), 0));

PowerShell:

[string]$myDomain = 'MyDomain' # or 'MyDomain.example.com'
[string]$ldapPath = 'LDAP://{0}' -f $MyDomain
[adsi]$domainAdsi = [adsi]$ldapPath
[System.Security.Principal.SecurityIdentifier]::new($domainAdsi.Value, 0)

PowerShell 1 Liner:

[System.Security.Principal.SecurityIdentifier]::new(([ADSI]('LDAP://MyDomain')).Value, 0)
like image 33
JohnLBevan Avatar answered Oct 28 '22 17:10

JohnLBevan