How to: Check if current user is member of ‘domain admins’


The scenario

Sometimes in business applications it’s interesting checking if current user is member of the ‘domain administrators’ role. For example I am used to checking if current user has administrative privileges in order to showing some advanced configuration options (changing the application’s connection string, or allow creating new users).

privileges_thumb

IsInRole

To acomplish this we could use WindowsPrincipal class and its IsInRole method (this method checks if an user is member of a Windows role and returns a bool value). One of its overrides allows to pass the SID of the role or a constant value based on the enumeration WindowsBuiltInrole.

Note: For performance reasons, it’s recommended to use the override: IsinRole(SecurityIdentifier).

To check if current user is a local administrator we only need to do this:

WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
return wp.IsInRole(WindowsBuiltInRole.Administrator);

Notice that it’s realy easy, but as -its name indicates- WindowsBuiltInrole enumeration only contains local roles. So, if we would check if our user is member of a domain group, we should find the role SID, and then copy this value in our code.

As you can imagine, this is not the best solution, isn’t it? Well, let’s investigate a little bit more…

WellKnownSidType

Let’s take a look at the following enumeration WellKnownSidType, this enumeration provides commonly used security identifiers. Uhm… sounds good! Let’s try to use it in our code:

WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.AccountDomainAdminsSid, null);
return wp.IsInRole(sid);

Do’h!It seems that we need to pass the second argument called DomainSId…

CurrentUserIsDomainAdminError

DomainSid

What the hell means DomainSId? At MSDN we can read a brief explanation: Represents the domain SID, and this value is required for some WellKnownSidType values.

At this point our goal should be know the domain SID, but wait… how can I retrieve the domain SID? After spend some time surfing the Internet, the only solution I could find was an utility called PSGetSid from Mark Russinovich inside PSTools components. If you want try it, you can download this utility and execute it from your console to know the SID of your domain (type your domain name as “microsoft.com” o “net.volvo.com”):

DomainSidConsole_thumb

However, I’m pretty sure exists a better solution to this issue. Thus, let’s try to ask to our domain their SID, using the namespace System.DirectoryServices:

Domain d = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain, getDomainName()));
using (DirectoryEntry de = d.GetDirectoryEntry())
{
    byte[] domSid = (byte[])de.Properties["objectSid"].Value;
    string sdomainSid = sIDtoString(domSid);
    Console.WriteLine(sdomainSid);
}

Here we need a couple of auxiliar methods. The first one retrieves the domain name, and the second one retrieves a string that represents a SID value (from a byte array).

public static string getDomainName()
{
    return IPGlobalProperties.GetIPGlobalProperties().DomainName;
}

public static string sIDtoString(byte[] sidBinary)
{
    SecurityIdentifier sid = new SecurityIdentifier(sidBinary, 0);
    return sid.ToString();
}

Then, the value of sdomainSid corresponds to the SID of our domain. Great! Now, we can use it to retrieve the SID of the domain administrators role.

Putting it all together

Like my collegue and friend @alegrebandolero, I’m also a fan of extension methods. So, let’s create an extension method for the WindowsIdentity class:

using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.Net.NetworkInformation;
using System.Security.Principal;

namespace TestAD
{
    public static class SecurityExtensions
    {
        public static bool IsDomainAdmin(this WindowsIdentity identity)
        {
            Domain d = Domain.GetDomain(new
                DirectoryContext(DirectoryContextType.Domain, getDomainName()));
            using (DirectoryEntry de = d.GetDirectoryEntry())
            {
                byte[] domainSIdArray = (byte[])de.Properties["objectSid"].Value;
                SecurityIdentifier domainSId = new SecurityIdentifier(domainSIdArray, 0);
                SecurityIdentifier domainAdminsSId = new SecurityIdentifier(
                WellKnownSidType.AccountDomainAdminsSid, domainSId);
                WindowsPrincipal wp = new WindowsPrincipal(identity);
                return wp.IsInRole(domainAdminsSId);
            }
        }

        private static string getDomainName()
        {
            return IPGlobalProperties.GetIPGlobalProperties().DomainName;
        }
    }
}

That’s all. Now, use it as follows:

if (WindowsIdentity.GetCurrent().IsDomainAdmin())
{
    //Some actions…
}

Edit 12/14/2010: Since Windows Vista, each Windows user have a couple of security tokens. The first one is the normal token with limited privileges, and the second one only works when you ‘run as administrator’. This code only works if you are using the second token, running the application as administrator.

HYEI, happy coding!

December 2010

About these ads

5 thoughts on “How to: Check if current user is member of ‘domain admins’

  1. Hello friend, I write for a blog that you wrote to upload emails to Sharepoint, that found me interesting so download the software to be installed but do not work me. I’ll be doing something wrong or I’m missing some other process. Thank you very much for your help

  2. That’s pretty cool, so I adapted it to a PowerShell Cmdlet in C# and do a swicth for local vs domain admin membership:

    using System;
    using System.DirectoryServices;
    using System.Management.Automation;
    using System.DirectoryServices.ActiveDirectory;
    using System.Security.Principal;

    namespace tomc {

    [Cmdlet(“Test”, “Administrator”)]
    public class TestAdministratorCmdlet : Cmdlet {
    protected override void ProcessRecord() {
    base.ProcessRecord();

    WindowsIdentity identity = WindowsIdentity.GetCurrent();

    bool isLocalAdmin = IsAdministrator(identity, true);
    bool isDomainAdmin = IsAdministrator(identity, false);

    PSObject pso = new PSObject();

    pso.Members.Add(new PSNoteProperty(“Domain”, (string)GetDomainName(identity)));
    pso.Members.Add(new PSNoteProperty(“User”, (string)identity.Name));
    pso.Members.Add(new PSNoteProperty(“LocalAdmin”, (bool)isLocalAdmin));
    pso.Members.Add(new PSNoteProperty(“DomainAdmin”, (bool)isDomainAdmin));

    WriteObject(pso);

    }

    private bool IsAdministrator(WindowsIdentity identity, bool local) {

    Domain d = GetDomain(GetDomainName(identity));

    using (DirectoryEntry de = d.GetDirectoryEntry()) {

    byte[] domainSidArray = (byte[])de.Properties[“objectSid”].Value;
    SecurityIdentifier domainSid = new SecurityIdentifier(domainSidArray, 0);
    SecurityIdentifier adminsSid = new SecurityIdentifier(
    local ? WellKnownSidType.BuiltinAdministratorsSid : WellKnownSidType.AccountDomainAdminsSid,
    domainSid
    );

    WindowsPrincipal wp = new WindowsPrincipal(identity);
    return wp.IsInRole(adminsSid);
    }
    }

    private string GetDomainName(WindowsIdentity identity) {
    return identity.Name.Split(‘\\’)[0];
    }

    private Domain GetDomain(string domain) {
    return Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain, domain));
    }

    }
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s