Printout Header
RSS Feed

Searching Objects in the Global Catalog


In the tutorial article "Searching for LDAP Directory Objects with ADO" was described how to search for directory objects in a script in general. On this page, we want to focus on LDAP search operations in the global catalog. Please remember: There is only read access to the global catalog, and only a subset of the attributes is provided there. So in our LDAP search filter, we can use only those attributes which are included in the global catalog!

 

Standard Search in the Global Catalog
GC Search using special credentials
GC Search over LDAP SSL
GC Search when the own domain name / forest is unknown



Standard Search in the Global Catalog


We use a normal LDAP search operation where the LDAP path name is changed, so that the TCP-Port-Nummer 3268 is used. Additionally, we have to set another LDAP Search base - this has to be the DNS name of the root domain in your AD forest (this is the domain which was installed in the AD forest as the first domain).

So if we have a forest with the root domain named 'cerrotorre.de', and we want to have a list of all DCs in the forest, the search would look like this:

filterStr = "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))" 'search for DCs Set ado = CreateObject("ADODB.Connection") 'create new ADO connection ado.Provider = "ADSDSOObject" 'use the ADSI interface ado.Open "AD-Search" 'use any name for the connection Set adoCmd = CreateObject("ADODB.Command") 'create new ADO command adoCmd.ActiveConnection = ado 'assignment to an existing ADO connection adoCmd.Properties("Page Size") = 1000 'set the Paged Results value to 1000 (AD standard) adoCmd.Properties("Cache Results") = True adoCmd.CommandText = "<GC://cerrotorre.de>;" & filterStr & ";ADsPath;subtree" Set objectList = adoCmd.Execute 'perform search While Not objectList.EOF Set dc = GetObject(objectList.Fields("ADsPath")) 'connect to the DC objects which were found WScript.Echo dc.dnsHostName 'output: FQDN of the DCs objectList.MoveNext 'jump to the next search result entry Wend

Please note that the usual LDAP base string (for example 'OU=accounts,DC=slefadsi,DC=org') is replaced by the DNS name of the root domain (here 'cerrotorre.de'). The GC needed for this search is detected automatically by internal ADSI API calls.


GC Search using special credentials


The common method of searching the directory always works when a logged on user wants to access objects of his own domain respectively his own Active Directory forest. However, it might quite often be necessary to access a directory service where you are not an currently authenticated user. In that case we have to use additional search parameters for the credentials. And: The bind variation OpenDSObject allows to pass the username and password and thus the logon to e.g. foreign forests is possible.

Set dso = GetObject("LDAP:") 'we need this later for the OpenDSObject call userName = "DOMAIN\userXYZ" 'set your own credentials here password = "P@ssw0rd" filterStr = "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))" 'search for DCs Set ado = CreateObject("ADODB.Connection") 'create new ADO connection ado.Provider = "ADSDSOObject" 'use the ADSI interface ado.Properties("User ID") = userName ado.Properties("Password") = password ado.Open "AD-Search" 'use any name for the connection Set adoCmd = CreateObject("ADODB.Command") 'create new ADO command adoCmd.ActiveConnection = ado 'assignment to an existing ADO connection adoCmd.Properties("Page Size") = 1000 'set the Paged Results value to 1000 (AD standard) adoCmd.Properties("Cache Results") = True adoCmd.CommandText = "<GC://cerrotorre.de>;" & filterStr & ";ADsPath;subtree" Set objectList = adoCmd.Execute 'perform search While Not objectList.EOF Set dc = dso.OpenDSObject(objectList.Fields("ADsPath"), userName, password, 1) 'connect to the DCs which were found WScript.Echo dc.dnsHostName 'output :FQDN of the DCs objectList.MoveNext 'jump to the next search result entry Wend

In this example the search returns the distinguished names of all domain controllers in the forest. We connect to them with an OpenDSObject call, the last parameter (1) acts as a logon-flag, ensuring a secure Kerberos logon.

Prerequisite is, of course, that the station where you start this script can resolve the domain name of the forest root domain ('cerrotorre.de' in this example) to an IP address of an DC in this domain. Using the SRV records stored in the DNS, a global catalog server can be detected with internal ADSI API functions.


GC Search over LDAP SSL


You can also use LDAP-SSL to search the global catalog. Simply use the TCP-Port-Nummer 3269 (instead of 3268) to initiate the connection. However, this is working only if a valid SSL certificate was installed on the server before.

The example demonstrate how to search for all disabled user accounts in the forest over an SSL search operation:

filterStr = "(&(sAMAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=2))" 'search for disabled accounts Set ado = CreateObject("ADODB.Connection") 'create new ADO connection ado.Provider = "ADSDSOObject" 'use the ADSI interface ado.Open "AD-Search" 'use any name for the connection Set adoCmd = CreateObject("ADODB.Command") 'create new ADO command adoCmd.ActiveConnection = ado 'assignment to an existing ADO connection adoCmd.Properties("Page Size") = 1000 'set the Paged Results value to 1000 (AD standard) adoCmd.Properties("Cache Results") = True adoCmd.CommandText = "<LDAP://cerrotorre.de:3269>;" & filterStr & ";ADsPath;subtree" Set objectList = adoCmd.Execute 'perform search While Not objectList.EOF Set user = GetObject(objectList.Fields("ADsPath")) 'connect to the user objects which were found WScript.Echo user.sAMAccountName & vbcrlf & " " & user.distinguishedName 'output: show the disabled users objectList.MoveNext 'jump to the next search result entry Wend

GC Search when the own domain name / forest is unknown


In many cases you want to develop scripts that run in different Active Directory environments. Think about a script that e.g. displays any information about certain objects within the own domain or is responsible for specific changes. In order that this script runs in any domains, you could let pass the domain name as parameter. But it is more sophisticated to automatically identify the current domain name by querying the Active Directory itself through severless binding.

The relevant information can be read in a special directory entry, available on every domain controller: the rootDSE (Root Directory Service Entry).

So this is an example to search for all disabled user accounts in the forest where the script is launched:

Set aoi = CreateObject("ADSystemInfo") rootDNS = aoi.ForestDNSName filterStr = "(&(sAMAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=2))" 'search for disabled accounts Set ado = CreateObject("ADODB.Connection") 'create new ADO connection ado.Provider = "ADSDSOObject" 'use the ADSI interface ado.Open "AD-Search" 'use any name for the connection Set adoCmd = CreateObject("ADODB.Command") 'create new ADO command adoCmd.ActiveConnection = ado 'assignment to an existing ADO connection adoCmd.Properties("Page Size") = 1000 'set the Paged Results value to 1000 (AD standard) adoCmd.Properties("Cache Results") = True adoCmd.CommandText = "<GC://" & rootDNS & ">;" & filterStr & ";ADsPath;subtree" Set objectList = adoCmd.Execute 'perform search While Not objectList.EOF Set user = GetObject(objectList.Fields("ADsPath")) 'connect to the user objects which were found WScript.Echo user.sAMAccountName & vbcrlf & " " & user.distinguishedName 'output: show the disabled users objectList.MoveNext 'jump to the next search result entry Wend

s