summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2021-09-28 18:03:24 +0900
committernagachika <nagachika@ruby-lang.org>2021-10-30 20:22:06 +0900
commit00e89fe36b57e2d7c4ea269bc827d9806edef5ed (patch)
treea076873763b50437c2ffaf258ca14e57a519067f /ext
parent5427b08381fb0d644ec69d5aa94234f90a4fbed1 (diff)
openssl: import v2.2.1
Bring the local copy of ruby/openssl in sync with the upstream gem release v2.2.1. The commits happened in the upstream repository can be found at: https://github.com/ruby/openssl/compare/v2.2.0...v2.2.1 Note that many of these have already been applied to ruby.git and don't appear in the file changes of this commit.
Diffstat (limited to 'ext')
-rw-r--r--ext/openssl/History.md53
-rw-r--r--ext/openssl/extconf.rb43
-rw-r--r--ext/openssl/lib/openssl/version.rb2
-rw-r--r--ext/openssl/openssl.gemspec3
-rw-r--r--ext/openssl/ossl_bn.c34
-rw-r--r--ext/openssl/ossl_cipher.c26
-rw-r--r--ext/openssl/ossl_digest.c8
-rw-r--r--ext/openssl/ossl_pkey_ec.c16
-rw-r--r--ext/openssl/ossl_ssl.c80
-rw-r--r--ext/openssl/ossl_ts.c16
-rw-r--r--ext/openssl/ossl_x509store.c59
11 files changed, 259 insertions, 81 deletions
diff --git a/ext/openssl/History.md b/ext/openssl/History.md
index a4a82a146c..46435f9be6 100644
--- a/ext/openssl/History.md
+++ b/ext/openssl/History.md
@@ -1,3 +1,20 @@
+Version 2.2.1
+=============
+
+Merged changes in 2.1.3. Additionally, the following issues are fixed by this
+release.
+
+Bug fixes
+---------
+
+* Fix crash in `OpenSSL::Timestamp::{Request,Response,TokenInfo}.new` when
+ invalid arguments are given.
+ [[GitHub #407]](https://github.com/ruby/openssl/pull/407)
+* Fix `OpenSSL::Timestamp::Factory#create_timestamp` with LibreSSL on platforms
+ where `time_t` has a different size from `long`.
+ [[GitHub #454]](https://github.com/ruby/openssl/pull/454)
+
+
Version 2.2.0
=============
@@ -75,6 +92,42 @@ Notable changes
[[GitHub #297]](https://github.com/ruby/openssl/pull/297)
+Version 2.1.3
+=============
+
+Bug fixes
+---------
+
+* Fix deprecation warnings on Ruby 3.0.
+* Add ".include" directive support in `OpenSSL::Config`.
+ [[GitHub #216]](https://github.com/ruby/openssl/pull/216)
+* Fix handling of IPv6 address SANs.
+ [[GitHub #185]](https://github.com/ruby/openssl/pull/185)
+* Hostname verification failure with `OpenSSL::SSL::SSLContext#verify_hostname=`
+ sets a proper error code.
+ [[GitHub #350]](https://github.com/ruby/openssl/pull/350)
+* Fix crash with `OpenSSL::BN.new(nil, 2)`.
+ [[Bug #15760]](https://bugs.ruby-lang.org/issues/15760)
+* `OpenSSL::SSL::SSLSocket#sys{read,write}` prevent internal string buffers from
+ being modified by another thread.
+ [[GitHub #453]](https://github.com/ruby/openssl/pull/453)
+* Fix misuse of input record separator in `OpenSSL::Buffering` where it was
+ for output.
+* Fix wrong interger casting in `OpenSSL::PKey::EC#dsa_verify_asn1`.
+ [[GitHub #460]](https://github.com/ruby/openssl/pull/460)
+* `extconf.rb` explicitly checks that OpenSSL's version number is 1.0.1 or
+ newer but also less than 3.0. Ruby/OpenSSL v2.1.x and v2.2.x will not support
+ OpenSSL 3.0 API.
+ [[GitHub #458]](https://github.com/ruby/openssl/pull/458)
+* Activate `digest` gem correctly. `digest` library could go into an
+ inconsistent state if there are multiple versions of `digest` is installed
+ and `openssl` is `require`d before `digest`.
+ [[GitHub #463]](https://github.com/ruby/openssl/pull/463)
+* Fix GC.compact compatibility.
+ [[GitHub #464]](https://github.com/ruby/openssl/issues/464)
+ [[GitHub #465]](https://github.com/ruby/openssl/pull/465)
+
+
Version 2.1.2
=============
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index 693e55cd97..e13595c7c7 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -33,9 +33,6 @@ if $mswin || $mingw
have_library("ws2_32")
end
-Logging::message "=== Checking for required stuff... ===\n"
-result = pkg_config("openssl") && have_header("openssl/ssl.h")
-
if $mingw
append_cflags '-D_FORTIFY_SOURCE=2'
append_ldflags '-fstack-protector'
@@ -92,19 +89,33 @@ def find_openssl_library
return false
end
-unless result
- unless find_openssl_library
- Logging::message "=== Checking for required stuff failed. ===\n"
- Logging::message "Makefile wasn't created. Fix the errors above.\n"
- raise "OpenSSL library could not be found. You might want to use " \
- "--with-openssl-dir=<dir> option to specify the prefix where OpenSSL " \
- "is installed."
- end
+Logging::message "=== Checking for required stuff... ===\n"
+pkg_config_found = pkg_config("openssl") && have_header("openssl/ssl.h")
+
+if !pkg_config_found && !find_openssl_library
+ Logging::message "=== Checking for required stuff failed. ===\n"
+ Logging::message "Makefile wasn't created. Fix the errors above.\n"
+ raise "OpenSSL library could not be found. You might want to use " \
+ "--with-openssl-dir=<dir> option to specify the prefix where OpenSSL " \
+ "is installed."
end
-unless checking_for("OpenSSL version is 1.0.1 or later") {
- try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") }
- raise "OpenSSL >= 1.0.1 or LibreSSL is required"
+version_ok = if have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h")
+ is_libressl = true
+ checking_for("LibreSSL version >= 2.5.0") {
+ try_static_assert("LIBRESSL_VERSION_NUMBER >= 0x20500000L", "openssl/opensslv.h") }
+else
+ checking_for("OpenSSL version >= 1.0.1 and < 3.0.0") {
+ try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") &&
+ !try_static_assert("OPENSSL_VERSION_MAJOR >= 3", "openssl/opensslv.h") }
+end
+unless version_ok
+ raise "OpenSSL >= 1.0.1, < 3.0.0 or LibreSSL >= 2.5.0 is required"
+end
+
+# Prevent wincrypt.h from being included, which defines conflicting macro with openssl/x509.h
+if is_libressl && ($mswin || $mingw)
+ $defs.push("-DNOCRYPT")
end
Logging::message "=== Checking for OpenSSL features... ===\n"
@@ -116,10 +127,6 @@ engines.each { |name|
have_func("ENGINE_load_#{name}()", "openssl/engine.h")
}
-if ($mswin || $mingw) && have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h")
- $defs.push("-DNOCRYPT")
-end
-
# added in 1.0.2
have_func("EC_curve_nist2nid")
have_func("X509_REVOKED_dup")
diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb
index 9c7515ba0f..d541cbf162 100644
--- a/ext/openssl/lib/openssl/version.rb
+++ b/ext/openssl/lib/openssl/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module OpenSSL
- VERSION = "2.2.0"
+ VERSION = "2.2.1"
end
diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec
index 471a3c4265..ebbd0923dd 100644
--- a/ext/openssl/openssl.gemspec
+++ b/ext/openssl/openssl.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "openssl"
- spec.version = "2.2.0"
+ spec.version = "2.2.1"
spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"]
spec.email = ["ruby-core@ruby-lang.org"]
spec.summary = %q{OpenSSL provides SSL, TLS and general purpose cryptography.}
@@ -17,6 +17,7 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = ">= 2.3.0"
+ spec.add_runtime_dependency "ipaddr"
spec.add_development_dependency "rake"
spec.add_development_dependency "rake-compiler"
spec.add_development_dependency "test-unit", "~> 3.0"
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index d94b8e375c..bec37299f7 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -453,7 +453,7 @@ ossl_bn_is_negative(VALUE self)
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
- if (!BN_##func(result, bn, ossl_bn_ctx)) { \
+ if (BN_##func(result, bn, ossl_bn_ctx) <= 0) { \
BN_free(result); \
ossl_raise(eBNError, NULL); \
} \
@@ -479,7 +479,7 @@ BIGNUM_1c(sqr)
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
- if (!BN_##func(result, bn1, bn2)) { \
+ if (BN_##func(result, bn1, bn2) <= 0) { \
BN_free(result); \
ossl_raise(eBNError, NULL); \
} \
@@ -512,7 +512,7 @@ BIGNUM_2(sub)
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
- if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \
+ if (BN_##func(result, bn1, bn2, ossl_bn_ctx) <= 0) { \
BN_free(result); \
ossl_raise(eBNError, NULL); \
} \
@@ -556,11 +556,21 @@ BIGNUM_2c(gcd)
BIGNUM_2c(mod_sqr)
/*
- * Document-method: OpenSSL::BN#mod_inverse
* call-seq:
- * bn.mod_inverse(bn2) => aBN
+ * bn.mod_inverse(bn2) => aBN
*/
-BIGNUM_2c(mod_inverse)
+static VALUE
+ossl_bn_mod_inverse(VALUE self, VALUE other)
+{
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result;
+ VALUE obj;
+ GetBN(self, bn1);
+ obj = NewBN(rb_obj_class(self));
+ if (!(result = BN_mod_inverse(NULL, bn1, bn2, ossl_bn_ctx)))
+ ossl_raise(eBNError, "BN_mod_inverse");
+ SetBN(obj, result);
+ return obj;
+}
/*
* call-seq:
@@ -609,7 +619,7 @@ ossl_bn_div(VALUE self, VALUE other)
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
- if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \
+ if (BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx) <= 0) { \
BN_free(result); \
ossl_raise(eBNError, NULL); \
} \
@@ -651,7 +661,7 @@ BIGNUM_3c(mod_exp)
{ \
BIGNUM *bn; \
GetBN(self, bn); \
- if (!BN_##func(bn, NUM2INT(bit))) { \
+ if (BN_##func(bn, NUM2INT(bit)) <= 0) { \
ossl_raise(eBNError, NULL); \
} \
return self; \
@@ -711,7 +721,7 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
- if (!BN_##func(result, bn, b)) { \
+ if (BN_##func(result, bn, b) <= 0) { \
BN_free(result); \
ossl_raise(eBNError, NULL); \
} \
@@ -741,7 +751,7 @@ BIGNUM_SHIFT(rshift)
int b; \
b = NUM2INT(bits); \
GetBN(self, bn); \
- if (!BN_##func(bn, bn, b)) \
+ if (BN_##func(bn, bn, b) <= 0) \
ossl_raise(eBNError, NULL); \
return self; \
}
@@ -780,7 +790,7 @@ BIGNUM_SELF_SHIFT(rshift)
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
- if (!BN_##func(result, b, top, bottom)) { \
+ if (BN_##func(result, b, top, bottom) <= 0) { \
BN_free(result); \
ossl_raise(eBNError, NULL); \
} \
@@ -809,7 +819,7 @@ BIGNUM_RAND(pseudo_rand)
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
- if (!BN_##func##_range(result, bn)) { \
+ if (BN_##func##_range(result, bn) <= 0) { \
BN_free(result); \
ossl_raise(eBNError, NULL); \
} \
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 0b78f40b72..5b92fc39f0 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -814,6 +814,31 @@ ossl_cipher_block_size(VALUE self)
}
/*
+ * call-seq:
+ * cipher.ccm_data_len = integer -> integer
+ *
+ * Sets the length of the plaintext / ciphertext message that will be
+ * processed in CCM mode. Make sure to call this method after #key= and
+ * #iv= have been set, and before #auth_data=.
+ *
+ * Only call this method after calling Cipher#encrypt or Cipher#decrypt.
+ */
+static VALUE
+ossl_cipher_set_ccm_data_len(VALUE self, VALUE data_len)
+{
+ int in_len, out_len;
+ EVP_CIPHER_CTX *ctx;
+
+ in_len = NUM2INT(data_len);
+
+ GetCipher(self, ctx);
+ if (EVP_CipherUpdate(ctx, NULL, &out_len, NULL, in_len) != 1)
+ ossl_raise(eCipherError, NULL);
+
+ return data_len;
+}
+
+/*
* INIT
*/
void
@@ -1043,6 +1068,7 @@ Init_ossl_cipher(void)
rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
+ rb_define_method(cCipher, "ccm_data_len=", ossl_cipher_set_ccm_data_len, 1);
id_auth_tag_len = rb_intern_const("auth_tag_len");
id_key_set = rb_intern_const("key_set");
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index e2157cb02f..6294fa2acf 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -313,8 +313,6 @@ ossl_digest_block_length(VALUE self)
void
Init_ossl_digest(void)
{
- rb_require("digest");
-
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
@@ -398,6 +396,12 @@ Init_ossl_digest(void)
* digest2 = sha256.digest(data2)
*
*/
+
+ /*
+ * Digest::Class is defined by the digest library. rb_require() cannot be
+ * used here because it bypasses RubyGems.
+ */
+ rb_funcall(Qnil, rb_intern_const("require"), 1, rb_str_new_cstr("digest"));
cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
/* Document-class: OpenSSL::Digest::DigestError
*
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index fc2bc6c815..1d105abd35 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -653,15 +653,15 @@ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
StringValue(data);
StringValue(sig);
- switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) {
- case 1: return Qtrue;
- case 0: return Qfalse;
- default: break;
+ switch (ECDSA_verify(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
+ (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), ec)) {
+ case 1:
+ return Qtrue;
+ case 0:
+ return Qfalse;
+ default:
+ ossl_raise(eECError, "ECDSA_verify");
}
-
- ossl_raise(eECError, "ECDSA_verify");
-
- UNREACHABLE;
}
/*
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 4b7efa39f5..7654be12ee 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -13,6 +13,12 @@
#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
+#if !defined(TLS1_3_VERSION) && \
+ defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER >= 0x3020000fL
+# define TLS1_3_VERSION 0x0304
+#endif
+
#ifdef _WIN32
# define TO_SOCKET(s) _get_osfhandle(s)
#else
@@ -33,7 +39,7 @@ static VALUE eSSLErrorWaitReadable;
static VALUE eSSLErrorWaitWritable;
static ID id_call, ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback,
- id_npn_protocols_encoded;
+ id_npn_protocols_encoded, id_each;
static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
@@ -54,6 +60,13 @@ static int ossl_sslctx_ex_store_p;
#endif
static void
+ossl_sslctx_mark(void *ptr)
+{
+ SSL_CTX *ctx = ptr;
+ rb_gc_mark((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx));
+}
+
+static void
ossl_sslctx_free(void *ptr)
{
SSL_CTX *ctx = ptr;
@@ -67,7 +80,7 @@ ossl_sslctx_free(void *ptr)
static const rb_data_type_t ossl_sslctx_type = {
"OpenSSL/SSL/CTX",
{
- 0, ossl_sslctx_free,
+ ossl_sslctx_mark, ossl_sslctx_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
@@ -616,7 +629,7 @@ static VALUE
ssl_encode_npn_protocols(VALUE protocols)
{
VALUE encoded = rb_str_new(NULL, 0);
- rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded);
+ rb_block_call(protocols, id_each, 0, 0, ssl_npn_encode_protocol_i, encoded);
return encoded;
}
@@ -686,7 +699,7 @@ static int
ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
void *arg)
{
- VALUE protocols = (VALUE)arg;
+ VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded);
*out = (const unsigned char *) RSTRING_PTR(protocols);
*outlen = RSTRING_LENINT(protocols);
@@ -908,7 +921,7 @@ ossl_sslctx_setup(VALUE self)
if (!NIL_P(val)) {
VALUE encoded = ssl_encode_npn_protocols(val);
rb_ivar_set(self, id_npn_protocols_encoded, encoded);
- SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)encoded);
+ SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self);
OSSL_Debug("SSL NPN advertise callback added");
}
if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
@@ -1527,6 +1540,14 @@ ssl_started(SSL *ssl)
}
static void
+ossl_ssl_mark(void *ptr)
+{
+ SSL *ssl = ptr;
+ rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx));
+ rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx));
+}
+
+static void
ossl_ssl_free(void *ssl)
{
SSL_free(ssl);
@@ -1535,7 +1556,7 @@ ossl_ssl_free(void *ssl)
const rb_data_type_t ossl_ssl_type = {
"OpenSSL/SSL",
{
- 0, ossl_ssl_free,
+ ossl_ssl_mark, ossl_ssl_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
@@ -1691,6 +1712,11 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
rb_io_wait_readable(fptr->fd);
continue;
case SSL_ERROR_SYSCALL:
+#ifdef __APPLE__
+ /* See ossl_ssl_write_internal() */
+ if (errno == EPROTOTYPE)
+ continue;
+#endif
if (errno) rb_sys_fail(funcname);
ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
#if defined(SSL_R_CERTIFICATE_VERIFY_FAILED)
@@ -1847,26 +1873,36 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr);
if (ssl_started(ssl)) {
- for (;;){
+ rb_str_locktmp(str);
+ for (;;) {
nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
switch(ssl_get_error(ssl, nread)){
case SSL_ERROR_NONE:
+ rb_str_unlocktmp(str);
goto end;
case SSL_ERROR_ZERO_RETURN:
+ rb_str_unlocktmp(str);
if (no_exception_p(opts)) { return Qnil; }
rb_eof_error();
case SSL_ERROR_WANT_WRITE:
- if (no_exception_p(opts)) { return sym_wait_writable; }
- write_would_block(nonblock);
+ if (nonblock) {
+ rb_str_unlocktmp(str);
+ if (no_exception_p(opts)) { return sym_wait_writable; }
+ write_would_block(nonblock);
+ }
rb_io_wait_writable(fptr->fd);
continue;
case SSL_ERROR_WANT_READ:
- if (no_exception_p(opts)) { return sym_wait_readable; }
- read_would_block(nonblock);
+ if (nonblock) {
+ rb_str_unlocktmp(str);
+ if (no_exception_p(opts)) { return sym_wait_readable; }
+ read_would_block(nonblock);
+ }
rb_io_wait_readable(fptr->fd);
continue;
case SSL_ERROR_SYSCALL:
if (!ERR_peek_error()) {
+ rb_str_unlocktmp(str);
if (errno)
rb_sys_fail(0);
else {
@@ -1883,6 +1919,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
}
/* fall through */
default:
+ rb_str_unlocktmp(str);
ossl_raise(eSSLError, "SSL_read");
}
}
@@ -1953,21 +1990,21 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
int nwrite = 0;
rb_io_t *fptr;
int nonblock = opts != Qfalse;
- VALUE io;
+ VALUE tmp, io;
- StringValue(str);
+ tmp = rb_str_new_frozen(StringValue(str));
GetSSL(self, ssl);
io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr);
if (ssl_started(ssl)) {
- for (;;){
- int num = RSTRING_LENINT(str);
+ for (;;) {
+ int num = RSTRING_LENINT(tmp);
/* SSL_write(3ssl) manpage states num == 0 is undefined */
if (num == 0)
goto end;
- nwrite = SSL_write(ssl, RSTRING_PTR(str), num);
+ nwrite = SSL_write(ssl, RSTRING_PTR(tmp), num);
switch(ssl_get_error(ssl, nwrite)){
case SSL_ERROR_NONE:
goto end;
@@ -1982,6 +2019,16 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
rb_io_wait_readable(fptr->fd);
continue;
case SSL_ERROR_SYSCALL:
+#ifdef __APPLE__
+ /*
+ * It appears that send syscall can return EPROTOTYPE if the
+ * socket is being torn down. Retry to get a proper errno to
+ * make the error handling in line with the socket library.
+ * [Bug #14713] https://bugs.ruby-lang.org/issues/14713
+ */
+ if (errno == EPROTOTYPE)
+ continue;
+#endif
if (errno) rb_sys_fail(0);
default:
ossl_raise(eSSLError, "SSL_write");
@@ -2997,6 +3044,7 @@ Init_ossl_ssl(void)
id_tmp_dh_callback = rb_intern_const("tmp_dh_callback");
id_tmp_ecdh_callback = rb_intern_const("tmp_ecdh_callback");
id_npn_protocols_encoded = rb_intern_const("npn_protocols_encoded");
+ id_each = rb_intern_const("each");
#define DefIVarID(name) do \
id_i_##name = rb_intern_const("@"#name); while (0)
diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c
index 692c0d620f..cff9b7bfff 100644
--- a/ext/openssl/ossl_ts.c
+++ b/ext/openssl/ossl_ts.c
@@ -205,8 +205,10 @@ ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self)
in = ossl_obj2bio(&arg);
ts_req = d2i_TS_REQ_bio(in, &ts_req);
BIO_free(in);
- if (!ts_req)
+ if (!ts_req) {
+ DATA_PTR(self) = NULL;
ossl_raise(eTimestampError, "Error when decoding the timestamp request");
+ }
DATA_PTR(self) = ts_req;
return self;
@@ -529,8 +531,10 @@ ossl_ts_resp_initialize(VALUE self, VALUE der)
in = ossl_obj2bio(&der);
ts_resp = d2i_TS_RESP_bio(in, &ts_resp);
BIO_free(in);
- if (!ts_resp)
+ if (!ts_resp) {
+ DATA_PTR(self) = NULL;
ossl_raise(eTimestampError, "Error when decoding the timestamp response");
+ }
DATA_PTR(self) = ts_resp;
return self;
@@ -871,8 +875,10 @@ ossl_ts_token_info_initialize(VALUE self, VALUE der)
in = ossl_obj2bio(&der);
info = d2i_TS_TST_INFO_bio(in, &info);
BIO_free(in);
- if (!info)
+ if (!info) {
+ DATA_PTR(self) = NULL;
ossl_raise(eTimestampError, "Error when decoding the timestamp token info");
+ }
DATA_PTR(self) = info;
return self;
@@ -1074,7 +1080,11 @@ ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data)
}
static int
+#if !defined(LIBRESSL_VERSION_NUMBER)
ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec)
+#else
+ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec)
+#endif
{
*sec = *((long *)data);
*usec = 0;
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index 61543d44f6..9035a70aa9 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -106,6 +106,13 @@ VALUE cX509StoreContext;
VALUE eX509StoreError;
static void
+ossl_x509store_mark(void *ptr)
+{
+ X509_STORE *store = ptr;
+ rb_gc_mark((VALUE)X509_STORE_get_ex_data(store, store_ex_verify_cb_idx));
+}
+
+static void
ossl_x509store_free(void *ptr)
{
X509_STORE_free(ptr);
@@ -114,7 +121,7 @@ ossl_x509store_free(void *ptr)
static const rb_data_type_t ossl_x509store_type = {
"OpenSSL/X509/STORE",
{
- 0, ossl_x509store_free,
+ ossl_x509store_mark, ossl_x509store_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
@@ -457,23 +464,16 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
}
/*
- * Public Functions
- */
-static void ossl_x509stctx_free(void*);
-
-
-static const rb_data_type_t ossl_x509stctx_type = {
- "OpenSSL/X509/STORE_CTX",
- {
- 0, ossl_x509stctx_free,
- },
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
-};
-
-/*
* Private functions
*/
static void
+ossl_x509stctx_mark(void *ptr)
+{
+ X509_STORE_CTX *ctx = ptr;
+ rb_gc_mark((VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx));
+}
+
+static void
ossl_x509stctx_free(void *ptr)
{
X509_STORE_CTX *ctx = ptr;
@@ -484,6 +484,14 @@ ossl_x509stctx_free(void *ptr)
X509_STORE_CTX_free(ctx);
}
+static const rb_data_type_t ossl_x509stctx_type = {
+ "OpenSSL/X509/STORE_CTX",
+ {
+ ossl_x509stctx_mark, ossl_x509stctx_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
static VALUE
ossl_x509stctx_alloc(VALUE klass)
{
@@ -517,7 +525,9 @@ static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
/*
* call-seq:
- * StoreContext.new(store, cert = nil, chain = nil)
+ * StoreContext.new(store, cert = nil, untrusted = nil)
+ *
+ * Sets up a StoreContext for a verification of the X.509 certificate _cert_.
*/
static VALUE
ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
@@ -527,15 +537,24 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
X509_STORE *x509st;
X509 *x509 = NULL;
STACK_OF(X509) *x509s = NULL;
+ int state;
rb_scan_args(argc, argv, "12", &store, &cert, &chain);
GetX509StCtx(self, ctx);
GetX509Store(store, x509st);
- if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */
- if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
- if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
+ if (!NIL_P(cert))
+ x509 = DupX509CertPtr(cert); /* NEED TO DUP */
+ if (!NIL_P(chain)) {
+ x509s = ossl_protect_x509_ary2sk(chain, &state);
+ if (state) {
+ X509_free(x509);
+ rb_jump_tag(state);
+ }
+ }
+ if (X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
+ X509_free(x509);
sk_X509_pop_free(x509s, X509_free);
- ossl_raise(eX509StoreError, NULL);
+ ossl_raise(eX509StoreError, "X509_STORE_CTX_init");
}
if (!NIL_P(t = rb_iv_get(store, "@time")))
ossl_x509stctx_set_time(self, t);