Dear Wiki user, You have subscribed to a wiki page or wiki category on "Tomcat Wiki" for change notification.
The "tools/SSLTest.java" page has been changed by ChristopherSchultz: https://wiki.apache.org/tomcat/tools/SSLTest.java New page: {{{ /* * SSLTest.java * * Tests servers for SSL/TLS protocol and cipher support. * * Copyright (c) 2015 Christopher Schultz * * Christopher Schultz licenses this file to You under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketTimeoutException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; /** * A driver class to test a server's SSL/TLS support. * * Usage: java SSLTest [opts] host[:port] * * Try "java SSLTest -h" for help. * * This tester will attempts to handshake with the target host with all * available protocols and ciphers and report which ones were accepted and * which were rejected. An HTTP connection is never fully made, so these * connections should not flood the host's access log with entries. * * @author Christopher Schultz */ public class SSLTest { public static void usage() { System.out.println("Usage: java " + SSLTest.class + " [opts] host[:port]"); System.out.println(); System.out.println("-sslprotocol Sets the SSL/TLS protocol to be used (e.g. SSL, TLS, SSLv3, TLSv1.2, etc.)"); System.out.println("-enabledprotocols protocols Sets individual SSL/TLS ptotocols that should be enabled"); System.out.println("-ciphers cipherspec A comma-separated list of SSL/TLS ciphers"); System.out.println("-truststore Sets the trust store for connections"); System.out.println("-truststoretype type Sets the type for the trust store"); System.out.println("-truststorepassword pass Sets the password for the trust store"); System.out.println("-truststorealgorithm alg Sets the algorithm for the trust store"); System.out.println("-truststoreprovider provider Sets the crypto provider for the trust store"); System.out.println("-no-check-certificate Ignores certificate errors"); System.out.println("-no-verify-hostname Ignores hostname mismatches"); System.out.println("-h -help --help Shows this help message"); } public static void main(String[] args) throws Exception { int connectTimeout = 0; // default = infinite int readTimeout = 1000; boolean disableHostnameVerification = true; boolean disableCertificateChecking = true; String trustStoreFilename = System.getProperty("javax.net.ssl.trustStore"); String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword"); String trustStoreType = System.getProperty("javax.net.ssl.trustStoreType"); String trustStoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider"); String trustStoreAlgorithm = null; String sslProtocol = "TLS"; String[] sslEnabledProtocols = new String[] { "SSLv2", "SSLv2hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" }; String[] sslCipherSuites = null; // Default = default for protocol String crlFilename = null; boolean showCerts = false; if(args.length < 1) { usage(); System.exit(0); } int argIndex; for(argIndex = 0; argIndex < args.length; ++argIndex) { String arg = args[argIndex]; if(!arg.startsWith("-")) break; else if("--".equals(arg)) break; else if("-no-check-certificate".equals(arg)) disableCertificateChecking = true; else if("-no-verify-hostname".equals(arg)) disableHostnameVerification = true; else if("-sslprotocol".equals(arg)) sslProtocol = args[++argIndex]; else if("-enabledprotocols".equals(arg)) sslEnabledProtocols = args[++argIndex].split("\\s*,\\s*"); else if("-ciphers".equals(arg)) sslCipherSuites = args[++argIndex].split("\\s*,\\s*"); else if("-connecttimeout".equals(arg)) connectTimeout = Integer.parseInt(args[++argIndex]); else if("-readtimeout".equals(arg)) readTimeout = Integer.parseInt(args[++argIndex]); else if("-truststore".equals(arg)) trustStoreFilename = args[++argIndex]; else if("-truststoretype".equals(arg)) trustStoreType = args[++argIndex]; else if("-truststorepassword".equals(arg)) trustStorePassword = args[++argIndex]; else if("-truststoreprovider".equals(arg)) trustStoreProvider = args[++argIndex]; else if("-truststorealgorithm".equals(arg)) trustStoreAlgorithm = args[++argIndex]; else if("-showcerts".equals(arg)) showCerts = true; else if("--help".equals(arg) || "-h".equals(arg) || "-help".equals(arg)) { usage(); System.exit(0); } else { System.err.println("Unrecognized option: " + arg); System.exit(1); } } if(argIndex >= args.length) { System.err.println("Unexpected additional arguments: " + java.util.Arrays.asList(args).subList(argIndex, args.length)); usage(); System.exit(1); } if(disableHostnameVerification) SSLUtils.disableSSLHostnameVerification(); TrustManager[] trustManagers; if(disableCertificateChecking || "true".equalsIgnoreCase(System.getProperty("disable.ssl.cert.checks"))) { trustManagers = SSLUtils.getTrustAllCertsTrustManagers(); } else if(null != trustStoreFilename) { if(null == trustStoreType) trustStoreType = "JKS"; trustManagers = SSLUtils.getTrustManagers(trustStoreFilename, trustStorePassword, trustStoreType, trustStoreProvider, trustStoreAlgorithm, null, crlFilename); } else trustManagers = null; int port = 443; String host = args[argIndex]; int pos = host.indexOf(':'); if(pos > 0) { port = Integer.parseInt(host.substring(pos + 1)); host = host.substring(0, pos); } System.out.println("Testing server " + host + ":" + port); SecureRandom rand = new SecureRandom(); String reportFormat = "%9s %8s %s\n"; System.out.print(String.format(reportFormat, "Supported", "Protocol", "Cipher")); InetSocketAddress address = new InetSocketAddress(host, port); ArrayList<String> supportedProtocols = new ArrayList<String>(Arrays.asList(sslEnabledProtocols)); for(String protocol : sslEnabledProtocols) { SSLContext sc; try { sc = SSLContext.getInstance(protocol); } catch (NoSuchAlgorithmException nsae) { System.out.print(String.format(reportFormat, "-----", protocol, " Not supported by client")); supportedProtocols.remove(protocol); continue; } catch (Exception e) { e.printStackTrace(); continue; // Skip this protocol } sc.init(null, null, rand); // Restrict cipher suites to those specified by sslCipherSuites HashSet<String> cipherSuites = new HashSet<String>(); cipherSuites.addAll(Arrays.asList(sc.getSocketFactory().getSupportedCipherSuites())); if(null != sslCipherSuites) cipherSuites.retainAll(Arrays.asList(sslCipherSuites)); if(cipherSuites.isEmpty()) { System.err.println("No overlapping cipher suites found for protocol " + protocol); supportedProtocols.remove(protocol); continue; // Go to the next protocol } for(String cipherSuite : cipherSuites) { String status; SSLSocketFactory sf = SSLUtils.getSSLSocketFactory(protocol, new String[] { protocol }, new String[] { cipherSuite }, rand, trustManagers); Socket sock = null; try { // // Note: SSLSocketFactory has several create() methods. // Those that take arguments all connect immediately // and have no options for specifying a connection timeout. // // So, we have to create a socket and connect it (with a // connection timeout), then have the SSLSocketFactory wrap // the already-connected socket. // sock = new Socket(); sock.setSoTimeout(readTimeout); sock.connect(address, connectTimeout); // Wrap plain socket in an SSL socket SSLSocket socket = (SSLSocket)sf.createSocket(sock, host, port, true); socket.startHandshake(); assert protocol.equals(socket.getSession().getProtocol()); assert cipherSuite.equals(socket.getSession().getCipherSuite()); status = "Accepted"; } catch (SocketTimeoutException ste) { status = "Failed"; } catch (IOException ioe) { // System.out.println(ioe); status = "Rejected"; } catch (Exception e) { System.out.print(e.getMessage()); status = "Rejected"; } finally { if(null != sock) try { sock.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } System.out.print(String.format(reportFormat, status, protocol, cipherSuite)); } } if(supportedProtocols.isEmpty()) { System.err.println("No protocols "); } // Now get generic and allow the server to decide on the protocol and cipher suite String[] protocolsToTry = supportedProtocols.toArray(new String[supportedProtocols.size()]); SSLSocketFactory sf = SSLUtils.getSSLSocketFactory(sslProtocol, protocolsToTry, sslCipherSuites, rand, trustManagers); Socket sock = null; try { // // Note: SSLSocketFactory has several create() methods. // Those that take arguments all connect immediately // and have no options for specifying a connection timeout. // // So, we have to create a socket and connect it (with a // connection timeout), then have the SSLSocketFactory wrap // the already-connected socket. // sock = new Socket(); sock.connect(address, connectTimeout); sock.setSoTimeout(readTimeout); // Wrap plain socket in an SSL socket SSLSocket socket = (SSLSocket)sf.createSocket(sock, host, port, true); socket.startHandshake(); System.out.print("Given this client's capabilities (" + supportedProtocols + "), the server prefers protocol="); System.out.print(socket.getSession().getProtocol()); System.out.print(", cipher="); System.out.println(socket.getSession().getCipherSuite()); if(showCerts) { for(Certificate cert : socket.getSession().getPeerCertificates()) { System.out.println("Certificate: " + cert.getType()); if("X.509".equals(cert.getType())) { X509Certificate x509 = (X509Certificate)cert; System.out.println("Subject: " + x509.getSubjectDN()); System.out.println("Issuer: " + x509.getIssuerDN()); System.out.println("Serial: " + x509.getSerialNumber()); // System.out.println("Signature: " + toHexString(x509.getSignature())); // System.out.println("cert bytes: " + toHexString(cert.getEncoded())); // System.out.println("cert bytes: " + cert.getPublicKey()); } else { System.out.println("Unknown certificate type (" + cert.getType() + "): " + cert); } } } } finally { if (null != sock) try { sock.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } } static final char[] hexChars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f' }; static String toHexString(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for(byte b : bytes) sb.append(hexChars[(b >> 4) & 0x0f]) .append(hexChars[b & 0x0f]); return sb.toString(); } } }}} --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org