Author: markt Date: Mon Jun 20 18:15:56 2016 New Revision: 1749374 URL: http://svn.apache.org/viewvc?rev=1749374&view=rev Log: Refactor key store creation to make it easier for users to insert certificate stores and trust stores programmatically.
Modified: tomcat/tc8.5.x/trunk/ (props changed) tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/LocalStrings_es.properties tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings_es.properties tomcat/tc8.5.x/trunk/webapps/docs/changelog.xml Propchange: tomcat/tc8.5.x/trunk/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Mon Jun 20 18:15:56 2016 @@ -1 +1 @@ -/tomcat/trunk:1734785,1734799,1734845,1734928,1735041,1735044,1735480,1735577,1735597,1735599-1735600,1735615,1736145,1736162,1736209,1736280,1736297,1736299,1736489,1736646,1736703,1736836,1736849,1737104-1737105,1737112,1737117,1737119-1737120,1737155,1737157,1737192,1737280,1737339,1737632,1737664,1737715,1737748,1737785,1737834,1737860,1737903,1737959,1738005,1738007,1738014-1738015,1738018,1738022,1738039,1738043,1738059-1738060,1738147,1738149,1738174-1738175,1738261,1738589,1738623-1738625,1738643,1738816,1738850,1738855,1738946-1738948,1738953-1738954,1738979,1738982,1739079-1739081,1739087,1739113,1739153,1739172,1739176,1739191,1739474,1739726,1739762,1739775,1739814,1739817-1739818,1739975,1740131,1740324,1740465,1740495,1740508-1740509,1740520,1740535,1740707,1740803,1740810,1740969,1740980,1740991,1740997,1741015,1741033,1741036,1741058,1741060,1741080,1741147,1741159,1741164,1741173,1741181,1741190,1741197,1741202,1741208,1741213,1741221,1741225,1741232,1741409,1741501 ,1741677,1741892,1741896,1741984,1742023,1742042,1742071,1742090,1742093,1742101,1742105,1742111,1742139,1742146,1742148,1742166,1742181,1742184,1742187,1742246,1742248-1742251,1742263-1742264,1742268,1742276,1742369,1742387,1742448,1742509-1742512,1742917,1742919,1742933,1742975-1742976,1742984,1742986,1743019,1743115,1743117,1743124-1743125,1743134,1743425,1743554,1743679,1743696-1743698,1743700-1743701,1744058,1744064-1744065,1744125,1744194,1744229,1744270,1744323,1744432,1744684,1744697,1744705,1744713,1744760,1744786,1745142-1745143,1745145,1745177,1745179-1745180,1745227,1745248,1745254,1745337,1745467,1745576,1745735,1745744,1746304,1746306-1746307,1746319,1746327,1746338,1746340-1746341,1746344,1746427,1746441,1746473,1746490,1746492,1746495-1746496,1746499-1746501,1746503-1746507,1746509,1746549,1746551,1746554,1746556,1746558,1746584,1746620,1746649,1746724,1746939,1746989,1747014,1747028,1747035,1747210,1747225,1747234,1747253,1747404,1747506,1747536,1747924,1747980,1747 993,1748001,1748253,1748452,1748547,1748676,1748715,1749287,1749296,1749328 +/tomcat/trunk:1734785,1734799,1734845,1734928,1735041,1735044,1735480,1735577,1735597,1735599-1735600,1735615,1736145,1736162,1736209,1736280,1736297,1736299,1736489,1736646,1736703,1736836,1736849,1737104-1737105,1737112,1737117,1737119-1737120,1737155,1737157,1737192,1737280,1737339,1737632,1737664,1737715,1737748,1737785,1737834,1737860,1737903,1737959,1738005,1738007,1738014-1738015,1738018,1738022,1738039,1738043,1738059-1738060,1738147,1738149,1738174-1738175,1738261,1738589,1738623-1738625,1738643,1738816,1738850,1738855,1738946-1738948,1738953-1738954,1738979,1738982,1739079-1739081,1739087,1739113,1739153,1739172,1739176,1739191,1739474,1739726,1739762,1739775,1739814,1739817-1739818,1739975,1740131,1740324,1740465,1740495,1740508-1740509,1740520,1740535,1740707,1740803,1740810,1740969,1740980,1740991,1740997,1741015,1741033,1741036,1741058,1741060,1741080,1741147,1741159,1741164,1741173,1741181,1741190,1741197,1741202,1741208,1741213,1741221,1741225,1741232,1741409,1741501 ,1741677,1741892,1741896,1741984,1742023,1742042,1742071,1742090,1742093,1742101,1742105,1742111,1742139,1742146,1742148,1742166,1742181,1742184,1742187,1742246,1742248-1742251,1742263-1742264,1742268,1742276,1742369,1742387,1742448,1742509-1742512,1742917,1742919,1742933,1742975-1742976,1742984,1742986,1743019,1743115,1743117,1743124-1743125,1743134,1743425,1743554,1743679,1743696-1743698,1743700-1743701,1744058,1744064-1744065,1744125,1744194,1744229,1744270,1744323,1744432,1744684,1744697,1744705,1744713,1744760,1744786,1745142-1745143,1745145,1745177,1745179-1745180,1745227,1745248,1745254,1745337,1745467,1745576,1745735,1745744,1746304,1746306-1746307,1746319,1746327,1746338,1746340-1746341,1746344,1746427,1746441,1746473,1746490,1746492,1746495-1746496,1746499-1746501,1746503-1746507,1746509,1746549,1746551,1746554,1746556,1746558,1746584,1746620,1746649,1746724,1746939,1746989,1747014,1747028,1747035,1747210,1747225,1747234,1747253,1747404,1747506,1747536,1747924,1747980,1747 993,1748001,1748253,1748452,1748547,1748676,1748715,1749287,1749296,1749328,1749373 Modified: tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties?rev=1749374&r1=1749373&r2=1749374&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties Mon Jun 20 18:15:56 2016 @@ -105,6 +105,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/tc8.5.x/trunk/java/org/apache/tomcat/util/net/LocalStrings_es.properties URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/LocalStrings_es.properties?rev=1749374&r1=1749373&r2=1749374&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/LocalStrings_es.properties (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/LocalStrings_es.properties Mon Jun 20 18:15:56 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/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java?rev=1749374&r1=1749373&r2=1749374&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java Mon Jun 20 18:15:56 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; @@ -99,6 +102,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; @@ -594,6 +598,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/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java?rev=1749374&r1=1749373&r2=1749374&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java Mon Jun 20 18:15:56 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/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java?rev=1749374&r1=1749373&r2=1749374&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java Mon Jun 20 18:15:56 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/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java?rev=1749374&r1=1749373&r2=1749374&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java Mon Jun 20 18:15:56 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/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties?rev=1749374&r1=1749373&r2=1749374&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties Mon Jun 20 18:15:56 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/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings_es.properties URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings_es.properties?rev=1749374&r1=1749373&r2=1749374&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings_es.properties (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings_es.properties Mon Jun 20 18:15:56 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/tc8.5.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/webapps/docs/changelog.xml?rev=1749374&r1=1749373&r2=1749374&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc8.5.x/trunk/webapps/docs/changelog.xml Mon Jun 20 18:15:56 2016 @@ -81,6 +81,14 @@ </fix> </changelog> </subsection> + <subsection name="Coyote"> + <changelog> + <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"> <changelog> <update> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org