We help IT Professionals succeed at work.

Authentication failure running ADO searches on remote domain

ryangorman
ryangorman asked
on
1,295 Views
Last Modified: 2011-10-03
I need to perform ADO searches on several remote domains. There are no trusts between the domains but conditional forwarding ensures name resolution. I have amended a script that works for my local domain but it fails when run against a remote domain. The script stops at the oCmd.Execute line with a "Provider: Permission denied" error. I can't see this authentication failure logged in the remote DCs Security logs. How can I authenticate and bind to the remote domain? I have hard-coded the domain name and security credentials for brevity and posting to EE.


Public      oRootDSE        :       Set oRootDSE = GetObject("LDAP://RootDSE")
Public      sDomain         :       sDomain = oRootDSE.Get("defaultNamingContext")
Public      oConn
Public      oCmd            
Public      oRset          

'/ Fill arrays with candidate user objects
GatherCandidateObjects

oConn.Close
Set oCmd = Nothing
Set oConn = Nothing

'/ Script Ends


'/ GatherCandidateObjects
'//////////////////////////////////////////////////////////////////////////////
Sub GatherCandidateObjects

'/Initialise ADO Query

set oConn = createobject("ADODB.Connection")
set oCmd = createobject("ADODB.Command")
set oRset = createobject("ADODB.Recordset")

oConn.ConnectionString = "Provider=ADsDSOObject;User ID=remotedomain\limitedacccount;Password=charsand123s;"

oConn.Open

oCmd.ActiveConnection = oConn
oCmd.Properties("Page Size") = 1000
oCmd.Properties("Searchscope") = ADS_SCOPE_SUBTREE
oCmd.Properties("Cache Results") = False

sDomain = "dc=remotedomain,dc=local"

sAttributes = "cn,company,department,description,division,distinguishedName,homeDirectory,homeMDB,l,lastLogonTimestamp,legacyExchangeDN,mailnickname,msExchHomeServerName,physicalDeliveryOfficeName,pwdLastSet,sAMAccountName,title,userAccountControl"
sFilter      = ">;(&(objectCategory=Person)(objectClass=User));"
sQuery = "<LDAP://" & sDomain & sFilter & sAttributes

oCmd.CommandText = sQuery
Set oRset = oCmd.Execute

End Sub
Comment
Watch Question

can you actually connect to remote AD with hardcoded credential using ldp.exe?

Author

Commented:
Thanks for the tip. I had 'proved' the connection with CSVDE but LDP is much better.

ld = ldap_open("remotedomain.local", 389);
Established connection to remotedomain.local.
Retrieving base DSA information...
Result <0>: (null)
Matched DNs:
Getting 1 entries:
>> Dn:
      1> currentTime: 02/01/2007 20:39:20 GMT Standard Time GMT Daylight Time;
      1> subschemaSubentry: CN=Aggregate,CN=Schema,CN=Configuration,DC=remotedomain,DC=local;
      1> dsServiceName: CN=NTDS Settings,CN=DC015066,CN=Servers,CN=Sites,CN=Configuration,DC=remotedomain,DC=local;
      3> namingContexts: CN=Schema,CN=Configuration,DC=remotedomain,DC=local; CN=Configuration,DC=remotedomain,DC=local; DC=remotedomain,DC=local;
      1> defaultNamingContext: DC=remotedomain,DC=local;
      1> schemaNamingContext: CN=Schema,CN=Configuration,DC=remotedomain,DC=local;
      1> configurationNamingContext: CN=Configuration,DC=remotedomain,DC=local;
      1> rootDomainNamingContext: DC=remotedomain,DC=local;
      16> supportedControl: 1.2.840.113556.1.4.319; 1.2.840.113556.1.4.801; 1.2.840.113556.1.4.473; 1.2.840.113556.1.4.528; 1.2.840.113556.1.4.417; 1.2.840.113556.1.4.619; 1.2.840.113556.1.4.841; 1.2.840.113556.1.4.529; 1.2.840.113556.1.4.805; 1.2.840.113556.1.4.521; 1.2.840.113556.1.4.970; 1.2.840.113556.1.4.1338; 1.2.840.113556.1.4.474; 1.2.840.113556.1.4.1339; 1.2.840.113556.1.4.1340; 1.2.840.113556.1.4.1413;
      2> supportedLDAPVersion: 3; 2;
      12> supportedLDAPPolicies: MaxPoolThreads; MaxDatagramRecv; MaxReceiveBuffer; InitRecvTimeout; MaxConnections; MaxConnIdleTime; MaxActiveQueries; MaxPageSize; MaxQueryDuration; MaxTempTableSize; MaxResultSetSize; MaxNotificationPerConn;
      1> highestCommittedUSN: 3947339;
      2> supportedSASLMechanisms: GSSAPI; GSS-SPNEGO;
      1> dnsHostName: DC015066.remotedomain.local;
      1> ldapServiceName: remotedomain.local:dc015066$@REMOTEDOMAIN.LOCAL;
      1> serverName: CN=DC015066,CN=Servers,CN=Sites,CN=Configuration,DC=remotedomain,DC=local;
      2> supportedCapabilities: 1.2.840.113556.1.4.800; 1.2.840.113556.1.4.1791;
      1> isSynchronized: TRUE;
      1> isGlobalCatalogReady: TRUE;
