This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new 2e3e6ed  Correct Javadoc and refactor code for clarity
2e3e6ed is described below

commit 2e3e6edfa286f14f011079fd1a5144aec5013e28
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Aug 19 15:56:09 2020 +0100

    Correct Javadoc and refactor code for clarity
    
    Based on a PR by Milo van der Zee
---
 .../realm/MessageDigestCredentialHandler.java      | 57 ++++++++++------------
 webapps/docs/changelog.xml                         |  6 +++
 2 files changed, 31 insertions(+), 32 deletions(-)

diff --git a/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java 
b/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java
index d16bd85..616e0e5 100644
--- a/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java
+++ b/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java
@@ -38,8 +38,9 @@ import 
org.apache.tomcat.util.security.ConcurrentMessageDigest;
  *     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>{SSHA}encodedCredential</b> - 20 byte Base64 encoded SHA1 digest
+ *     followed by variable length salt.
+ *     <pre>{SSHA}&lt;sha-1 digest:20&gt;&lt;salt:n&gt;</pre></li>
  * <li><b>salt$iterationCount$encodedCredential</b> - a hex encoded salt,
  *     iteration code and a hex encoded credential, each separated by $</li>
  * </ul>
@@ -72,8 +73,7 @@ public class MessageDigestCredentialHandler extends 
DigestCredentialHandlerBase
             try {
                 this.encoding = B2CConverter.getCharset(encodingName);
             } catch (UnsupportedEncodingException e) {
-                log.error(sm.getString("mdCredentialHandler.unknownEncoding",
-                        encodingName, encoding.name()));
+                log.error(sm.getString("mdCredentialHandler.unknownEncoding", 
encodingName, encoding.name()));
             }
         }
     }
@@ -94,7 +94,6 @@ public class MessageDigestCredentialHandler extends 
DigestCredentialHandlerBase
 
     @Override
     public boolean matches(String inputCredentials, String storedCredentials) {
-
         if (inputCredentials == null || storedCredentials == null) {
             return false;
         }
@@ -106,33 +105,30 @@ public class MessageDigestCredentialHandler extends 
DigestCredentialHandlerBase
             // Some directories and databases prefix the password with the hash
             // type. The string is in a format compatible with Base64.encode 
not
             // the normal hex encoding of the digest
-            if (storedCredentials.startsWith("{MD5}") ||
-                    storedCredentials.startsWith("{SHA}")) {
+            if (storedCredentials.startsWith("{MD5}") || 
storedCredentials.startsWith("{SHA}")) {
                 // Server is storing digested passwords with a prefix 
indicating
                 // the digest type
-                String serverDigest = storedCredentials.substring(5);
-                String userDigest = 
Base64.encodeBase64String(ConcurrentMessageDigest.digest(
-                        getAlgorithm(), 
inputCredentials.getBytes(StandardCharsets.ISO_8859_1)));
-                return userDigest.equals(serverDigest);
-
+                String base64ServerDigest = storedCredentials.substring(5);
+                byte[] userDigest = ConcurrentMessageDigest.digest(
+                        getAlgorithm(), 
inputCredentials.getBytes(StandardCharsets.ISO_8859_1));
+                String base64UserDigest = 
Base64.encodeBase64String(userDigest);
+                return base64UserDigest.equals(base64ServerDigest);
             } else if (storedCredentials.startsWith("{SSHA}")) {
-                // Server is storing digested passwords with a prefix 
indicating
-                // the digest type and the salt used when creating that digest
-
-                String serverDigestPlusSalt = storedCredentials.substring(6);
-
+                // "{SSHA}<sha-1 digest:20><salt:n>"
                 // Need to convert the salt to bytes to apply it to the user's
                 // digested password.
-                byte[] serverDigestPlusSaltBytes =
-                        Base64.decodeBase64(serverDigestPlusSalt);
-                final int saltPos = 20;
-                byte[] serverDigestBytes = new byte[saltPos];
-                System.arraycopy(serverDigestPlusSaltBytes, 0,
-                        serverDigestBytes, 0, saltPos);
-                final int saltLength = serverDigestPlusSaltBytes.length - 
saltPos;
+                String serverDigestPlusSalt = storedCredentials.substring(6);
+                byte[] serverDigestPlusSaltBytes = 
Base64.decodeBase64(serverDigestPlusSalt);
+
+                // Extract the first 20 bytes containing the SHA-1 digest
+                final int digestLength = 20;
+                byte[] serverDigestBytes = new byte[digestLength];
+                System.arraycopy(serverDigestPlusSaltBytes, 0, 
serverDigestBytes, 0, digestLength);
+
+                // the remaining bytes are the salt
+                final int saltLength = serverDigestPlusSaltBytes.length - 
digestLength;
                 byte[] serverSaltBytes = new byte[saltLength];
-                System.arraycopy(serverDigestPlusSaltBytes, saltPos,
-                        serverSaltBytes, 0, saltLength);
+                System.arraycopy(serverDigestPlusSaltBytes, digestLength, 
serverSaltBytes, 0, saltLength);
 
                 // Generate the digested form of the user provided password
                 // using the salt
@@ -141,10 +137,8 @@ public class MessageDigestCredentialHandler extends 
DigestCredentialHandlerBase
                         serverSaltBytes);
 
                 return Arrays.equals(userDigestBytes, serverDigestBytes);
-
             } else if (storedCredentials.indexOf('$') > -1) {
                 return matchesSaltIterationsEncoded(inputCredentials, 
storedCredentials);
-
             } else {
                 // Hex hashes should be compared case-insensitively
                 String userDigest = mutate(inputCredentials, null, 1);
@@ -164,13 +158,12 @@ public class MessageDigestCredentialHandler extends 
DigestCredentialHandlerBase
         if (algorithm == null) {
             return inputCredentials;
         } else {
+            byte[] inputCredentialbytes = inputCredentials.getBytes(encoding);
             byte[] userDigest;
             if (salt == null) {
-                userDigest = ConcurrentMessageDigest.digest(algorithm, 
iterations,
-                        inputCredentials.getBytes(encoding));
+                userDigest = ConcurrentMessageDigest.digest(algorithm, 
iterations, inputCredentialbytes);
             } else {
-                userDigest = ConcurrentMessageDigest.digest(algorithm, 
iterations,
-                        salt, inputCredentials.getBytes(encoding));
+                userDigest = ConcurrentMessageDigest.digest(algorithm, 
iterations, salt, inputCredentialbytes);
             }
             return HexUtils.toHexString(userDigest);
         }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index af4dfee..1f09bd7 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -82,6 +82,12 @@
         the requested resource. Based on a pull request by Sergey Ponomarev.
         (markt)
       </fix>
+      <fix>
+        Correct the description of the storage format for salted hashes in the
+        Javadoc for <code>MessageDigestCredentialHandler</code> and refactor 
the
+        associated code for clarity.
+        Based on a patch provided by Milo van der Zee. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">


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

Reply via email to