This is an automated email from the ASF dual-hosted git repository.
schultz 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 b7b89e16a9 Allow digest.sh to accept password from a file or from stdin
b7b89e16a9 is described below
commit b7b89e16a90d1dd9b9c867fed36ef4cfb868832b
Author: Christopher Schultz <[email protected]>
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 afc60b25a9..a81bd63e7a 100644
--- a/java/org/apache/catalina/realm/RealmBase.java
+++ b/java/org/apache/catalina/realm/RealmBase.java
@@ -29,6 +29,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;
@@ -1317,6 +1321,9 @@ public abstract class RealmBase extends
LifecycleMBeanBase implements Realm {
* 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
@@ -1329,7 +1336,7 @@ public abstract class RealmBase extends
LifecycleMBeanBase implements Realm {
*
* @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;
@@ -1341,6 +1348,8 @@ public abstract class RealmBase extends
LifecycleMBeanBase implements Realm {
// the command line
String algorithm = null;
String handlerClassName = null;
+ // File name to read password(s) from
+ String passwordFile = null;
if (args.length == 0) {
usage();
@@ -1348,8 +1357,12 @@ public abstract class RealmBase extends
LifecycleMBeanBase implements Realm {
}
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];
@@ -1375,6 +1388,18 @@ public abstract class RealmBase extends
LifecycleMBeanBase implements Realm {
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;
@@ -1434,18 +1459,52 @@ public abstract class RealmBase extends
LifecycleMBeanBase implements Realm {
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 d8842e1476..f4c5e63ea5 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -193,6 +193,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 11c9960349..04d91d5897 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 <algorithm>] [-e
<encoding>]
[-i <iterations>] [-s <salt-length>] [-k
<key-length>]
- [-h <handler-class-name>] <credentials>
+ [-h <handler-class-name>] [-f <password-file> |
<credentials>]
</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: [email protected]
For additional commands, e-mail: [email protected]