funkman 2003/08/04 17:54:26 Modified: catalina/src/share/org/apache/catalina/realm JNDIRealm.java Log: Fix bugs: 18698 - Exception message in JNDI realm is not "Socket closed" on different ldap implementations 11678 - JNDIRealm times out/prompts for password with BASIC authentication 19864 - JNDIRealm NullPointerException / CommunicationException when Context Closed 20518 - JNDIRealm not retrying primary LDAP server after failed attempt against alternate server Thanks to Bradley M. Handy bhandy aT users dot sf (another dot) net for 20518 For the first 3 bugs: When CommunicationException is thrown, check that message is not null. When CommunicationException is thrown close the connection if - Message is null - Message contains "closed" (was "Socket closed") For the last bug: Put connectionAttempt = 0 in a finally block Other thanks to David DeWolf (david at daviddewolf com) and Jeff Tulley (jtulley at novell com) Committing to 4.1 first since this has a better chance of being tested there first. My text editor strips trailing white space (for seemingly unchanged lines) In reality, about 4 lines of code really changed. Revision Changes Path 1.12 +103 -95 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/JNDIRealm.java Index: JNDIRealm.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/JNDIRealm.java,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- JNDIRealm.java 11 Jan 2003 01:47:13 -0000 1.11 +++ JNDIRealm.java 5 Aug 2003 00:54:26 -0000 1.12 @@ -107,7 +107,7 @@ * substituting the presented username into a pattern configured by the * <code>userPattern</code> property.</li> * - * <li>Alternatively, if the <code>userPattern</code> property is not + * <li>Alternatively, if the <code>userPattern</code> property is not * specified, a unique element can be located by searching the directory * context. In this case: * <ul> @@ -122,7 +122,7 @@ * requests a search of only the current level.</li> * </ul> * </li> - * + * * <li>The user may be authenticated by binding to the directory with the * username and password presented. This method is used when the * <code>userPassword</code> property is not specified.</li> @@ -244,19 +244,20 @@ /** - * The protocol that will be used in the communication with the directory server. + * The protocol that will be used in the communication with the + * directory server. */ protected String protocol = null; /** - * How should we handle referrals? Microsoft Active Directory can't handle - * the default case, so an application authenticating against AD must + * How should we handle referrals? Microsoft Active Directory can't handle + * the default case, so an application authenticating against AD must * set referrals to "follow". */ protected String referrals = null; - - + + /** * The base element for user searches. */ @@ -292,7 +293,7 @@ /** * The message format used to form the distinguished name of a * user, with "{0}" marking the spot where the specified username - * goes. + * goes. */ protected String userPattern = null; @@ -342,11 +343,11 @@ */ protected boolean roleSubtree = false; - /** + /** * An alternate URL, to which, we should connect if connectionURL fails. */ - protected String alternateURL; - + protected String alternateURL; + /** * The number of connection attempts. If greater than zero we use the * alternate url. @@ -357,24 +358,24 @@ /** * Return the type of authentication to use. - */ + */ public String getAuthentication() { return authentication; - + } - + /** * Set the type of authentication to use. * * @param authentication The authentication */ public void setAuthentication(String authentication) { - + this.authentication = authentication; - + } - + /** * Return the connection username for this Realm. */ @@ -467,20 +468,20 @@ * Return the protocol to be used. */ public String getProtocol() { - + return protocol; - + } - + /** * Set the protocol for this Realm. * * @param protocol The new protocol. */ public void setProtocol(String protocol) { - + this.protocol = protocol; - + } @@ -493,13 +494,13 @@ /** - * How do we handle JNDI referrals? ignore, follow, or throw + * How do we handle JNDI referrals? ignore, follow, or throw * (see javax.naming.Context.REFERRAL for more information). */ public void setReferrals (String referrals) { this.referrals = referrals; } - + /** * Return the base element for user searches. @@ -737,10 +738,10 @@ * @return Value of property alternateURL. */ public String getAlternateURL() { - + return this.alternateURL; - - } + + } /** * Setter for property alternateURL. @@ -748,11 +749,11 @@ * @param alternateURL New value of property alternateURL. */ public void setAlternateURL(String alternateURL) { - + this.alternateURL = alternateURL; - + } - + // ---------------------------------------------------------- Realm Methods @@ -779,35 +780,39 @@ // Ensure that we have a directory context available context = open(); - + // Occassionally the directory context will timeout. Try one more // time before giving up. try { - + // Authenticate the specified username if possible principal = authenticate(context, username, credentials); - + } catch (CommunicationException e) { - - // If not a "Socket closed." error then rethrow. - if (e.getMessage().indexOf("Socket closed") < 0) + + + // If contains the work closed. Then assume socket is closed. + // If message is null, assume the worst and allow the + // connection to be closed. + if (e.getMessage()!=null && + e.getMessage().indexOf("closed") < 0) throw(e); - + // log the exception so we know it's there. log(sm.getString("jndiRealm.exception"), e); - + // close the connection so we know it will be reopened. if (context != null) close(context); - + // open a new directory context. context = open(); - + // Try the authentication again. principal = authenticate(context, username, credentials); - + } - + // Release this context release(context); @@ -854,7 +859,7 @@ String credentials) throws NamingException { - if (username == null || username.equals("") + if (username == null || username.equals("") || credentials == null || credentials.equals("")) return (null); @@ -894,7 +899,7 @@ */ protected User getUser(DirContext context, String username) throws NamingException { - + User user = null; // Get attributes to retrieve from user entry @@ -912,7 +917,7 @@ } else { user = getUserBySearch(context, username, attrIds); } - + return user; } @@ -960,7 +965,7 @@ } if (attrs == null) return (null); - + // Retrieve value of userPassword String password = null; if (userPassword != null) @@ -969,8 +974,8 @@ // Retrieve values of userRoleName attribute ArrayList roles = null; if (userRoleName != null) - roles = addAttributeValues(userRoleName, attrs, roles); - + roles = addAttributeValues(userRoleName, attrs, roles); + return new User(username, dn, password, roles); } @@ -1010,17 +1015,17 @@ // Specify the attributes to be retrieved if (attrIds == null) attrIds = new String[0]; - constraints.setReturningAttributes(attrIds); - + constraints.setReturningAttributes(attrIds); + if (debug > 3) { log(" Searching for " + username); log(" base: " + userBase + " filter: " + filter); } - - NamingEnumeration results = + + NamingEnumeration results = context.search(userBase, filter, constraints); - - + + // Fail if no entries found if (results == null || !results.hasMore()) { if (debug > 2) { @@ -1028,10 +1033,10 @@ } return (null); } - + // Get result for the first entry found SearchResult result = (SearchResult)results.next(); - + // Check no further entries were found if (results.hasMore()) { log("username " + username + " has multiple entries"); @@ -1046,7 +1051,7 @@ Name name = contextName.addAll(baseName); name = name.addAll(entryName); String dn = name.toString(); - + if (debug > 2) log(" entry found for " + username + " with dn " + dn); @@ -1063,8 +1068,8 @@ // Retrieve values of userRoleName attribute ArrayList roles = null; if (userRoleName != null) - roles = addAttributeValues(userRoleName, attrs, roles); - + roles = addAttributeValues(userRoleName, attrs, roles); + return new User(username, dn, password, roles); } @@ -1088,7 +1093,7 @@ User user, String credentials) throws NamingException { - + boolean validated = false; if (userPassword == null) { @@ -1096,7 +1101,7 @@ } else { validated = compareCredentials(context, user, credentials); } - + if (debug >= 2) { if (validated) { log(sm.getString("jndiRealm.authenticateSuccess", @@ -1166,20 +1171,20 @@ if (credentials == null || user == null) return (false); - + String dn = user.dn; if (dn == null) return (false); - + // Validate the credentials specified by the user if (debug >= 3) { log(" validating credentials by binding as the user"); } - + // Set up security environment to bind as the user context.addToEnvironment(Context.SECURITY_PRINCIPAL, dn); context.addToEnvironment(Context.SECURITY_CREDENTIALS, credentials); - + // Elicit an LDAP bind operation boolean validated = false; try { @@ -1194,22 +1199,23 @@ log(" bind attempt failed"); } } - + // Restore the original security environment if (connectionName != null) { - context.addToEnvironment(Context.SECURITY_PRINCIPAL, connectionName); + context.addToEnvironment(Context.SECURITY_PRINCIPAL, + connectionName); } else { context.removeFromEnvironment(Context.SECURITY_PRINCIPAL); } - if (connectionPassword != null) { + if (connectionPassword != null) { context.addToEnvironment(Context.SECURITY_CREDENTIALS, connectionPassword); } else { context.removeFromEnvironment(Context.SECURITY_CREDENTIALS); } - + return (validated); } @@ -1239,7 +1245,7 @@ if (debug >= 2) log(" getRoles(" + dn + ")"); - + // Start with roles retrieved from the user entry ArrayList list = user.roles; if (list == null) { @@ -1273,8 +1279,8 @@ SearchResult result = (SearchResult) results.next(); Attributes attrs = result.getAttributes(); if (attrs == null) - continue; - list = addAttributeValues(roleName, attrs, list); + continue; + list = addAttributeValues(roleName, attrs, list); } // Return the augmented list of roles @@ -1316,7 +1322,7 @@ valueString = new String((byte[]) value); else valueString = value.toString(); - + return valueString; } @@ -1349,7 +1355,7 @@ while(e.hasMore()) { String value = (String)e.next(); values.add(value); - } + } return values; } @@ -1422,37 +1428,39 @@ return (context); try { - + // Ensure that we have a directory context available context = new InitialDirContext(getDirectoryContextEnvironment()); - + } catch (NamingException e) { - + connectionAttempt = 1; - + // log the first exception. log(sm.getString("jndiRealm.exception"), e); - + // Try connecting to the alternate url. context = new InitialDirContext(getDirectoryContextEnvironment()); - + + } finally { + // reset it in case the connection times out. // the primary may come back. connectionAttempt = 0; - + } - + return (context); } - + /** * Create our directory context configuration. * * @return java.util.Hashtable the configuration for the directory context. */ protected Hashtable getDirectoryContextEnvironment() { - + Hashtable env = new Hashtable(); // Configure our directory context environment. @@ -1472,12 +1480,12 @@ if (authentication != null) env.put(Context.SECURITY_AUTHENTICATION, authentication); if (protocol != null) - env.put(Context.SECURITY_PROTOCOL, protocol); + env.put(Context.SECURITY_PROTOCOL, protocol); if (referrals != null) - env.put(Context.REFERRAL, referrals); - + env.put(Context.REFERRAL, referrals); + return env; - + } @@ -1532,7 +1540,7 @@ close(this.context); } - + } @@ -1546,9 +1554,9 @@ String dn = null; String password = null; ArrayList roles = null; - - User(String username, + + User(String username, String dn, String password, ArrayList roles) {
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]