You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2015/06/22 23:50:32 UTC

svn commit: r1686949 - in /tomcat/trunk: java/org/apache/catalina/startup/ java/org/apache/tomcat/util/net/ webapps/docs/config/

Author: markt
Date: Mon Jun 22 21:50:31 2015
New Revision: 1686949

URL: http://svn.apache.org/r1686949
Log:
Add configuration support for SSLHostConfigCertificate
Document the new configuration
Get multiple certificates working with NIO (tested with SSLLabs). Should also be working for NIO2 but untested.

Added:
    tomcat/trunk/java/org/apache/catalina/startup/CertificateCreateRule.java   (with props)
Modified:
    tomcat/trunk/java/org/apache/catalina/startup/Catalina.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
    tomcat/trunk/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java
    tomcat/trunk/webapps/docs/config/http.xml

Modified: tomcat/trunk/java/org/apache/catalina/startup/Catalina.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/Catalina.java?rev=1686949&r1=1686948&r2=1686949&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/Catalina.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/Catalina.java Mon Jun 22 21:50:31 2015
@@ -340,8 +340,15 @@ public class Catalina {
                                  "org.apache.tomcat.util.net.SSLHostConfig");
         digester.addSetProperties("Server/Service/Connector/SSLHostConfig");
         digester.addSetNext("Server/Service/Connector/SSLHostConfig",
-                            "addSslHostConfig",
-                            "org.apache.tomcat.util.net.SSLHostConfig");
+                "addSslHostConfig",
+                "org.apache.tomcat.util.net.SSLHostConfig");
+
+        digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
+                         new CertificateCreateRule());
+        digester.addSetProperties("Server/Service/Connector/SSLHostConfig/Certificate");
+        digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate",
+                            "addCertificate",
+                            "org.apache.tomcat.util.net.SSLHostConfigCertificate");
 
         digester.addObjectCreate("Server/Service/Connector/Listener",
                                  null, // MUST be specified in the element

Added: tomcat/trunk/java/org/apache/catalina/startup/CertificateCreateRule.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/CertificateCreateRule.java?rev=1686949&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/CertificateCreateRule.java (added)
+++ tomcat/trunk/java/org/apache/catalina/startup/CertificateCreateRule.java Mon Jun 22 21:50:31 2015
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+ */
+package org.apache.catalina.startup;
+
+import org.apache.tomcat.util.digester.Rule;
+import org.apache.tomcat.util.net.SSLHostConfig;
+import org.apache.tomcat.util.net.SSLHostConfigCertificate;
+import org.apache.tomcat.util.net.SSLHostConfigCertificate.Type;
+import org.xml.sax.Attributes;
+
+/**
+ * Rule implementation that creates a SSLHostConfigCertificate.
+ */
+public class CertificateCreateRule extends Rule {
+
+    @Override
+    public void begin(String namespace, String name, Attributes attributes) throws Exception {
+        SSLHostConfig sslHostConfig = (SSLHostConfig)digester.peek();
+
+        Type type;
+        String typeValue = attributes.getValue("type");
+        if (typeValue == null || typeValue.length() == 0) {
+            type = Type.UNDEFINED;
+        } else {
+            type = Type.valueOf(typeValue);
+        }
+
+        SSLHostConfigCertificate certificate = new SSLHostConfigCertificate(sslHostConfig, type);
+
+        digester.push(certificate);
+    }
+
+
+    /**
+     * Process the end of this element.
+     *
+     * @param namespace the namespace URI of the matching element, or an
+     *   empty string if the parser is not namespace aware or the element has
+     *   no namespace
+     * @param name the local name if the parser is namespace aware, or just
+     *   the element name otherwise
+     */
+    @Override
+    public void end(String namespace, String name) throws Exception {
+        digester.pop();
+    }
+}

Propchange: tomcat/trunk/java/org/apache/catalina/startup/CertificateCreateRule.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tomcat/trunk/java/org/apache/catalina/startup/CertificateCreateRule.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java?rev=1686949&r1=1686948&r2=1686949&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java Mon Jun 22 21:50:31 2015
@@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
 import java.nio.channels.AsynchronousSocketChannel;
 import java.nio.channels.CompletionHandler;
 import java.nio.channels.WritePendingException;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
@@ -336,10 +337,9 @@ public class SecureNio2Channel extends N
         switch (extractor.getResult()) {
         case COMPLETE:
             hostName = extractor.getSNIValue();
-            clientRequestedCiphers = extractor.getClientRequestedCiphers();
-            break;
+            //$FALL-THROUGH$ to set the client requested ciphers
         case NOT_PRESENT:
-            // NO-OP
+            clientRequestedCiphers = extractor.getClientRequestedCiphers();
             break;
         case NEED_READ:
             sc.read(netInBuffer, socket, handshakeReadCompletionHandler);
@@ -350,6 +350,7 @@ public class SecureNio2Channel extends N
                 log.debug(sm.getString("channel.nio.ssl.sniDefault"));
             }
             hostName = endpoint.getDefaultSSLHostConfigName();
+            clientRequestedCiphers = Collections.emptyList();
             break;
         }
 

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java?rev=1686949&r1=1686948&r2=1686949&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java Mon Jun 22 21:50:31 2015
@@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
 import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
 import java.nio.channels.SocketChannel;
