Skip to content

Commit 2dcb292

Browse files
committed
Merge branch 'maint-2.1' into maint-2.2
* maint-2.1: Ruby/OpenSSL 2.1.3 ssl: avoid directly storing String object in NPN callback x509store: explicitly call rb_gc_mark() against Store/StoreContext ssl: explicitly call rb_gc_mark() against SSLContext/SSLSocket objects digest: load digest library using Kernel#require pkey: use RSTRING_LENINT() instead of casting to int ext/openssl/extconf.rb: require OpenSSL version >= 1.0.1, < 3 .github/workflows: update OpenSSL/LibreSSL versions test: adjust test cases for LibreSSL 3.2.4 ssl: temporary lock string buffer while reading ssl: create a temporary frozen string buffer when writing Use rb_block_call() instead of the deprecated rb_iterate() in OpenSSL
2 parents 8a6d375 + e8ee01b commit 2dcb292

File tree

10 files changed

+195
-73
lines changed

10 files changed

+195
-73
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ jobs:
7474
- openssl-1.0.1u # EOL
7575
- openssl-1.0.2u # EOL
7676
- openssl-1.1.0l # EOL
77-
- openssl-1.1.1j
7877
- libressl-2.9.2 # EOL
79-
- libressl-3.1.5
80-
- libressl-3.2.0
78+
- libressl-3.1.5 # EOL
79+
- libressl-3.2.6
80+
- libressl-3.3.4
8181
steps:
8282
- name: repo checkout
8383
uses: actions/checkout@v2

