/** * '$RCSfile$' * Purpose: An implementation of the AuthInterface interface that * allows Metacat to use the LDAP protocol for * directory services * Copyright: 2000 Regents of the University of California and the * National Center for Ecological Analysis and Synthesis * Authors: Matt Jones * * '$Author$' * '$Date$' * '$Revision$' * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.dataone.portal.servlets.ldap; import java.io.IOException; import java.net.ConnectException; import java.net.URLDecoder; import java.util.HashMap; import java.util.Hashtable; import java.util.Vector; import javax.naming.AuthenticationException; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.ReferralException; import javax.naming.SizeLimitExceededException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.LdapContext; import javax.naming.ldap.StartTlsRequest; import javax.naming.ldap.StartTlsResponse; import javax.net.ssl.SSLSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dataone.configuration.Settings; import org.dataone.service.types.v1.Group; import org.dataone.service.types.v1.Person; import org.dataone.service.types.v1.Subject; import org.dataone.service.types.v1.SubjectInfo; /** * An implementation of the AuthInterface interface that allows Metacat to use * the LDAP protocol for directory services. The LDAP authentication service is * used to determine if a user is authenticated, and whether they are a member * of a particular group. */ public class AuthLdap { private String ldapUrl; private String ldapBase; private String referral; private String ldapConnectTimeLimit; private int ldapSearchTimeLimit; private int ldapSearchCountLimit; private String currentReferralInfo; Hashtable env = new Hashtable(11); ReferralException refExc; private static Log log = LogFactory.getLog(AuthLdap.class); /** * Construct an AuthLdap */ public AuthLdap() throws InstantiationException { // Read LDAP URI for directory service information try { this.ldapUrl = Settings.getConfiguration().getString("ldap.url"); this.ldapBase = Settings.getConfiguration().getString("ldap.base"); this.referral = Settings.getConfiguration().getString("ldap.referral"); this.ldapConnectTimeLimit = Settings.getConfiguration().getString("ldap.connectTimeLimit"); this.ldapSearchTimeLimit = Integer.parseInt(Settings.getConfiguration().getString("ldap.searchTimeLimit")); this.ldapSearchCountLimit = Integer.parseInt(Settings.getConfiguration().getString("ldap.searchCountLimit")); } catch (Exception e) { throw new InstantiationException( "Could not instantiate AuthLdap - " + e.getMessage()); } // Store referral info for use in building group DNs in getGroups() this.currentReferralInfo = ""; } /** * Determine if a user/password are valid according to the authentication * service. * * @param user * the name of the principal to authenticate * @param password * the password to use for authentication * @returns boolean true if authentication successful, false otherwise */ public boolean authenticate(String user, String password) throws ConnectException { String ldapUrl = this.ldapUrl; String ldapBase = this.ldapBase; boolean authenticated = false; String identifier = user; // get uid here. if (user.indexOf(",") == -1) { throw new ConnectException("Invalid LDAP user credential: " + user + ". Missing ','"); } String uid = user.substring(0, user.indexOf(",")); user = user.substring(user.indexOf(","), user.length()); log.debug("AuthLdap.authenticate - identifier: " + identifier + ", uid: " + uid +", user: " + user); try { // Check the usename as passed in log.info("AuthLdap.authenticate - Calling ldapAuthenticate" + " with user as identifier: " + identifier); authenticated = ldapAuthenticate(identifier, password); // if not found, try looking up a valid DN then auth again if (!authenticated) { log.info("AuthLdap.authenticate - Not Authenticated"); log.info("AuthLdap.authenticate - Looking up DN for: " + identifier); identifier = getIdentifyingName(identifier, ldapUrl, ldapBase); if (identifier == null) { log.info("AuthLdap.authenticate - No DN found from getIdentifyingName"); return authenticated; } log.info("AuthLdap.authenticate - DN found from getIdentifyingName: " + identifier); String decoded = URLDecoder.decode(identifier); log.info("AuthLdap.authenticate - DN decoded: " + decoded); identifier = decoded; String refUrl = ""; String refBase = ""; if (identifier.startsWith("ldap")) { log.debug("AuthLdap.authenticate - identifier starts with \"ldap\""); refUrl = identifier.substring(0, identifier.lastIndexOf("/") + 1); int position = identifier.indexOf(","); int position2 = identifier.indexOf(",", position + 1); refBase = identifier.substring(position2 + 1); identifier = identifier.substring(identifier.lastIndexOf("/") + 1); log.info("AuthLdap.authenticate - Calling ldapAuthenticate: " + "with user as identifier: " + identifier + " and refUrl as: " + refUrl + " and refBase as: " + refBase); authenticated = ldapAuthenticate(identifier, password, refUrl, refBase); } else { log.info("AuthLdap.authenticate - identifier doesnt start with ldap"); identifier = identifier + "," + ldapBase; log.info("AuthLdap.authenticate - Calling ldapAuthenticate" + "with user as identifier: " + identifier); authenticated = ldapAuthenticate(identifier, password); } } } catch (NullPointerException npe) { log.error("AuthLdap.authenticate - NullPointerException while authenticating in " + "AuthLdap.authenticate: " + npe); npe.printStackTrace(); throw new ConnectException("AuthLdap.authenticate - NullPointerException while authenticating in " + "AuthLdap.authenticate: " + npe); } catch (NamingException ne) { log.error("AuthLdap.authenticate - Naming exception while authenticating in " + "AuthLdap.authenticate: " + ne); ne.printStackTrace(); } return authenticated; } /** * Connect to the LDAP directory and do the authentication using the * username and password as passed into the routine. * * @param identifier * the distinguished name to check against LDAP * @param password * the password for authentication */ private boolean ldapAuthenticate(String identifier, String password) throws ConnectException, NamingException, NullPointerException { return ldapAuthenticate(identifier, password, this.ldapUrl, this.ldapBase); } /** * Connect to the LDAP directory and do the authentication using the * username and password as passed into the routine. * * @param identifier * the distinguished name to check against LDAP * @param password * the password for authentication */ private boolean ldapAuthenticate(String dn, String password, String rootServer, String rootBase) { boolean authenticated = false; String server = ""; String userDN = ""; log.info("AuthLdap.ldapAuthenticate - dn is: " + dn); int position = dn.lastIndexOf("/"); log.debug("AuthLdap.ldapAuthenticate - position is: " + position); if (position == -1) { server = rootServer; if (dn.indexOf(userDN) < 0) { userDN = dn + "," + rootBase; } else { userDN = dn; } log.info("AuthLdap.ldapAuthenticate - userDN is: " + userDN); } else { server = dn.substring(0, position + 1); userDN = dn.substring(position + 1); log.info("AuthLdap.ldapAuthenticate - server is: " + server); log.info("AuthLdap.ldapAuthenticate - userDN is: " + userDN); } log.warn("AuthLdap.ldapAuthenticate - Trying to authenticate: " + userDN + " Using server: " + server); Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, server); env.put(Context.REFERRAL, "throw"); try { authenticated = authenticateTLS(env, userDN, password); } catch (AuthenticationException ee) { log.info("AuthLdap.ldapAuthenticate - failed to login : "+ee.getMessage()); String aliasedDn = null; try { aliasedDn = getAliasedDnTLS(userDN, env); if(aliasedDn != null) { log.warn("AuthLdap.ldapAuthenticate - an aliased object " + aliasedDn + " was found for the DN "+userDN+". We will try to authenticate this new DN "+aliasedDn+"."); authenticated = authenticateTLS(env, aliasedDn, password); } } catch (NamingException e) { log.error("AuthLdap.ldapAuthenticate - NamingException "+e.getMessage()+" happend when the ldap server authenticated the aliased object "+aliasedDn); } catch (IOException e) { log.error("AuthLdap.ldapAuthenticate - IOException "+e.getMessage()+" happend when the ldap server authenticated the aliased object "+aliasedDn); } } return authenticated; } public SubjectInfo getSubjectInfo(String username) { SubjectInfo info = new SubjectInfo(); Person person = new Person(); Subject subject = new Subject(); subject.setValue(username); person.setSubject(subject); // get attributes try { HashMap> attributes = this.getAttributes(username); if (attributes.containsKey("mail")) { person.addEmail(attributes.get("mail").firstElement()); } if (attributes.containsKey("givenName")) { person.addGivenName(attributes.get("givenName").firstElement()); } if (attributes.containsKey("sn")) { person.setFamilyName(attributes.get("sn").firstElement()); } } catch (Exception e) { log.warn("Error looking up person", e); } // get group membership try { String[][] groups = this.getGroups(null, null, username); for (String[] group: groups) { Group g = new Group(); Subject groupSubject = new Subject(); groupSubject.setValue(group[0]); g.setSubject(groupSubject); g.addHasMember(subject); person.addIsMemberOf(groupSubject); info.addGroup(g); } } catch (ConnectException e) { log.warn("Error looking up group", e); } info.addPerson(person); return info; } /* * Get the aliased dn through a TLS connection. The null will be returned if there is no real name associated with the alias */ private String getAliasedDnTLS(String alias, Hashtable env) throws NamingException, IOException { boolean useTLS = true; return getAliasedDn(alias, env, useTLS); } /* * Get the aliasedDN (the real DN) for a specified an alias name */ private String getAliasedDn(String alias, Hashtable env, boolean useTLS) throws NamingException, IOException { String aliasedDn = null; if(env != null) { env.put(Context.REFERRAL, "ignore"); } LdapContext sctx = new InitialLdapContext(env, null); StartTlsResponse tls = null; if(useTLS) { tls = (StartTlsResponse) sctx.extendedOperation(new StartTlsRequest()); // Open a TLS connection (over the existing LDAP association) and get details // of the negotiated TLS session: cipher suite, peer certificate, etc. SSLSession session = tls.negotiate(); } SearchControls ctls = new SearchControls(); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); String filter = "(objectClass=*)"; NamingEnumeration answer = sctx.search(alias, filter, ctls); while(answer.hasMore()) { SearchResult result = (SearchResult) answer.next(); if(!result.isRelative()) { //if is not relative, this will be alias. aliasedDn = result.getNameInNamespace(); break; } } if(useTLS && tls != null) { tls.close(); } sctx.close(); return aliasedDn; } private boolean authenticateTLS(Hashtable env, String userDN, String password) throws AuthenticationException{ log.info("AuthLdap.authenticateTLS - Trying to authenticate with TLS"); try { LdapContext ctx = null; double startTime; double stopTime; startTime = System.currentTimeMillis(); ctx = new InitialLdapContext(env, null); // Start up TLS here so that we don't pass our jewels in // cleartext StartTlsResponse tls = (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest()); // tls.setHostnameVerifier(new SampleVerifier()); SSLSession sess = tls.negotiate(); ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple"); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password); ctx.reconnect(null); stopTime = System.currentTimeMillis(); log.info("AuthLdap.authenticateTLS - Connection time thru " + ldapUrl + " was: " + (stopTime - startTime) / 1000 + " seconds."); } catch (AuthenticationException ae) { log.warn("AuthLdap.authenticateTLS - Authentication exception: " + ae.getMessage()); throw ae; } catch (NamingException ne) { throw new AuthenticationException("AuthLdap.authenticateTLS - Naming error when athenticating via TLS: " + ne.getMessage()); } catch (IOException ioe) { throw new AuthenticationException("AuthLdap.authenticateTLS - I/O error when athenticating via TLS: " + ioe.getMessage()); } return true; } /** * Get the identifying name for a given userid or name. This is the name * that is used in conjunction withthe LDAP BaseDN to create a distinguished * name (dn) for the record * * @param user * the user for which the identifying name is requested * @returns String the identifying name for the user, or null if not found */ private String getIdentifyingName(String user, String ldapUrl, String ldapBase) throws NamingException { String identifier = null; Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.REFERRAL, "throw"); env.put(Context.PROVIDER_URL, ldapUrl + ldapBase); try { int position = user.indexOf(","); if(position < 0){ return null; } String uid = user.substring(user.indexOf("=") + 1, position); log.info("AuthLdap.getIdentifyingName - uid is: " + uid); String org = user.substring(user.indexOf("=", position + 1) + 1, user .indexOf(",", position + 1)); log.info("AuthLdap.getIdentifyingName - org is: " + org); DirContext sctx = new InitialDirContext(env); SearchControls ctls = new SearchControls(); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); String filter = "(&(uid=" + uid + ")(o=" + org + "))"; log.warn("AuthLdap.getIdentifyingName - Searching for DNs with following filter: " + filter); for (boolean moreReferrals = true; moreReferrals;) { try { // Perform the search NamingEnumeration answer = sctx.search("", filter, ctls); // Return the answer while (answer.hasMore()) { SearchResult sr = (SearchResult) answer.next(); identifier = sr.getName(); return identifier; } // The search completes with no more referrals moreReferrals = false; } catch (ReferralException e) { log.info("AuthLdap.getIdentifyingName - Got referral: " + e.getReferralInfo()); // Point to the new context from the referral if (moreReferrals) { // try following referral, skip if error boolean referralError = true; while (referralError) { try { sctx = (DirContext) e.getReferralContext(); referralError = false; } catch (NamingException ne) { log.error("NamingException when getting referral contex. Skipping this referral. " + ne.getMessage()); e.skipReferral(); referralError = true; } } } } } } catch (NamingException e) { log.error("AuthLdap.getIdentifyingName - Naming exception while getting dn: " + e); throw new NamingException("Naming exception in AuthLdap.getIdentifyingName: " + e); } return identifier; } /** * Get all users from the authentication service * * @param user * the user for authenticating against the service * @param password * the password for authenticating against the service * @returns string array of all of the user names */ public String[] getUserInfo(String user, String password) throws ConnectException { String[] userinfo = new String[3]; log.info("AuthLdap.getUserInfo - get the user info for user "+user); // Identify service provider to use Hashtable env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, ldapUrl); String realName = null; try { realName = getAliasedDnTLS(user,env); } catch(Exception e) { log.warn("AuthLdap.getUserInfo - can't get the alias name for the user "+user+" since "+e.getMessage()); } log.info("AuthLdap.getUserInfo - the aliased dn for "+user+" is "+realName); if(realName != null) { //the the user is an alias name. we need to use the the real name user = realName; } try { // Create the initial directory context env.put(Context.REFERRAL, referral); DirContext ctx = new InitialDirContext(env); // Specify the attributes to match. // Users are objects that have the attribute // objectclass=InetOrgPerson. SearchControls ctls = new SearchControls(); String[] attrIDs = { "cn", "o", "mail" }; ctls.setReturningAttributes(attrIDs); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); // ctls.setCountLimit(1000); // create the filter based on the uid String filter = null; /*if (user.indexOf("o=") > 0) { String tempStr = user.substring(user.indexOf("o=")); filter = "(&(" + user.substring(0, user.indexOf(",")) + ")(" + tempStr.substring(0, tempStr.indexOf(",")) + "))"; } else { filter = "(&(" + user.substring(0, user.indexOf(",")) + "))"; }*/ filter = "(&(" + user.substring(0, user.indexOf(",")) + "))"; NamingEnumeration namingEnum = ctx.search(user, filter, ctls); Attributes tempAttr = null; try { while (namingEnum.hasMore()) { SearchResult sr = (SearchResult) namingEnum.next(); tempAttr = sr.getAttributes(); if ((tempAttr.get("cn") + "").startsWith("cn: ")) { userinfo[0] = (tempAttr.get("cn") + "").substring(4); } else { userinfo[0] = (tempAttr.get("cn") + ""); } if ((tempAttr.get("o") + "").startsWith("o: ")) { userinfo[1] = (tempAttr.get("o") + "").substring(3); } else { userinfo[1] = (tempAttr.get("o") + ""); } if ((tempAttr.get("mail") + "").startsWith("mail: ")) { userinfo[2] = (tempAttr.get("mail") + "").substring(6); } else { userinfo[2] = (tempAttr.get("mail") + ""); } } } catch (SizeLimitExceededException slee) { log.error("AuthLdap.getUserInfo - LDAP Server size limit exceeded. " + "Returning incomplete record set."); } // Close the context when we're done ctx.close(); } catch (NamingException e) { log.error("AuthLdap.getUserInfo - Problem getting users:" + e); // e.printStackTrace(System.err); throw new ConnectException("Problem getting users in AuthLdap.getUsers:" + e); } return userinfo; } /** * Get the users for a particular group from the authentication service * * @param group * the group whose user list should be returned * @returns string array of the user names belonging to the group */ private String[] getUsers(String group) throws ConnectException { String[] users = null; // Identify service provider to use Hashtable env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.REFERRAL, referral); env.put(Context.PROVIDER_URL, ldapUrl); try { // Create the initial directory context DirContext ctx = new InitialDirContext(env); // Specify the ids of the attributes to return String[] attrIDs = { "uniqueMember" }; Attributes answer = ctx.getAttributes(group, attrIDs); Vector uvec = new Vector(); try { for (NamingEnumeration ae = answer.getAll(); ae.hasMore();) { Attribute attr = (Attribute) ae.next(); for (NamingEnumeration e = attr.getAll(); e.hasMore(); uvec.add(e .next())) { ; } } } catch (SizeLimitExceededException slee) { log.error("AuthLdap.getUsers - LDAP Server size limit exceeded. " + "Returning incomplete record set."); } // initialize users[]; fill users[] users = new String[uvec.size()]; for (int i = 0; i < uvec.size(); i++) { users[i] = (String) uvec.elementAt(i); } // Close the context when we're done ctx.close(); } catch (NamingException e) { log.error("AuthLdap.getUsers - Problem getting users for a group in " + "AuthLdap.getUsers:" + e); /* * throw new ConnectException( "Problem getting users for a group in * AuthLdap.getUsers:" + e); */ } return users; } /** * Get the groups for a particular user from the authentication service * * @param user * the user for authenticating against the service * @param password * the password for authenticating against the service * @param foruser * the user whose group list should be returned * @returns string array of the group names */ private String[][] getGroups(String user, String password, String foruser) throws ConnectException { log.debug("AuthLdap.getGroups - getGroups() called."); // create vectors to store group and dscription values returned from the // ldap servers Vector gvec = new Vector(); Vector desc = new Vector(); Attributes tempAttr = null; Attributes rsrAttr = null; // DURING getGroups(), DO WE NOT BIND USING userName AND userPassword?? // NEED TO FIX THIS ... // Identify service provider to use env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.REFERRAL, "throw"); env.put(Context.PROVIDER_URL, ldapUrl); env.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit); // Iterate through the referrals, handling NamingExceptions in the // outer catch statement, ReferralExceptions in the inner catch // statement try { // outer try // Create the initial directory context DirContext ctx = new InitialDirContext(env); // Specify the attributes to match. // Groups are objects with attribute objectclass=groupofuniquenames. // and have attribute uniquemember: uid=foruser,ldapbase. SearchControls ctls = new SearchControls(); // Specify the ids of the attributes to return String[] attrIDs = { "cn", "o", "description" }; ctls.setReturningAttributes(attrIDs); // set the ldap search scope ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); // set a 10 second time limit on searches to limit non-responding // servers ctls.setTimeLimit(ldapSearchTimeLimit); // return at most 20000 entries ctls.setCountLimit(ldapSearchCountLimit); // build the ldap search filter that represents the "group" concept String filter = null; String gfilter = "(objectClass=groupOfUniqueNames)"; if (null == foruser) { filter = gfilter; } else { filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))"; } log.info("AuthLdap.getGroups - group filter is: " + filter); // now, search and iterate through the referrals for (boolean moreReferrals = true; moreReferrals;) { try { // inner try NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls); // Print the groups while (namingEnum.hasMore()) { SearchResult sr = (SearchResult) namingEnum.next(); tempAttr = sr.getAttributes(); if ((tempAttr.get("description") + "") .startsWith("description: ")) { desc.add((tempAttr.get("description") + "").substring(13)); } else { desc.add(tempAttr.get("description") + ""); } // check for an absolute URL value or an answer value // relative // to the target context if (!sr.getName().startsWith("ldap") && sr.isRelative()) { log.debug("AuthLdap.getGroups - Search result entry is relative ..."); gvec.add(sr.getName() + "," + ldapBase); log.info("AuthLdap.getGroups - group " + sr.getName() + "," + ldapBase + " added to the group vector"); } else { log.debug("AuthLdap.getGroups - Search result entry is absolute ..."); // search the top level directory for referral // objects and match // that of the search result's absolute URL. This // will let us // rebuild the group name from the search result, // referral point // in the top directory tree, and ldapBase. // configure a new directory search first Hashtable envHash = new Hashtable(11); // Identify service provider to use envHash.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); envHash.put(Context.REFERRAL, "ignore"); envHash.put(Context.PROVIDER_URL, ldapUrl); envHash.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit); try { // Create the initial directory context DirContext DirCtx = new InitialDirContext(envHash); SearchControls searchCtls = new SearchControls(); // Specify the ids of the attributes to return String[] attrNames = { "o" }; searchCtls.setReturningAttributes(attrNames); // set the ldap search scope - only look for top // level referrals searchCtls.setSearchScope(SearchControls.ONELEVEL_SCOPE); // set a time limit on searches to limit // non-responding servers searchCtls.setTimeLimit(ldapSearchTimeLimit); // return the configured number of entries searchCtls.setCountLimit(ldapSearchCountLimit); // Specify the attributes to match. // build the ldap search filter to match // referral entries that // match the search result String rFilter = "(&(objectClass=referral)(ref=" + currentReferralInfo.substring(0, currentReferralInfo.indexOf("?")) + "))"; log.debug("AuthLdap.getGroups - rFilter is: " + rFilter); NamingEnumeration rNamingEnum = DirCtx.search(ldapBase, rFilter, searchCtls); while (rNamingEnum.hasMore()) { SearchResult rsr = (SearchResult) rNamingEnum.next(); rsrAttr = rsr.getAttributes(); log.debug("AuthLdap.getGroups - referral search result is: " + rsr.toString()); // add the returned groups to the group // vector. Test the // syntax of the returned attributes - // sometimes they are // preceded with the attribute id and a // colon if ((tempAttr.get("cn") + "").startsWith("cn: ")) { gvec.add("cn=" + (tempAttr.get("cn") + "").substring(4) + "," + "o=" + (rsrAttr.get("o") + "").substring(3) + "," + ldapBase); log.info("AuthLdap.getGroups - group " + (tempAttr.get("cn") + "").substring(4) + "," + "o=" + (rsrAttr.get("o") + "").substring(3) + "," + ldapBase + " added to the group vector"); } else { gvec.add("cn=" + tempAttr.get("cn") + "," + "o=" + rsrAttr.get("o") + "," + ldapBase); log.info("AuthLdap.getGroups - group " + "cn=" + tempAttr.get("cn") + "," + "o=" + rsrAttr.get("o") + "," + ldapBase + " added to the group vector"); } } } catch (NamingException nameEx) { log.debug("AuthLdap.getGroups - Caught naming exception: "); nameEx.printStackTrace(System.err); } } }// end while moreReferrals = false; } catch (ReferralException re) { log .info("AuthLdap.getGroups - caught referral exception: " + re.getReferralInfo()); this.currentReferralInfo = (String) re.getReferralInfo(); // set moreReferrals to true and set the referral context moreReferrals = true; // try following referral, skip if error boolean referralError = true; while (referralError) { try { ctx = (DirContext) re.getReferralContext(); referralError = false; } catch (NamingException ne) { log.error("NamingException when getting referral contex. Skipping this referral. " + ne.getMessage()); re.skipReferral(); referralError = true; } } }// end inner try }// end for // close the context now that all initial and referral // searches are processed ctx.close(); } catch (NamingException e) { // naming exceptions get logged, groups are returned log.info("AuthLdap.getGroups - caught naming exception: "); e.printStackTrace(System.err); } finally { // once all referrals are followed, report and return the groups // found log.warn("AuthLdap.getGroups - The user is in the following groups: " + gvec.toString()); // build and return the groups array String groups[][] = new String[gvec.size()][2]; for (int i = 0; i < gvec.size(); i++) { groups[i][0] = (String) gvec.elementAt(i); groups[i][1] = (String) desc.elementAt(i); } return groups; }// end outer try } /** * Get attributes describing a user or group * * @param foruser * the user for which the attribute list is requested * @returns HashMap a map of attribute name to a Vector of values */ public HashMap> getAttributes(String foruser) throws ConnectException { HashMap> attributes = new HashMap>(); String ldapUrl = this.ldapUrl; // Identify service provider to use Hashtable env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.REFERRAL, referral); env.put(Context.PROVIDER_URL, ldapUrl); try { // Create the initial directory context DirContext ctx = new InitialDirContext(env); // Ask for all attributes of the user // Attributes attrs = ctx.getAttributes(userident); Attributes attrs = ctx.getAttributes(foruser); // Print all of the attributes NamingEnumeration en = attrs.getAll(); while (en.hasMore()) { Attribute att = (Attribute) en.next(); Vector values = new Vector(); String attName = att.getID(); NamingEnumeration attvalues = att.getAll(); while (attvalues.hasMore()) { try { String value = (String) attvalues.next(); values.add(value); } catch (ClassCastException cce) { log.debug("Could not cast LDAP attribute (" + attName + ") to a String value, so skipping."); } } attributes.put(attName, values); } // Close the context when we're done ctx.close(); } catch (NamingException e) { log.error("AuthLdap.getAttributes - Problem getting attributes:" + e); throw new ConnectException( "Problem getting attributes in AuthLdap.getAttributes:" + e); } return attributes; } }