Author: markt Date: Mon Jun 20 18:13:07 2016 New Revision: 1749373 URL: http://svn.apache.org/viewvc?rev=1749373&view=rev Log: Refactor key store creation to make it easier for users to insert certificate stores and trust stores programmatically.
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings_es.properties tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings_es.properties tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties?rev=1749373&r1=1749372&r2=1749373&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties Mon Jun 20 18:13:07 2016 @@ -104,6 +104,9 @@ channel.nio.ssl.expandNetOutBuffer=Expan channel.nio.ssl.sniDefault=Unable to buffer enough data to determine requested SNI host name. Using default channel.nio.ssl.sniHostName=The SNI host name extracted for this connection was [{0}] +jsse.invalid_truststore_password=The provided trust store password could not be used to unlock and/or validate the trust store. Retrying to access the trust store with a null password which will skip validation. +jsse.keystore_load_failed=Failed to load keystore type [{0}] with path [{1}] due to [{2}] + sniExtractor.clientHelloTooBig=The ClientHello was not presented in a single TLS record so no SNI information could be extracted socket.closed=The socket associated with this connection has been closed. Modified: tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings_es.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings_es.properties?rev=1749373&r1=1749372&r2=1749373&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings_es.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings_es.properties Mon Jun 20 18:13:07 2016 @@ -34,3 +34,6 @@ endpoint.debug.channelCloseFail = No pue endpoint.debug.socketCloseFail = No pude cerrar el enchufe (socket) endpoint.apr.noSslCertFile = El atribiuto del conector SSLCertificateFile debe de ser definido al usar SSL con APR endpoint.apr.invalidSslProtocol = Se ha proporcionado un valor inv\u00E1lido [{0}] para el atributo SSLProtocol + +jsse.invalid_truststore_password = La clave del almac\u00E9n de confianza suministrada no se pudo usar para desbloquear y/o validar el almac\u00E9n de confianza. Reintentando acceder el almac\u00E9n de confianza con una clave nula que se saltar\u00E1 la validaci\u00F3n. +jsse.keystore_load_failed = No pude cargar almac\u00E9n de claves de tipo [{0}] con ruta [{1}] debido a [{2}] Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java?rev=1749373&r1=1749372&r2=1749373&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java Mon Jun 20 18:13:07 2016 @@ -17,6 +17,9 @@ package org.apache.tomcat.util.net; import java.io.File; +import java.io.IOException; +import java.security.KeyStore; +import java.security.UnrecoverableKeyException; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; @@ -96,6 +99,7 @@ public class SSLHostConfig { private String truststorePassword = System.getProperty("javax.net.ssl.trustStorePassword"); private String truststoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider"); private String truststoreType = System.getProperty("javax.net.ssl.trustStoreType"); + private KeyStore truststore = null; // OpenSSL private String certificateRevocationListPath; private String caCertificateFile; @@ -583,6 +587,38 @@ public class SSLHostConfig { } + public void setTrustStore(KeyStore truststore) { + this.truststore = truststore; + } + + + public KeyStore getTruststore() throws IOException { + KeyStore result = truststore; + if (result == null) { + if (truststoreFile != null){ + try { + result = SSLUtilBase.getStore(truststoreType, truststoreProvider, + truststoreFile, truststorePassword); + } catch (IOException ioe) { + Throwable cause = ioe.getCause(); + if (cause instanceof UnrecoverableKeyException) { + // Log a warning we had a password issue + log.warn(sm.getString("jsse.invalid_truststore_password"), + cause); + // Re-try + result = SSLUtilBase.getStore(truststoreType, truststoreProvider, + truststoreFile, null); + } else { + // Something else went wrong - re-throw + throw ioe; + } + } + } + } + return result; + } + + // ------------------------------- OpenSSL specific configuration properties // TODO: These certificate setters can be removed once it is no longer Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java?rev=1749373&r1=1749372&r2=1749373&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java Mon Jun 20 18:13:07 2016 @@ -16,6 +16,8 @@ */ package org.apache.tomcat.util.net; +import java.io.IOException; +import java.security.KeyStore; import java.util.HashSet; import java.util.Set; @@ -53,6 +55,7 @@ public class SSLHostConfigCertificate { private String certificateKeystoreFile = System.getProperty("user.home")+"/.keystore"; private String certificateKeystoreProvider = DEFAULT_KEYSTORE_PROVIDER; private String certificateKeystoreType = DEFAULT_KEYSTORE_TYPE; + private KeyStore certificateKeystore = null; // OpenSSL private String certificateChainFile; @@ -170,6 +173,23 @@ public class SSLHostConfigCertificate { } + public void setCertificateKeystore(KeyStore certificateKeystore) { + this.certificateKeystore = certificateKeystore; + } + + + public KeyStore getCertificateKeystore() throws IOException { + KeyStore result = certificateKeystore; + + if (result == null) { + result = SSLUtilBase.getStore(certificateKeystoreType, certificateKeystoreProvider, + certificateKeystoreFile, certificateKeystorePassword); + } + + return result; + } + + // OpenSSL public void setCertificateChainFile(String certificateChainFile) { Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java?rev=1749373&r1=1749372&r2=1749373&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java Mon Jun 20 18:13:07 2016 @@ -16,12 +16,18 @@ */ package org.apache.tomcat.util.net; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.file.ConfigFileLoader; import org.apache.tomcat.util.res.StringManager; /** @@ -29,6 +35,7 @@ import org.apache.tomcat.util.res.String */ public abstract class SSLUtilBase implements SSLUtil { + private static final Log log = LogFactory.getLog(SSLUtilBase.class); private static final StringManager sm = StringManager.getManager(SSLUtilBase.class); protected final SSLHostConfigCertificate certificate; @@ -101,6 +108,59 @@ public abstract class SSLUtilBase implem return enabled; } + + /* + * Gets the key- or truststore with the specified type, path, and password. + */ + static KeyStore getStore(String type, String provider, String path, + String pass) throws IOException { + + KeyStore ks = null; + InputStream istream = null; + try { + if (provider == null) { + ks = KeyStore.getInstance(type); + } else { + ks = KeyStore.getInstance(type, provider); + } + if(!("PKCS11".equalsIgnoreCase(type) || + "".equalsIgnoreCase(path)) || + "NONE".equalsIgnoreCase(path)) { + istream = ConfigFileLoader.getInputStream(path); + } + + char[] storePass = null; + if (pass != null && !"".equals(pass)) { + storePass = pass.toCharArray(); + } + ks.load(istream, storePass); + } catch (FileNotFoundException fnfe) { + log.error(sm.getString("jsse.keystore_load_failed", type, path, + fnfe.getMessage()), fnfe); + throw fnfe; + } catch (IOException ioe) { + // May be expected when working with a trust store + // Re-throw. Caller will catch and log as required + throw ioe; + } catch(Exception ex) { + String msg = sm.getString("jsse.keystore_load_failed", type, path, + ex.getMessage()); + log.error(msg, ex); + throw new IOException(msg); + } finally { + if (istream != null) { + try { + istream.close(); + } catch (IOException ioe) { + // Do nothing + } + } + } + + return ks; + } + + @Override public String[] getEnabledProtocols() { return enabledProtocols; Modified: tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java?rev=1749373&r1=1749372&r2=1749373&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java Mon Jun 20 18:13:07 2016 @@ -16,13 +16,11 @@ */ package org.apache.tomcat.util.net.jsse; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; import java.security.cert.CRL; import java.security.cert.CRLException; import java.security.cert.CertPathParameters; @@ -150,92 +148,6 @@ public class JSSEUtil extends SSLUtilBas } - /* - * Gets the SSL server's truststore. - */ - protected KeyStore getTrustStore() throws IOException { - KeyStore trustStore = null; - - String truststoreFile = sslHostConfig.getTruststoreFile(); - String truststoreType = sslHostConfig.getTruststoreType(); - String truststoreProvider = sslHostConfig.getTruststoreProvider(); - - if (truststoreFile != null){ - try { - trustStore = getStore(truststoreType, truststoreProvider, - truststoreFile, sslHostConfig.getTruststorePassword()); - } catch (IOException ioe) { - Throwable cause = ioe.getCause(); - if (cause instanceof UnrecoverableKeyException) { - // Log a warning we had a password issue - log.warn(sm.getString("jsse.invalid_truststore_password"), - cause); - // Re-try - trustStore = getStore(truststoreType, truststoreProvider, - truststoreFile, null); - } else { - // Something else went wrong - re-throw - throw ioe; - } - } - } - - return trustStore; - } - - - /* - * Gets the key- or truststore with the specified type, path, and password. - */ - private KeyStore getStore(String type, String provider, String path, - String pass) throws IOException { - - KeyStore ks = null; - InputStream istream = null; - try { - if (provider == null) { - ks = KeyStore.getInstance(type); - } else { - ks = KeyStore.getInstance(type, provider); - } - if(!("PKCS11".equalsIgnoreCase(type) || - "".equalsIgnoreCase(path)) || - "NONE".equalsIgnoreCase(path)) { - istream = ConfigFileLoader.getInputStream(path); - } - - char[] storePass = null; - if (pass != null && !"".equals(pass)) { - storePass = pass.toCharArray(); - } - ks.load(istream, storePass); - } catch (FileNotFoundException fnfe) { - log.error(sm.getString("jsse.keystore_load_failed", type, path, - fnfe.getMessage()), fnfe); - throw fnfe; - } catch (IOException ioe) { - // May be expected when working with a trust store - // Re-throw. Caller will catch and log as required - throw ioe; - } catch(Exception ex) { - String msg = sm.getString("jsse.keystore_load_failed", type, path, - ex.getMessage()); - log.error(msg, ex); - throw new IOException(msg); - } finally { - if (istream != null) { - try { - istream.close(); - } catch (IOException ioe) { - // Do nothing - } - } - } - - return ks; - } - - @Override protected Log getLog() { return log; @@ -263,9 +175,6 @@ public class JSSEUtil extends SSLUtilBas @Override public KeyManager[] getKeyManagers() throws Exception { String keystoreType = certificate.getCertificateKeystoreType(); - String keystoreProvider = certificate.getCertificateKeystoreProvider(); - String keystoreFile = certificate.getCertificateKeystoreFile(); - String keystorePass = certificate.getCertificateKeystorePassword(); String keyAlias = certificate.getCertificateKeyAlias(); String algorithm = sslHostConfig.getKeyManagerAlgorithm(); String keyPass = certificate.getCertificateKeyPassword(); @@ -277,11 +186,9 @@ public class JSSEUtil extends SSLUtilBas KeyManager[] kms = null; - KeyStore ks; + KeyStore ks = certificate.getCertificateKeystore(); - if (certificate.getCertificateFile() == null) { - ks = getStore(keystoreType, keystoreProvider, keystoreFile, keystorePass); - } else { + if (ks == null) { // create an in-memory keystore and import the private key // and the certificate chain from the PEM files ks = KeyStore.getInstance("JKS"); @@ -350,7 +257,7 @@ public class JSSEUtil extends SSLUtilBas TrustManager[] tms = null; - KeyStore trustStore = getTrustStore(); + KeyStore trustStore = sslHostConfig.getTruststore(); if (trustStore != null || className != null) { if (crlf == null) { TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); Modified: tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties?rev=1749373&r1=1749372&r2=1749373&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties Mon Jun 20 18:13:07 2016 @@ -14,9 +14,7 @@ # limitations under the License. jsse.alias_no_key_entry=Alias name {0} does not identify a key entry -jsse.keystore_load_failed=Failed to load keystore type {0} with path {1} due to {2} jsse.invalid_ssl_conf=SSL configuration is invalid due to {0} -jsse.invalid_truststore_password=The provided trust store password could not be used to unlock and/or validate the trust store. Retrying to access the trust store with a null password which will skip validation. jsse.invalidTrustManagerClassName=The trustManagerClassName provided [{0}] does not implement javax.net.ssl.TrustManager jsse.requested_ciphers_not_supported=None of the ciphers specified are supported by the SSL engine : {0} jsse.enableable_ciphers=Specified SSL ciphers that are supported and enableable are : {0} Modified: tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings_es.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings_es.properties?rev=1749373&r1=1749372&r2=1749373&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings_es.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings_es.properties Mon Jun 20 18:13:07 2016 @@ -13,7 +13,5 @@ # See the License for the specific language governing permissions and # limitations under the License. jsse.alias_no_key_entry = El nombre de Alias {0} no identifica una entrada de clave -jsse.keystore_load_failed = No pude cargar almac\u00E9n de claves de tipo {0} con ruta {1} debido a {2} jsse.invalid_ssl_conf = La configuraci\u00F3n SSL no es v\u00E1lida debido a {0} -jsse.invalid_truststore_password = La clave del almac\u00E9n de confianza suministrada no se pudo usar para desbloquear y/o validar el almac\u00E9n de confianza. Reintentando acceder el almac\u00E9n de confianza con una clave nula que se saltar\u00E1 la validaci\u00F3n. jsse.invalidTrustManagerClassName = El trustManagerClassName suministrado [{0}] no implementa javax.net.ssl.TrustManager Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1749373&r1=1749372&r2=1749373&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Mon Jun 20 18:13:07 2016 @@ -91,6 +91,10 @@ <fix> Fix a cause of multiple attempts to close the same socket. (markt) </fix> + <scode> + Refactor the certifcate keystore and trust store generation to make it + easier for embedded users to inject their own key stores. (markt) + </scode> </changelog> </subsection> <subsection name="Other"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org