From: markt Date: Tue, 15 Sep 2009 17:50:54 +0000 (+0000) Subject: Fix Tomcat side of https://issues.apache.org/bugzilla/show_bug.cgi?id=46950 X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=e8352de55d0bca9862dedcef62171cdb2690fdc9;p=tomcat7.0 Fix Tomcat side of https://issues.apache.org/bugzilla/show_bug.cgi?id=46950 - 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 --- diff --git a/java/org/apache/catalina/core/AprLifecycleListener.java b/java/org/apache/catalina/core/AprLifecycleListener.java index fba6862ff..6ea8f508b 100644 --- a/java/org/apache/catalina/core/AprLifecycleListener.java +++ b/java/org/apache/catalina/core/AprLifecycleListener.java @@ -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 diff --git a/java/org/apache/coyote/http11/Http11AprProcessor.java b/java/org/apache/coyote/http11/Http11AprProcessor.java index 9fe459c21..813e576a5 100644 --- a/java/org/apache/coyote/http11/Http11AprProcessor.java +++ b/java/org/apache/coyote/http11/Http11AprProcessor.java @@ -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); diff --git a/java/org/apache/tomcat/jni/SSLSocket.java b/java/org/apache/tomcat/jni/SSLSocket.java index fd408ffe0..a6029f7ba 100644 --- a/java/org/apache/tomcat/jni/SSLSocket.java +++ b/java/org/apache/tomcat/jni/SSLSocket.java @@ -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. + *
+ * This is used to change the verification level for a connection prior to + * starting a re-negotiation. + *
+ * The following levels are available for level: + *
+     * 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
+     * 
+ *
+ * @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.