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

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


The following commit(s) were added to refs/heads/8.5.x by this push:
     new 85da6cda04 Allow digest.sh to accept password from a file or from stdin
85da6cda04 is described below

commit 85da6cda0404b6f50c56fd16c694799b8e80a3db
Author: Christopher Schultz <ch...@christopherschultz.net>
AuthorDate: Mon Mar 11 10:42:57 2024 -0400

    Allow digest.sh to accept password from a file or from stdin
    
    This fixes https://bz.apache.org/bugzilla/show_bug.cgi?id=57130
---
 java/org/apache/catalina/realm/RealmBase.java | 73 ++++++++++++++++++++++++---
 webapps/docs/changelog.xml                    |  4 ++
 webapps/docs/realm-howto.xml                  |  5 +-
 3 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/java/org/apache/catalina/realm/RealmBase.java 
b/java/org/apache/catalina/realm/RealmBase.java
index afd195d021..c2cace463d 100644
--- a/java/org/apache/catalina/realm/RealmBase.java
+++ b/java/org/apache/catalina/realm/RealmBase.java
@@ -30,6 +30,10 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.io.File;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.InputStreamReader;
 
 import javax.servlet.annotation.ServletSecurity.TransportGuarantee;
 import javax.servlet.http.HttpServletResponse;
@@ -1368,6 +1372,9 @@ public abstract class RealmBase extends 
LifecycleMBeanBase implements org.apache
      * specified, the default for the CredentialHandler will be used.</li>
      * <li><b>-h</b> - The fully qualified class name of the CredentialHandler 
to use. If not specified, the built-in
      * handlers will be tested in turn and the first one to accept the 
specified algorithm will be used.</li>
+     * <li><b>-f</b> - The name of the file that contains passwords to encode. 
Each
+     *                 line in the file should contain only one password. 
Using this
+     *                 option ignores other password input.</li>
      * </ul>
      * <p>
      * This generation process currently supports the following 
CredentialHandlers, the correct one being selected based
@@ -1380,7 +1387,7 @@ public abstract class RealmBase extends 
LifecycleMBeanBase implements org.apache
      *
      * @param args The parameters passed on the command line
      */