History.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,42 @@ Notable changes
7575
[[GitHub #297]](https://github.com/ruby/openssl/pull/297)
7676

7777

78+
Version 2.1.3
79+
=============
80+
81+
Bug fixes
82+
---------
83+
84+
* Fix deprecation warnings on Ruby 3.0.
85+
* Add ".include" directive support in `OpenSSL::Config`.
86+
[[GitHub #216]](https://github.com/ruby/openssl/pull/216)
87+
* Fix handling of IPv6 address SANs.
88+
[[GitHub #185]](https://github.com/ruby/openssl/pull/185)
89+
* Hostname verification failure with `OpenSSL::SSL::SSLContext#verify_hostname=`
90+
sets a proper error code.
91+
[[GitHub #350]](https://github.com/ruby/openssl/pull/350)
92+
* Fix crash with `OpenSSL::BN.new(nil, 2)`.
93+
[[Bug #15760]](https://bugs.ruby-lang.org/issues/15760)
94+
* `OpenSSL::SSL::SSLSocket#sys{read,write}` prevent internal string buffers from
95+
being modified by another thread.
96+
[[GitHub #453]](https://github.com/ruby/openssl/pull/453)
97+
* Fix misuse of input record separator in `OpenSSL::Buffering` where it was
98+
for output.
99+
* Fix wrong interger casting in `OpenSSL::PKey::EC#dsa_verify_asn1`.
100+
[[GitHub #460]](https://github.com/ruby/openssl/pull/460)
101+
* `extconf.rb` explicitly checks that OpenSSL's version number is 1.0.1 or
102+
newer but also less than 3.0. Ruby/OpenSSL v2.1.x and v2.2.x will not support
103+
OpenSSL 3.0 API.
104+
[[GitHub #458]](https://github.com/ruby/openssl/pull/458)
105+
* Activate `digest` gem correctly. `digest` library could go into an
106+
inconsistent state if there are multiple versions of `digest` is installed
107+
and `openssl` is `require`d before `digest`.
108+
[[GitHub #463]](https://github.com/ruby/openssl/pull/463)
109+
* Fix GC.compact compatibility.
110+
[[GitHub #464]](https://github.com/ruby/openssl/issues/464)
111+
[[GitHub #465]](https://github.com/ruby/openssl/pull/465)
112+
113+
78114
Version 2.1.2
79115
=============
80116

ext/openssl/extconf.rb

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@
3333
have_library("ws2_32")
3434
end
3535

36-
Logging::message "=== Checking for required stuff... ===\n"
37-
result = pkg_config("openssl") && have_header("openssl/ssl.h")
38-
3936
if $mingw
4037
append_cflags '-D_FORTIFY_SOURCE=2'
4138
append_ldflags '-fstack-protector'
@@ -92,19 +89,33 @@ def find_openssl_library
9289
return false
9390
end
9491

95-
unless result
96-
unless find_openssl_library
97-
Logging::message "=== Checking for required stuff failed. ===\n"
98-
Logging::message "Makefile wasn't created. Fix the errors above.\n"
99-
raise "OpenSSL library could not be found. You might want to use " \
100-
"--with-openssl-dir=<dir> option to specify the prefix where OpenSSL " \
101-
"is installed."
102-
end
92+
Logging::message "=== Checking for required stuff... ===\n"
93+
pkg_config_found = pkg_config("openssl") && have_header("openssl/ssl.h")
94+
95+
if !pkg_config_found && !find_openssl_library
96+
Logging::message "=== Checking for required stuff failed. ===\n"
97+
Logging::message "Makefile wasn't created. Fix the errors above.\n"
98+
raise "OpenSSL library could not be found. You might want to use " \
99+
"--with-openssl-dir=<dir> option to specify the prefix where OpenSSL " \
100+
"is installed."
103101
end
104102

105-
unless checking_for("OpenSSL version is 1.0.1 or later") {
106-
try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") }
107-
raise "OpenSSL >= 1.0.1 or LibreSSL is required"
103+
version_ok = if have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h")
104+
is_libressl = true
105+
checking_for("LibreSSL version >= 2.5.0") {
106+
try_static_assert("LIBRESSL_VERSION_NUMBER >= 0x20500000L", "openssl/opensslv.h") }
107+
else
108+
checking_for("OpenSSL version >= 1.0.1 and < 3.0.0") {
109+
try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") &&
110+
!try_static_assert("OPENSSL_VERSION_MAJOR >= 3", "openssl/opensslv.h") }
111+
end
112+
unless version_ok
113+
raise "OpenSSL >= 1.0.1, < 3.0.0 or LibreSSL >= 2.5.0 is required"
114+
end
115+
116+
# Prevent wincrypt.h from being included, which defines conflicting macro with openssl/x509.h
117+
if is_libressl && ($mswin || $mingw)
118+
$defs.push("-DNOCRYPT")
108119
end
109120

110121
Logging::message "=== Checking for OpenSSL features... ===\n"
@@ -116,10 +127,6 @@ def find_openssl_library
116127
have_func("ENGINE_load_#{name}()", "openssl/engine.h")
117128
}
118129

119-
if ($mswin || $mingw) && have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h")
120-
$defs.push("-DNOCRYPT")
121-
end
122-
123130
# added in 1.0.2
124131
have_func("EC_curve_nist2nid")
125132
have_func("X509_REVOKED_dup")

ext/openssl/ossl_digest.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,6 @@ ossl_digest_block_length(VALUE self)
313313
void
314314
Init_ossl_digest(void)
315315
{
316-
rb_require("digest");
317-
318316
#if 0
319317
mOSSL = rb_define_module("OpenSSL");
320318
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
@@ -398,6 +396,12 @@ Init_ossl_digest(void)
398396
* digest2 = sha256.digest(data2)
399397
*
400398
*/
399+
400+
/*
401+
* Digest::Class is defined by the digest library. rb_require() cannot be
402+
* used here because it bypasses RubyGems.
403+
*/
404+
rb_funcall(Qnil, rb_intern_const("require"), 1, rb_str_new_cstr("digest"));
401405
cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
402406
/* Document-class: OpenSSL::Digest::DigestError
403407
*

ext/openssl/ossl_pkey_ec.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -653,15 +653,15 @@ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
653653
StringValue(data);
654654
StringValue(sig);
655655

656-
switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) {
657-
case 1: return Qtrue;
658-
case 0: return Qfalse;
659-
default: break;
656+
switch (ECDSA_verify(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
657+
(unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), ec)) {
658+
case 1:
659+
return Qtrue;
660+
case 0:
661+
return Qfalse;
662+
default:
663+
ossl_raise(eECError, "ECDSA_verify");
660664
}
661-
662-
ossl_raise(eECError, "ECDSA_verify");
663-
664-
UNREACHABLE;
665665
}
666666

667667
/*

ext/openssl/ossl_ssl.c

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313

1414
#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
1515

16+
#if !defined(TLS1_3_VERSION) && \
17+
defined(LIBRESSL_VERSION_NUMBER) && \
18+
LIBRESSL_VERSION_NUMBER >= 0x3020000fL
19+
# define TLS1_3_VERSION 0x0304
20+
#endif
21+
1622
#ifdef _WIN32
1723
# define TO_SOCKET(s) _get_osfhandle(s)
1824
#else
@@ -33,7 +39,7 @@ static VALUE eSSLErrorWaitReadable;
3339
static VALUE eSSLErrorWaitWritable;
3440

3541
static ID id_call, ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback,
36-
id_npn_protocols_encoded;
42+
id_npn_protocols_encoded, id_each;
3743
static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
3844

3945
static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
@@ -53,6 +59,13 @@ static int ossl_sslctx_ex_ptr_idx;
5359
static int ossl_sslctx_ex_store_p;
5460
#endif
5561

62+
static void
63+
ossl_sslctx_mark(void *ptr)
64+
{
65+
SSL_CTX *ctx = ptr;
66+
rb_gc_mark((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx));
67+
}
68+
5669
static void
5770
ossl_sslctx_free(void *ptr)
5871
{
@@ -67,7 +80,7 @@ ossl_sslctx_free(void *ptr)
6780
static const rb_data_type_t ossl_sslctx_type = {
6881
"OpenSSL/SSL/CTX",
6982
{
70-
0, ossl_sslctx_free,
83+
ossl_sslctx_mark, ossl_sslctx_free,
7184
},
7285
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
7386
};
@@ -616,7 +629,7 @@ static VALUE
616629
ssl_encode_npn_protocols(VALUE protocols)
617630
{
618631
VALUE encoded = rb_str_new(NULL, 0);
619-
rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded);
632+
rb_block_call(protocols, id_each, 0, 0, ssl_npn_encode_protocol_i, encoded);
620633
return encoded;
621634
}
622635

@@ -686,7 +699,7 @@ static int
686699
ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
687700
void *arg)
688701
{
689-
VALUE protocols = (VALUE)arg;
702+
VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded);
690703

691704
*out = (const unsigned char *) RSTRING_PTR(protocols);
692705
*outlen = RSTRING_LENINT(protocols);
@@ -908,7 +921,7 @@ ossl_sslctx_setup(VALUE self)
908921
if (!NIL_P(val)) {
909922
VALUE encoded = ssl_encode_npn_protocols(val);
910923
rb_ivar_set(self, id_npn_protocols_encoded, encoded);
911-
SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)encoded);
924+
SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self);
912925
OSSL_Debug("SSL NPN advertise callback added");
913926
}
914927
if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
@@ -1526,6 +1539,14 @@ ssl_started(SSL *ssl)
15261539
return SSL_get_fd(ssl) >= 0;
15271540
}
15281541

1542+
static void
1543+
ossl_ssl_mark(void *ptr)
1544+
{
1545+
SSL *ssl = ptr;
1546+
rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx));
1547+
rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx));
1548+
}
1549+
15291550
static void
15301551
ossl_ssl_free(void *ssl)
15311552
{
@@ -1535,7 +1556,7 @@ ossl_ssl_free(void *ssl)
15351556
const rb_data_type_t ossl_ssl_type = {
15361557
"OpenSSL/SSL",
15371558
{
1538-
0, ossl_ssl_free,
1559+
ossl_ssl_mark, ossl_ssl_free,
15391560
},
15401561
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
15411562
};
@@ -1852,26 +1873,36 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
18521873
io = rb_attr_get(self, id_i_io);
18531874
GetOpenFile(io, fptr);
18541875
if (ssl_started(ssl)) {
1855-
for (;;){
1876+
rb_str_locktmp(str);
1877+
for (;;) {
18561878
nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
18571879
switch(ssl_get_error(ssl, nread)){
18581880
case SSL_ERROR_NONE:
1881+
rb_str_unlocktmp(str);
18591882
goto end;
18601883
case SSL_ERROR_ZERO_RETURN:
1884+
rb_str_unlocktmp(str);
18611885
if (no_exception_p(opts)) { return Qnil; }
18621886
rb_eof_error();
18631887
case SSL_ERROR_WANT_WRITE:
1864-
if (no_exception_p(opts)) { return sym_wait_writable; }
1865-
write_would_block(nonblock);
1888+
if (nonblock) {
1889+
rb_str_unlocktmp(str);
1890+
if (no_exception_p(opts)) { return sym_wait_writable; }
1891+
write_would_block(nonblock);
1892+
}
18661893
rb_io_wait_writable(fptr->fd);
18671894
continue;
18681895
case SSL_ERROR_WANT_READ:
1869-
if (no_exception_p(opts)) { return sym_wait_readable; }
1870-
read_would_block(nonblock);
1896+
if (nonblock) {
1897+
rb_str_unlocktmp(str);
1898+
if (no_exception_p(opts)) { return sym_wait_readable; }
1899+
read_would_block(nonblock);
1900+
}
18711901
rb_io_wait_readable(fptr->fd);
18721902
continue;
18731903
case SSL_ERROR_SYSCALL:
18741904
if (!ERR_peek_error()) {
1905+
rb_str_unlocktmp(str);
18751906
if (errno)
18761907
rb_sys_fail(0);
18771908
else {
@@ -1888,6 +1919,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
18881919
}
18891920
/* fall through */
18901921
default:
1922+
rb_str_unlocktmp(str);
18911923
ossl_raise(eSSLError, "SSL_read");
18921924
}
18931925
}
@@ -1958,21 +1990,21 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
19581990
int nwrite = 0;
19591991
rb_io_t *fptr;
19601992
int nonblock = opts != Qfalse;
1961-
VALUE io;
1993+
VALUE tmp, io;
19621994

1963-
StringValue(str);
1995+
tmp = rb_str_new_frozen(StringValue(str));
19641996
GetSSL(self, ssl);
19651997
io = rb_attr_get(self, id_i_io);
19661998
GetOpenFile(io, fptr);
19671999
if (ssl_started(ssl)) {
1968-
for (;;){
1969-
int num = RSTRING_LENINT(str);
2000+
for (;;) {
2001+
int num = RSTRING_LENINT(tmp);
19702002

19712003
/* SSL_write(3ssl) manpage states num == 0 is undefined */
19722004
if (num == 0)
19732005
goto end;
19742006

1975-
nwrite = SSL_write(ssl, RSTRING_PTR(str), num);
2007+
nwrite = SSL_write(ssl, RSTRING_PTR(tmp), num);
19762008
switch(ssl_get_error(ssl, nwrite)){
19772009
case SSL_ERROR_NONE:
19782010
goto end;
@@ -3014,6 +3046,7 @@ Init_ossl_ssl(void)
30143046
id_tmp_dh_callback = rb_intern("tmp_dh_callback");
30153047
id_tmp_ecdh_callback = rb_intern("tmp_ecdh_callback");
30163048
id_npn_protocols_encoded = rb_intern("npn_protocols_encoded");
3049+
id_each = rb_intern_const("each");
30173050

30183051
#define DefIVarID(name) do \
30193052
id_i_##name = rb_intern("@"#name); while (0)

0 commit comments

Comments
 (0)