You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2015/12/03 18:14:57 UTC

svn commit: r1717808 - in /tomcat/trunk: build.xml java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java test/org/apache/tomcat/util/net/TesterSupport.java

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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org