Author: remm Date: Thu Dec 3 17:14:57 2015 New Revision: 1717808 URL: http://svn.apache.org/viewvc?rev=1717808&view=rev Log: - Add some renegotiation code to the OpenSSL SSLEngine. It seems to do something, but certificate extraction doesn't work (returns null). - Allow using the OpenSSL engine with the testsuite using a test.sslImplementation property (set to the sslImplementationName from server.xml).
Modified: tomcat/trunk/build.xml tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java Modified: tomcat/trunk/build.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/build.xml?rev=1717808&r1=1717807&r2=1717808&view=diff ============================================================================== --- tomcat/trunk/build.xml (original) +++ tomcat/trunk/build.xml Thu Dec 3 17:14:57 2015 @@ -1455,6 +1455,7 @@ <sysproperty key="tomcat.test.reports" value="${test.reports}" /> <sysproperty key="tomcat.test.openssl.path" value="${test.openssl.path}" /> <sysproperty key="tomcat.test.relaxTiming" value="${test.relaxTiming}" /> + <sysproperty key="tomcat.test.sslImplementation" value="${test.sslImplementation}" /> <!-- File for Cobertura to write coverage results to --> <sysproperty key="net.sourceforge.cobertura.datafile" file="${cobertura.datafile}" /> Modified: tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java?rev=1717808&r1=1717807&r2=1717808&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java Thu Dec 3 17:14:57 2015 @@ -445,6 +445,7 @@ public class OpenSSLContext implements o SSLContext.free(ctx); } } - destroyPools(); + //FIXME: this causes crashes in the testsuite + //destroyPools(); } } Modified: tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java?rev=1717808&r1=1717807&r2=1717808&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java Thu Dec 3 17:14:57 2015 @@ -161,8 +161,8 @@ public final class OpenSSLEngine extends private volatile String cipher; private volatile String applicationProtocol; - // We store this outside of the SslSession so we not need to create an instance during verifyCertificates(...) private volatile Certificate[] peerCerts; + private volatile X509Certificate[] x509PeerCerts; private volatile ClientAuthMode clientAuth = ClientAuthMode.NONE; // SSL Engine status variables @@ -629,18 +629,7 @@ public final class OpenSSLEngine extends // check if SSL_read returned <= 0. In this case we need to check the error and see if it was something // fatal. if (lastPrimingReadResult <= 0) { - // Check for OpenSSL errors caused by the priming read - long error = SSL.getLastErrorNumber(); - if (error != SSL.SSL_ERROR_NONE) { - String err = SSL.getErrorString(error); - if (logger.isDebugEnabled()) { - logger.debug(sm.getString("engine.readFromSSLFailed", Long.toString(error), - Integer.toString(lastPrimingReadResult), err)); - } - // There was an internal error -- shutdown - shutdown(); - throw new SSLException(err); - } + checkLastError(); } return SSL.pendingReadableBytesInSSL(ssl); } @@ -835,45 +824,6 @@ public final class OpenSSLEngine extends } } - private Certificate[] initPeerCertChain() throws SSLPeerUnverifiedException { - byte[][] chain = SSL.getPeerCertChain(ssl); - byte[] clientCert; - if (!clientMode) { - // if used on the server side SSL_get_peer_cert_chain(...) will not include the remote peer certificate. - // We use SSL_get_peer_certificate to get it in this case and add it to our array later. - // - // See https://www.openssl.org/docs/ssl/SSL_get_peer_cert_chain.html - clientCert = SSL.getPeerCertificate(ssl); - } else { - clientCert = null; - } - - if (chain == null && clientCert == null) { - throw new SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer")); - } - int len = 0; - if (chain != null) { - len += chain.length; - } - - int i = 0; - Certificate[] peerCerts; - if (clientCert != null) { - len++; - peerCerts = new Certificate[len]; - peerCerts[i++] = new OpenSslX509Certificate(clientCert); - } else { - peerCerts = new Certificate[len]; - } - if (chain != null) { - int a = 0; - for (; i < peerCerts.length; i++) { - peerCerts[i] = new OpenSslX509Certificate(chain[a++]); - } - } - return peerCerts; - } - @Override public SSLSession getSession() { return session; @@ -899,7 +849,8 @@ public final class OpenSSLEngine extends accepted = 2; // Next time this method is invoked by the user, we should raise an exception. break; case 2: - throw RENEGOTIATION_UNSUPPORTED; + renegotiate(); + break; default: throw new Error(); } @@ -919,17 +870,7 @@ public final class OpenSSLEngine extends private void handshake() throws SSLException { int code = SSL.doHandshake(ssl); if (code <= 0) { - // Check for OpenSSL errors caused by the handshake - long error = SSL.getLastErrorNumber(); - if (error != SSL.SSL_ERROR_NONE) { - String err = SSL.getErrorString(error); - if (logger.isDebugEnabled()) { - logger.debug(sm.getString("engine.handshakeFailure", err)); - } - // There was an internal error -- shutdown - shutdown(); - throw new SSLException(err); - } + checkLastError(); } else { if (alpn) { selectedProtocol = SSL.getAlpnSelected(ssl); @@ -944,6 +885,31 @@ public final class OpenSSLEngine extends } } + private void renegotiate() throws SSLException { + int code = SSL.renegotiate(ssl); + if (code <= 0) { + checkLastError(); + } else { + handshakeFinished = false; + peerCerts = null; + x509PeerCerts = null; + } + code = SSL.doHandshake(ssl); + if (code <= 0) { + checkLastError(); + } + } + + private void checkLastError() throws SSLException { + long error = SSL.getLastErrorNumber(); + if (error != SSL.SSL_ERROR_NONE) { + String err = SSL.getErrorString(error); + // There was an internal error -- shutdown + shutdown(); + throw new SSLException(err); + } + } + private static long memoryAddress(ByteBuffer buf) { return Buffer.address(buf); } @@ -1109,9 +1075,6 @@ public final class OpenSSLEngine extends private class OpenSSLSession implements SSLSession { - // SSLSession implementation seems to not need to be thread-safe so no need for volatile etc. - private X509Certificate[] x509PeerCerts; - // lazy init for memory reasons private Map<String, Object> values; @@ -1222,7 +1185,41 @@ public final class OpenSSLEngine extends if (SSL.isInInit(ssl) != 0) { throw new SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer")); } - c = peerCerts = initPeerCertChain(); + byte[][] chain = SSL.getPeerCertChain(ssl); + byte[] clientCert; + if (!clientMode) { + // if used on the server side SSL_get_peer_cert_chain(...) will not include the remote peer certificate. + // We use SSL_get_peer_certificate to get it in this case and add it to our array later. + // + // See https://www.openssl.org/docs/ssl/SSL_get_peer_cert_chain.html + clientCert = SSL.getPeerCertificate(ssl); + } else { + clientCert = null; + } + if (chain == null && clientCert == null) { + return null; + } + int len = 0; + if (chain != null) { + len += chain.length; + } + + int i = 0; + Certificate[] certificates; + if (clientCert != null) { + len++; + certificates = new Certificate[len]; + certificates[i++] = new OpenSslX509Certificate(clientCert); + } else { + certificates = new Certificate[len]; + } + if (chain != null) { + int a = 0; + for (; i < certificates.length; i++) { + certificates[i] = new OpenSslX509Certificate(chain[a++]); + } + } + c = peerCerts = certificates; } return c; } Modified: tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java?rev=1717808&r1=1717807&r2=1717808&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java (original) +++ tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java Thu Dec 3 17:14:57 2015 @@ -38,6 +38,8 @@ import javax.servlet.http.HttpServletRes import org.apache.catalina.Context; import org.apache.catalina.authenticator.SSLAuthenticator; import org.apache.catalina.connector.Connector; +import org.apache.catalina.core.AprLifecycleListener; +import org.apache.catalina.core.StandardServer; import org.apache.catalina.startup.TesterMapRealm; import org.apache.catalina.startup.Tomcat; import org.apache.tomcat.util.descriptor.web.LoginConfig; @@ -58,6 +60,14 @@ public final class TesterSupport { String protocol = tomcat.getConnector().getProtocolHandlerClassName(); if (protocol.indexOf("Apr") == -1) { Connector connector = tomcat.getConnector(); + String sslImplementation = System.getProperty("tomcat.test.sslImplementation"); + if (sslImplementation != null && !"${test.sslImplementation}".equals(sslImplementation)) { + StandardServer server = (StandardServer) tomcat.getServer(); + AprLifecycleListener listener = new AprLifecycleListener(); + listener.setSSLRandomSeed("/dev/urandom"); + server.addLifecycleListener(listener); + tomcat.getConnector().setAttribute("sslImplementationName", sslImplementation); + } connector.setProperty("sslProtocol", "tls"); File keystoreFile = new File("test/org/apache/tomcat/util/net/" + keystore); --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org