summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2026-05-14 00:46:54 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2026-05-13 15:01:28 -0700
commit729e1512dfad3d341ed5916c87a500bce378545b (patch)
tree408371b84098a8f2fd1f456d421a6fa0cf44d95d /ext
parent7ae3c34c8d43a0a235778b68b0f631429a9a0e97 (diff)
Merge openssl-4.0.1
The changes can be found at: https://github.com/ruby/openssl/compare/v4.0.0...v4.0.1
Diffstat (limited to 'ext')
-rw-r--r--ext/openssl/History.md20
-rw-r--r--ext/openssl/lib/openssl/version.rb2
-rw-r--r--ext/openssl/openssl.gemspec2
-rw-r--r--ext/openssl/ossl_cipher.c13
-rw-r--r--ext/openssl/ossl_ocsp.c4
-rw-r--r--ext/openssl/ossl_pkcs7.c2
-rw-r--r--ext/openssl/ossl_pkey_ec.c2
-rw-r--r--ext/openssl/ossl_ssl.c88
8 files changed, 89 insertions, 44 deletions
diff --git a/ext/openssl/History.md b/ext/openssl/History.md
index 419237ff16..c78c7e4633 100644
--- a/ext/openssl/History.md
+++ b/ext/openssl/History.md
@@ -1,3 +1,23 @@
+Version 4.0.1
+=============
+
+Notable changes
+---------------
+
+* Add `sync_close` keyword argument to `OpenSSL::SSL::SSLSocket.new` as a
+ short-hand for setting `sync_close` attribute on the created `SSLSocket`
+ instance.
+ [[GitHub #955]](https://github.com/ruby/openssl/issues/955)
+ [[GitHub #996]](https://github.com/ruby/openssl/pull/996)
+
+
+Bug fixes
+---------
+
+* Fix uninitialized variables in `OpenSSL::OCSP::BasicResponse#status`.
+ [[GitHub #1004]](https://github.com/ruby/openssl/pull/1004)
+
+
Version 4.0.0
=============
diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb
index 88570562e2..45c150be11 100644
--- a/ext/openssl/lib/openssl/version.rb
+++ b/ext/openssl/lib/openssl/version.rb
@@ -2,5 +2,5 @@
module OpenSSL
# The version string of Ruby/OpenSSL.
- VERSION = "4.0.0"
+ VERSION = "4.0.1"
end
diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec
index 7072d599d8..c594c6f177 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 = "4.0.0"
+ spec.version = "4.0.1"
spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"]
spec.email = ["ruby-core@ruby-lang.org"]
spec.summary = %q{SSL/TLS and general-purpose cryptography for Ruby}
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index db65e99888..f3cd247c8f 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -401,9 +401,9 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
}
out_len = in_len + EVP_MAX_BLOCK_LENGTH;
- if (NIL_P(str)) {
- str = rb_str_new(0, out_len);
- } else {
+ if (NIL_P(str))
+ str = rb_str_buf_new(out_len);
+ else {
StringValue(str);
if ((long)rb_str_capacity(str) >= out_len)
rb_str_modify(str);
@@ -411,9 +411,9 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
rb_str_modify_expand(str, out_len - RSTRING_LEN(str));
}
- if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len))
- ossl_raise(eCipherError, NULL);
- assert(out_len <= RSTRING_LEN(str));
+ if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str),
+ &out_len, in, in_len))
+ ossl_raise(eCipherError, "EVP_CipherUpdate");
rb_str_set_len(str, out_len);
return str;
@@ -456,7 +456,6 @@ ossl_cipher_final(VALUE self)
ossl_raise(eCipherError, "cipher final failed");
}
}
- assert(out_len <= RSTRING_LEN(str));
rb_str_set_len(str, out_len);
return str;
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index 93d8bc8567..ddb67fcf07 100644
--- a/ext/openssl/ossl_ocsp.c
+++ b/ext/openssl/ossl_ocsp.c
@@ -905,8 +905,8 @@ ossl_ocspbres_get_status(VALUE self)
int count = OCSP_resp_count(bs);
for (int i = 0; i < count; i++) {
OCSP_SINGLERESP *single = OCSP_resp_get0(bs, i);
- ASN1_TIME *revtime, *thisupd, *nextupd;
- int reason;
+ ASN1_TIME *revtime = NULL, *thisupd = NULL, *nextupd = NULL;
+ int reason = -1;
int status = OCSP_single_get0_status(single, &reason, &revtime, &thisupd, &nextupd);
if (status < 0)
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index 6e51fd42b9..ae0d35b723 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -1010,7 +1010,7 @@ static VALUE
ossl_pkcs7si_get_signed_time(VALUE self)
{
PKCS7_SIGNER_INFO *p7si;
- ASN1_TYPE *asn1obj;
+ const ASN1_TYPE *asn1obj;
GetPKCS7si(self, p7si);
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index bb19533edf..35f031819d 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -702,7 +702,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
break;
default:
- ossl_raise(rb_eArgError, "wrong number of arguments");
+ ossl_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1 or 4)", argc);
}
ASSUME(group);
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 630d46e43f..c6dec32a9e 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -47,7 +47,7 @@ static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
id_i_session_remove_cb, id_i_npn_select_cb, id_i_npn_protocols,
id_i_alpn_select_cb, id_i_alpn_protocols, id_i_servername_cb,
id_i_verify_hostname, id_i_keylog_cb, id_i_tmp_dh_callback;
-static ID id_i_io, id_i_context, id_i_hostname;
+static ID id_i_io, id_i_context, id_i_hostname, id_i_sync_close;
static int ossl_ssl_ex_ptr_idx;
static int ossl_sslctx_ex_ptr_idx;
@@ -1590,32 +1590,31 @@ ossl_ssl_s_alloc(VALUE klass)
}
static VALUE
-peer_ip_address(VALUE self)
+peer_ip_address(VALUE io)
{
- VALUE remote_address = rb_funcall(rb_attr_get(self, id_i_io), rb_intern("remote_address"), 0);
+ VALUE remote_address = rb_funcall(io, rb_intern("remote_address"), 0);
return rb_funcall(remote_address, rb_intern("inspect_sockaddr"), 0);
}
static VALUE
-fallback_peer_ip_address(VALUE self, VALUE args)
+fallback_peer_ip_address(VALUE self, VALUE exc)
{
return rb_str_new_cstr("(null)");
}
static VALUE
-peeraddr_ip_str(VALUE self)
+peeraddr_ip_str(VALUE io)
{
- VALUE rb_mErrno = rb_const_get(rb_cObject, rb_intern("Errno"));
- VALUE rb_eSystemCallError = rb_const_get(rb_mErrno, rb_intern("SystemCallError"));
-
- return rb_rescue2(peer_ip_address, self, fallback_peer_ip_address, (VALUE)0, rb_eSystemCallError, NULL);
+ return rb_rescue2(peer_ip_address, io, fallback_peer_ip_address, Qnil,
+ rb_eSystemCallError, (VALUE)0);
}
/*
* call-seq:
* SSLSocket.new(io) => aSSLSocket
* SSLSocket.new(io, ctx) => aSSLSocket
+ * SSLSocket.new(io, ctx, sync_close:) => aSSLSocket
*
* Creates a new SSL socket from _io_ which must be a real IO object (not an
* IO-like object that responds to read/write).
@@ -1623,6 +1622,10 @@ peeraddr_ip_str(VALUE self)
* If _ctx_ is provided the SSL Sockets initial params will be taken from
* the context.
*
+ * The optional _sync_close_ keyword parameter sets the _sync_close_ instance
+ * variable. Setting this to +true+ will cause the underlying socket to be
+ * closed when the SSL/TLS connection is shut down.
+ *
* The OpenSSL::Buffering module provides additional IO methods.
*
* This method will freeze the SSLContext if one is provided;
@@ -1631,6 +1634,10 @@ peeraddr_ip_str(VALUE self)
static VALUE
ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
{
+ static ID kw_ids[1];
+ VALUE kw_args[1];
+ VALUE opts;
+
VALUE io, v_ctx;
SSL *ssl;
SSL_CTX *ctx;
@@ -1639,9 +1646,18 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
if (ssl)
ossl_raise(eSSLError, "SSL already initialized");
- if (rb_scan_args(argc, argv, "11", &io, &v_ctx) == 1)
+ if (rb_scan_args(argc, argv, "11:", &io, &v_ctx, &opts) == 1)
v_ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
+ if (!kw_ids[0]) {
+ kw_ids[0] = rb_intern_const("sync_close");
+ }
+
+ rb_get_kwargs(opts, kw_ids, 0, 1, kw_args);
+ if (kw_args[0] != Qundef) {
+ rb_ivar_set(self, id_i_sync_close, kw_args[0]);
+ }
+
GetSSLCTX(v_ctx, ctx);
rb_ivar_set(self, id_i_context, v_ctx);
ossl_sslctx_setup(v_ctx);
@@ -1696,11 +1712,15 @@ ossl_ssl_setup(VALUE self)
return Qtrue;
}
+static int
+errno_mapped(void)
+{
#ifdef _WIN32
-#define ssl_get_error(ssl, ret) (errno = rb_w32_map_errno(WSAGetLastError()), SSL_get_error((ssl), (ret)))
+ return rb_w32_map_errno(WSAGetLastError());
#else
-#define ssl_get_error(ssl, ret) SSL_get_error((ssl), (ret))
+ return errno;
#endif
+}
static void
write_would_block(int nonblock)
@@ -1741,13 +1761,13 @@ static void
io_wait_writable(VALUE io)
{
#ifdef HAVE_RB_IO_MAYBE_WAIT
- if (!rb_io_maybe_wait_writable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) {
+ if (!rb_io_wait(io, INT2NUM(RUBY_IO_WRITABLE), RUBY_IO_TIMEOUT_DEFAULT)) {
rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become writable!");
}
#else
rb_io_t *fptr;
GetOpenFile(io, fptr);
- rb_io_wait_writable(fptr->fd);
+ rb_thread_fd_writable(fptr->fd);
#endif
}
@@ -1755,13 +1775,13 @@ static void
io_wait_readable(VALUE io)
{
#ifdef HAVE_RB_IO_MAYBE_WAIT
- if (!rb_io_maybe_wait_readable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) {
+ if (!rb_io_wait(io, INT2NUM(RUBY_IO_READABLE), RUBY_IO_TIMEOUT_DEFAULT)) {
rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become readable!");
}
#else
rb_io_t *fptr;
GetOpenFile(io, fptr);
- rb_io_wait_readable(fptr->fd);
+ rb_thread_wait_fd(fptr->fd);
#endif
}
@@ -1769,7 +1789,6 @@ static VALUE
ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
{
SSL *ssl;
- int ret, ret2;
VALUE cb_state;
int nonblock = opts != Qfalse;
@@ -1779,7 +1798,8 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
VALUE io = rb_attr_get(self, id_i_io);
for (;;) {
- ret = func(ssl);
+ int ret = func(ssl);
+ int saved_errno = errno_mapped();
cb_state = rb_attr_get(self, ID_callback_state);
if (!NIL_P(cb_state)) {
@@ -1791,7 +1811,8 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
if (ret > 0)
break;
- switch ((ret2 = ssl_get_error(ssl, ret))) {
+ int code = SSL_get_error(ssl, ret);
+ switch (code) {
case SSL_ERROR_WANT_WRITE:
if (no_exception_p(opts)) { return sym_wait_writable; }
write_would_block(nonblock);
@@ -1805,10 +1826,11 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
case SSL_ERROR_SYSCALL:
#ifdef __APPLE__
/* See ossl_ssl_write_internal() */
- if (errno == EPROTOTYPE)
+ if (saved_errno == EPROTOTYPE)
continue;
#endif
- if (errno) rb_sys_fail(funcname);
+ if (saved_errno)
+ rb_exc_raise(rb_syserr_new(saved_errno, funcname));
/* fallthrough */
default: {
VALUE error_append = Qnil;
@@ -1829,10 +1851,10 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
ossl_raise(eSSLError,
"%s%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s%"PRIsVALUE,
funcname,
- ret2 == SSL_ERROR_SYSCALL ? " SYSCALL" : "",
- ret2,
- errno,
- peeraddr_ip_str(self),
+ code == SSL_ERROR_SYSCALL ? " SYSCALL" : "",
+ code,
+ saved_errno,
+ peeraddr_ip_str(io),
SSL_state_string_long(ssl),
error_append);
}
@@ -1974,6 +1996,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
for (;;) {
rb_str_locktmp(str);
int nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
+ int saved_errno = errno_mapped();
rb_str_unlocktmp(str);
cb_state = rb_attr_get(self, ID_callback_state);
@@ -1983,7 +2006,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
rb_jump_tag(NUM2INT(cb_state));
}
- switch (ssl_get_error(ssl, nread)) {
+ switch (SSL_get_error(ssl, nread)) {
case SSL_ERROR_NONE:
rb_str_set_len(str, nread);
return str;
@@ -2006,8 +2029,8 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
break;
case SSL_ERROR_SYSCALL:
if (!ERR_peek_error()) {
- if (errno)
- rb_sys_fail(0);
+ if (saved_errno)
+ rb_exc_raise(rb_syserr_new(saved_errno, "SSL_read"));
else {
/*
* The underlying BIO returned 0. This is actually a
@@ -2092,6 +2115,7 @@ ossl_ssl_write_internal_safe(VALUE _args)
for (;;) {
int nwritten = SSL_write(ssl, RSTRING_PTR(str), num);
+ int saved_errno = errno_mapped();
cb_state = rb_attr_get(self, ID_callback_state);
if (!NIL_P(cb_state)) {
@@ -2100,7 +2124,7 @@ ossl_ssl_write_internal_safe(VALUE _args)
rb_jump_tag(NUM2INT(cb_state));
}
- switch (ssl_get_error(ssl, nwritten)) {
+ switch (SSL_get_error(ssl, nwritten)) {
case SSL_ERROR_NONE:
return INT2NUM(nwritten);
case SSL_ERROR_WANT_WRITE:
@@ -2121,10 +2145,11 @@ ossl_ssl_write_internal_safe(VALUE _args)
* make the error handling in line with the socket library.
* [Bug #14713] https://bugs.ruby-lang.org/issues/14713
*/
- if (errno == EPROTOTYPE)
+ if (saved_errno == EPROTOTYPE)
continue;
#endif
- if (errno) rb_sys_fail(0);
+ if (saved_errno)
+ rb_exc_raise(rb_syserr_new(saved_errno, "SSL_write"));
/* fallthrough */
default:
ossl_raise(eSSLError, "SSL_write");
@@ -3300,5 +3325,6 @@ Init_ossl_ssl(void)
DefIVarID(io);
DefIVarID(context);
DefIVarID(hostname);
+ DefIVarID(sync_close);
#endif /* !defined(OPENSSL_NO_SOCK) */
}