Author: remm
Date: Mon Jun 19 14:40:46 2017
New Revision: 1799216

URL: http://svn.apache.org/viewvc?rev=1799216&view=rev
Log:
Derived from 60461, protect the SSL session provided by the OpenSSL engine from 
concurrent destruction.

Modified:
    tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java
    tomcat/trunk/webapps/docs/changelog.xml

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=1799216&r1=1799215&r2=1799216&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 Mon 
Jun 19 14:40:46 2017
@@ -1041,8 +1041,13 @@ public final class OpenSSLEngine extends
 
         @Override
         public byte[] getId() {
-            // We don't cache that to keep memory usage to a minimum.
-            byte[] id = SSL.getSessionId(ssl);
+            byte[] id;
+            synchronized (OpenSSLEngine.this) {
+                if (destroyed) {
+                    throw new 
IllegalStateException(sm.getString("engine.noSession"));
+                }
+                id = SSL.getSessionId(ssl);
+            }
             if (id == null) {
                 // The id should never be null, if it was null then the 
SESSION itself was not valid.
                 throw new 
IllegalStateException(sm.getString("engine.noSession"));
@@ -1058,7 +1063,14 @@ public final class OpenSSLEngine extends
         @Override
         public long getCreationTime() {
             // We need to multiply by 1000 as OpenSSL uses seconds and we need 
milliseconds.
-            return SSL.getTime(ssl) * 1000L;
+            long creationTime = 0;
+            synchronized (OpenSSLEngine.this) {
+                if (destroyed) {
+                    throw new 
IllegalStateException(sm.getString("engine.noSession"));
+                }
+                creationTime = SSL.getTime(ssl);
+            }
+            return creationTime * 1000L;
         }
 
         @Override
@@ -1140,19 +1152,22 @@ public final class OpenSSLEngine extends
             // these are lazy created to reduce memory overhead
             Certificate[] c = peerCerts;
             if (c == null) {
-                if (SSL.isInInit(ssl) != 0) {
-                    throw new 
SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer"));
-                }
-                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;
+                byte[][] chain;
+                synchronized (OpenSSLEngine.this) {
+                    if (destroyed || SSL.isInInit(ssl) != 0) {
+                        throw new 
SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer"));
+                    }
+                    chain = SSL.getPeerCertChain(ssl);
+                    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;
@@ -1193,10 +1208,13 @@ public final class OpenSSLEngine extends
             // these are lazy created to reduce memory overhead
             X509Certificate[] c = x509PeerCerts;
             if (c == null) {
-                if (SSL.isInInit(ssl) != 0) {
-                    throw new 
SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer"));
+                byte[][] chain;
+                synchronized (OpenSSLEngine.this) {
+                    if (destroyed || SSL.isInInit(ssl) != 0) {
+                        throw new 
SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer"));
+                    }
+                    chain = SSL.getPeerCertChain(ssl);
                 }
-                byte[][] chain = SSL.getPeerCertChain(ssl);
                 if (chain == null) {
                     throw new 
SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer"));
                 }
@@ -1241,7 +1259,14 @@ public final class OpenSSLEngine extends
                 return INVALID_CIPHER;
             }
             if (cipher == null) {
-                String c = 
OpenSSLCipherConfigurationParser.openSSLToJsse(SSL.getCipherForSSL(ssl));
+                String ciphers;
+                synchronized (OpenSSLEngine.this) {
+                    if (destroyed) {
+                        return INVALID_CIPHER;
+                    }
+                    ciphers = SSL.getCipherForSSL(ssl);
+                }
+                String c = 
OpenSSLCipherConfigurationParser.openSSLToJsse(ciphers);
                 if (c != null) {
                     cipher = c;
                 }
@@ -1253,7 +1278,12 @@ public final class OpenSSLEngine extends
         public String getProtocol() {
             String applicationProtocol = 
OpenSSLEngine.this.applicationProtocol;
             if (applicationProtocol == null) {
-                applicationProtocol = SSL.getNextProtoNegotiated(ssl);
+                synchronized (OpenSSLEngine.this) {
+                    if (destroyed) {
+                        throw new 
IllegalStateException(sm.getString("engine.noSession"));
+                    }
+                    applicationProtocol = SSL.getNextProtoNegotiated(ssl);
+                }
                 if (applicationProtocol == null) {
                     applicationProtocol = fallbackApplicationProtocol;
                 }
@@ -1263,7 +1293,13 @@ public final class OpenSSLEngine extends
                     OpenSSLEngine.this.applicationProtocol = 
applicationProtocol = "";
                 }
             }
-            String version = SSL.getVersion(ssl);
+            String version;
+            synchronized (OpenSSLEngine.this) {
+                if (destroyed) {
+                    throw new 
IllegalStateException(sm.getString("engine.noSession"));
+                }
+                version = SSL.getVersion(ssl);
+            }
             if (applicationProtocol.isEmpty()) {
                 return version;
             } else {

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1799216&r1=1799215&r2=1799216&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Mon Jun 19 14:40:46 2017
@@ -148,6 +148,11 @@
         <code>AsyncListener</code>s after an I/O error on a non-container
         thread. (markt)
       </fix>
+      <fix>
+        Add additional syncs to the SSL session object provided by the OpenSSL
+        engine so that a concurrent destruction cannot cause a JVM crash.
+        (remm)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Jasper">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to