How to check if user with [UserName] and [Password] is domain administrator of [DomainName] without impersonation?

4

Impersonation example

I can check is user domain administrator with next lines of code:

using (Impersonation im = new Impersonation(UserName, Domain, Password))
{
    System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
    bool isDomainAdmin = identity.IsDomainAdmin(Domain, UserName, Password);
    if (!isDomainAdmin)
    {
        //deny access, for example
    }
}

where IsDomainAdmin - is extension method

public static bool IsDomainAdmin(this WindowsIdentity identity, string domain, string userName, string password)
{
    Domain d = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain, domain, userName, password));

    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);
    }
}

But, when method IsDomainAdmin is called, it is trying to write some files to the %LOCALAPPDATA% for impersonated user, and if program is runnig not as administrator, it throws an exception

Could not load file or assembly 'System.DirectoryServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. Either a required impersonation level was not provided, or the provided impersonation level is invalid. (Exception from HRESULT: 0x80070542)

c#
.net
active-directory
asked on Stack Overflow Mar 13, 2012 by stukselbax • edited Oct 6, 2014 by Kiquenet

3 Answers

3

You certainly don't need a user's password to verify if the user is a member of a group. So why don't you just query AD in a straight-forward manner using DirectoryEntry or DirectorySearcher? If you also need to verify that the password supplied is correct you can do that in an additional step using PrincipalContext.ValidateCredentials. (See PrincipalContext.ValidateCredentials Method (String, String)).

static void Main(string[] args) {
    string userDomain = "somedomain";
    string userName = "username";
    string password = "apassword";

    if (IsDomainAdmin(userDomain, userName)) {
        string fullUserName = userDomain + @"\" + userName;
        PrincipalContext context = new PrincipalContext(
            ContextType.Domain, userDomain);
        if (context.ValidateCredentials(fullUserName, password)) {
            Console.WriteLine("Success!");
        }
    }
}

public static bool IsDomainAdmin(string domain, string userName) {
    string adminDn = GetAdminDn(domain);
    SearchResult result = (new DirectorySearcher(
        new DirectoryEntry("LDAP://" + domain),
        "(&(objectCategory=user)(samAccountName=" + userName + "))",
        new[] { "memberOf" })).FindOne();
    return result.Properties["memberOf"].Contains(adminDn);
}

public static string GetAdminDn(string domain) {
    return (string)(new DirectorySearcher(
        new DirectoryEntry("LDAP://" + domain),
        "(&(objectCategory=group)(cn=Domain Admins))")
        .FindOne().Properties["distinguishedname"][0]);
}
answered on Stack Overflow Mar 13, 2012 by Joshua Honig
2

We are modified @jmh_gr answer, and it seems to become independent from "Domain Admins" group name.

static string BuildOctetString(SecurityIdentifier sid)
{
    byte[] items = new byte[sid.BinaryLength];
    sid.GetBinaryForm(items, 0);
    StringBuilder sb = new StringBuilder();
    foreach (byte b in items)
    {
        sb.Append(b.ToString("X2"));
    }
    return sb.ToString();
}
public static bool IsDomainAdmin(string domain, string userName)
{
    using (DirectoryEntry domainEntry = new DirectoryEntry(string.Format("LDAP://{0}", domain)))
    {
        byte[] domainSIdArray = (byte[])domainEntry.Properties["objectSid"].Value;

        SecurityIdentifier domainSId = new SecurityIdentifier(domainSIdArray, 0);
        SecurityIdentifier domainAdminsSId = new SecurityIdentifier(WellKnownSidType.AccountDomainAdminsSid, domainSId);

        using (DirectoryEntry groupEntry = new DirectoryEntry(string.Format("LDAP://<SID={0}>", BuildOctetString(domainAdminsSId))))
        {
            string adminDn = groupEntry.Properties["distinguishedname"].Value as string;
            SearchResult result = (new DirectorySearcher(domainEntry, string.Format("(&(objectCategory=user)(samAccountName={0}))", userName), new[] { "memberOf" })).FindOne();
            return result.Properties["memberOf"].Contains(adminDn);
        }
    }
}

Anyway, thanks to @jmh_gr for the answer.

answered on Stack Overflow Mar 14, 2012 by stukselbax
0

Using this code by @lluisfranco

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

namespace Alpha.Code
{
    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[] bdomSid = (byte[])de.Properties["objectSid"].Value;
                string sdomainSid = sIDtoString(bdomSid);
                WindowsPrincipal wp = new WindowsPrincipal(identity);
                SecurityIdentifier dsid = new SecurityIdentifier(sdomainSid);
                SecurityIdentifier dasid = new SecurityIdentifier(
                    WellKnownSidType.AccountDomainAdminsSid, dsid);
                return wp.IsInRole(dasid);
            }
        }

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

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

Usage sample:

if (WindowsIdentity.GetCurrent().IsDomainAdmin())
{
    //Actions to do if user is domain admin
}

Source:
http://geeks.ms/blogs/lfranco/archive/2009/11/25/how-to-191-como-saber-si-el-usuario-actual-es-administrador-del-dominio.aspx

answered on Stack Overflow Oct 3, 2014 by Kiquenet

User contributions licensed under CC BY-SA 3.0