tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From funk...@apache.org
Subject cvs commit: jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm JNDIRealm.java
Date Wed, 06 Aug 2003 18:51:27 GMT
funkman     2003/08/06 11:51:27

  Modified:    catalina/src/share/org/apache/catalina/realm JNDIRealm.java
  Log:
  Resync with 4.1 for the many bug fixes for JNDIRealm
  
  Revision  Changes    Path
  1.5       +127 -98   jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm/JNDIRealm.java
  
  Index: JNDIRealm.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/realm/JNDIRealm.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- JNDIRealm.java	11 Jan 2003 01:57:39 -0000	1.4
  +++ JNDIRealm.java	6 Aug 2003 18:51:27 -0000	1.5
  @@ -86,7 +86,7 @@
   import org.apache.catalina.LifecycleException;
   import org.apache.catalina.Realm;
   import org.apache.catalina.util.StringManager;
  -
  +import org.apache.catalina.util.Base64;
   
   /**
    * <p>Implementation of <strong>Realm</strong> that works with a directory
  @@ -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>
  @@ -183,6 +183,13 @@
    * format objects) so that <code>authenticate()</code> does not have to be
    * synchronized.</p>
    *
  + * <p><strong>WARNING</strong> - There is a reported bug against the
Netscape
  + * provider code (com.netscape.jndi.ldap.LdapContextFactory) with respect to
  + * successfully authenticated a non-existing user. The
  + * report is here: http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11210 .
  + * With luck, Netscape has updated their provider code and this is not an
  + * issue. </p>
  + *
    * @author John Holman
    * @author Craig R. McClanahan
    * @version $Revision$ $Date$
  @@ -244,19 +251,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 +300,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 +350,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 +365,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 +475,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 +501,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 +745,10 @@
        * @return Value of property alternateURL.
        */
       public String getAlternateURL() {
  -        
  +
           return this.alternateURL;
  -        
  -    }    
  +
  +    }
   
       /**
        * Setter for property alternateURL.
  @@ -748,11 +756,11 @@
        * @param alternateURL New value of property alternateURL.
        */
       public void setAlternateURL(String alternateURL) {
  -        
  +
           this.alternateURL = alternateURL;
  -        
  +
       }
  -    
  +
   
       // ---------------------------------------------------------- Realm Methods
   
  @@ -779,35 +787,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 +866,7 @@
                                                  String credentials)
           throws NamingException {
   
  -        if (username == null || username.equals("") 
  +        if (username == null || username.equals("")
               || credentials == null || credentials.equals(""))
               return (null);
   
  @@ -894,7 +906,7 @@
        */
       protected User getUser(DirContext context, String username)
           throws NamingException {
  -        
  +
           User user = null;
   
           // Get attributes to retrieve from user entry
  @@ -912,7 +924,7 @@
           } else {
               user = getUserBySearch(context, username, attrIds);
           }
  -        
  +
           return user;
       }
   
  @@ -960,7 +972,7 @@
           }
           if (attrs == null)
               return (null);
  -        
  +
           // Retrieve value of userPassword
           String password = null;
           if (userPassword != null)
  @@ -969,8 +981,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 +1022,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 +1040,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 +1058,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 +1075,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 +1100,7 @@
                                        User user,
                                        String credentials)
            throws NamingException {
  -         
  +
            boolean validated = false;
   
            if (userPassword == null) {
  @@ -1096,7 +1108,7 @@
            } else {
                validated = compareCredentials(context, user, credentials);
            }
  -         
  +
            if (debug >= 2) {
                if (validated) {
                    log(sm.getString("jndiRealm.authenticateSuccess",
  @@ -1139,8 +1151,22 @@
   
           boolean validated = false;
           if (hasMessageDigest()) {
  -            // Hex hashes should be compared case-insensitive
  -            validated = (digest(credentials).equalsIgnoreCase(password));
  +            // iPlanet support if the values starts with {SHA1}
  +            // The string is in a format compatible with Base64.encode not
  +            // the Hex encoding of the parent class.
  +            if (password.startsWith("{SHA}")) {
  +                /* sync since super.digest() does this same thing */
  +                synchronized (this) {
  +                    password = password.substring(5);
  +                    md.reset();
  +                    md.update(credentials.getBytes());
  +                    String digestedPassword = new String(Base64.encode(md.digest()));
  +                    validated = password.equals(digestedPassword);
  +                }
  +            } else {
  +                // Hex hashes should be compared case-insensitive
  +                validated = (digest(credentials).equalsIgnoreCase(password));
  +            }
           } else
               validated = (digest(credentials).equals(password));
           return (validated);
  @@ -1166,20 +1192,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 +1220,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 +1266,7 @@
   
           if (debug >= 2)
               log("  getRoles(" + dn + ")");
  -        
  +
           // Start with roles retrieved from the user entry
           ArrayList list = user.roles;
           if (list == null) {
  @@ -1273,8 +1300,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 +1343,7 @@
               valueString = new String((byte[]) value);
           else
               valueString = value.toString();
  -        
  +
           return valueString;
       }
   
  @@ -1349,7 +1376,7 @@
           while(e.hasMore()) {
               String value = (String)e.next();
               values.add(value);
  -        }                       
  +        }
           return values;
       }
   
  @@ -1422,37 +1449,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 +1501,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 +1561,7 @@
           close(this.context);
   
       }
  -    
  +
   
   }
   
  @@ -1546,9 +1575,9 @@
       String dn = null;
       String password = null;
       ArrayList roles = null;
  -    
   
  -    User(String username, 
  +
  +    User(String username,
                String dn,
                String password,
                ArrayList roles) {
  
  
  

Mime
View raw message