views:

628

answers:

3

I'm writing some C++/Win32 code to search for a user in an LDAP directory (really I need to validate a username/password is correct, and then verify group membership). I have the username, so I'm hoping something like the following will work:

(&(objectCategory=person)(objectClass=user)(uid={username}))

When I call ldap_search with this search/filter, I have to provide a starting base (node/OU/whatever) to search. But I don't know where to start the search -- all I have is the username. Is there anyway to specify the root of the tree that will work with OpenLDAP, Active Directory, Netscape LDAP, etc, etc?

Also, anyone that can answer that could probably help with this: Is the uid attribute universally supported, or do I need to search on a different attribute depending on what brand of LDAP server I'm talking to? (I've seen references to people needing to search on uid, CN and even SAMAccountName).

A: 

You need to define what container to start searching in. So this would be something like

"LDAP://" + _ADSPath + ":" + _ADSPort + "/" + _ADSRootContainer

where _ADSPath is the server hostname/ip; _ADSPort is the port number (usually 389 by default); and _ADSRootContainer is the rest of the path to the container (like ou=Users. The path would depend on the implementation you are searching against. You can start up higher than the container holding the users and set the parameters on the search object to use a multi-level search. But it will be much slower.

DancesWithBamboo
+2  A: 

Regarding your first question about generically retrieving a search base:

Every LDAP directory server (conforming to the LDAP protocol I think) exposes some operational thingies under a node called RootDSE. One of the things you can retrieve through RootDSE are the namingContexts which essentially can tell you what the different trees are hosted on this server.

So you can retrieve a top-level search base for your username-search. Please be aware: some LDAP (OpenLDAP for example) servers can host multiple trees so you have to come up with a solution when multiple naming contexts are found.

The RootDSE can be retrieved by querying the server for the DN "" (empty string) and specifiyng that you want to get all the operational attributes as well. Just some example for an OpenLDAP server:

ldapsearch -H ldap://ldap.mydomain.com -x -s base -b "" +
# note the + returns operational attributes

This should return something similar to that shown below (from OpenLDAP 2.4.8) - the values in parentheses are added explanations and are not returned by the server:

dn:
structuralObjectClass: OpenLDAProotDSE
configContext: cn=config
namingContexts: dc=example,dc=com
namingContexts: dc=example,dc=net
monitorContext: cn=Monitor
supportedControl: 1.3.6.1.4.1.4203.1.9.1.1 (Contentsync RFC 4530)
[...]
supportedExtension: 1.3.6.1.4.1.4203.1.11.1 (ModifyPassword RFC3088)
[...]
supportedFeatures: 1.3.6.1.1.14 (Modify-Increment RFC4525)
[...]
supportedLDAPVersion: 3
supportedSASLMechanisms: NTLM
[...]
entryDN:
subschemaSubentry: cn=Subschema

(from http://www.zytrax.com/books/ldap/ch3/#operational)


Regarding your second question about the availability of the uid attribute:

I don't think that you should rely on this one as it strongly depends on the schema used for storing user data (although most user-schema-classes will have a uid attribute I think). But that depends on the flexibility you want to put into your program. Perhaps the best way would be to make the user-filter-string configurable by the end-user (you could even do this with the search base which would have some performance advantages (no need to search the whole tree when users are only located in a small subtree and no need to query the RootDSE)).

Stefan Gehrig
+2  A: 

I would not rely on uid being the proper search attribute for the user entries in LDAP. Many companies will only guarantee the employeeID as being unique within the LDAP DIT.

jeemster