In fact you can’t do it without knowing DN! There is an anonymous access in openLDAP which is enabled by default. The anonymous access let one to query(search filter) openLDAP without knowing bind username/password.
Run following command on your openLDAP server :
ldapwhoami -H ldap:// -x
If you get “anonymous” as result you are all set and your openLDAP is supporting anonymous query, otherwise this blog is not the one you are looking for!
So What’s the Deal?
Assume you know UID of the user in ldap directory but not his DN and assume the root directory hierarchy is : dc=devcrutch,dc=com . How do you want to get CN and then DN of such user in LDAP just by using UID? you might think of such query to get data out of openLDAP
uid=USERNAME,dc=devcrutch,dc=com
If you run this query, it’ll get you to nowhere.
Here Comes the Anonymous Query
First of all you have to query the whole directory for finding such user. You have to create a query similar to following:
(&(objectClass=*)(uid=USERNAME))
This query will search the entire Directory Information Tree (DIT) for such user name.
ldapsearch -x -h 127.0.0.1 -b dc=devcrutch,dc=com "(&(objectClass=*)(uid=USERNAME))"
With such query you can get the DN. Using DN and password you can authenticate against LDAP.
Well this was the idea, applying a search filter using USERNAME via anonymous identity then find the DN and finally login using the retrieved DN.
Time for Some java
Now we have the rough idea it’s time to implement it in java. For finding DN you need to query the entire LDAP directory (note: in real world searching the entire directory is not a good idea, you have to narrow your query, otherwise your query might consume all the server’s resources)
private String findDN(String user) throws Exception { DirContext ctx = getContext(); String dn = null; String filter = "(&(objectClass=*)(uid=" + user + "))"; NamingEnumeration answer = ctx.search("", filter, getSimpleSearchControls()); if (answer.hasMore()) { SearchResult result = (SearchResult) answer.next(); dn = result.getNameInNamespace(); } answer.close(); return dn; }
Then after finding the correct DN you can bind your username and password
public DirContext bind(String username, String password) throws Exception { DirContext dirContext; Hashtable<String, String> env = new Hashtable<String, String>(); String dn = findDN(username); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, dn); env.put(Context.SECURITY_CREDENTIALS, password); try { dirContext = getContext(env); } catch (javax.naming.AuthenticationException e) { throw new Exception(e); } return dirContext; }
That’s it.
You can find a working source code on my github
My chief interest is software engineering, mainly dealing with Linux and Java projects, but also interested in teaching what I’ve learned, have published a couple of CBTs about programming in Persian (java/Android) and here I’ll share my thoughts and experiences in English as well.
Leave a Reply