import com.novell.ldap.*; import java.util.*; import java.io.UnsupportedEncodingException; import junit.framework.TestCase; import javax.naming.NamingException; import javax.naming.Context; import javax.naming.AuthenticationException; import javax.naming.directory.InitialDirContext; import javax.naming.directory.DirContext; /** * User: carr1den * Date: Jun 13, 2007 * Time: 8:10:51 AM */ public class MyLdapTest extends TestCase { /** * Users in our directory (AD) are not stored in one OU. * Rather, there is an OU=Users for each of the Offices in the organization. * To use the Novell library one must get the distinguished name (DN) of the user before * the bind call. The DN is available only when the user entry is found - by either a lookup * based on knowing the correct office, or by searching in each branch of the tree that * begins with "OU=Users". * Those extra steps are unnecessary with simpleBind(). */ String LDAP_SERVER = "ldapad"; int LDAP_PORT = 389; String LDAP_BASE_DN = "DC=ad,DC=dot,DC=state,DC=mn,DC=us"; String LDAP_UID_ATTR = "sAMAccountName"; String ORG_UNIT_NAME = "organizationalUnit"; String ORG_PERSON = "organizationalPerson"; String LDAP_UID = "ldapbrowse"; String LDAP_PASSWORD = "ldapbrowse"; String USERS_OU = "Users"; public void testTrueSimpleBind() { boolean b = false; try { b = simpleBind("carr1den", ""); } catch (NamingException e) { e.printStackTrace(); } // Succeeds without using ldapbrowse/ldapbrowse credential assertTrue(b); } public void testBind() { // Bind Succeeds assertTrue (search("carr1den", "", getOrgUnitDn("materials")).startsWith("Bind Succeeded")); // In our environment a bind with a blank password succeeds... // but, using the Novell LDAP library, only after a successful bind with read only credential: ldapbrowse/ldapbrowse // Go figure. // Bind Succeeds String testSearchBase = "OU=LDAP Testing,OU=Enterprise Administration" + "," + LDAP_BASE_DN; assertTrue (bind("ldap2tst", "", testSearchBase).startsWith("Bind Succeeded")); // Bind Succeeds assertTrue (bind("ldap2tst", "tuesday99", testSearchBase).startsWith("Bind Succeeded")); // Invalid Credentials for ldap2tst assertTrue (bind("ldap2tst", "tuesday9999", testSearchBase).startsWith("Invalid Credentials")); } public void testFalseSimpleBind() { boolean b = true; try { b = simpleBind("carr1den", "xx"); } catch (NamingException ae) { b = false; } assertFalse(b); } private boolean simpleBind(String uid, String pw) throws NamingException { /** * the context factory comes from the sun jndi ldap classes */ String contextFactory = "com.sun.jndi.ldap.LdapCtxFactory"; /** * the provider url is the LDAP server (the port at the end is required, 329 is default */ String providerURL = "ldap://"+LDAP_SERVER+":"+LDAP_PORT; boolean b = false; // create LDAP environment Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY,contextFactory); env.put(Context.PROVIDER_URL,providerURL); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, uid + "@ad.dot.state.mn.us"); env.put(Context.SECURITY_CREDENTIALS, pw); // authenticate to LDAP DirContext ctx = null; try { // Create initial context ctx = new InitialDirContext(env); if( ctx != null ) { b = true; } else { b = false; } // Close the context when we're done ctx.close(); } catch( NamingException ne ) { System.out.println (ne.getExplanation()); throw new AuthenticationException(ne.getMessage()); } finally { if (ctx != null) ctx.close(); } return b; } public void testOrgUnits() { String office = "materials"; String dn = getOrgUnitDn(office); assertTrue (dn.toUpperCase().indexOf("OU="+office.toUpperCase()) >= 0); office = "Commissioner"; dn = getOrgUnitDn(office); assertTrue (dn.toUpperCase().indexOf("OU="+office.toUpperCase()) >= 0); } /** * Searches for the given string within the distingushed name of objects * where (objectclass="organizationalUnit") - case insensitive compare * * @return rc The distinguishedName attribute of the object or a blank string. */ public String getOrgUnitDn(String ou) { String rc = ""; LDAPConnection lc = new LDAPConnection(); String thisSearchBase = LDAP_BASE_DN; String searchFilter = "(objectclass="+ ORG_UNIT_NAME +")"; String attrs[] = {"name"}; try { // connect to the server lc.connect( LDAP_SERVER, LDAP_PORT ); lc.bind( LDAPConnection.LDAP_V3, LDAP_UID, LDAP_PASSWORD.getBytes("UTF8") ); // Perform the search - SYNCHRONOUS SEARCH USED HERE //System.out.println("\nFinding DN of 'Users'..."); LDAPSearchResults res = lc.search( thisSearchBase, LDAPConnection.SCOPE_SUB, searchFilter, // null, // all attributes attrs, // only attrs[] attributes false); // and values too while (res.hasMore()) { LDAPEntry entry; try { entry = res.next(); if (entry != null) { String n = getAttr(entry, "name"); if (n.equals(USERS_OU)) { String dn = entry.getDN(); if (dn.toUpperCase().indexOf(ou.toUpperCase()) >= 0) { // returns the distinguishedName rc = dn; } } } } catch (LDAPException e) { if (e instanceof LDAPReferralException) // returns a blank string continue; else { rc = e.getMessage(); break; } } } // All done - disconnect if (lc.isConnected()) lc.disconnect(); } catch (LDAPException e) { rc = e.toString(); //System.out.println(e.toString()); } catch (UnsupportedEncodingException e) { System.out.println("Error: " + e.toString()); } return rc; } public String bind(String uid, String password, String searchBase) { return search(uid, password, searchBase); } /** * Returns either "Bind Succeeded for ..." or "Invalid Credentials..." */ public String search(String uid, String password, String searchBase) { String rc = ""; // return only those with objectclass=organizationalPerson String searchFilter = "(objectclass="+ORG_PERSON+")"; String attrs[] = {LDAP_UID_ATTR}; LDAPConnection lc = new LDAPConnection(); try { // connect to the server lc.connect( LDAP_SERVER, LDAP_PORT ); lc.bind( LDAPConnection.LDAP_V3, LDAP_UID, LDAP_PASSWORD.getBytes("UTF8") ); // Perform the search - SYNCHRONOUS SEARCH USED HERE //System.out.println("\nCalling search request..."); LDAPSearchResults res = lc.search( searchBase, LDAPConnection.SCOPE_SUB, searchFilter, // null, // all attributes attrs, // only attrs[] attributes false); // and values too while (res.hasMore()) { LDAPEntry entry; try { entry = res.next(); if (entry != null) { String samAccountName = getAttr(entry, LDAP_UID_ATTR); if (samAccountName.toUpperCase().equals(uid.toUpperCase())) { lc.bind( LDAPConnection.LDAP_V3, entry.getDN(), password.getBytes("UTF8") ); rc = "Bind Succeeded for " + samAccountName +" (dn: " + entry.getDN() + ")"; } } } catch (LDAPException e) { if (e instanceof LDAPReferralException) continue; else { rc = e.getMessage(); //System.out.println(e.getMessage() + " for " + uid); break; } } } // All done - disconnect if (lc.isConnected()) lc.disconnect(); } catch (LDAPException e) { rc = e.getMessage(); //System.out.println(e.toString()); } catch (UnsupportedEncodingException e) { System.out.println("Error: " + e.toString()); } return rc; } private String getAttr(LDAPEntry nextEntry, String attrName) { String rc = ""; if (attrName == null || "".equals(attrName)) return rc; // Get the attributes of the entry LDAPAttributeSet findAttrs = nextEntry.getAttributeSet(); Iterator enumAttrs = findAttrs.iterator(); // Loop on attributes while (enumAttrs.hasNext()) { LDAPAttribute anAttr = (LDAPAttribute) enumAttrs.next(); // get attribute name String anAttrName = anAttr.getName(); if (anAttrName.equals(attrName)) { // get the first attribute value return (String) anAttr.getStringValues().nextElement(); } } return rc; } }