-----------
res = ldap_bind_s(ld, NULL, &NtAuthIdentity, 1158); // v.3
      {NtAuthIdentity: User='limitedacccount'; Pwd= <unavailable>; domain = 'remotedomain'.}
Authenticated as dn:'limitedacccount'.


Author

Commented:
P.S. I've looked at 'How Can I Use Alternate Credentials When Searching Active Directory?' [1].

[1] http://www.microsoft.com/technet/scriptcenter/resources/qanda/dec05/hey1209.mspx
ldp output looks good.

now in the script, why not use connection object's property to set "user id" and "password"? I am not sure if specifying userid and password in connection string will work, or if you need to escape "\". But by using oConn.Properties("User ID") and oConn.Properties("password"), you should be good to go.

http://www.microsoft.com/technet/scriptcenter/resources/qanda/dec05/hey1209.mspx

Author

Commented:
Here's my version of that script

Const ADS_SCOPE_SUBTREE = 2

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand =   CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"

objConnection.Properties("User ID") = "remotedomain\limitedaccount"
objConnection.Properties("Password") = "charsand123s"
objConnection.Properties("Encrypt Password") = TRUE
objConnection.Properties("ADSI Flag") = 3

objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection

objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE

objCommand.CommandText = _
    "SELECT Name FROM 'LDAP://DC=remotedomain,DC=local' WHERE " _
        & "objectCategory='user'"  
Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst
Do Until objRecordSet.EOF
    Wscript.Echo objRecordSet.Fields("Name").Value
    objRecordSet.MoveNext
Loop

And the result...

Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

C:\Report\CH test2.vbs(21, 1) Provider: Permission denied.

Author

Commented:
Originally I was using

oConnProperties("User ID") = "remotedomain\limitedaccount"
oConn.Properties("Password") = "charsand123s"

and only started using oConn.ConnectionString = "Provider=ADsDSOObject;User ID=remotedomain\limitedacccount;Password=charsand123s;"

after reading chapter 9 of 'Advanced VBScript for Microsoft Windows Administrators' which says

objConn.ConnectionString = "Provider=ADSDSOObject;" _
 "User ID=MyUserID;Password=MyPassword;"

Author

Commented:
Slight typo

objConn.ConnectionString = "Provider=ADSDSOObject;" & _
 "User ID=MyUserID;Password=MyPassword;"

Author

Commented:
OK, I found the answer (at least for the first remote domain)

Just like the The Scripting Team example and my MS Press book I was using serverless binding. In fact, I had used serverless binding when using LDP. However, serverless wasn't working.

I had tried specifying the preferred remote server but hadn't realised that the script needed to be 'told' via the ADSI Flag

Const ADS_SCOPE_SUBTREE = 2
Const ADS_SERVER_BIND = &h200

set oConn = createobject("ADODB.Connection")
set oCmd = createobject("ADODB.Command")
set oRset = createobject("ADODB.Recordset")

oConn.Provider = "ADsDSOObject"

oConn.Properties("User ID") = "remotedomain\limitedaccount"
oConn.Properties("Password") = "charsand123s"
oConn.Properties("Encrypt Password") = TRUE
oConn.Properties("ADSI Flag") = ADS_SERVER_BIND

oConn.Open "Active Directory Provider"

Set oCmd.ActiveConnection = oConn
oCmd.Properties("Page Size") = 1000
oCmd.Properties("Searchscope") = ADS_SCOPE_SUBTREE
oCmd.Properties("Cache Results") = False

sDomain = "dc015066.remotedomain.local/dc=remotedomain,dc=local"

sAttributes = "name,cn,company,department,description,division,distinguishedName,homeDirectory,homeMDB,l,lastLogonTimestamp,legacyExchangeDN,mailnickname,msExchHomeServerName,physicalDeliveryOfficeName,pwdLastSet,sAMAccountName,title,userAccountControl"
sFilter     = "(&(objectCategory=person)(objectClass=user))"
'sQuery = "<LDAP://" & sDomain & ">;" & sFilter & ";" & sAttributes

oCmd.CommandText = sQuery
Set oRset = oCmd.Execute

Do Until oRSet.EOF
    Wscript.Echo oRSet.Fields("Name").Value
    oRSet.MoveNext
Loop

oConn.Close
Set oCmd = Nothing
Set oConn = Nothing


Lastly, asking ADO to return attributes that don't exist will return a "Provider: Unspecified error". I.e a non-Exchange Windows 2000 domain won't have attributes like homeMDB or lastLogonTimestamp.
Glad you worked it out. Could the reason that you have to use server bind be that you hardcoded server name instead of using domain name in the ldap path?

Author

Commented:
I only added the server name after using just the domain name failed.
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.