+import java.util.Collections;
 import java.util.List;
 
 import javax.net.ssl.SSLEngine;
@@ -274,10 +275,9 @@ public class SecureNioChannel extends Ni
         switch (extractor.getResult()) {
         case COMPLETE:
             hostName = extractor.getSNIValue();
-            clientRequestedCiphers = extractor.getClientRequestedCiphers();
-            break;
+            //$FALL-THROUGH$ to set the client requested ciphers
         case NOT_PRESENT:
-            // NO-OP
+            clientRequestedCiphers = extractor.getClientRequestedCiphers();
             break;
         case NEED_READ:
             return SelectionKey.OP_READ;
@@ -287,6 +287,7 @@ public class SecureNioChannel extends Ni
                 log.debug(sm.getString("channel.nio.ssl.sniDefault"));
             }
             hostName = endpoint.getDefaultSSLHostConfigName();
+            clientRequestedCiphers = Collections.emptyList();
             break;
         }
 

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java?rev=1686949&r1=1686948&r2=1686949&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java Mon Jun 22 21:50:31 2015
@@ -58,7 +58,7 @@ public class TLSClientHelloExtractor {
         int pos = netInBuffer.position();
         int limit = netInBuffer.limit();
         ExtractorResult result = ExtractorResult.NOT_PRESENT;
-        List<Cipher> clientRequestedCiphers = null;
+        List<Cipher> clientRequestedCiphers = new ArrayList<>();
         String sniValue = null;
         try {
             // Switch to read mode.
@@ -101,7 +101,6 @@ public class TLSClientHelloExtractor {
             // Cipher Suites
             // (2 bytes for length, each cipher ID is 2 bytes)
             int cipherCount = netInBuffer.getChar() / 2;
-            clientRequestedCiphers = new ArrayList<>(cipherCount);
             for (int i = 0; i < cipherCount; i++) {
                 int cipherId = netInBuffer.getChar();
                 clientRequestedCiphers.add(Cipher.valueOf(cipherId));
@@ -150,7 +149,7 @@ public class TLSClientHelloExtractor {
 
 
     public List<Cipher> getClientRequestedCiphers() {
-        if (result == ExtractorResult.COMPLETE) {
+        if (result == ExtractorResult.COMPLETE || result == ExtractorResult.NOT_PRESENT) {
             return clientRequestedCiphers;
         } else {
             throw new IllegalStateException();

Modified: tomcat/trunk/webapps/docs/config/http.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/http.xml?rev=1686949&r1=1686948&r2=1686949&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/http.xml (original)
+++ tomcat/trunk/webapps/docs/config/http.xml Mon Jun 22 21:50:31 2015
@@ -929,8 +929,12 @@
   the host name requested by the client. To facilitate this, Tomcat 9 added the
   <strong>SSLHostConfig</strong> element which can be used to define one of
   these configurations. Any number of <strong>SSLHostConfig</strong> may be
-  nested in a <strong>Connector</strong>. For further information, see the
-  SSL Support section below.</p>
+  nested in a <strong>Connector</strong>. Tomcat 9 also adds support for
+  mutliple cerificates to be associated with a single
+  <strong>SSLHostConfig</strong>. Each SSL certificate is therefore configured
+  in a <strong>Certificate</strong> element with in an
+  <strong>SSLHostConfig</strong>. For further information, see the SSL Support
+  section below.</p>
 
 </section>
 
@@ -998,10 +1002,14 @@
   match the <code>sslDefaultHost</code> attribute of the
   <strong>Connector</strong>.</p>
 
+  <p>Each <strong>SSLHostConfig</strong> must in turn define at least one
+  <strong>Certificate</strong>. The types of the <strong>Certificate</strong>s
+  must be unique.</p>
+
   <p>As of Tomcat 9, the majority of the SSL configuration attributes in the
   <strong>Connector</strong> are deprecated. If specified, they will be used to
-  configure a <strong>SSLHostConfig</strong> for the
-  <code>sslDefaultHost</code>. Note that if an explicit
+  configure a <strong>SSLHostConfig</strong> and <strong>Certificate</strong>for
+  the <code>sslDefaultHost</code>. Note that if an explicit
   <strong>SSLHostConfig</strong> element also exists for the
   <code>sslDefaultHost</code> then that will be treated as a configuration
   error. It is expected that Tomcat 10 will drop support for the SSL
@@ -1018,84 +1026,6 @@
 
   <attributes>
 
-    <attribute name="certificateFile" required="true">
-      <p>OpenSSL only.</p>
-      <p>Name of the file that contains the server certificate. The format is
-      PEM-encoded. Relative paths will be resolved against
-      <code>$CATALINA_BASE</code>.</p>
-      <p>In addition to the certificate, the file can also contain as optional
-      elements DH parameters and/or an EC curve name for ephemeral keys, as
-      generated by <code>openssl dhparam</code> and <code>openssl ecparam</code>,
-      respectively. The output of the respective OpenSSL command can simply
-      be concatenated to the certificate file.</p>
-    </attribute>
-
-    <attribute name="certificateKeyAlias" required="false">
-      <p>JSSE only.</p>
-      <p>The alias used for the server key and certificate in the keystore. If
-      not specified, the first key read from the keystore will be used. The
-      order in which keys are read from the keystore is implementation
-      dependent. It may not be the case that keys are read from the keystore in
-      the same order as they were added. If more than one key is present in the
-      kesytore it is strongly recommended that a keyAlias is configured to
-      ensure that the correct key is used.</p>
-    </attribute>
-
-    <attribute name="certificateKeyFile" required="false">
-      <p>OpenSSL only.</p>
-      <p>Name of the file that contains the server private key. The format is
-      PEM-encoded. The default value is the value of
-      <strong>certificateFile</strong> and in this case both certificate and
-      private key have to be in this file (NOT RECOMMENDED). Relative paths will
-      be resolved against <code>$CATALINA_BASE</code>.</p>
-    </attribute>
-
-    <attribute name="certificateKeyPassword" required="false">
-      <p>The password used to access the private key associated with the server
-      certificate from the specified file.</p>
-      <p>If not specified, the default behaviour for JSSE is to use the
-      <strong>certificateKeystorePassword</strong>. For OpenSSL the default
-      behaviour is not to use a password.</p>
-    </attribute>
-
-    <attribute name="certificateKeystoreFile" required="false">
-      <p>JSSE only.</p>
-      <p>The pathname of the keystore file where you have stored the server
-      certificate and key to be loaded. By default, the pathname is the file
-      <code>.keystore</code> in the operating system home directory of the user
-      that is running Tomcat. If your <code>keystoreType</code> doesn't need a
-      file use <code>""</code> (empty string) or <code>NONE</code> for this
-      parameter.  Relative paths will be resolved against
-      <code>$CATALINA_BASE</code>.</p>
-    </attribute>
-
-    <attribute name="certificateKeystorePassword" required="false">
-      <p>JSSE only.</p>
-      <p>The password to use to access the keystore containing the server&apos;s
-      private key and certificate. If not specified, a default of
-      <code>changeit</code> will be used.</p>
-    </attribute>
-
-    <attribute name="certificateKeystoreProvider" required="false">
-      <p>JSSE only.</p>
-      <p>The name of the keystore provider to be used for the server
-      certificate. If not specified, the value of the system property
-      <code>javax.net.ssl.keyStoreProvider</code> is used. If neither this
-      attribute nor the system property are set, the list of registered
-      providers is traversed in preference order and the first provider that
-      supports the <code>keystoreType</code> is used.
-      </p>
-    </attribute>
-
-    <attribute name="certificateKeystoreType" required="false">
-      <p>JSSE only.</p>
-      <p>The type of keystore file to be used for the server certificate.
-      If not specified, the value of the system property
-      <code>javax.net.ssl.keyStoreType</code> is used. If neither this attribute
-      nor the system property are set, a default value of "<code>JKS</code>". is
-      used.</p>
-    </attribute>
-
     <attribute name="certificateRevocationFile" required="false">
       <p>Name of the file that contains the concatenated certificate revocation
       lists for the certificate authorities. The format is PEM-encoded. If not
@@ -1310,6 +1240,105 @@
 
   </attributes>
 
+  </subsection>
+
+  <subsection name="SSL Support - Certificate">
+
+  <p></p>
+
+  <attributes>
+
+    <attribute name="certificateFile" required="true">
+      <p>OpenSSL only.</p>
+      <p>Name of the file that contains the server certificate. The format is
+      PEM-encoded. Relative paths will be resolved against
+      <code>$CATALINA_BASE</code>.</p>
+      <p>In addition to the certificate, the file can also contain as optional
+      elements DH parameters and/or an EC curve name for ephemeral keys, as
+      generated by <code>openssl dhparam</code> and <code>openssl ecparam</code>,
+      respectively. The output of the respective OpenSSL command can simply
+      be concatenated to the certificate file.</p>
+    </attribute>
+
+    <attribute name="certificateKeyAlias" required="false">
+      <p>JSSE only.</p>
+      <p>The alias used for the server key and certificate in the keystore. If
+      not specified, the first key read from the keystore will be used. The
+      order in which keys are read from the keystore is implementation
+      dependent. It may not be the case that keys are read from the keystore in
+      the same order as they were added. If more than one key is present in the
+      kesytore it is strongly recommended that a keyAlias is configured to
+      ensure that the correct key is used.</p>
+    </attribute>
+
+    <attribute name="certificateKeyFile" required="false">
+      <p>OpenSSL only.</p>
+      <p>Name of the file that contains the server private key. The format is
+      PEM-encoded. The default value is the value of
+      <strong>certificateFile</strong> and in this case both certificate and
+      private key have to be in this file (NOT RECOMMENDED). Relative paths will
+      be resolved against <code>$CATALINA_BASE</code>.</p>
+    </attribute>
+
+    <attribute name="certificateKeyPassword" required="false">
+      <p>The password used to access the private key associated with the server
+      certificate from the specified file.</p>
+      <p>If not specified, the default behaviour for JSSE is to use the
+      <strong>certificateKeystorePassword</strong>. For OpenSSL the default
+      behaviour is not to use a password.</p>
+    </attribute>
+
+    <attribute name="certificateKeystoreFile" required="false">
+      <p>JSSE only.</p>
+      <p>The pathname of the keystore file where you have stored the server
+      certificate and key to be loaded. By default, the pathname is the file
+      <code>.keystore</code> in the operating system home directory of the user
+      that is running Tomcat. If your <code>keystoreType</code> doesn't need a
+      file use <code>""</code> (empty string) or <code>NONE</code> for this
+      parameter.  Relative paths will be resolved against
+      <code>$CATALINA_BASE</code>.</p>
+    </attribute>
+
+    <attribute name="certificateKeystorePassword" required="false">
+      <p>JSSE only.</p>
+      <p>The password to use to access the keystore containing the server&apos;s
+      private key and certificate. If not specified, a default of
+      <code>changeit</code> will be used.</p>
+    </attribute>
+
+    <attribute name="certificateKeystoreProvider" required="false">
+      <p>JSSE only.</p>
+      <p>The name of the keystore provider to be used for the server
+      certificate. If not specified, the value of the system property
+      <code>javax.net.ssl.keyStoreProvider</code> is used. If neither this
+      attribute nor the system property are set, the list of registered
+      providers is traversed in preference order and the first provider that
+      supports the <code>keystoreType</code> is used.
+      </p>
+    </attribute>
+
+    <attribute name="certificateKeystoreType" required="false">
+      <p>JSSE only.</p>
+      <p>The type of keystore file to be used for the server certificate.
+      If not specified, the value of the system property
+      <code>javax.net.ssl.keyStoreType</code> is used. If neither this attribute
+      nor the system property are set, a default value of "<code>JKS</code>". is
+      used.</p>
+    </attribute>
+
+    <attribute name="type" required="false">
+      <p>The type of certificate. This is used to idenitfy the ciphers that are
+      compatible with the certificate. It must be one of <code>UNDEFINED</code>,
+      <code>RSA</code>, <code>DSS</code> or <code>EC</code>. If only one
+      <strong>Certificate</strong> is nested within a <code>SSLHostConfig</code>
+      then this attribute is not required and will default to
+      <code>UNDEFINED</code>. If multiple <strong>Certificate</strong>s are
+      nested within a <code>SSLHostConfig</code> then this attribute is required
+      and each <strong>Certificate</strong> must have a unique type.</p>
+    </attribute>
+
+  </attributes>
+
   </subsection>
 
   <subsection name="SSL Support - Connector - NIO and NIO2">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org