1

My customer has a huge Active Directory forerst. For example:

Root

company.com
  de.company.com
  us.company.com
  in.company.com
  xx.company.com

When i get the current user i get domainname\username. When i grab domainname and want to search in this domain for other users in the world, i can't cause i need to know company.com to do a directory search.

Is there a way in C# to get the root object which i use with the DirectorySearcher or any other C# method to query the AD?

STORM
  • 4,005
  • 11
  • 49
  • 98

2 Answers2

2

root forest name can be ontained from RootDSE partition. Look at rootDomainNamingContext attribute. This wiil return you forest root domain. I do not recommend to extract forest name from user DN, as it will not work in case if you have 2 domain trees in one forest. The second option is to search users in global catalog of current domain. Global catalog contains partial replica of all users from the entire forest

The code below performs the search over the global catalog. I have 2 domains, in my forest so it returns me 2 users. Be aware, that you will have to deal with multiple results returned:

        var forest = Forest.GetCurrentForest();
        var globalCatalog = GlobalCatalog.FindOne(new DirectoryContext(DirectoryContextType.Forest, forest.Name));

        using (var connection = new LdapConnection(new LdapDirectoryIdentifier(globalCatalog.Name, 3268)))
        {
            var entries = new List<SearchResultEntry>();

            var searchRequest = new SearchRequest(string.Empty, "(samaccountname=administrator)", SearchScope.Subtree, null);
            var searchOptionsControl = new SearchOptionsControl(System.DirectoryServices.Protocols.SearchOption.DomainScope);

            searchRequest.Controls.Add(searchOptionsControl);

            var pageResultRequestControl = new PageResultRequestControl(1000);

            searchRequest.Controls.Add(pageResultRequestControl);

            do
            {
                var response = (SearchResponse)connection.SendRequest(searchRequest);

                if (response != null)
                {
                    if (response.ResultCode != ResultCode.Success)
                    {
                        throw new ActiveDirectoryOperationException(response.ErrorMessage, (int) response.ResultCode);
                    }

                    foreach (var c in response.Controls.OfType<PageResultResponseControl>())
                    {
                        pageResultRequestControl.Cookie = c.Cookie;
                        break;
                    }

                    entries.AddRange(response.Entries.Cast<SearchResultEntry>());
                }
            }
            while (pageResultRequestControl.Cookie != null && pageResultRequestControl.Cookie.Length > 0);
        }

Several notes on this code: 1. of course this code it not a production one. You can write more general LdapSearcher, for example one can be found here. You can make a synchronous version of this searcher if needed. 2. I do strongly recommend to use LdapConnection instead of DirectorySearcher in service based applications, because using DirectorySearcher in enterprise environment leads to memory leaks and other issues

Community
  • 1
  • 1
oldovets
  • 695
  • 4
  • 9
  • Hm, ok i will try it with rootDomainNamingContext. This sounds good and the samples on the net are transparent/understandable and maybe the thing i am searching for, but could you please give a little more info on Global catalog? – STORM Nov 10 '16 at 15:19
  • 1
    A global catalog is a domain controller, which stores specific attributes of all forest objects. For each attribute Active Directory schema specifies if that attribute is stored in a global catalog. You can look at the System.DirectoryServices.ActiveDirectory.Forest class, which provides you with info of all available global catalogs. This method works in case if you don't know the domain name that searched user belongs to. To query global catalog you need to specify GC:// instead of LDAP:// – oldovets Nov 10 '16 at 19:44
  • In case if searched attributes are missing in global catalog you can still create Forest class, then get forest domains list from this class and search for the user in each domain – oldovets Nov 10 '16 at 19:48
  • If you provide me with more details on how you are going to search users, i. e. based on what attributes and what information you are going to query from AD i could give you a more specific advice – oldovets Nov 10 '16 at 19:58
  • given: name or lastname or amaccountname or email address. Cause i am searching for a user on one of the information above, i have NOT a domainname. Its a ASP.NET MVC application which runs on a Windows Server with IIS and the server is joined to the domain. I have also a classic WinForms solution where i have exactly the same requirements. The desktop app runs on the users client which is also connected to the domain. I need to enable the user to search for a user/users based on the filter information above. It would be great if you have a specific advice for me. – STORM Nov 11 '16 at 08:12
0

To get the root object of a user, use the property or attribute distinguished name to determine the fully qualified path in the Active Direcotry. Read the structure from right and extract the root element.

E. g. cn=John Doe, ou=People, dc=sun.com

enter image description here

Andre Hofmeister
  • 3,185
  • 11
  • 51
  • 74
  • But what if you have something like `dc=de,dc=eu,dc=company,dc=com` (de.eu.company.com) and you need for root only `dc=company,dc=com` (company.com)? – STORM Nov 10 '16 at 15:18
  • 1
    @STORM Just read the distinguished name of the current user and `RegEx`, `Split` or `Substring` the value. – Andre Hofmeister Nov 11 '16 at 05:51