You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2017/02/06 20:37:00 UTC

svn commit: r1781943 - in /tomcat/native/trunk: native/include/ssl_private.h native/os/win32/system.c native/src/ssl.c native/src/sslcontext.c native/src/sslnetwork.c native/src/sslutils.c xdocs/miscellaneous/changelog.xml

Author: markt
Date: Mon Feb  6 20:37:00 2017
New Revision: 1781943

URL: http://svn.apache.org/viewvc?rev=1781943&view=rev
Log:
Ensure that the per thread error hash maintained by OpenSSL is cleaned up as individual threads exit to ensure it does not grow too large.
Patch provided by Nate Clark.

Modified:
    tomcat/native/trunk/native/include/ssl_private.h
    tomcat/native/trunk/native/os/win32/system.c
    tomcat/native/trunk/native/src/ssl.c
    tomcat/native/trunk/native/src/sslcontext.c
    tomcat/native/trunk/native/src/sslnetwork.c
    tomcat/native/trunk/native/src/sslutils.c
    tomcat/native/trunk/xdocs/miscellaneous/changelog.xml

Modified: tomcat/native/trunk/native/include/ssl_private.h
URL: http://svn.apache.org/viewvc/tomcat/native/trunk/native/include/ssl_private.h?rev=1781943&r1=1781942&r2=1781943&view=diff
==============================================================================
--- tomcat/native/trunk/native/include/ssl_private.h (original)
+++ tomcat/native/trunk/native/include/ssl_private.h Mon Feb  6 20:37:00 2017
@@ -363,4 +363,13 @@ int         SSL_callback_select_next_pro
 int         SSL_callback_alpn_select_proto(SSL *, const unsigned char **, unsigned char *, const unsigned char *, unsigned int, void *);
 
 
+void SSL_thread_exit(void);
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) && ! defined(WIN32)
+unsigned long SSL_ERR_get(void);
+void SSL_ERR_clear(void);
+#else
+#define SSL_ERR_get() ERR_get_error()
+#define SSL_ERR_clear() ERR_clear_error()
+#endif
+
 #endif /* SSL_PRIVATE_H */

