Author: markt Date: Tue Aug 12 12:42:18 2014 New Revision: 1617461 URL: http://svn.apache.org/r1617461 Log: Follow-on to r1617445 If a client certificate is required and one is not available then force renegotiation to obtain it. If a client certificate is optional then do not force renegotiation before trying to obtain it.
Modified: tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java tomcat/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Processor.java tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java tomcat/trunk/test/org/apache/tomcat/util/net/TestClientCert.java Modified: tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java?rev=1617461&r1=1617460&r2=1617461&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java Tue Aug 12 12:42:18 2014 @@ -567,7 +567,7 @@ public abstract class AuthenticatorBase } if (!authRequired && context.getPreemptiveAuthentication()) { - X509Certificate[] certs = getRequestCertificates(request); + X509Certificate[] certs = getRequestCertificates(request, false); authRequired = certs != null && certs.length > 0; } @@ -625,11 +625,13 @@ public abstract class AuthenticatorBase * extracting the certificate chain from the Coyote request. * * @param request Request to be processed + * @param force Should a renegotiation be forced to request certificates + * from the user agent if none have been provided * * @return The X509 certificate chain if found, <code>null</code> * otherwise. */ - protected X509Certificate[] getRequestCertificates(final Request request) + protected X509Certificate[] getRequestCertificates(final Request request, boolean force) throws IllegalStateException { X509Certificate certs[] = @@ -637,7 +639,7 @@ public abstract class AuthenticatorBase if ((certs == null) || (certs.length < 1)) { try { - request.getCoyoteRequest().action (ActionCode.REQ_SSL_CERTIFICATE, null); + request.getCoyoteRequest().action(ActionCode.REQ_SSL_CERTIFICATE, Boolean.valueOf(force)); certs = (X509Certificate[]) request.getAttribute(Globals.CERTIFICATES_ATTR); } catch (IllegalStateException ise) { // Request body was too large for save buffer Modified: tomcat/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java?rev=1617461&r1=1617460&r2=1617461&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java (original) +++ tomcat/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java Tue Aug 12 12:42:18 2014 @@ -95,7 +95,7 @@ public class SSLAuthenticator extends Au containerLog.debug(" Looking up certificates"); } - X509Certificate certs[] = getRequestCertificates(request); + X509Certificate certs[] = getRequestCertificates(request, true); if ((certs == null) || (certs.length < 1)) { if (containerLog.isDebugEnabled()) { Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java?rev=1617461&r1=1617460&r2=1617461&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java Tue Aug 12 12:42:18 2014 @@ -419,18 +419,26 @@ public class Http11AprProcessor extends } case REQ_SSL_CERTIFICATE: { if (endpoint.isSSLEnabled() && (socketRef != 0)) { - // 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]); + boolean force = ((Boolean) param).booleanValue(); + if (force) { + /* Forced triggers a handshake so 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 { - // Configure connection to require a certificate - SSLSocket.setVerify(socketRef, SSL.SSL_CVERIFY_REQUIRE, - ((AprEndpoint)endpoint).getSSLVerifyDepth()); - // Renegotiate certificates - if (SSLSocket.renegotiate(socketRef) == 0) { - // Don't look for certs unless we know renegotiation worked. + if (force) { + // Configure connection to require a certificate + SSLSocket.setVerify(socketRef, SSL.SSL_CVERIFY_REQUIRE, + ((AprEndpoint)endpoint).getSSLVerifyDepth()); + } + if (!force || SSLSocket.renegotiate(socketRef) == 0) { + // Only look for certs if not forcing a renegotiation or + // if we know renegotiation worked. // Get client certificate and the certificate chain if present // certLength == -1 indicates an error int certLength = SSLSocket.getInfoI(socketRef,SSL.SSL_INFO_CLIENT_CERT_CHAIN); Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Processor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Processor.java?rev=1617461&r1=1617460&r2=1617461&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Processor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Processor.java Tue Aug 12 12:42:18 2014 @@ -465,18 +465,20 @@ public class Http11Nio2Processor extends } case REQ_SSL_CERTIFICATE: { if (sslSupport != null && socketWrapper.getSocket() != null) { - /* - * 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]); + boolean force = ((Boolean) param).booleanValue(); + if (force) { + /* Forced triggers a handshake so 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]); + } SecureNio2Channel sslChannel = (SecureNio2Channel) socketWrapper.getSocket(); SSLEngine engine = sslChannel.getSslEngine(); - if (!engine.getNeedClientAuth()) { + if (!engine.getNeedClientAuth() && force) { // Need to re-negotiate SSL connection engine.setNeedClientAuth(true); try { @@ -493,9 +495,8 @@ public class Http11Nio2Processor extends // use force=false since re-negotiation is handled above // (and it is a NO-OP for NIO anyway) Object sslO = sslSupport.getPeerCertificateChain(false); - if( sslO != null) { - request.setAttribute - (SSLSupport.CERTIFICATE_KEY, sslO); + if (sslO != null) { + request.setAttribute(SSLSupport.CERTIFICATE_KEY, sslO); } } catch (Exception e) { log.warn(sm.getString("http11processor.socket.ssl"), e); Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java?rev=1617461&r1=1617460&r2=1617461&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Tue Aug 12 12:42:18 2014 @@ -434,18 +434,20 @@ public class Http11NioProcessor extends } case REQ_SSL_CERTIFICATE: { if (sslSupport != null) { - /* - * 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]); + boolean force = ((Boolean) param).booleanValue(); + if (force) { + /* Forced triggers a handshake so 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]); + } SecureNioChannel sslChannel = (SecureNioChannel) socketWrapper.getSocket(); SSLEngine engine = sslChannel.getSslEngine(); - if (!engine.getNeedClientAuth()) { + if (!engine.getNeedClientAuth() && force) { // Need to re-negotiate SSL connection engine.setNeedClientAuth(true); try { @@ -462,9 +464,8 @@ public class Http11NioProcessor extends // use force=false since re-negotiation is handled above // (and it is a NO-OP for NIO anyway) Object sslO = sslSupport.getPeerCertificateChain(false); - if( sslO != null) { - request.setAttribute - (SSLSupport.CERTIFICATE_KEY, sslO); + if (sslO != null) { + request.setAttribute(SSLSupport.CERTIFICATE_KEY, sslO); } } catch (Exception e) { log.warn(sm.getString("http11processor.socket.ssl"), e); Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java?rev=1617461&r1=1617460&r2=1617461&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java Tue Aug 12 12:42:18 2014 @@ -350,17 +350,19 @@ public class Http11Processor extends Abs } case REQ_SSL_CERTIFICATE: { if (sslSupport != null) { - /* - * 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]); + boolean force = ((Boolean) param).booleanValue(); + if (force) { + /* Forced triggers a handshake so 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 { - Object sslO = sslSupport.getPeerCertificateChain(true); + Object sslO = sslSupport.getPeerCertificateChain(force); if( sslO != null) { request.setAttribute (SSLSupport.CERTIFICATE_KEY, sslO); Modified: tomcat/trunk/test/org/apache/tomcat/util/net/TestClientCert.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/net/TestClientCert.java?rev=1617461&r1=1617460&r2=1617461&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/util/net/TestClientCert.java (original) +++ tomcat/trunk/test/org/apache/tomcat/util/net/TestClientCert.java Tue Aug 12 12:42:18 2014 @@ -45,16 +45,24 @@ public class TestClientCert extends Tomc doTestClientCertGet(true); } - public void doTestClientCertGet(boolean preemtive) throws Exception { + private void doTestClientCertGet(boolean preemtive) throws Exception { Assume.assumeTrue("SSL renegotiation has to be supported for this test", TesterSupport.isRenegotiationSupported(getTomcatInstance())); if (preemtive) { + Tomcat tomcat = getTomcatInstance(); // Only one context deployed - Context c = (Context) getTomcatInstance().getHost().findChildren()[0]; + Context c = (Context) tomcat.getHost().findChildren()[0]; + // Enable pre-emptive auth c.setPreemptiveAuthentication(true); + + // Connector needs to advertise is accepts client certs for + // pre-emptive to work + tomcat.getConnector().setAttribute("clientAuth", "want"); } + getTomcatInstance().start(); + // Unprotected resource ByteChunk res = getUrl("https://localhost:" + getPort() + "/unprotected"); @@ -95,6 +103,8 @@ public class TestClientCert extends Tomc Assume.assumeTrue("SSL renegotiation has to be supported for this test", TesterSupport.isRenegotiationSupported(getTomcatInstance())); + getTomcatInstance().start(); + byte[] body = new byte[bodySize]; Arrays.fill(body, TesterSupport.DATA); @@ -122,9 +132,6 @@ public class TestClientCert extends Tomc TesterSupport.configureClientCertContext(tomcat); - // Start Tomcat - tomcat.start(); - TesterSupport.configureClientSsl(); } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org