-    public static void main(String args[]) {
+    public static void main(String args[]) throws IOException {
 
         // Use negative values since null is not an option to indicate 'not 
set'
         int saltLength = -1;
@@ -1392,6 +1399,8 @@ public abstract class RealmBase extends 
LifecycleMBeanBase implements org.apache
         // the command line
         String algorithm = null;
         String handlerClassName = null;
+        // File name to read password(s) from
+        String passwordFile = null;
 
         if (args.length == 0) {
             usage();
@@ -1399,8 +1408,12 @@ public abstract class RealmBase extends 
LifecycleMBeanBase implements org.apache
         }
 
         int argIndex = 0;
+        // Boolean to check and see if we've reached the -- option
+        boolean endOfList = false;
 
-        while (args.length > argIndex + 2 && args[argIndex].length() == 2 && 
args[argIndex].charAt(0) == '-') {
+        // Note: Reducing args.length requirement to argIndex+1 so that -f 
works and ignores
+        // trailing words
+        while (args.length > argIndex + 1 && args[argIndex].length() == 2 && 
args[argIndex].charAt(0) == '-' && !endOfList) {
             switch (args[argIndex].charAt(1)) {
                 case 'a': {
                     algorithm = args[argIndex + 1];
@@ -1426,6 +1439,18 @@ public abstract class RealmBase extends 
LifecycleMBeanBase implements org.apache
                     handlerClassName = args[argIndex + 1];
                     break;
                 }
+                case 'f': {
+                    passwordFile = args[argIndex + 1];
+                    break;
+                }
+                case '-': {
+                    // When encountering --  option don't parse anything else 
as an option
+                    endOfList = true;
+                    // The -- opt doesn't take an argument, decrement the 
argIndex so that it parses
+                    // all remaining args
+                    argIndex--;
+                    break;
+                }
                 default: {
                     usage();
                     return;
@@ -1485,18 +1510,52 @@ public abstract class RealmBase extends 
LifecycleMBeanBase implements org.apache
         if (keyLength > 0) {
             IntrospectionUtils.setProperty(handler, "keyLength", 
Integer.toString(keyLength));
         }
+        if (passwordFile != null) {
+            // If the file name is used, then don't parse the trailing 
arguments
+            argIndex = args.length;
+
+            try {
+                BufferedReader br;
+                // Special case, allow for - filename to refer to stdin
+                if (passwordFile.equals("-")) {
+                    br = new BufferedReader(new InputStreamReader(System.in));
+                } else {
+                    br = new BufferedReader(new FileReader(passwordFile));
+                }
 
+                String line;
+                while ((line = br.readLine()) != null) {
+                    // Mutate each line in the file, or stdin
+                    mutateCredential(line, handler);
+                }
+            } catch (Exception e) {
+                // A FileNotFound is the likely exception here and 
self-explanatory. Softly
+                // reporting it and exit 1 so that you can tell it failed from 
the command line.
+                if (e instanceof java.io.FileNotFoundException) {
+                    System.err.println("cannot stat '" + passwordFile +
+                            "': No such file or directory");
+                    // Not sure if using an exit here is OK, but I wanted to 
return a code that
+                    // showed failure.
+                    System.exit(1);
+                } else {
+                    throw e;
+                }
+            }
+        }
         for (; argIndex < args.length; argIndex++) {
-            String credential = args[argIndex];
-            System.out.print(credential + ":");
-            System.out.println(handler.mutate(credential));
+            mutateCredential(args[argIndex], handler);
         }
     }
 
+    private static void mutateCredential(String credential, CredentialHandler 
handler) {
+        System.out.print(credential + ":");
+        System.out.println(handler.mutate(credential));
+    }
 
     private static void usage() {
-        System.out.println("Usage: RealmBase [-a <algorithm>] [-e <encoding>] 
" +
-                "[-i <iterations>] [-s <salt-length>] [-k <key-length>] " + 
"[-h <handler-class-name>] <credentials>");
+        System.out.println("Usage: RealmBase [-a <algorithm>] [-e <encoding>]"
+              + " [-i <iterations>] [-s <salt-length>] [-k <key-length>]"
+              + " [-h <handler-class-name>] | <XX credentials>");
     }
 
 
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index f5ca224806..a6609e9efe 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -165,6 +165,10 @@
       <add>
         Improvements to Japanese translations by tak7iji. (markt)
       </add>
+      <fix>
+        <bug>57130</bug>: Allow digest.(sh|bat) to accept password from a file
+        or stdin. (csutherl/schultz)
+      </fix>
     </changelog>
   </subsection>
 </section>
diff --git a/webapps/docs/realm-howto.xml b/webapps/docs/realm-howto.xml
index 0bcc140770..ed442aea1b 100644
--- a/webapps/docs/realm-howto.xml
+++ b/webapps/docs/realm-howto.xml
@@ -226,7 +226,7 @@ simplified to <code>{digest}</code>.</p>
 <p>The full syntax of <code>CATALINA_HOME/bin/digest.[bat|sh]</code> is:</p>
 <source>CATALINA_HOME/bin/digest.[bat|sh] [-a &lt;algorithm&gt;] [-e 
&lt;encoding&gt;]
         [-i &lt;iterations&gt;] [-s &lt;salt-length&gt;] [-k 
&lt;key-length&gt;]
-        [-h &lt;handler-class-name&gt;] &lt;credentials&gt;
+        [-h &lt;handler-class-name&gt;] [-f &lt;password-file&gt; | 
&lt;credentials&gt;]
 </source>
 <ul>
 <li><b>-a</b> - The algorithm to use to generate the stored
@@ -251,6 +251,9 @@ simplified to <code>{digest}</code>.</p>
                 tested in turn (MessageDigestCredentialHandler then
                 SecretKeyCredentialHandler) and the first one to accept the
                 specified algorithm will be used.</li>
+<li><b>-f</b> - The name of the file that contains passwords to encode. Each
+                line in the file should contain only one password. Using this
+                option ignores other password input.</li>
 </ul>
 </subsection>
 


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

Reply via email to