Modified: tomcat/native/trunk/native/os/win32/system.c
URL: http://svn.apache.org/viewvc/tomcat/native/trunk/native/os/win32/system.c?rev=1781943&r1=1781942&r2=1781943&view=diff
==============================================================================
--- tomcat/native/trunk/native/os/win32/system.c (original)
+++ tomcat/native/trunk/native/os/win32/system.c Mon Feb  6 20:37:00 2017
@@ -101,6 +101,9 @@ DllMain(
         /** The thread of the attached process terminates.
          */
         case DLL_THREAD_DETACH:
+#ifdef HAVE_OPENSSL
+            SSL_thread_exit();
+#endif
             break;
 
         /** DLL unload due to process termination

Modified: tomcat/native/trunk/native/src/ssl.c
URL: http://svn.apache.org/viewvc/tomcat/native/trunk/native/src/ssl.c?rev=1781943&r1=1781942&r2=1781943&view=diff
==============================================================================
--- tomcat/native/trunk/native/src/ssl.c (original)
+++ tomcat/native/trunk/native/src/ssl.c Mon Feb  6 20:37:00 2017
@@ -49,6 +49,8 @@ struct CRYPTO_dynlock_value {
     int line;
     apr_thread_mutex_t *mutex;
 };
+
+apr_threadkey_t *thread_exit_key;
 #endif
 
 /*
@@ -435,7 +437,29 @@ static unsigned long ssl_thread_id(void)
 #endif
 }
 
+void SSL_thread_exit(void) {
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+    ERR_remove_thread_state(NULL);
+    apr_threadkey_private_set(NULL, thread_exit_key);
+#endif
+}
+
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
+unsigned long SSL_ERR_get() {
+    apr_threadkey_private_set(thread_exit_key, thread_exit_key);
+    return ERR_get_error();
+}
+
+void SSL_ERR_clear() {
+    apr_threadkey_private_set(thread_exit_key, thread_exit_key);
+    ERR_clear_error();
+}
+
+static void _ssl_thread_exit(void *data) {
+    UNREFERENCED(data);
+    SSL_thread_exit();
+}
+
 static void ssl_set_thread_id(CRYPTO_THREADID *id)
 {
     CRYPTO_THREADID_set_numeric(id, ssl_thread_id());
@@ -700,6 +724,9 @@ TCN_IMPLEMENT_CALL(jint, SSL, initialize
 {
     jclass clazz;
     jclass sClazz;
+#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER < 0x10100000L
+    apr_status_t err = APR_SUCCESS;
+#endif
 
     TCN_ALLOC_CSTRING(engine);
 
@@ -729,6 +756,14 @@ TCN_IMPLEMENT_CALL(jint, SSL, initialize
     OPENSSL_load_builtin_modules();
 
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
+    err = apr_threadkey_private_create(&thread_exit_key, _ssl_thread_exit,
+                                       tcn_global_pool);
+    if (err != APR_SUCCESS) {
+        ssl_init_cleanup(NULL);
+        tcn_ThrowAPRException(e, err);
+        return (jint)err;
+    }
+
     /* Initialize thread support */
     ssl_thread_setup(tcn_global_pool);
 #endif
@@ -736,7 +771,6 @@ TCN_IMPLEMENT_CALL(jint, SSL, initialize
 #ifndef OPENSSL_NO_ENGINE
     if (J2S(engine)) {
         ENGINE *ee = NULL;
-        apr_status_t err = APR_SUCCESS;
         if(strcmp(J2S(engine), "auto") == 0) {
             ENGINE_register_all_complete();
         }
@@ -859,7 +893,7 @@ TCN_IMPLEMENT_CALL(jint, SSL, fipsModeSe
 #ifdef OPENSSL_FIPS
     if(1 != (r = (jint)FIPS_mode_set((int)mode))) {
       /* arrange to get a human-readable error message */
-      unsigned long err = ERR_get_error();
+      unsigned long err = SSL_ERR_get();
       char msg[256];
 
       /* ERR_load_crypto_strings() already called in initialize() */
@@ -1196,7 +1230,7 @@ TCN_IMPLEMENT_CALL(jstring, SSL, getLast
 {
     char buf[256];
     UNREFERENCED(o);
-    ERR_error_string(ERR_get_error(), buf);
+    ERR_error_string(SSL_ERR_get(), buf);
     return tcn_new_string(e, buf);
 }
 
@@ -1208,7 +1242,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSL, hasOp)
 /*** Begin Twitter 1:1 API addition ***/
 TCN_IMPLEMENT_CALL(jint, SSL, getLastErrorNumber)(TCN_STDARGS) {
     UNREFERENCED_STDARGS;
-    return ERR_get_error();
+    return SSL_ERR_get();
 }
 
 static void ssl_info_callback(const SSL *ssl, int where, int ret) {
@@ -1784,7 +1818,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSL, setCip
     }
     if (!SSL_set_cipher_list(ssl_, J2S(ciphers))) {
         char err[256];
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Unable to configure permitted SSL ciphers (%s)", err);
         rv = JNI_FALSE;
     }

Modified: tomcat/native/trunk/native/src/sslcontext.c
URL: http://svn.apache.org/viewvc/tomcat/native/trunk/native/src/sslcontext.c?rev=1781943&r1=1781942&r2=1781943&view=diff
==============================================================================
--- tomcat/native/trunk/native/src/sslcontext.c (original)
+++ tomcat/native/trunk/native/src/sslcontext.c Mon Feb  6 20:37:00 2017
@@ -206,7 +206,7 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, ma
 
     if (!ctx) {
         char err[256];
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Invalid Server SSL Protocol (%s)", err);
         goto init_failed;
     }
@@ -478,7 +478,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     if (!SSL_CTX_set_cipher_list(c->ctx, J2S(ciphers))) {
 #endif
         char err[256];
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Unable to configure permitted SSL ciphers (%s)", err);
         rv = JNI_FALSE;
     }
@@ -512,7 +512,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     if (J2S(file)) {
         lookup = X509_STORE_add_lookup(c->crl, X509_LOOKUP_file());
         if (lookup == NULL) {
-            ERR_error_string(ERR_get_error(), err);
+            ERR_error_string(SSL_ERR_get(), err);
             X509_STORE_free(c->crl);
             c->crl = NULL;
             tcn_Throw(e, "Lookup failed for file %s (%s)", J2S(file), err);
@@ -523,7 +523,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     if (J2S(path)) {
         lookup = X509_STORE_add_lookup(c->crl, X509_LOOKUP_hash_dir());
         if (lookup == NULL) {
-            ERR_error_string(ERR_get_error(), err);
+            ERR_error_string(SSL_ERR_get(), err);
             X509_STORE_free(c->crl);
             c->crl = NULL;
             tcn_Throw(e, "Lookup failed for path %s (%s)", J2S(file), err);
@@ -577,7 +577,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     if (!SSL_CTX_load_verify_locations(c->ctx,
                                        J2S(file), J2S(path))) {
         char err[256];
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Unable to configure locations "
                   "for client authentication (%s)", err);
         rv = JNI_FALSE;
@@ -642,7 +642,7 @@ TCN_IMPLEMENT_CALL(void, SSLContext, set
     bio = BIO_new_file(J2S(file), "r");
     if (!bio) {
         char err[256];
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error while configuring DH using %s: %s", J2S(file), err);
         TCN_FREE_CSTRING(file);
         return;
@@ -652,7 +652,7 @@ TCN_IMPLEMENT_CALL(void, SSLContext, set
     BIO_free(bio);
     if (!dh) {
         char err[256];
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error while configuring DH: no DH parameter found in %s (%s)", J2S(file), err);
         TCN_FREE_CSTRING(file);
         return;
@@ -661,7 +661,7 @@ TCN_IMPLEMENT_CALL(void, SSLContext, set
     if (1 != SSL_CTX_set_tmp_dh(c->ctx, dh)) {
         char err[256];
         DH_free(dh);
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error while configuring DH with file %s: %s", J2S(file), err);
         TCN_FREE_CSTRING(file);
         return;
@@ -702,7 +702,7 @@ TCN_IMPLEMENT_CALL(void, SSLContext, set
     if (1 != SSL_CTX_set_tmp_ecdh(c->ctx, ecdh)) {
         char err[256];
         EC_KEY_free(ecdh);
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error while configuring elliptic curve %s: %s", J2S(curveName), err);
         TCN_FREE_CSTRING(curveName);
         return;
@@ -809,7 +809,7 @@ static X509 *load_pem_cert(tcn_ssl_ctxt_
                 (void *)cb_data);
     if (cert == NULL &&
        (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE)) {
-        ERR_clear_error();
+        SSL_ERR_clear();
         BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL);
         cert = d2i_X509_bio(bio, NULL);
     }
@@ -921,7 +921,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     }
     if ((p = strrchr(cert_file, '.')) != NULL && strcmp(p, ".pkcs12") == 0) {
         if (!ssl_load_pkcs12(c, cert_file, &c->keys[idx], &c->certs[idx], 0)) {
-            ERR_error_string(ERR_get_error(), err);
+            ERR_error_string(SSL_ERR_get(), err);
             tcn_Throw(e, "Unable to load certificate %s (%s)",
                       cert_file, err);
             rv = JNI_FALSE;
@@ -930,14 +930,14 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     }
     else {
         if ((c->keys[idx] = load_pem_key(c, key_file)) == NULL) {
-            ERR_error_string(ERR_get_error(), err);
+            ERR_error_string(SSL_ERR_get(), err);
             tcn_Throw(e, "Unable to load certificate key %s (%s)",
                       key_file, err);
             rv = JNI_FALSE;
             goto cleanup;
         }
         if ((c->certs[idx] = load_pem_cert(c, cert_file)) == NULL) {
-            ERR_error_string(ERR_get_error(), err);
+            ERR_error_string(SSL_ERR_get(), err);
             tcn_Throw(e, "Unable to load certificate %s (%s)",
                       cert_file, err);
             rv = JNI_FALSE;
@@ -945,19 +945,19 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
         }
     }
     if (SSL_CTX_use_certificate(c->ctx, c->certs[idx]) <= 0) {
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error setting certificate (%s)", err);
         rv = JNI_FALSE;
         goto cleanup;
     }
     if (SSL_CTX_use_PrivateKey(c->ctx, c->keys[idx]) <= 0) {
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error setting private key (%s)", err);
         rv = JNI_FALSE;
         goto cleanup;
     }
     if (SSL_CTX_check_private_key(c->ctx) <= 0) {
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Private key does not match the certificate public key (%s)",
                   err);
         rv = JNI_FALSE;
@@ -1050,7 +1050,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     tmp = (const unsigned char *)cert;
     certs = d2i_X509(NULL, &tmp, lengthOfCert);
     if (certs == NULL) {
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error reading certificate (%s)", err);
         rv = JNI_FALSE;
         goto cleanup;
@@ -1066,7 +1066,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     evp = PEM_read_bio_PrivateKey(bio, NULL, 0, NULL);
     if (evp == NULL) {
         BIO_free(bio);
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error reading private key (%s)", err);
         rv = JNI_FALSE;
         goto cleanup;
@@ -1078,19 +1078,19 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     c->keys[idx] = evp;
 
     if (SSL_CTX_use_certificate(c->ctx, c->certs[idx]) <= 0) {
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error setting certificate (%s)", err);
         rv = JNI_FALSE;
         goto cleanup;
     }
     if (SSL_CTX_use_PrivateKey(c->ctx, c->keys[idx]) <= 0) {
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error setting private key (%s)", err);
         rv = JNI_FALSE;
         goto cleanup;
     }
     if (SSL_CTX_check_private_key(c->ctx) <= 0) {
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Private key does not match the certificate public key (%s)",
                   err);
         rv = JNI_FALSE;
@@ -1145,11 +1145,11 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     tmp = (const unsigned char *)cert;
     certs = d2i_X509(NULL, &tmp, lengthOfCert);
     if (certs == NULL) {
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error reading certificate (%s)", err);
         rv = JNI_FALSE;
     } else if (SSL_CTX_add0_chain_cert(c->ctx, certs) <= 0) {
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(e, "Error adding certificate to chain (%s)", err);
         rv = JNI_FALSE;
     }

Modified: tomcat/native/trunk/native/src/sslnetwork.c
URL: http://svn.apache.org/viewvc/tomcat/native/trunk/native/src/sslnetwork.c?rev=1781943&r1=1781942&r2=1781943&view=diff
==============================================================================
--- tomcat/native/trunk/native/src/sslnetwork.c (original)
+++ tomcat/native/trunk/native/src/sslnetwork.c Mon Feb  6 20:37:00 2017
@@ -127,7 +127,7 @@ static tcn_ssl_conn_t *ssl_create(JNIEnv
     }
     if ((ssl = SSL_new(ctx->ctx)) == NULL) {
         char err[256];
-        ERR_error_string(ERR_get_error(), err);
+        ERR_error_string(SSL_ERR_get(), err);
         tcn_Throw(env, "SSL_new failed (%s)", err);
         con = NULL;
         return NULL;
@@ -320,7 +320,7 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, hand
 
     apr_socket_timeout_get(con->sock, &timeout);
     while (!SSL_is_init_finished(con->ssl)) {
-        ERR_clear_error();
+        SSL_ERR_clear();
         if ((s = SSL_do_handshake(con->ssl)) <= 0) {
             if (!con->ssl)
                 return APR_ENOTSOCK;
@@ -406,7 +406,7 @@ ssl_socket_recv(apr_socket_t *sock, char
     }
     apr_socket_timeout_get(con->sock, &timeout);
     for (;;) {
-        ERR_clear_error();
+        SSL_ERR_clear();
         if ((s = SSL_read(con->ssl, buf, rd)) <= 0) {
             if (!con->ssl)
                 return APR_ENOTSOCK;
@@ -488,7 +488,7 @@ ssl_socket_send(apr_socket_t *sock, cons
     }
     apr_socket_timeout_get(con->sock, &timeout);
     for (;;) {
-        ERR_clear_error();
+        SSL_ERR_clear();
         if ((s = SSL_write(con->ssl, buf, wr)) <= 0) {
             if (!con->ssl)
                 return APR_ENOTSOCK;

Modified: tomcat/native/trunk/native/src/sslutils.c
URL: http://svn.apache.org/viewvc/tomcat/native/trunk/native/src/sslutils.c?rev=1781943&r1=1781942&r2=1781943&view=diff
==============================================================================
--- tomcat/native/trunk/native/src/sslutils.c (original)
+++ tomcat/native/trunk/native/src/sslutils.c Mon Feb  6 20:37:00 2017
@@ -281,7 +281,7 @@ int SSL_CTX_use_certificate_chain(SSL_CT
             BIO_free(bio);
             return -1;
         }
-        while (ERR_get_error() > 0) ;
+        while (SSL_ERR_get() > 0) ;
     }
     BIO_free(bio);
     return n;

Modified: tomcat/native/trunk/xdocs/miscellaneous/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/native/trunk/xdocs/miscellaneous/changelog.xml?rev=1781943&r1=1781942&r2=1781943&view=diff
==============================================================================
--- tomcat/native/trunk/xdocs/miscellaneous/changelog.xml (original)
+++ tomcat/native/trunk/xdocs/miscellaneous/changelog.xml Mon Feb  6 20:37:00 2017
@@ -61,6 +61,11 @@
       an external is used to reference the main code. (markt)
     </fix>
     <fix>
+      <bug>59797</bug>: Ensure that the per thread error hash maintained by
+      OpenSSL is cleaned up as individual threads exit to ensure it does not
+      grow too large. Patch provided by Nate Clark. (markt) 
+    </fix>
+    <fix>
       <bug>59996</bug>: Correctly handle building tc-native on a 64-bit system
       when using an OpenSSL distribution that is not in <code>/usr</code>.
       (csutherl)



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