Find Domain Name in Active Directory

14,221

Solution 1

One thing I am unclear on is your question about retrieving the domain name given a directoryentry in a domain controller. I am assuming that you have a server that can see multiple trusted domains, and that a user can log into your application from any one of them such that you don't know against what domain you need to test role membership.

For controlling access to features via ADGroup membership, could you use the

HttpContext.Current.User.IsInRole("appdomain\groupname") 

where User.Identity.Name=="userdomain\user". I'm not familiar with domain trust issues, but this assumes that you can add users from the trusted domain into the domain group that you control so you don't need to worry about the group domain location.

If you can't, or if you have the same group name in each different domain, then you could do something like this?

HttpContext.Current.User.IsInRole(userDomainname + "\groupname")

Some points:

  1. unless you already have a large established AD codebase, I would recommend using objects from the System.DirectoryServices.AccountManagement namespace.
  2. I highly recommend the ADExplorer utility from Sysinternals to get a more LDAP view of your domain(s) which helps with LDAP connection strings and directory programming in general.
  3. If you are comfortable with interop, and need to perform any LDAP connection string parsing, check out this site.
  4. The System.DirectoryServices.AccountManagement.PrincipalContext.Container and System.DirectoryServices.DirectoryEntry.Path properties return the LDAP connection string w/ the domain at the end of the string (i.e., DC=mycompany,DC=com)
  5. Don't forget about trusty old Environment.UserDomainName & Environment.UserName (which grabs the WindowsPrincipal from the currently executing thread; see Table 1: Thread Exposed CurrentPrincipal Object @ http://msdn.microsoft.com/en-us/library/Aa480475.aspx for a great table on what the current user is within the asp.net runtime. )

** UPDATE 6/8/2011 2:15 PM**

If I understand AD correctly, the user's domain is an integral part of the user object returned by AD. Expanding on your example of "Bob Newaccountant"...

So given the following 2 Domains with a trust between them:

1. "abcdc.com"
    CN=Users
        CN="Bob NewAccountant"
2. "abc.com"
    CN=Users
        CN="Local User1"
    OU=Applications
        OU=MyApplication
            CN=ReportReaders (Members: abcdc\BNewAccountant, abc\luser1)

You should get the users' info given the following query:

//name parameter = domain
//container parameter = distinguished name
using(var ctx = new PrincipalContext(
                     ContextType.Domain,
                     name: "abc.com",
                     container: "OU=MyApplication,OU=Applications,DC=abc,DC=com",
                     "abc\serviceaccountname",
                     "Password1"))
{
    var officeGroup = GroupPrincipal.FindByIdentity(ctx,
                                     IdentityType.SamAccountName,
                                     "ReportReaders");

    foreach(Principal prin in officeGroup.GetMembers(recursive: true))
    {
        Console.WriteLine("DistinguishedName: " + prin.DistinguishedName 
            + " UPN: " + prin.UserPrincipalName);
    }
    //Should result in
    //  DistinguishedName: CN=luser1,CN=Users,DC=abc,DC=com UPN: [email protected]
    //  DistinguishedName: CN=BNewAccountant,CN=Users,DC=abcdc,DC=com UPN: [email protected]
}

So you should be able to get the user's domain via distinguishedName or userPrincipalName properties of active directory. (Note: I don't have a dual domain setup handy to me so I am not able to test the above code at this time.) Is that getting closer?

Solution 2

Here is the WMI way to find it. I give you the PowerShell writting, but you can transform it for VBScript or C# easily

PS C:\> (Get-WmiObject Win32_NTDomain).DomainName

Be careful, the Domain part of the 'pre windows 2000 domain' can be completly different from the user Principal Name (user@domain) use to logon onto Active-Directory. the DOMAIN is the Primary Domain Controleur name or the Netbios domain name. DOMAIN is created during domain creation, by default it's part of the DNS name, but it can be completly changed during domain creation.

