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]

Reply via email to