Alternate credentials can be passed to ADO by
assigning values to properties of the ADO connection object. The syntax
is shown below. In this example, I include several constants that I have
seen used for the "ADSI Flag" value. I also show three different forms
that can be used for the user name.
' ADS Authentication constants that can be used.
Const ADS_SECURE_AUTHENTICATION = &H1
Const ADS_USE_ENCRYPTION = &H2
Const ADS_USE_SSL = &H2
Const ADS_USE_SIGNING = &H40
Const ADS_USE_SEALING = &H80
Const ADS_USE_DELEGATION = &H100
Const ADS_SERVER_BIND = &H200
' Specify credentials.
' Select one of the three possible forms for the user name.
strUser = "cn=TestUser,ou=Sales,dc=MyDomain,dc=com"
strUser = "TestUser@MyDomain.com"
strUser = "MyDomain\TestUser"
strPassword = "xyz12345"
' Create the ADO Connection object.
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Properties("User ID") = strUser
adoConnection.Properties("Password") = strPassword
adoConnection.Properties("Encrypt Password") = True
adoConnection.Properties("ADSI Flag") = ADS_SERVER_BIND _
Or ADS_SECURE_AUTHENTICATION
adoConnection.Open "Active Directory Provider"
The client computer must be joined to the domain. If the user is authenticated to the domain you can
use serverless binding. However, if the user is logged in locally to the computer, and not authenticated
to the domain, I find that you must use a server bind. You must specify the name of a Domain Controller.
In the example below I assume the user is logged in locally. This VBScript program queries for all user
objects in the domain and outputs the Distinguished Names. The name of a Domain Controller is hard coded,
but the program uses the RootDSE object to retrieve the DNS name of the domain. The alternate credentials
must also be used to connect to this object. You could instead hard code the DNS name of the domain.
Option Explicit
Dim objRootDSE, strDNSDomain, adoCommand, adoConnection
Dim strBase, strFilter, strAttributes, strQuery, adoRecordset
Dim strDN, strUser, strPassword, objNS, strServer
Const ADS_SECURE_AUTHENTICATION = &H1
Const ADS_SERVER_BIND = &H200
' Specify a server (Domain Controller).
strServer = "MyServer"
' Specify or prompt for credentials.
strUser = "MyDomain\TestUser"
strPassword = "xyz12345"
' Determine DNS domain name. Use server binding and alternate
' credentials. The value of strDNSDomain can also be hard coded.
Set objNS = GetObject("LDAP:")
Set objRootDSE = objNS.OpenDSObject("LDAP://" & strServer & "/RootDSE", _
strUser, strPassword, _
ADS_SERVER_BIND Or ADS_SECURE_AUTHENTICATION)
strDNSDomain = objRootDSE.Get("defaultNamingContext")
' Use ADO to search Active Directory.
' Use alternate credentials.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Properties("User ID") = strUser
adoConnection.Properties("Password") = strPassword
adoConnection.Properties("Encrypt Password") = True
adoConnection.Properties("ADSI Flag") = ADS_SERVER_BIND _
Or ADS_SECURE_AUTHENTICATION
adoConnection.Open "Active Directory Provider"
Set
adoCommand.ActiveConnection = adoConnection
' Search entire domain. Use server binding.
strBase = "<LDAP://" & strServer & "/" & strDNSDomain & ">"
' Search for all users.
strFilter = "(&(objectCategory=person)(objectClass=user))"
' Comma delimited list of attribute values to retrieve.
strAttributes = "distinguishedName"
' Construct the LDAP query.
strQuery = strBase & ";" & strFilter & ";" _
& strAttributes & ";subtree"
' Run the query.
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
Set adoRecordset = adoCommand.Execute
' Enumerate the resulting recordset.
Do Until adoRecordset.EOF
' Retrieve values.
strDN = adoRecordset.Fields("distinguishedName").Value
Wscript.Echo strDN
adoRecordset.MoveNext
Loop
' Clean up.
adoRecordset.Close
adoConnection.Close
If the user is authenticated to the domain, but lacks permission to run the
query, you can use the more normal serverless binding and alternate
credentials.