8219861: Add new keytool -showinfo -tls command for displaying TLS configuration information
Reviewed-by: mullan
--- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java Tue Mar 26 01:46:06 2019 -0700
+++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java Thu Apr 04 20:22:16 2019 +0800
@@ -175,6 +175,8 @@
private Set<char[]> passwords = new HashSet<>();
private String startDate = null;
+ private boolean tlsInfo = false;
+
private List<String> ids = new ArrayList<>(); // used in GENCRL
private List<String> v3ext = new ArrayList<>();
@@ -260,6 +262,8 @@
STOREPASSWD("Changes.the.store.password.of.a.keystore",
NEW, KEYSTORE, CACERTS, STOREPASS, STORETYPE, PROVIDERNAME,
ADDPROVIDER, PROVIDERCLASS, PROVIDERPATH, V),
+ SHOWINFO("showinfo.command.help",
+ TLS, V),
// Undocumented start here, KEYCLONE is used a marker in -help;
@@ -365,6 +369,7 @@
STARTDATE("startdate", "<date>", "certificate.validity.start.date.time"),
STOREPASS("storepass", "<arg>", "keystore.password"),
STORETYPE("storetype", "<type>", "keystore.type"),
+ TLS("tls", null, "tls.option.help"),
TRUSTCACERTS("trustcacerts", null, "trust.certificates.from.cacerts"),
V("v", null, "verbose.output"),
VALIDITY("validity", "<days>", "validity.number.of.days");
@@ -678,6 +683,8 @@
protectedPath = true;
} else if (collator.compare(flags, "-srcprotected") == 0) {
srcprotectedPath = true;
+ } else if (collator.compare(flags, "-tls") == 0) {
+ tlsInfo = true;
} else {
System.err.println(rb.getString("Illegal.option.") + flags);
tinyHelp();
@@ -705,7 +712,7 @@
}
boolean isKeyStoreRelated(Command cmd) {
- return cmd != PRINTCERT && cmd != PRINTCERTREQ;
+ return cmd != PRINTCERT && cmd != PRINTCERTREQ && cmd != SHOWINFO;
}
/**
@@ -874,8 +881,7 @@
// Check if keystore exists.
// If no keystore has been specified at the command line, try to use
// the default, which is located in $HOME/.keystore.
- // If the command is "genkey", "identitydb", "import", or "printcert",
- // it is OK not to have a keystore.
+ // No need to check if isKeyStoreRelated(command) is false.
// DO NOT open the existing keystore if this is an in-place import.
// The keystore should be created as brand new.
@@ -889,6 +895,9 @@
}
ksStream = new FileInputStream(ksfile);
} catch (FileNotFoundException e) {
+ // These commands do not need the keystore to be existing.
+ // Either it will create a new one or the keystore is
+ // optional (i.e. PRINTCRL).
if (command != GENKEYPAIR &&
command != GENSECKEY &&
command != IDENTITYDB &&
@@ -1311,6 +1320,8 @@
}
} else if (command == PRINTCRL) {
doPrintCRL(filename, out);
+ } else if (command == SHOWINFO) {
+ doShowInfo();
}
// If we need to save the keystore, do so.
@@ -2707,6 +2718,14 @@
}
}
+ private void doShowInfo() throws Exception {
+ if (tlsInfo) {
+ ShowInfo.tls(verbose);
+ } else {
+ System.out.println(rb.getString("showinfo.no.option"));
+ }
+ }
+
private Collection<? extends Certificate> generateCertificates(InputStream in)
throws CertificateException, IOException {
byte[] data = in.readAllBytes();
--- a/src/java.base/share/classes/sun/security/tools/keytool/Resources.java Tue Mar 26 01:46:06 2019 -0700
+++ b/src/java.base/share/classes/sun/security/tools/keytool/Resources.java Thu Apr 04 20:22:16 2019 +0800
@@ -96,6 +96,8 @@
"Generates a self-signed certificate"}, //-selfcert
{"Changes.the.store.password.of.a.keystore",
"Changes the store password of a keystore"}, //-storepasswd
+ {"showinfo.command.help", "Displays security-related information"},
+
// keytool: help: options
{"alias.name.of.the.entry.to.process",
"alias name of the entry to process"}, //-alias
@@ -141,6 +143,7 @@
"do not prompt"}, //-noprompt
{"password.through.protected.mechanism",
"password through protected mechanism"}, //-protected
+ {"tls.option.help", "Displays TLS configuration information"},
// The following 2 values should span 2 lines, the first for the
// option itself, the second for its -providerArg value.
@@ -472,6 +475,8 @@
{"backup.keystore.warning", "The original keystore \"%1$s\" is backed up as \"%3$s\"..."},
{"importing.keystore.status", "Importing keystore %1$s to %2$s..."},
{"keyalg.option.1.missing.warning", "No -keyalg option. The default key algorithm (%s) is a legacy algorithm and is no longer recommended. In a subsequent release of the JDK, the default will be removed and the -keyalg option must be specified."},
+
+ {"showinfo.no.option", "Missing option for -showinfo. Try \"keytool -showinfo -tls\"."},
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/tools/keytool/ShowInfo.java Thu Apr 04 20:22:16 2019 +0800
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.tools.keytool;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+
+class ShowInfo {
+
+ // verbose is not used yet.
+ static void tls(boolean verbose) throws Exception {
+
+ SSLSocket ssls = (SSLSocket)
+ SSLContext.getDefault().getSocketFactory().createSocket();
+
+ System.out.println("Enabled Protocols");
+ System.out.println("-----------------");
+ for (String s : ssls.getEnabledProtocols()) {
+ System.out.println(s);
+ }
+
+ System.out.println();
+
+ System.out.println("Enabled Cipher Suites");
+ System.out.println("---------------------");
+ for (String s : ssls.getEnabledCipherSuites()) {
+ System.out.println(s);
+ }
+ }
+}