You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2014/09/25 21:32:18 UTC

svn commit: r1627597 - in /tomcat/trunk/java/org/apache/catalina: CredentialHandler.java realm/MessageDigestCredentialHandler.java

Author: markt
Date: Thu Sep 25 19:32:18 2014
New Revision: 1627597

URL: http://svn.apache.org/r1627597
Log:
Add support for the salt$iter$pwd format

Modified:
    tomcat/trunk/java/org/apache/catalina/CredentialHandler.java
    tomcat/trunk/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java

Modified: tomcat/trunk/java/org/apache/catalina/CredentialHandler.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/CredentialHandler.java?rev=1627597&r1=1627596&r2=1627597&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/CredentialHandler.java (original)
+++ tomcat/trunk/java/org/apache/catalina/CredentialHandler.java Thu Sep 25 19:32:18 2014
@@ -20,5 +20,5 @@ public interface CredentialHandler {
 
     boolean matches(String inputCredentials, String storedCredentials);
 
-    String mutate(String inputCredentials);
+    String mutate(String inputCredentials, byte[] salt, int iterations);
 }

Modified: tomcat/trunk/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java?rev=1627597&r1=1627596&r2=1627597&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java (original)
+++ tomcat/trunk/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java Thu Sep 25 19:32:18 2014
@@ -32,6 +32,28 @@ import org.apache.tomcat.util.codec.bina
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.tomcat.util.security.ConcurrentMessageDigest;
 
+/**
+ * This credential handler supports the following forms of stored passwords:
+ * <ul>
+ * <li><b>encodedCredential</b> - a hex encoded digest of the password digested
+ *     using the configured digest</li>
+ * <li><b>{MD5}encodedCredential</b> - a Base64 encoded MD5 digest of the
+ *     password</li>
+ * <li><b>{SHA}encodedCredential</b> - a Base64 encoded SHA1 digest of the
+ *     password</li>
+ * <li><b>{SSHA}encodedCredential</b> - 20 character salt followed by the salted
+ *     SHA1 digest Base64 encoded</li>
+ * <li><b>salt$iterationCount$encodedCredential</b> - a hex encoded salt,
+ *     iteration code and a hex encoded credential, each separated by $</li>
+ * </ul>
+ *
+ * Prefixes of {MD5} and {SHA}
+ * <p>
+ * If the stored password form does not included an iteration count then an
+ * iteration count of 1 is used.
+ * <p>
+ * If the stored password form does not include salt then no salt is used.
+ */
 public class MessageDigestCredentialHandler implements CredentialHandler {
 
     private static final Log log = LogFactory.getLog(MessageDigestCredentialHandler.class);
@@ -126,9 +148,20 @@ public class MessageDigestCredentialHand
 
                 return Arrays.equals(userDigestBytes, serverDigestBytes);
 
+            } else if (storedCredentials.indexOf('$') > -1) {
+                int sep1 = storedCredentials.indexOf('$');
+                int sep2 = storedCredentials.indexOf('$', sep1);
+                String hexSalt = storedCredentials.substring(0,  sep1);
+                int iterations = Integer.parseInt(storedCredentials.substring(sep1 + 1, sep2));
+                String hexEncoded = storedCredentials.substring(sep2 + 1);
+                byte[] salt = HexUtils.fromHexString(hexSalt);
+
+                String userDigest = mutate(inputCredentials, salt, iterations);
+
+                return hexEncoded.equalsIgnoreCase(userDigest);
             } else {
                 // Hex hashes should be compared case-insensitively
-                String userDigest = mutate(inputCredentials);
+                String userDigest = mutate(inputCredentials, null, 1);
                 return storedCredentials.equalsIgnoreCase(userDigest);
             }
         }
@@ -136,12 +169,19 @@ public class MessageDigestCredentialHand
 
 
     @Override
-    public String mutate(String inputCredentials) {
+    public String mutate(String inputCredentials, byte[] salt, int iterations) {
         if (digest == null) {
             return inputCredentials;
         } else {
-            return HexUtils.toHexString(ConcurrentMessageDigest.digest(digest,
-                    inputCredentials.getBytes(encoding)));
+            byte[] userDigest;
+            if (salt == null) {
+                userDigest = ConcurrentMessageDigest.digest(digest, iterations,
+                        inputCredentials.getBytes(encoding));
+            } else {
+                userDigest = ConcurrentMessageDigest.digest(digest, iterations,
+                        salt, inputCredentials.getBytes(encoding));
+            }
+            return HexUtils.toHexString(userDigest);
         }
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org