You can find it with nETBIOSName attribute :

ldifde -f netbios.ldf -d "CN=Partitions,CN=Configuration,DC=your-DNS-Name" -r "(netbiosname=*)" 

Edited

Here is the CSharp code

ManagementObjectSearcher domainInfos1 = new ManagementObjectSearcher("select * from WIN32_NTDomain");

foreach (ManagementObject domainInfo in domainInfos1.Get())
{
  Console.WriteLine("Name : {0}", domainInfo.GetPropertyValue("Name"));
  Console.WriteLine("Computer/domain : {0}", domainInfo.GetPropertyValue("Caption"));
  Console.WriteLine("Domain name : {0}", domainInfo.GetPropertyValue("DomainName"));
  Console.WriteLine("Status : {0}", domainInfo.GetPropertyValue("Status"));
}

Solution 3

DC stands for domain component. A seemingly decent rundown for programming with Active Directory is here. There's a bit much over there to do a decent copy and paste here, but I did find the following which may help you:

domainname=inputbox("Enter DNS Domain Name" & vbcrlf & "(Leave blank for current domain):")
username=inputbox("Enter username:")


IF domainname = "" THEN
    SET objRoot = GETOBJECT("LDAP://RootDSE")
    domainname = objRoot.GET("defaultNamingContext")
END IF

IF username <> "" THEN
    wscript.echo finduser(username,domainname)
END IF


FUNCTION FindUser(BYVAL UserName, BYVAL Domain) 
    ON ERROR RESUME NEXT

    SET cn = CREATEOBJECT("ADODB.Connection")
    SET cmd = CREATEOBJECT("ADODB.Command")
    SET rs = CREATEOBJECT("ADODB.Recordset")

    cn.open "Provider=ADsDSOObject;"

    cmd.activeconnection=cn
    cmd.commandtext="SELECT ADsPath FROM 'LDAP://" & Domain & _
             "' WHERE sAMAccountName = '" & UserName & "'"

    SET rs = cmd.EXECUTE

    IF err<>0 THEN
        FindUser="Error connecting to Active Directory Database:" & err.description
    ELSE
        IF NOT rs.BOF AND NOT rs.EOF THEN
                rs.MoveFirst
                FindUser = rs(0)
        ELSE
            FindUser = "Not Found"
        END IF
    END IF
    cn.close
END FUNCTION
Share:
14,221
Seattle Badger
Author by

Seattle Badger

Updated on June 09, 2022

