ruby-changes:43209
From: rhe <ko1@a...>
Date: Sun, 5 Jun 2016 21:46:11 +0900 (JST)
Subject: [ruby-changes:43209] rhe:r55283 (trunk): openssl: support OpenSSL 1.1.0's new multi-threading API
rhe 2016-06-05 21:46:05 +0900 (Sun, 05 Jun 2016) New Revision: 55283 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=55283 Log: openssl: support OpenSSL 1.1.0's new multi-threading API * ext/openssl/extconf.rb: Check absence of CRYPTO_lock() to see if the OpenSSL has the new threading API. In OpenSSL <= 1.0.2, an application had to set locking callbacks to use OpenSSL in a multi-threaded environment. OpenSSL 1.1.0 now finds pthreads or Windows threads so we don't need to do something special. [ruby-core:75225] [Feature #12324] Also check existence of *_up_ref(). Some structures in OpenSSL have a reference counter. We used to increment it with CRYPTO_add() which is a part of the old API. * ext/openssl/openssl_missing.h: Implement *_up_ref() if missing. * ext/openssl/ossl.c: Don't set locking callbacks if unneeded. * ext/openssl/ossl_pkey.c, ext/openssl/ossl_ssl.c, ext/openssl/ossl_x509cert.c, ext/openssl/ossl_x509crl.c, ext/openssl/ossl_x509store.c: Use *_up_ref() instead of CRYPTO_add(). Modified files: trunk/ChangeLog trunk/ext/openssl/extconf.rb trunk/ext/openssl/openssl_missing.h trunk/ext/openssl/ossl.c trunk/ext/openssl/ossl_pkey.c trunk/ext/openssl/ossl_ssl.c trunk/ext/openssl/ossl_x509cert.c trunk/ext/openssl/ossl_x509crl.c trunk/ext/openssl/ossl_x509store.c Index: ext/openssl/ossl_x509crl.c =================================================================== --- ext/openssl/ossl_x509crl.c (revision 55282) +++ ext/openssl/ossl_x509crl.c (revision 55283) @@ -67,7 +67,7 @@ DupX509CRLPtr(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_x509crl.c#L67 X509_CRL *crl; SafeGetX509CRL(obj, crl); - CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL); + X509_CRL_up_ref(crl); return crl; } Index: ext/openssl/extconf.rb =================================================================== --- ext/openssl/extconf.rb (revision 55282) +++ ext/openssl/extconf.rb (revision 55283) @@ -107,9 +107,15 @@ OpenSSL.check_func_or_macro("SSL_CTX_set https://github.com/ruby/ruby/blob/trunk/ext/openssl/extconf.rb#L107 OpenSSL.check_func_or_macro("SSL_get_server_tmp_key", "openssl/ssl.h") # added in 1.1.0 +have_func("CRYPTO_lock") || $defs.push("-DHAVE_OPENSSL_110_THREADING_API") OpenSSL.check_func("RAND_pseudo_bytes", "openssl/rand.h") # deprecated have_func("X509_STORE_get_ex_data") have_func("X509_STORE_set_ex_data") +have_func("X509_up_ref") +have_func("X509_CRL_up_ref") +have_func("X509_STORE_up_ref") +have_func("SSL_SESSION_up_ref") +have_func("EVP_PKEY_up_ref") OpenSSL.check_func_or_macro("SSL_CTX_set_tmp_ecdh_callback", "openssl/ssl.h") # removed Logging::message "=== Checking done. ===\n" Index: ext/openssl/ossl_ssl.c =================================================================== --- ext/openssl/ossl_ssl.c (revision 55282) +++ ext/openssl/ossl_ssl.c (revision 55283) @@ -128,8 +128,10 @@ static void https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L128 ossl_sslctx_free(void *ptr) { SSL_CTX *ctx = ptr; +#if !defined(HAVE_X509_STORE_UP_REF) if(ctx && SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_store_p)== (void*)1) ctx->cert_store = NULL; +#endif SSL_CTX_free(ctx); } @@ -397,7 +399,7 @@ ossl_sslctx_session_new_cb(SSL *ssl, SSL https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L399 return 1; ssl_obj = (VALUE)ptr; sess_obj = rb_obj_alloc(cSSLSession); - CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION); + SSL_SESSION_up_ref(sess); DATA_PTR(sess_obj) = sess; ary = rb_ary_new2(2); @@ -446,7 +448,7 @@ ossl_sslctx_session_remove_cb(SSL_CTX *c https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L448 return; sslctx_obj = (VALUE)ptr; sess_obj = rb_obj_alloc(cSSLSession); - CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION); + SSL_SESSION_up_ref(sess); DATA_PTR(sess_obj) = sess; ary = rb_ary_new2(2); @@ -708,7 +710,6 @@ ossl_sslctx_setup(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L710 { SSL_CTX *ctx; X509 *cert = NULL, *client_ca = NULL; - X509_STORE *store; EVP_PKEY *key = NULL; char *ca_path = NULL, *ca_file = NULL; int verify_mode; @@ -743,16 +744,20 @@ ossl_sslctx_setup(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L744 #endif /* OPENSSL_NO_EC */ val = ossl_sslctx_get_cert_store(self); - if(!NIL_P(val)){ + if (!NIL_P(val)) { + X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */ + SSL_CTX_set_cert_store(ctx, store); +#if !defined(HAVE_X509_STORE_UP_REF) /* * WORKAROUND: * X509_STORE can count references, but * X509_STORE_free() doesn't care it. * So we won't increment it but mark it by ex_data. */ - store = GetX509StorePtr(val); /* NO NEED TO DUP */ - SSL_CTX_set_cert_store(ctx, store); - SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1); + SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void *)1); +#else /* Fixed in OpenSSL 1.0.2; bff9ce4db38b (master), 5b4b9ce976fc (1.0.2) */ + X509_STORE_up_ref(store); +#endif } val = ossl_sslctx_get_extra_cert(self); Index: ext/openssl/ossl_pkey.c =================================================================== --- ext/openssl/ossl_pkey.c (revision 55282) +++ ext/openssl/ossl_pkey.c (revision 55283) @@ -191,7 +191,7 @@ DupPKeyPtr(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey.c#L191 EVP_PKEY *pkey; SafeGetPKey(obj, pkey); - CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); + EVP_PKEY_up_ref(pkey); return pkey; } @@ -205,7 +205,7 @@ DupPrivPKeyPtr(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey.c#L205 ossl_raise(rb_eArgError, "Private key is needed."); } SafeGetPKey(obj, pkey); - CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); + EVP_PKEY_up_ref(pkey); return pkey; } Index: ext/openssl/ossl.c =================================================================== --- ext/openssl/ossl.c (revision 55282) +++ ext/openssl/ossl.c (revision 55283) @@ -508,6 +508,7 @@ ossl_fips_mode_set(VALUE self, VALUE ena https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl.c#L508 #endif } +#if !defined(HAVE_OPENSSL_110_THREADING_API) /** * Stores locks needed for OpenSSL thread safety */ @@ -595,6 +596,7 @@ static void Init_ossl_locks(void) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl.c#L596 CRYPTO_set_dynlock_lock_callback(ossl_dyn_lock_callback); CRYPTO_set_dynlock_destroy_callback(ossl_dyn_destroy_callback); } +#endif /* !HAVE_OPENSSL_110_THREADING_API */ /* * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the @@ -1195,7 +1197,9 @@ Init_openssl(void) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl.c#L1197 */ ossl_s_to_der = rb_intern("to_der"); +#if !defined(HAVE_OPENSSL_110_THREADING_API) Init_ossl_locks(); +#endif /* * Init components Index: ext/openssl/openssl_missing.h =================================================================== --- ext/openssl/openssl_missing.h (revision 55282) +++ ext/openssl/openssl_missing.h (revision 55283) @@ -45,4 +45,29 @@ int EC_curve_nist2nid(const char *); https://github.com/ruby/ruby/blob/trunk/ext/openssl/openssl_missing.h#L45 (newf), (dupf), (freef)) #endif +#if !defined(HAVE_X509_UP_REF) +# define X509_up_ref(x) \ + CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509) +#endif + +#if !defined(HAVE_X509_CRL_UP_REF) +# define X509_CRL_up_ref(x) \ + CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509_CRL); +#endif + +#if !defined(HAVE_X509_STORE_UP_REF) +# define X509_STORE_up_ref(x) \ + CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509_STORE); +#endif + +#if !defined(HAVE_SSL_SESSION_UP_REF) +# define SSL_SESSION_up_ref(x) \ + CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_SSL_SESSION); +#endif + +#if !defined(HAVE_EVP_PKEY_UP_REF) +# define EVP_PKEY_up_ref(x) \ + CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_EVP_PKEY); +#endif + #endif /* _OSSL_OPENSSL_MISSING_H_ */ Index: ext/openssl/ossl_x509store.c =================================================================== --- ext/openssl/ossl_x509store.c (revision 55282) +++ ext/openssl/ossl_x509store.c (revision 55283) @@ -98,7 +98,7 @@ DupX509StorePtr(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_x509store.c#L98 X509_STORE *store; SafeGetX509Store(obj, store); - CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE); + X509_STORE_up_ref(store); return store; } Index: ext/openssl/ossl_x509cert.c =================================================================== --- ext/openssl/ossl_x509cert.c (revision 55282) +++ ext/openssl/ossl_x509cert.c (revision 55283) @@ -122,7 +122,7 @@ DupX509CertPtr(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_x509cert.c#L122 SafeGetX509(obj, x509); - CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(x509); return x509; } Index: ChangeLog =================================================================== --- ChangeLog (revision 55282) +++ ChangeLog (revision 55283) @@ -1,3 +1,24 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sun Jun 5 21:42:24 2016 Kazuki Yamaguchi <k@r...> + + * ext/openssl/extconf.rb: Check absence of CRYPTO_lock() to see if the + OpenSSL has the new threading API. In OpenSSL <= 1.0.2, an application + had to set locking callbacks to use OpenSSL in a multi-threaded + environment. OpenSSL 1.1.0 now finds pthreads or Windows threads so we + don't need to do something special. + [ruby-core:75225] [Feature #12324] + + Also check existence of *_up_ref(). Some structures in OpenSSL have + a reference counter. We used to increment it with CRYPTO_add() which + is a part of the old API. + + * ext/openssl/openssl_missing.h: Implement *_up_ref() if missing. + + * ext/openssl/ossl.c: Don't set locking callbacks if unneeded. + + * ext/openssl/ossl_pkey.c, ext/openssl/ossl_ssl.c, + ext/openssl/ossl_x509cert.c, ext/openssl/ossl_x509crl.c, + ext/openssl/ossl_x509store.c: Use *_up_ref() instead of CRYPTO_add(). + Sun Jun 5 21:38:13 2016 Kazuki Yamaguchi <k@r...> * ext/openssl/extconf.rb: Check if RAND_pseudo_bytes() is usable. It is -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/