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