Reputation: 121
I am querying Active Directory using VBA from Microsoft Access. Like many examples posted online, I am using a ADO connection to perform an LDAP query. I can successfully pull some attributes, like sn
,givenName
,mail
, proxyAddresses
and some of the miscellaneous MS Exchange properties like the msExchExtensionAttribute##
properties.
Now I am trying to query the memberOf
attribute and am receiving no return value for any user other than myself. I can easily see other user's group memberships in Outlook or see who is the member of groups by doing a search using the Windows Active Directory search tool. Sounds to me like a permissions issue, so I dug into my connection string. I had a suspicion that I was making my request anonymously since I did not specify a username or password.
I am trying to ensure I use Windows authentication and this must be able to be run by an average user (as I am on this domain as well), so no admin powers will be available to do this.
Some basic rummaging around led me to believe that setting the Integrated Security property of the connection properties to SSPI
should do it. That doesn't work, though. At this point, I'm just trying to get it to work, so the function is only returning a string for debug, but I'll eventually return an array or object.
Here's what I've got so far:
Function GetMembershipFromUsername(uname As String) As String
'Get the domain root
Dim root As IADs
Set root = GetObject("LDAP://RootDSE")
'Set the query parameters
Dim base as String, fltr as String, attr as String, scope as String
base = "<LDAP://" & root.Get("defaultNamingContext") & ">"
fltr = "(&(objectCLass=user)(objectCategory=Person)(sAMAccountName=" & uname & "))"
attr = "sAMAccountName,memberOf"
scope = "subtree"
'Connect to the LDAP server
Dim conn As ADODB.Connection
Set conn = CreateObject("ADODB.Connection")
conn.Provider = "ADsDSOObject"
conn.Properties.Item("Integrated Security").Value = "SSPI"
conn.Open "Active Directory Provider"
'Create LDAP command object
Dim cmd As ADODB.Command
Set cmd = CreateObject("ADODB.Command")
Set cmd.ActiveConnection = conn
'Build command
cmd.CommandText = base & ";" & fltr & ";" & attr & ";" & scope
'Execute and return info
Dim rs as ADODB.Recordset, vi as Variant, ml as String
Set rs = cmd.Execute
If rs.RecordCount > 0 Then
For Each vi In rs.Fields(1).Value
ml = ml & vi & Chr(10)
Next vi
End If
rs.Close
conn.Close
GetMembershipFromUsername = ml
End Function
Am I running into a permissions issue, am I somehow still making my request anonymously, or am I making some other mistake that would only allow me to pull my own group membership?
Upvotes: 2
Views: 2455
Reputation: 16045
The IADsOpenDSObject interface should be used instead of IADs for binding to AD objects using a security context other than the one of the user currently requesting the binding.
The IADsOpenDSObject interface is designed to supply a security context for binding to an object in the underlying directory store. It provides a means for specifying credentials of a client. Use this interface to bind to an ADSI object when you must supply a set of credentials for authentication in any directory service.
You'll need to create a reference to IADsOpenDSObject using GetObject()
method, just as you do with an IADs interface. You can then call the OpenDSObject()
method that allows to bind to an ADSI object using arbitrary credentials :
Dim ds As IADsOpenDSObject
Set ds = GetObject("LDAP://RootDSE")
Dim root As IADs
Set root = ds.OpenDSObject(dn, username, password, ADS_SECURE_AUTHENTICATION)
The last parameter is an authentication flag (see ADS_AUTHENTICATION_ENUM
) that determines which authentication process to use.
Upvotes: 2