--- orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/DataSourceRealm.java 2011-08-16 07:26:14.000000000 -0500 +++ orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/DataSourceRealm.java 2011-10-05 11:51:11.000000000 -0500 @@ -33,6 +33,7 @@ import org.apache.catalina.LifecycleException; import org.apache.catalina.ServerFactory; import org.apache.catalina.core.StandardServer; +import org.apache.catalina.util.HexUtils; import org.apache.catalina.util.StringManager; /** @@ -340,10 +341,13 @@ // Validate the user's credentials boolean validated = false; if (hasMessageDigest()) { - // Hex hashes should be compared case-insensitive - validated = (digest(credentials).equalsIgnoreCase(dbCredentials)); + byte salt[] = null; + if (digest.equals("ssha")) { + salt = HexUtils.convert(dbCredentials.substring(dbCredentials.length()-8)); // salt is last 4 bytes = 8 characters + } + validated = dbCredentials.equalsIgnoreCase(digest(credentials,salt)); } else - validated = (digest(credentials).equals(dbCredentials)); + validated = (digest(credentials,null).equals(dbCredentials)); if (validated) { if (containerLog.isTraceEnabled()) --- orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/JAASCallbackHandler.java 2011-08-16 07:26:14.000000000 -0500 +++ orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/JAASCallbackHandler.java 2011-10-05 11:47:39.000000000 -0500 @@ -69,7 +69,7 @@ this.username = username; if (realm.hasMessageDigest()) { - this.password = realm.digest(password); + this.password = realm.digest(password,null); } else { this.password = password; --- orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/JDBCRealm.java 2011-08-16 07:26:14.000000000 -0500 +++ orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/JDBCRealm.java 2011-10-05 11:51:23.000000000 -0500 @@ -29,6 +29,7 @@ import java.util.Properties; import org.apache.catalina.LifecycleException; +import org.apache.catalina.util.HexUtils; import org.apache.catalina.util.StringManager; @@ -416,10 +417,13 @@ // Validate the user's credentials boolean validated = false; if (hasMessageDigest()) { - // Hex hashes should be compared case-insensitive - validated = (digest(credentials).equalsIgnoreCase(dbCredentials)); + byte[] salt = null; + if (digest.equals("ssha")) { + salt = HexUtils.convert(dbCredentials.substring(dbCredentials.length()-8)); // salt is last 4 bytes = 8 characters + } + validated = dbCredentials.equalsIgnoreCase(digest(credentials,salt)); } else { - validated = (digest(credentials).equals(dbCredentials)); + validated = (digest(credentials,null).equals(dbCredentials)); } if (validated) { --- orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/JNDIRealm.java 2011-08-16 07:26:14.000000000 -0500 +++ orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/JNDIRealm.java 2011-10-05 11:46:05.000000000 -0500 @@ -1520,10 +1520,10 @@ } // End synchronized(this) block } else { // Hex hashes should be compared case-insensitive - validated = (digest(credentials).equalsIgnoreCase(password)); + validated = (digest(credentials,null).equalsIgnoreCase(password)); } } else - validated = (digest(credentials).equals(password)); + validated = (digest(credentials,null).equals(password)); return (validated); } --- orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/MemoryRealm.java 2011-08-16 07:26:14.000000000 -0500 +++ orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/MemoryRealm.java 2011-10-05 11:51:03.000000000 -0500 @@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.Map; import org.apache.catalina.LifecycleException; +import org.apache.catalina.util.HexUtils; import org.apache.catalina.util.StringManager; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; @@ -150,12 +151,16 @@ boolean validated = false; if (principal != null && credentials != null) { if (hasMessageDigest()) { + String serverCredentials = principal.getPassword(); + byte[] salt = null; + if (digest.equals("ssha")) { + salt = HexUtils.convert(serverCredentials.substring(serverCredentials.length()-8)); // salt is last 4 bytes = 8 characters + } + validated = serverCredentials.equalsIgnoreCase(digest(credentials,salt)); // Hex hashes should be compared case-insensitive - validated = (digest(credentials) - .equalsIgnoreCase(principal.getPassword())); } else { validated = - (digest(credentials).equals(principal.getPassword())); + (digest(credentials,null).equals(principal.getPassword())); } } --- orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/RealmBase.java 2011-08-16 07:26:14.000000000 -0500 +++ orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/RealmBase.java 2011-10-05 13:16:40.000000000 -0500 @@ -28,6 +28,7 @@ import java.security.Principal; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Random; import javax.management.Attribute; import javax.management.MBeanRegistration; @@ -311,7 +312,11 @@ if ( serverCredentials == null ) { validated = false; } else if(hasMessageDigest()) { - validated = serverCredentials.equalsIgnoreCase(digest(credentials)); + byte[] salt = null; + if (digest.equals("ssha")) { + salt = HexUtils.convert(serverCredentials.substring(serverCredentials.length()-8)); // salt is last 4 bytes = 8 characters + } + validated = serverCredentials.equalsIgnoreCase(digest(credentials,salt)); } else { validated = serverCredentials.equals(credentials); } @@ -1052,7 +1057,7 @@ // Create a MessageDigest instance for credentials, if desired if (digest != null) { try { - md = MessageDigest.getInstance(digest); + md = MessageDigest.getInstance(digest.equals("ssha") ? "sha1" : digest); } catch (NoSuchAlgorithmException e) { throw new LifecycleException (sm.getString("realmBase.algorithm", digest), e); @@ -1107,16 +1112,29 @@ // ------------------------------------------------------ Protected Methods + /** + * Digest the password using the specified algorithm and + * convert the result to a corresponding hexadecimal string. + * If exception, the plain credentials string is returned. + * + * @param credentials Password or other credentials to use in + * authenticating this username + */ + protected String digest(String credentials) { + return digest(credentials,null); + } /** * Digest the password using the specified algorithm and * convert the result to a corresponding hexadecimal string. * If exception, the plain credentials string is returned. + * If salt is not-null, the message digest is updated with + * that salt and it is appended to the string * * @param credentials Password or other credentials to use in * authenticating this username */ - protected String digest(String credentials) { + protected String digest(String credentials,byte[] salt) { // If no MessageDigest instance is specified, return unchanged if (hasMessageDigest() == false) @@ -1139,6 +1157,10 @@ } } md.update(bytes); + if (salt != null) { + md.update(salt); + return (HexUtils.convert(md.digest())) + HexUtils.convert(salt); + } return (HexUtils.convert(md.digest())); } catch (Exception e) { @@ -1242,7 +1264,7 @@ try { // Obtain a new message digest with "digest" encryption MessageDigest md = - (MessageDigest) MessageDigest.getInstance(algorithm).clone(); + (MessageDigest) MessageDigest.getInstance(algorithm.equals("ssha") ? "sha1" : algorithm).clone(); // encode the credentials // Should use the digestEncoding, but that's not a static field @@ -1251,9 +1273,19 @@ } else { md.update(credentials.getBytes(encoding)); } + if (algorithm.equals("ssha")) { + Random r = new Random(); + byte[] salt = new byte[4]; + for(int i = 0; i < salt.length; i++) { + salt[i] = (byte)r.nextInt(256); + } - // Digest the credentials and return as hexadecimal - return (HexUtils.convert(md.digest())); + md.update(salt); + return (HexUtils.convert(md.digest())) + HexUtils.convert(salt); + } else { + // Digest the credentials and return as hexadecimal + return (HexUtils.convert(md.digest())); + } } catch(Exception ex) { log.error(ex); return credentials;