diff options
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | ext/openssl/ossl.c | 65 | ||||
-rw-r--r-- | ext/openssl/ossl_cipher.c | 2 | ||||
-rw-r--r-- | ext/openssl/ossl_ssl.c | 31 | ||||
-rw-r--r-- | test/openssl/test_cipher.rb | 7 | ||||
-rw-r--r-- | test/openssl/test_pair.rb | 21 | ||||
-rw-r--r-- | version.h | 2 |
7 files changed, 110 insertions, 51 deletions
@@ -1,4 +1,9 @@ -Thu Mar 28 15:24:15 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> +Wed Mar 28 15:48:30 2018 Kazuki Yamaguchi <k@rhe.jp> + + backport some changes from openssl gem v2.0.6 and v2.0.7. + [Backport #13935] + +Wed Mar 28 15:24:15 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> Fix setting method visibility on method wrapped with prepend @@ -8,7 +13,7 @@ Thu Mar 28 15:24:15 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> From: Dylan Thacker-Smith Dylan.Smith@shopify.com -Thu Mar 28 15:02:43 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> +Wed Mar 28 15:02:43 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> resolv.rb: close socket @@ -27,14 +32,14 @@ Thu Mar 28 15:02:43 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> From: quixoten (Devin Christensen) quixoten@gmail.com -Thu Mar 28 14:59:27 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> +Wed Mar 28 14:59:27 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> socket.c: null byte at Socket.getnameinfo * ext/socket/socket.c (sock_s_getnameinfo): check null byte. patched by tommy (Masahiro Tomita) in . [Bug #13994] -Thu Mar 28 14:53:57 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> +Wed Mar 28 14:53:57 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> date_core.c: defensive code @@ -43,14 +48,14 @@ Thu Mar 28 14:53:57 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> * ext/date/date_core.c (d_lite_step): deal with the comparison result more defensively. [Bug #14549] -Thu Mar 28 14:50:52 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> +Wed Mar 28 14:50:52 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> string.c: clear substring code range * string.c (str_substr): substring of broken code range string may be valid or broken. patch by tommy (Masahiro Tomita) at [Bug #14388]. -Thu Mar 28 14:48:13 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> +Wed Mar 28 14:48:13 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> win32.c: memcpy instead of strlcpy @@ -59,7 +64,7 @@ Thu Mar 28 14:48:13 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> * win32/win32.c (w32_cmdvector): ditto, with NUL-terminating. -Mon Mar 28 14:45:02 2018 Koichi Sasada <ko1@atdot.net> +Wed Mar 28 14:45:02 2018 Koichi Sasada <ko1@atdot.net> check array for zsuper. [Bug #14279] @@ -68,7 +73,7 @@ Mon Mar 28 14:45:02 2018 Koichi Sasada <ko1@atdot.net> * test/ruby/test_super.rb: add a test for this bug. -Sun Mar 28 14:40:25 2018 Eric Wong <normalperson@yhbt.net> +Wed Mar 28 14:40:25 2018 Eric Wong <normalperson@yhbt.net> net/ftp: fix FrozenError in BufferedSocket @@ -82,7 +87,7 @@ Sun Mar 28 14:40:25 2018 Eric Wong <normalperson@yhbt.net> * test/net/ftp/test_buffered_socket.rb (test_read_nil): new test [Bug #14323] -Thu Mar 28 14:29:26 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> +Wed Mar 28 14:29:26 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> clean autogenerated files @@ -96,7 +101,7 @@ Thu Mar 28 14:29:26 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> Ignore enc/jis/props.h -Thu Mar 28 14:14:25 2018 URABE Shyouhei <shyouhei@ruby-lang.org> +Wed Mar 28 14:14:25 2018 URABE Shyouhei <shyouhei@ruby-lang.org> fix SEGV touching uninitialized memory This function can be called from boot_defclass(). @@ -119,7 +124,7 @@ Thu Mar 28 14:14:25 2018 URABE Shyouhei <shyouhei@ruby-lang.org> gc_writebarrier_incremental is called before or in middle of object initialization. Can casue SEGV. -Thu Mar 28 13:56:17 2018 NARUSE, Yui <naruse@ruby-lang.org> +Wed Mar 28 13:56:17 2018 NARUSE, Yui <naruse@ruby-lang.org> raise error if value contains CR/LF in iniheader of initialize_http_header @@ -127,21 +132,21 @@ Thu Mar 28 13:56:17 2018 NARUSE, Yui <naruse@ruby-lang.org> like r59693, initialize_http_header also should raise error. [Bug #14208] -Thu Mar 28 13:48:35 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> +Wed Mar 28 13:48:35 2018 Nobuyoshi Nakada <nobu@ruby-lang.org> parse.y: end of script at newline * parse.y (parser_yylex): deal with end of script chars just after ignored newline as other places. [Bug #14206] -Thu Mar 28 13:42:55 2018 Kazuhiro NISHIYAMA <zn@mbf.nifty.com> +Wed Mar 28 13:42:55 2018 Kazuhiro NISHIYAMA <zn@mbf.nifty.com> [DOC] IO.new accepts external_encoding Revert part of r61278 [Bug #13655] [ci skip] -Thu Mar 28 13:42:55 2018 NARUSE, Yui <naruse@ruby-lang.org> +Wed Mar 28 13:42:55 2018 NARUSE, Yui <naruse@ruby-lang.org> IO.new doesn't receive "-" as external_encoding [Bug #13655] diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index fb8f2c8171..0ee380507a 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -468,32 +468,46 @@ ossl_fips_mode_set(VALUE self, VALUE enabled) * Stores locks needed for OpenSSL thread safety */ #include "ruby/thread_native.h" -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)); + /* 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); rb_nativethread_lock_initialize(&dynlock->lock); return dynlock; } @@ -501,7 +515,7 @@ ossl_dyn_create_callback(const char *file, int line) 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 @@ -525,21 +539,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); diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c index 24caba6e37..e167995d49 100644 --- a/ext/openssl/ossl_cipher.c +++ b/ext/openssl/ossl_cipher.c @@ -560,6 +560,8 @@ ossl_cipher_set_auth_data(VALUE self, VALUE data) in_len = RSTRING_LEN(data); GetCipher(self, ctx); + if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)) + ossl_raise(eCipherError, "AEAD not supported by this cipher"); if (!ossl_cipher_update_long(ctx, NULL, &out_len, in, in_len)) ossl_raise(eCipherError, "couldn't set additional authenticated data"); diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 7a0eb4ec90..cd35ee3771 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -427,6 +427,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) @@ -1427,21 +1434,25 @@ 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); GetOpenFile(ossl_ssl_get_io(self), fptr); if (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; @@ -1481,8 +1492,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/test/openssl/test_cipher.rb b/test/openssl/test_cipher.rb index 95058b5f19..a89bced254 100644 --- a/test/openssl/test_cipher.rb +++ b/test/openssl/test_cipher.rb @@ -253,6 +253,13 @@ class OpenSSL::TestCipher < Test::Unit::TestCase assert_equal tag1, tag2 end if has_cipher?("aes-128-gcm") + def test_non_aead_cipher_set_auth_data + assert_raise(OpenSSL::Cipher::CipherError) { + cipher = OpenSSL::Cipher.new("aes-128-cfb").encrypt + cipher.auth_data = "123" + } + end + end private diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb index e999d206cf..6c89f1969a 100644 --- a/test/openssl/test_pair.rb +++ b/test/openssl/test_pair.rb @@ -213,6 +213,27 @@ module OpenSSL::TestPairM } end + def test_read_with_outbuf + ssl_pair { |s1, s2| + s1.write("abc\n") + buf = "" + ret = s2.read(2, buf) + assert_same ret, buf + assert_equal "ab", ret + buf = "garbage" + ret = s2.read(2, buf) + assert_same ret, buf + assert_equal "c\n", ret + buf = "garbage" + assert_equal :wait_readable, s2.read_nonblock(100, buf, exception: false) + assert_equal "", buf + s1.close + buf = "garbage" + assert_equal nil, s2.read(100, buf) + assert_equal "", buf + } + end + def write_nonblock(socket, meth, str) ret = socket.send(meth, str) ret.is_a?(Symbol) ? 0 : ret @@ -1,6 +1,6 @@ #define RUBY_VERSION "2.3.7" #define RUBY_RELEASE_DATE "2018-03-28" -#define RUBY_PATCHLEVEL 447 +#define RUBY_PATCHLEVEL 448 #define RUBY_RELEASE_YEAR 2018 #define RUBY_RELEASE_MONTH 3 |