Dear Wiki user, You have subscribed to a wiki page or wiki category on "Tomcat Wiki" for change notification.
The "tools/SSLUtils.java" page has been changed by ChristopherSchultz: https://wiki.apache.org/tomcat/tools/SSLUtils.java New page: /* * SSLUtils.java * * Contains useful SSL/TLS methods. * * 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.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.security.InvalidAlgorithmParameterException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.cert.CRL; import java.security.cert.CRLException; import java.security.cert.CertPathParameters; import java.security.cert.CertStore; import java.security.cert.CertStoreParameters; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.PKIXBuilderParameters; import java.security.cert.X509CertSelector; import java.security.cert.X509Certificate; import java.util.Collection; import javax.net.ssl.CertPathTrustManagerParameters; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.ManagerFactoryParameters; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; /** * Lots of useful SSL-related goodies. * * @author Christopher Schultz * @author Apache Software Foundation (some code adapted/lifted from Apache Tomcat). */ public class SSLUtils { public static void disableSSLHostnameVerification() { HostnameVerifier verifyEverything = new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }; HttpsURLConnection.setDefaultHostnameVerifier(verifyEverything); } private static final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { // Trust all clients } public void checkServerTrusted(X509Certificate[] certs, String authType) { // Trust all servers } } }; public static TrustManager[] getTrustAllCertsTrustManagers() { return trustAllCerts.clone(); } /** * Configures SSLSocketFactory for Java's HttpsURLConnection. */ public static void configureHttpsURLConnection(String protocol, String[] sslEnabledProtocols, String[] sslCipherSuites, SecureRandom random, TrustManager[] tms) throws NoSuchAlgorithmException, KeyManagementException { HttpsURLConnection.setDefaultSSLSocketFactory(getSSLSocketFactory(protocol, sslEnabledProtocols, sslCipherSuites, random, tms)); } /** * Creates an SSLSocketFactory that supports only the specified protocols * and ciphers. */ public static SSLSocketFactory getSSLSocketFactory(String protocol, String[] sslEnabledProtocols, String[] sslCipherSuites, SecureRandom random, TrustManager[] tms) throws NoSuchAlgorithmException, KeyManagementException { SSLContext sc = SSLContext.getInstance(protocol); // System.out.println("Wanted protocol: " + protocol); // System.out.println("Got protocol: " + sc.getProtocol()); sc.init(null, tms, random); SSLSocketFactory sf = sc.getSocketFactory(); if(null != sslEnabledProtocols || null != sslCipherSuites) sf = new CustomSSLSocketFactory(sf, sslEnabledProtocols, sslCipherSuites); return sf; } /** * In order to customize the specific enabled protocols and cipher suites, * a customized SSLSocketFactory must be used. * * This is just a wrapper around that customization. */ public static class CustomSSLSocketFactory extends javax.net.ssl.SSLSocketFactory { private final String[] _sslEnabledProtocols; private final String[] _sslCipherSuites; private final SSLSocketFactory _base; public CustomSSLSocketFactory(SSLSocketFactory base, String[] sslEnabledProtocols, String[] sslCipherSuites) { _base = base; if(null == sslEnabledProtocols) _sslEnabledProtocols = null; else _sslEnabledProtocols = sslEnabledProtocols.clone(); if(null == sslCipherSuites || 0 == sslCipherSuites.length) _sslCipherSuites = getDefaultCipherSuites(); else if(1 == sslCipherSuites.length && "ALL".equalsIgnoreCase(sslCipherSuites[0])) _sslCipherSuites = getSupportedCipherSuites(); else _sslCipherSuites = sslCipherSuites.clone(); } public String[] getDefaultCipherSuites() { return _base.getDefaultCipherSuites(); } public String[] getSupportedCipherSuites() { return _base.getSupportedCipherSuites(); } private SSLSocket customize(Socket s) { SSLSocket socket = (SSLSocket)s; if(null != _sslEnabledProtocols) socket.setEnabledProtocols(_sslEnabledProtocols); socket.setEnabledCipherSuites(_sslCipherSuites); return socket; } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return customize(_base.createSocket(s, host, port, autoClose)); } @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { return customize(_base.createSocket(host, port)); } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return customize(_base.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { return customize(_base.createSocket(host, port, localHost, localPort)); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return customize(_base.createSocket(address, port, localAddress, localPort)); } } /** * In order to customize the specific enabled protocols and cipher suites, * a customized SSLSocketFactory must be used. * * This is just a wrapper around that customization. */ public static class CustomSSLServerSocketFactory extends javax.net.ssl.SSLServerSocketFactory { private final String[] _sslEnabledProtocols; private final String[] _sslCipherSuites; private final SSLServerSocketFactory _base; public CustomSSLServerSocketFactory(SSLServerSocketFactory base, String[] sslEnabledProtocols, String[] sslCipherSuites) { _base = base; if(null == sslEnabledProtocols) _sslEnabledProtocols = null; else _sslEnabledProtocols = sslEnabledProtocols.clone(); if(null == sslCipherSuites || 0 == sslCipherSuites.length) _sslCipherSuites = getDefaultCipherSuites(); else if(1 == sslCipherSuites.length && "ALL".equalsIgnoreCase(sslCipherSuites[0])) _sslCipherSuites = getSupportedCipherSuites(); else _sslCipherSuites = sslCipherSuites.clone(); } public String[] getDefaultCipherSuites() { return _base.getDefaultCipherSuites(); } public String[] getSupportedCipherSuites() { return _base.getSupportedCipherSuites(); } private SSLServerSocket customize(ServerSocket s) { SSLServerSocket socket = (SSLServerSocket)s; if(null != _sslEnabledProtocols) socket.setEnabledProtocols(_sslEnabledProtocols); socket.setEnabledCipherSuites(_sslCipherSuites); return socket; } @Override public SSLServerSocket createServerSocket() throws IOException { return customize(_base.createServerSocket()); } @Override public SSLServerSocket createServerSocket(int port) throws IOException { return customize(_base.createServerSocket(port)); } @Override public SSLServerSocket createServerSocket(int port, int backlog) throws IOException { return customize(_base.createServerSocket(port, backlog)); } @Override public SSLServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException { return customize(_base.createServerSocket(port, backlog, ifAddress)); } } /** * Creates an SSLSocketFactory that supports only the specified protocols * and ciphers. */ public static SSLServerSocketFactory getSSLServerSocketFactory(String protocol, String[] sslEnabledProtocols, String[] sslCipherSuites, SecureRandom random, TrustManager[] tms) throws NoSuchAlgorithmException, KeyManagementException { SSLContext sc = SSLContext.getInstance(protocol); // System.out.println("Wanted protocol: " + protocol); // System.out.println("Got protocol: " + sc.getProtocol()); sc.init(null, tms, random); SSLServerSocketFactory sf = sc.getServerSocketFactory(); if(null != sslEnabledProtocols || null != sslCipherSuites) sf = new CustomSSLServerSocketFactory(sf, sslEnabledProtocols, sslCipherSuites); return sf; } // // All the code for loading TrustManagers was adapted from code in // the Apache Tomcat project. // /** * Gets an array of TrustManagers for the specified trust store * and optional CRL file. * * @param trustStoreFilename * @param trustStorePassword * @param trustStoreType * @param trustStoreProvider * @param trustStoreAlgorithm * @param maxCertificatePathLength * @param crlFilename * * @return An array of TrustManagers * * @throws IOException * @throws KeyStoreException * @throws NoSuchProviderException * @throws NoSuchAlgorithmException * @throws CertificateException * @throws InvalidAlgorithmParameterException * @throws CRLException */ protected static TrustManager[] getTrustManagers(String trustStoreFilename, String trustStorePassword, String trustStoreType, String trustStoreProvider, String trustStoreAlgorithm, Integer maxCertificatePathLength, String crlFilename) throws IOException, KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, CertificateException, InvalidAlgorithmParameterException, CRLException { KeyStore trustStore = getStore(trustStoreFilename, trustStorePassword, trustStoreType, trustStoreProvider); if(null == trustStoreAlgorithm) trustStoreAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(trustStoreAlgorithm); if (null == crlFilename) { tmf.init(trustStore); } else { CertPathParameters params = getParameters(trustStoreAlgorithm, crlFilename, maxCertificatePathLength, trustStore); ManagerFactoryParameters mfp = new CertPathTrustManagerParameters(params); tmf.init(mfp); } return tmf.getTrustManagers(); } /** * Return the initialization parameters for the TrustManager. * Currently, only the default <code>PKIX</code> is supported. * * @param algorithm The algorithm to get parameters for. * @param crlFilename The path to the CRL file. * @param maxCertificateChainLength Optional maximum cert chain length. * @param trustStore The configured TrustStore. * * @return The parameters including the TrustStore and any CRLs. * * @throws InvalidAlgorithmParameterException * @throws KeyStoreException * @throws IOException * @throws CertificateException * @throws CRLException * @throws NoSuchAlgorithmException */ protected static CertPathParameters getParameters(String algorithm, String crlFilename, Integer maxCertificateChainLength, KeyStore trustStore) throws KeyStoreException, InvalidAlgorithmParameterException, CRLException, CertificateException, IOException, NoSuchAlgorithmException { CertPathParameters params = null; if("PKIX".equalsIgnoreCase(algorithm)) { PKIXBuilderParameters xparams = new PKIXBuilderParameters(trustStore, new X509CertSelector()); Collection<? extends CRL> crls = getCRLs(crlFilename); CertStoreParameters csp = new CollectionCertStoreParameters(crls); CertStore store = CertStore.getInstance("Collection", csp); xparams.addCertStore(store); xparams.setRevocationEnabled(true); if(maxCertificateChainLength != null) xparams.setMaxPathLength(maxCertificateChainLength.intValue()); params = xparams; } else { throw new CRLException("CRLs not supported for type: " + algorithm); } return params; } /** * Loads a collection of Certificate Revocation Lists (CRLs) * from a file. * * @param crlFilename The file name of the CRL. * * @return A Collection of CRLs from the specified file. * * @throws IOException If the CRL file could not be loaded. * @throws CRLException If the CRL list cannot be loaded. * @throws CertificateException If there is a problem with one * of the certificates in the revocation list. */ public static Collection<? extends CRL> getCRLs(String crlFilename) throws IOException, CRLException, CertificateException { File crlFile = new File(crlFilename); Collection<? extends CRL> crls = null; InputStream is = null; try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); is = new FileInputStream(crlFile); crls = cf.generateCRLs(is); } finally { if(is != null) try{ is.close(); } catch(IOException ioe) { ioe.printStackTrace(); } } return crls; } /** * Loads a keystore. * * @param storeFilename The file name of the keystore. * @param storePassword The keystore password. * @param storeType The type of the keystore. * @param storeProvider Optional keystore provider. * * @return A KeyStore loaded from the specified file. * * @throws IOException If the file cannot be read. * @throws KeyStoreException If the KeyStore cannot be read. * @throws NoSuchProviderException If the provider is not recognized. * @throws NoSuchAlgorithmException If the an algorithm used by the KeyStore is no recognized. * @throws CertificateException If there is a problem with a certificate in the KeyStore. */ public static KeyStore getStore(String storeFilename, String storePassword, String storeType, String storeProvider) throws IOException, KeyStoreException, NoSuchProviderException, CertificateException, NoSuchAlgorithmException { KeyStore ks = null; InputStream in = null; try { if(null == storeProvider) ks = KeyStore.getInstance(storeType); else ks = KeyStore.getInstance(storeType, storeProvider); // TODO: Explicitly check for PKCS11? in = new FileInputStream(storeFilename); char[] storePass = null; if (storePassword != null && !"".equals(storePassword)) storePass = storePassword.toCharArray(); ks.load(in, storePass); return ks; } finally { if(null != in) try { in.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org