delimeat52
delimeat52

Reputation: 121

Retrieving User Membership from Access VBA Using ADO to Perform LDAP Query

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

Answers (1)

EricLavault
EricLavault

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

Related Questions