Fix Tomcat side of https://issues.apache.org/bugzilla/show_bug.cgi?id=46950
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Tue, 15 Sep 2009 17:50:54 +0000 (17:50 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Tue, 15 Sep 2009 17:50:54 +0000 (17:50 +0000)
- adds new setVerify() method
- uses it before renegotiation to change the cert verification level for the connection
- increments minimum tc native version to 1.1.17 as it requires the new setVerify() method

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@815418 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/core/AprLifecycleListener.java
java/org/apache/coyote/http11/Http11AprProcessor.java
java/org/apache/tomcat/jni/SSLSocket.java

index fba6862..6ea8f50 100644 (file)
@@ -58,9 +58,9 @@ public class AprLifecycleListener
 
     protected static final int TCN_REQUIRED_MAJOR = 1;
     protected static final int TCN_REQUIRED_MINOR = 1;
-    protected static final int TCN_REQUIRED_PATCH = 8;
+    protected static final int TCN_REQUIRED_PATCH = 17;
     protected static final int TCN_RECOMMENDED_MIN = 1;
-    protected static final int TCN_RECOMMENDED_PV = 16;
+    protected static final int TCN_RECOMMENDED_PV = 17;
 
 
     // ---------------------------------------------- Properties
index 9fe459c..813e576 100644 (file)
@@ -1118,10 +1118,11 @@ public class Http11AprProcessor implements ActionHook {
                         request.setAttribute(AprEndpoint.CIPHER_SUITE_KEY, sslO);
                     }
                     // Get client certificate and the certificate chain if present
+                    // certLength == -1 indicates an error
                     int certLength = SSLSocket.getInfoI(socket, SSL.SSL_INFO_CLIENT_CERT_CHAIN);
                     byte[] clientCert = SSLSocket.getInfoB(socket, SSL.SSL_INFO_CLIENT_CERT);
                     X509Certificate[] certs = null;
-                    if (clientCert != null) {
+                    if (clientCert != null  && certLength > -1) {
                         certs = new X509Certificate[certLength + 1];
                         CertificateFactory cf = CertificateFactory.getInstance("X.509");
                         certs[0] = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(clientCert));
@@ -1152,29 +1153,35 @@ public class Http11AprProcessor implements ActionHook {
         } else if (actionCode == ActionCode.ACTION_REQ_SSL_CERTIFICATE) {
 
             if (ssl && (socket != 0)) {
-                 // Consume and buffer the request body, so that it does not
-                 // interfere with the client's handshake messages
+                // Consume and buffer the request body, so that it does not
+                // interfere with the client's handshake messages
                 InputFilter[] inputFilters = inputBuffer.getFilters();
                 ((BufferedInputFilter) inputFilters[Constants.BUFFERED_FILTER]).setLimit(maxSavePostSize);
                 inputBuffer.addActiveFilter(inputFilters[Constants.BUFFERED_FILTER]);
                 try {
-                    // Renegociate certificates
-                    SSLSocket.renegotiate(socket);
-                    // Get client certificate and the certificate chain if present
-                    int certLength = SSLSocket.getInfoI(socket, SSL.SSL_INFO_CLIENT_CERT_CHAIN);
-                    byte[] clientCert = SSLSocket.getInfoB(socket, SSL.SSL_INFO_CLIENT_CERT);
-                    X509Certificate[] certs = null;
-                    if (clientCert != null) {
-                        certs = new X509Certificate[certLength + 1];
-                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
-                        certs[0] = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(clientCert));
-                        for (int i = 0; i < certLength; i++) {
-                            byte[] data = SSLSocket.getInfoB(socket, SSL.SSL_INFO_CLIENT_CERT_CHAIN + i);
-                            certs[i+1] = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(data));
+                    // Configure connection to require a certificate
+                    SSLSocket.setVerify(socket, SSL.SSL_CVERIFY_REQUIRE,
+                            endpoint.getSSLVerifyDepth());
+                    // Renegotiate certificates
+                    if (SSLSocket.renegotiate(socket) == 0) {
+                        // Don't look for certs unless we know renegotiation worked.
+                        // Get client certificate and the certificate chain if present
+                        // certLength == -1 indicates an error 
+                        int certLength = SSLSocket.getInfoI(socket,SSL.SSL_INFO_CLIENT_CERT_CHAIN);
+                        byte[] clientCert = SSLSocket.getInfoB(socket, SSL.SSL_INFO_CLIENT_CERT);
+                        X509Certificate[] certs = null;
+                        if (clientCert != null && certLength > -1) {
+                            certs = new X509Certificate[certLength + 1];
+                            CertificateFactory cf = CertificateFactory.getInstance("X.509");
+                            certs[0] = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(clientCert));
+                            for (int i = 0; i < certLength; i++) {
+                                byte[] data = SSLSocket.getInfoB(socket, SSL.SSL_INFO_CLIENT_CERT_CHAIN + i);
+                                certs[i+1] = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(data));
+                            }
+                        }
+                        if (certs != null) {
+                            request.setAttribute(AprEndpoint.CERTIFICATE_KEY, certs);
                         }
-                    }
-                    if (certs != null) {
-                        request.setAttribute(AprEndpoint.CERTIFICATE_KEY, certs);
                     }
                 } catch (Exception e) {
                     log.warn(sm.getString("http11processor.socket.ssl"), e);
index fd408ff..a6029f7 100644 (file)
@@ -48,7 +48,7 @@ public class SSLSocket {
      * response is sent. In more detail: the renegotiation happens after the
      * request line and MIME headers were read, but _before_ the attached
      * request body is read. The reason simply is that in the HTTP protocol
-     * usually there is no acknowledgment step between the headers and the
+     * usually there is no acknowledgement step between the headers and the
      * body (there is the 100-continue feature and the chunking facility
      * only), so Apache has no API hook for this step.
      *
@@ -57,7 +57,30 @@ public class SSLSocket {
     public static native int renegotiate(long thesocket);
 
     /**
-     * Retrun SSL Info parameter as byte array.
+     * Set Type of Client Certificate verification and Maximum depth of CA
+     * Certificates in Client Certificate verification.
+     * <br />
+     * This is used to change the verification level for a connection prior to
+     * starting a re-negotiation.
+     * <br />
+     * The following levels are available for level:
+     * <PRE>
+     * SSL_CVERIFY_NONE           - No client Certificate is required at all
+     * SSL_CVERIFY_OPTIONAL       - The client may present a valid Certificate
+     * SSL_CVERIFY_REQUIRE        - The client has to present a valid
+     *                              Certificate
+     * SSL_CVERIFY_OPTIONAL_NO_CA - The client may present a valid Certificate
+     *                              but it need not to be (successfully)
+     *                              verifiable
+     * </PRE>
+     * <br />
+     * @param sock  The socket to change.
+     * @param level Type of Client Certificate verification.
+     */
+    public static native void setVerify(long sock, int level, int depth);
+    
+    /**    
+     * Return SSL Info parameter as byte array.
      *
      * @param sock The socket to read the data from.
      * @param id Parameter id.
@@ -67,7 +90,7 @@ public class SSLSocket {
         throws Exception;
 
     /**
-     * Retrun SSL Info parameter as String.
+     * Return SSL Info parameter as String.
      *
      * @param sock The socket to read the data from.
      * @param id Parameter id.
@@ -77,7 +100,7 @@ public class SSLSocket {
         throws Exception;
 
     /**
-     * Retrun SSL Info parameter as integer.
+     * Return SSL Info parameter as integer.
      *
      * @param sock The socket to read the data from.
      * @param id Parameter id.