diff options
author | nagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-19 15:11:08 +0000 |
---|---|---|
committer | nagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-19 15:11:08 +0000 |
commit | b503ff8b4336af550f48f3dc63c0c07c9d5fd0d1 (patch) | |
tree | 88cb297908c24f3214c59dc6ca5f409ae57ed2a7 /ext/openssl | |
parent | 093c6ce7c24aadc3c439ce3ae507d7309304e893 (diff) |
Update rubygems to 2.0.6. [Bug #13935]
The patch is provided by Kazuki Yamaguchi.
From: Kazuki Yamaguchi <k@rhe.jp>
Date: Mon, 25 Sep 2017 01:32:02 +0900
Subject: [PATCH] openssl: import v2.0.6
Import Ruby/OpenSSL 2.0.6. This contains only bug fixes and test
improvements. The full commit log since v2.0.5 (imported at r59567, to
trunk) can be found at:
https://github.com/ruby/openssl/compare/v2.0.5...v2.0.6
All the changes included in this patch are already imported to trunk by
r59734, r59751, r59857, and r60013.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@62842 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/openssl')
-rw-r--r-- | ext/openssl/History.md | 20 | ||||
-rw-r--r-- | ext/openssl/lib/openssl/buffering.rb | 9 | ||||
-rw-r--r-- | ext/openssl/openssl.gemspec | 8 | ||||
-rw-r--r-- | ext/openssl/ossl.c | 175 | ||||
-rw-r--r-- | ext/openssl/ossl_cipher.c | 12 | ||||
-rw-r--r-- | ext/openssl/ossl_ssl.c | 43 | ||||
-rw-r--r-- | ext/openssl/ossl_version.h | 2 | ||||
-rw-r--r-- | ext/openssl/ruby_missing.h | 10 |
8 files changed, 208 insertions, 71 deletions
diff --git a/ext/openssl/History.md b/ext/openssl/History.md index 8baa0208ea..d592bc6a1f 100644 --- a/ext/openssl/History.md +++ b/ext/openssl/History.md @@ -1,3 +1,23 @@ +Version 2.0.6 +============= + +Bug fixes +--------- + +* The session_remove_cb set to an OpenSSL::SSL::SSLContext is no longer called + during GC. +* A possible deadlock in OpenSSL::SSL::SSLSocket#sysread is fixed. + [[GitHub #139]](https://github.com/ruby/openssl/pull/139) +* OpenSSL::BN#hash could return an unnormalized fixnum value on Windows. + [[Bug #13877]](https://bugs.ruby-lang.org/issues/13877) +* OpenSSL::SSL::SSLSocket#sysread and #sysread_nonblock set the length of the + destination buffer String to 0 on error. + [[GitHub #153]](https://github.com/ruby/openssl/pull/153) +* Possible deadlock is fixed. This happened only when built with older versions + of OpenSSL (before 1.1.0) or LibreSSL. + [[GitHub #155]](https://github.com/ruby/openssl/pull/155) + + Version 2.0.5 ============= diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb index d773637c0e..b0dffefd3e 100644 --- a/ext/openssl/lib/openssl/buffering.rb +++ b/ext/openssl/lib/openssl/buffering.rb @@ -164,10 +164,9 @@ module OpenSSL::Buffering # when the peer requests a new TLS/SSL handshake. See openssl the FAQ for # more details. http://www.openssl.org/support/faq.html # - # By specifying a keyword argument _exception_ to +false+, you can indicate + # By specifying `exception: false`, the options hash allows you to indicate # that read_nonblock should not raise an IO::Wait*able exception, but - # return the symbol +:wait_writable+ or +:wait_readable+ instead. At EOF, - # it will return +nil+ instead of raising EOFError. + # return the symbol :wait_writable or :wait_readable instead. def read_nonblock(maxlen, buf=nil, exception: true) if maxlen == 0 @@ -377,9 +376,9 @@ module OpenSSL::Buffering # is when the peer requests a new TLS/SSL handshake. See the openssl FAQ # for more details. http://www.openssl.org/support/faq.html # - # By specifying a keyword argument _exception_ to +false+, you can indicate + # By specifying `exception: false`, the options hash allows you to indicate # that write_nonblock should not raise an IO::Wait*able exception, but - # return the symbol +:wait_writable+ or +:wait_readable+ instead. + # return the symbol :wait_writable or :wait_readable instead. def write_nonblock(s, exception: true) flush diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec index 7cbbfeb513..2af041ebde 100644 --- a/ext/openssl/openssl.gemspec +++ b/ext/openssl/openssl.gemspec @@ -1,16 +1,16 @@ # -*- encoding: utf-8 -*- -# stub: openssl 2.0.5 ruby lib +# stub: openssl 2.0.6 ruby lib # stub: ext/openssl/extconf.rb Gem::Specification.new do |s| s.name = "openssl".freeze - s.version = "2.0.5" + s.version = "2.0.6" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "msys2_mingw_dependencies" => "openssl" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Martin Bosslet".freeze, "SHIBATA Hiroshi".freeze, "Zachary Scott".freeze, "Kazuki Yamaguchi".freeze] - s.date = "2017-08-08" + s.date = "2017-09-24" s.description = "It wraps the OpenSSL library.".freeze s.email = ["ruby-core@ruby-lang.org".freeze] s.extensions = ["ext/openssl/extconf.rb".freeze] @@ -20,7 +20,7 @@ Gem::Specification.new do |s| s.licenses = ["Ruby".freeze] s.rdoc_options = ["--main".freeze, "README.md".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) - s.rubygems_version = "2.6.12".freeze + s.rubygems_version = "2.6.13".freeze s.summary = "OpenSSL provides SSL, TLS and general purpose cryptography.".freeze if s.respond_to? :specification_version then diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index c22966df5a..88bb8f2101 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -414,44 +414,123 @@ ossl_fips_mode_set(VALUE self, VALUE enabled) #endif } +#if defined(OSSL_DEBUG) +#if !defined(LIBRESSL_VERSION_NUMBER) && \ + (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \ + defined(CRYPTO_malloc_debug_init)) +/* + * call-seq: + * OpenSSL.mem_check_start -> nil + * + * Calls CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON). Starts tracking memory + * allocations. See also OpenSSL.print_mem_leaks. + * + * This is available only when built with a capable OpenSSL and --enable-debug + * configure option. + */ +static VALUE +mem_check_start(VALUE self) +{ + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); + return Qnil; +} + +/* + * call-seq: + * OpenSSL.print_mem_leaks -> true | false + * + * For debugging the Ruby/OpenSSL library. Calls CRYPTO_mem_leaks_fp(stderr). + * Prints detected memory leaks to standard error. This cleans the global state + * up thus you cannot use any methods of the library after calling this. + * + * Returns true if leaks detected, false otherwise. + * + * This is available only when built with a capable OpenSSL and --enable-debug + * configure option. + * + * === Example + * OpenSSL.mem_check_start + * NOT_GCED = OpenSSL::PKey::RSA.new(256) + * + * END { + * GC.start + * OpenSSL.print_mem_leaks # will print the leakage + * } + */ +static VALUE +print_mem_leaks(VALUE self) +{ +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + int ret; +#endif + + BN_CTX_free(ossl_bn_ctx); + ossl_bn_ctx = NULL; + +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + ret = CRYPTO_mem_leaks_fp(stderr); + if (ret < 0) + ossl_raise(eOSSLError, "CRYPTO_mem_leaks_fp"); + return ret ? Qfalse : Qtrue; +#else + CRYPTO_mem_leaks_fp(stderr); + return Qnil; +#endif +} +#endif +#endif + #if !defined(HAVE_OPENSSL_110_THREADING_API) /** * Stores locks needed for OpenSSL thread safety */ -static rb_nativethread_lock_t *ossl_locks; +struct CRYPTO_dynlock_value { + rb_nativethread_lock_t lock; + rb_nativethread_id_t owner; + size_t count; +}; static void -ossl_lock_unlock(int mode, rb_nativethread_lock_t *lock) +ossl_lock_init(struct CRYPTO_dynlock_value *l) { - if (mode & CRYPTO_LOCK) { - rb_nativethread_lock_lock(lock); - } else { - rb_nativethread_lock_unlock(lock); - } + rb_nativethread_lock_initialize(&l->lock); + l->count = 0; } static void -ossl_lock_callback(int mode, int type, const char *file, int line) +ossl_lock_unlock(int mode, struct CRYPTO_dynlock_value *l) { - ossl_lock_unlock(mode, &ossl_locks[type]); + if (mode & CRYPTO_LOCK) { + /* TODO: rb_nativethread_id_t is not necessarily compared with ==. */ + rb_nativethread_id_t tid = rb_nativethread_self(); + if (l->count && l->owner == tid) { + l->count++; + return; + } + rb_nativethread_lock_lock(&l->lock); + l->owner = tid; + l->count = 1; + } else { + if (!--l->count) + rb_nativethread_lock_unlock(&l->lock); + } } -struct CRYPTO_dynlock_value { - rb_nativethread_lock_t lock; -}; - static struct CRYPTO_dynlock_value * ossl_dyn_create_callback(const char *file, int line) { - struct CRYPTO_dynlock_value *dynlock = (struct CRYPTO_dynlock_value *)OPENSSL_malloc((int)sizeof(struct CRYPTO_dynlock_value)); - rb_nativethread_lock_initialize(&dynlock->lock); + /* Do not use xmalloc() here, since it may raise NoMemoryError */ + struct CRYPTO_dynlock_value *dynlock = + OPENSSL_malloc(sizeof(struct CRYPTO_dynlock_value)); + if (dynlock) + ossl_lock_init(dynlock); return dynlock; } static void ossl_dyn_lock_callback(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line) { - ossl_lock_unlock(mode, &l->lock); + ossl_lock_unlock(mode, l); } static void @@ -475,21 +554,22 @@ static unsigned long ossl_thread_id(void) } #endif +static struct CRYPTO_dynlock_value *ossl_locks; + +static void +ossl_lock_callback(int mode, int type, const char *file, int line) +{ + ossl_lock_unlock(mode, &ossl_locks[type]); +} + static void Init_ossl_locks(void) { int i; int num_locks = CRYPTO_num_locks(); - if ((unsigned)num_locks >= INT_MAX / (int)sizeof(VALUE)) { - rb_raise(rb_eRuntimeError, "CRYPTO_num_locks() is too big: %d", num_locks); - } - ossl_locks = (rb_nativethread_lock_t *) OPENSSL_malloc(num_locks * (int)sizeof(rb_nativethread_lock_t)); - if (!ossl_locks) { - rb_raise(rb_eNoMemError, "CRYPTO_num_locks() is too big: %d", num_locks); - } - for (i = 0; i < num_locks; i++) { - rb_nativethread_lock_initialize(&ossl_locks[i]); - } + ossl_locks = ALLOC_N(struct CRYPTO_dynlock_value, num_locks); + for (i = 0; i < num_locks; i++) + ossl_lock_init(&ossl_locks[i]); #ifdef HAVE_CRYPTO_THREADID_PTR CRYPTO_THREADID_set_callback(ossl_threadid_func); @@ -1114,15 +1194,40 @@ Init_openssl(void) Init_ossl_ocsp(); Init_ossl_engine(); Init_ossl_asn1(); -} #if defined(OSSL_DEBUG) -/* - * Check if all symbols are OK with 'make LDSHARED=gcc all' - */ -int -main(int argc, char *argv[]) -{ - return 0; + /* + * For debugging Ruby/OpenSSL. Enable only when built with --enable-debug + */ +#if !defined(LIBRESSL_VERSION_NUMBER) && \ + (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \ + defined(CRYPTO_malloc_debug_init)) + rb_define_module_function(mOSSL, "mem_check_start", mem_check_start, 0); + rb_define_module_function(mOSSL, "print_mem_leaks", print_mem_leaks, 0); + +#if defined(CRYPTO_malloc_debug_init) /* <= 1.0.2 */ + CRYPTO_malloc_debug_init(); +#endif + +#if defined(V_CRYPTO_MDEBUG_ALL) /* <= 1.0.2 */ + CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000 /* <= 1.0.2 */ + { + int i; + /* + * See crypto/ex_data.c; call def_get_class() immediately to avoid + * allocations. 15 is the maximum number that is used as the class index + * in OpenSSL 1.0.2. + */ + for (i = 0; i <= 15; i++) { + if (CRYPTO_get_ex_new_index(i, 0, (void *)"ossl-mdebug-dummy", 0, 0, 0) < 0) + rb_raise(rb_eRuntimeError, "CRYPTO_get_ex_new_index for " + "class index %d failed", i); + } + } +#endif +#endif +#endif } -#endif /* OSSL_DEBUG */ diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c index c2f0927a75..36e42ede8c 100644 --- a/ext/openssl/ossl_cipher.c +++ b/ext/openssl/ossl_cipher.c @@ -631,13 +631,11 @@ ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self) * call-seq: * cipher.auth_tag = string -> string * - * Sets the authentication tag to verify the contents of the - * ciphertext. The tag must be set after calling Cipher#decrypt, - * Cipher#key= and Cipher#iv=, but before assigning the associated - * authenticated data using Cipher#auth_data= and of course, before - * decrypting any of the ciphertext. After all decryption is - * performed, the tag is verified automatically in the call to - * Cipher#final. + * Sets the authentication tag to verify the integrity of the ciphertext. + * This can be called only when the cipher supports AE. The tag must be set + * after calling Cipher#decrypt, Cipher#key= and Cipher#iv=, but before + * calling Cipher#final. After all decryption is performed, the tag is + * verified automatically in the call to Cipher#final. * * For OCB mode, the tag length must be supplied with #auth_tag_len= * beforehand. diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index f9c9d76fc2..aa2dbbc8f7 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -476,6 +476,13 @@ ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess) void *ptr; int state = 0; + /* + * This callback is also called for all sessions in the internal store + * when SSL_CTX_free() is called. + */ + if (rb_during_gc()) + return; + OSSL_Debug("SSL SESSION remove callback entered"); if ((ptr = SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_ptr_idx)) == NULL) @@ -1601,10 +1608,10 @@ ossl_ssl_connect(VALUE self) * retry * end * - * By specifying a keyword argument _exception_ to +false+, you can indicate + * By specifying `exception: false`, the options hash allows you to indicate * that connect_nonblock should not raise an IO::WaitReadable or - * IO::WaitWritable exception, but return the symbol +:wait_readable+ or - * +:wait_writable+ instead. + * IO::WaitWritable exception, but return the symbol :wait_readable or + * :wait_writable instead. */ static VALUE ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self) @@ -1649,10 +1656,10 @@ ossl_ssl_accept(VALUE self) * retry * end * - * By specifying a keyword argument _exception_ to +false+, you can indicate + * By specifying `exception: false`, the options hash allows you to indicate * that accept_nonblock should not raise an IO::WaitReadable or - * IO::WaitWritable exception, but return the symbol +:wait_readable+ or - * +:wait_writable+ instead. + * IO::WaitWritable exception, but return the symbol :wait_readable or + * :wait_writable instead. */ static VALUE ossl_ssl_accept_nonblock(int argc, VALUE *argv, VALUE self) @@ -1681,22 +1688,26 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) } ilen = NUM2INT(len); - if(NIL_P(str)) str = rb_str_new(0, ilen); - else{ - StringValue(str); - rb_str_modify(str); - rb_str_resize(str, ilen); + if (NIL_P(str)) + str = rb_str_new(0, ilen); + else { + StringValue(str); + if (RSTRING_LEN(str) >= ilen) + rb_str_modify(str); + else + rb_str_modify_expand(str, ilen - RSTRING_LEN(str)); } - if(ilen == 0) return str; + OBJ_TAINT(str); + rb_str_set_len(str, 0); + if (ilen == 0) + return str; GetSSL(self, ssl); io = rb_attr_get(self, id_i_io); GetOpenFile(io, fptr); if (ssl_started(ssl)) { - if(!nonblock && SSL_pending(ssl) <= 0) - rb_thread_wait_fd(FPTR_TO_FD(fptr)); for (;;){ - nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LENINT(str)); + nread = SSL_read(ssl, RSTRING_PTR(str), ilen); switch(ssl_get_error(ssl, nread)){ case SSL_ERROR_NONE: goto end; @@ -1746,8 +1757,6 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) end: rb_str_set_len(str, nread); - OBJ_TAINT(str); - return str; } diff --git a/ext/openssl/ossl_version.h b/ext/openssl/ossl_version.h index be3eebe1f2..7725bc0525 100644 --- a/ext/openssl/ossl_version.h +++ b/ext/openssl/ossl_version.h @@ -10,6 +10,6 @@ #if !defined(_OSSL_VERSION_H_) #define _OSSL_VERSION_H_ -#define OSSL_VERSION "2.0.5" +#define OSSL_VERSION "2.0.6" #endif /* _OSSL_VERSION_H_ */ diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h index 8dacc8266e..5b1481aea7 100644 --- a/ext/openssl/ruby_missing.h +++ b/ext/openssl/ruby_missing.h @@ -15,9 +15,15 @@ #define FPTR_TO_FD(fptr) ((fptr)->fd) +/* Ruby 2.4 */ #ifndef RB_INTEGER_TYPE_P -/* for Ruby 2.3 compatibility */ -#define RB_INTEGER_TYPE_P(obj) (RB_FIXNUM_P(obj) || RB_TYPE_P(obj, T_BIGNUM)) +# define RB_INTEGER_TYPE_P(obj) (RB_FIXNUM_P(obj) || RB_TYPE_P(obj, T_BIGNUM)) +#endif + +/* Ruby 2.5 */ +#ifndef ST2FIX +# define RB_ST2FIX(h) LONG2FIX((long)(h)) +# define ST2FIX(h) RB_ST2FIX(h) #endif #endif /* _OSSL_RUBY_MISSING_H_ */ |