Comments

  • Seattle Badger
    Seattle Badger almost 2 years

    I'm running an ASP.NET 4.0 app which uses the user name (i.e. HttpContext.Current.Request.LogonUserIdentity.Name.ToString()) to manage access to various components.

    The user name being returned is in the form "abc\jsmith" where "abc" is the domain name and "jsmith" is the login name of the user.

    Part of the security module for this app accesses the Active Directory groups that the user belongs to (e.g., "Accounting", "AccountsPayable", "AdminDepartment"). I'm able to get the user's name from Active Directory using the DirectoryEntry.Properties (i.e., System.DirectoryServices.PropertyCollection") "sAMAccountName".Value.

    So far, everything is fine, but I want to be able to expand the app across multiple domains, which mean I need to be able to find the domain name in Active Directory as well as the user's Login Name. I can get a "Domain" value from PrincipalContext, but it's returning "abcdc", instead of "abc". Can I assume that this property will always return "dc" (as in "Domain Controller") at the end of each domain (in which case I can use a Substring of the property), or is there somewhere else I can get the user's current domain name?

  • Seattle Badger
    Seattle Badger almost 13 years
    Actually, in this case, I found that "dc" is part of the domain name ("design center"), not "domain component".
  • Seattle Badger
    Seattle Badger almost 13 years
    Looked into this, using DirectoryEntry.Properties["userPrincipalName"].Value. I'm still getting the "abcdc" as the domain name. Still looking into the netBios thing. Thanks again for your input.
  • Seattle Badger
    Seattle Badger almost 13 years
    The Environment.UserDomainName is very useful for finding the domain of the computer on which the user is currently logged in. However, I need to be able to have my Security Administrator be able to add and manage users. I can get the users "login name" from Active Directory using "sAMAccountName". But how can I get the Domain Name? That's the real question. And, by the way, the DC=myCompany isn't what I'm looking for. That's what giving me "abcdc". What I need is "abc". -- Many thanks for your input. It's given me more paths to consider. -- Badger
  • Seattle Badger
    Seattle Badger almost 13 years
    I'm getting "DC=abcdc". I'm also having some trouble accessing the UserPrincipalName. I've tried "["UserPrincipalName"].Value", "["User-Prinicpal-Name"].Value", and about everything else I could think of, but keep coming up with "null" values. These are, of course, from the DirectoryEntry.Properties PropertyCollection. Am I on the right track? -- Thanks again, Badger
  • Seattle Badger
    Seattle Badger almost 13 years
    Tried running the "ldifde" in a command window. Got an error that "'ldifde' is not recognized as an internal or external command, operable program or batch file." -- Fortunately, no pre-2000 domains on my network. -- I'll look into translating your PowerShell command into C# to make this easier to integrate into the rest of the app. -- Thanks for your input. Badger
  • JPBlanc
    JPBlanc almost 13 years
    Ldifde is present on Domain Controlers.
  • Jason
    Jason almost 13 years
    Hmmm... Maybe it's more of a basic thing I'm missing then. Because I believe the only users that will be stored in a domain controller can be from that domain. Let me modify my answer to show what I mean.
  • Seattle Badger
    Seattle Badger almost 13 years
    Ahh, but I need to be able to let my Security Administrator have access to this info in order to manage users' access to various pieces of the app. -- thanks again
  • JPBlanc
    JPBlanc almost 13 years
    I Edited the answer. LDIFDE.EXE is just an exe file you can copy from W2K or W2K3 machine.
  • Seattle Badger
    Seattle Badger almost 13 years
    Perhaps if I give the scenario of the Security Admin (SA) user: company hires new accountant; SA user logs on to app, which searches Active Directory and returns a list of users; SA can then select user (e.g., "Bob Newaccountant") and give him permissions to appropriate features (e.g., reports). We want to set the app up so that SA can not only see all the users in our AD but also see what domain they're in. Does that make it more clear? Thanks again for your input. Badger
  • Seattle Badger
    Seattle Badger almost 13 years
    By the way, during my research, this is the 2nd time I've seen the VB.Net method "GetObject", which doesn't work in C#. Anybody got a C# method that works in a similar fashion?
  • Seattle Badger
    Seattle Badger almost 13 years
    This looks much closer. Is there a way to get the ctx data without knowing the user's password? As we work through the Active Directory (and the groups in it), I can see this as a "foreach" loop, but I won't have access to each user's password. Thanks, again. I think we're on the right track!!
  • Seattle Badger
    Seattle Badger almost 13 years
    This works really well in getting the domain name for the system I'm on. It correctly shows "Domain Name: abc". However, I need to be able to walk through the Active Directory and check each Name and DomainName. Or else, I'll be looking at "what's the DomainName for user 'NewHire'"? Any ideas?? Thanks for all your help. I think we're getting close to what I need!!
  • Jason
    Jason almost 13 years
    Awesome! Yup you don't need the user password. We have a situation where are are not using impersonation, so we have a special service account setup that we use to connect to active directory (so that's what the username and password are for). See the constructor overloads for PrincipalContext for those that do not require username and password: msdn.microsoft.com/en-us/library/….
  • Seattle Badger
    Seattle Badger almost 13 years
    I think that's got it! I need to tweak it a litte to make it fit, but I truly think that this is it!! Many, many thanks!!