1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

openssl: import v2.1.3

Bring the local copy of ruby/openssl in sync with the upstream gem
release v2.1.3. The commits happened in the upstream repository can be
found at:

	https://github.com/ruby/openssl/compare/v2.1.2...v2.1.3

Note that many of these have already been applied to ruby.git and don't
appear in the file changes of this commit.
This commit is contained in:
Kazuki Yamaguchi 2021-09-28 15:55:12 +09:00 committed by usa
parent 8737878248
commit e0b323632f
19 changed files with 439 additions and 160 deletions

View file

@ -1,3 +1,39 @@
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 Version 2.1.2
============= =============

View file

@ -37,9 +37,6 @@ if $mswin || $mingw
have_library("ws2_32") have_library("ws2_32")
end end
Logging::message "=== Checking for required stuff... ===\n"
result = pkg_config("openssl") && have_header("openssl/ssl.h")
def find_openssl_library def find_openssl_library
if $mswin || $mingw if $mswin || $mingw
# required for static OpenSSL libraries # required for static OpenSSL libraries
@ -90,19 +87,33 @@ def find_openssl_library
return false return false
end end
unless result Logging::message "=== Checking for required stuff... ===\n"
unless find_openssl_library pkg_config_found = pkg_config("openssl") && have_header("openssl/ssl.h")
Logging::message "=== Checking for required stuff failed. ===\n"
Logging::message "Makefile wasn't created. Fix the errors above.\n" if !pkg_config_found && !find_openssl_library
raise "OpenSSL library could not be found. You might want to use " \ Logging::message "=== Checking for required stuff failed. ===\n"
"--with-openssl-dir=<dir> option to specify the prefix where OpenSSL " \ Logging::message "Makefile wasn't created. Fix the errors above.\n"
"is installed." raise "OpenSSL library could not be found. You might want to use " \
end "--with-openssl-dir=<dir> option to specify the prefix where OpenSSL " \
"is installed."
end end
unless checking_for("OpenSSL version is 1.0.1 or later") { version_ok = if have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h")
try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") } is_libressl = true
raise "OpenSSL >= 1.0.1 or LibreSSL is required" 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 end
Logging::message "=== Checking for OpenSSL features... ===\n" Logging::message "=== Checking for OpenSSL features... ===\n"
@ -114,10 +125,6 @@ engines.each { |name|
OpenSSL.check_func_or_macro("ENGINE_load_#{name}", "openssl/engine.h") OpenSSL.check_func_or_macro("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 # added in 1.0.2
have_func("EC_curve_nist2nid") have_func("EC_curve_nist2nid")
have_func("X509_REVOKED_dup") have_func("X509_REVOKED_dup")

View file

@ -1,29 +1,27 @@
# -*- encoding: utf-8 -*- Gem::Specification.new do |spec|
spec.name = "openssl"
spec.version = "2.1.3"
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.}
spec.description = %q{It wraps the OpenSSL library.}
spec.homepage = "https://github.com/ruby/openssl"
spec.license = "Ruby"
Gem::Specification.new do |s| spec.files = Dir["lib/**/*.rb", "ext/**/*.{c,h,rb}", "*.md", "BSDL", "LICENSE.txt"]
s.name = "openssl" spec.require_paths = ["lib"]
s.version = "2.1.2" spec.extensions = ["ext/openssl/extconf.rb"]
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= spec.extra_rdoc_files = Dir["*.md"]
s.metadata = { "msys2_mingw_dependencies" => "openssl" } if s.respond_to? :metadata= spec.rdoc_options = ["--main", "README.md"]
s.require_paths = ["lib"]
s.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"]
s.date = "2018-10-17"
s.description = "It wraps the OpenSSL library."
s.email = ["ruby-core@ruby-lang.org"]
s.extensions = ["ext/openssl/extconf.rb"]
s.extra_rdoc_files = ["README.md", "CONTRIBUTING.md", "History.md"]
s.files = ["BSDL", "CONTRIBUTING.md", "History.md", "LICENSE.txt", "README.md", "ext/openssl/deprecation.rb", "ext/openssl/extconf.rb", "ext/openssl/openssl_missing.c", "ext/openssl/openssl_missing.h", "ext/openssl/ossl.c", "ext/openssl/ossl.h", "ext/openssl/ossl_asn1.c", "ext/openssl/ossl_asn1.h", "ext/openssl/ossl_bio.c", "ext/openssl/ossl_bio.h", "ext/openssl/ossl_bn.c", "ext/openssl/ossl_bn.h", "ext/openssl/ossl_cipher.c", "ext/openssl/ossl_cipher.h", "ext/openssl/ossl_config.c", "ext/openssl/ossl_config.h", "ext/openssl/ossl_digest.c", "ext/openssl/ossl_digest.h", "ext/openssl/ossl_engine.c", "ext/openssl/ossl_engine.h", "ext/openssl/ossl_hmac.c", "ext/openssl/ossl_hmac.h", "ext/openssl/ossl_kdf.c", "ext/openssl/ossl_kdf.h", "ext/openssl/ossl_ns_spki.c", "ext/openssl/ossl_ns_spki.h", "ext/openssl/ossl_ocsp.c", "ext/openssl/ossl_ocsp.h", "ext/openssl/ossl_pkcs12.c", "ext/openssl/ossl_pkcs12.h", "ext/openssl/ossl_pkcs7.c", "ext/openssl/ossl_pkcs7.h", "ext/openssl/ossl_pkey.c", "ext/openssl/ossl_pkey.h", "ext/openssl/ossl_pkey_dh.c", "ext/openssl/ossl_pkey_dsa.c", "ext/openssl/ossl_pkey_ec.c", "ext/openssl/ossl_pkey_rsa.c", "ext/openssl/ossl_rand.c", "ext/openssl/ossl_rand.h", "ext/openssl/ossl_ssl.c", "ext/openssl/ossl_ssl.h", "ext/openssl/ossl_ssl_session.c", "ext/openssl/ossl_version.h", "ext/openssl/ossl_x509.c", "ext/openssl/ossl_x509.h", "ext/openssl/ossl_x509attr.c", "ext/openssl/ossl_x509cert.c", "ext/openssl/ossl_x509crl.c", "ext/openssl/ossl_x509ext.c", "ext/openssl/ossl_x509name.c", "ext/openssl/ossl_x509req.c", "ext/openssl/ossl_x509revoked.c", "ext/openssl/ossl_x509store.c", "ext/openssl/ruby_missing.h", "lib/openssl.rb", "lib/openssl/bn.rb", "lib/openssl/buffering.rb", "lib/openssl/cipher.rb", "lib/openssl/config.rb", "lib/openssl/digest.rb", "lib/openssl/pkcs5.rb", "lib/openssl/pkey.rb", "lib/openssl/ssl.rb", "lib/openssl/x509.rb"]
s.homepage = "https://github.com/ruby/openssl"
s.licenses = ["Ruby"]
s.rdoc_options = ["--main", "README.md"]
s.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
s.rubygems_version = "3.0.0.beta1"
s.summary = "OpenSSL provides SSL, TLS and general purpose cryptography."
s.add_runtime_dependency("ipaddr", [">= 0"]) spec.required_ruby_version = ">= 2.3.0"
s.add_development_dependency("rake", [">= 0"])
s.add_development_dependency("rake-compiler", [">= 0"]) spec.add_runtime_dependency "ipaddr"
s.add_development_dependency("test-unit", ["~> 3.0"]) spec.add_development_dependency "rake"
s.add_development_dependency("rdoc", [">= 0"]) spec.add_development_dependency "rake-compiler"
spec.add_development_dependency "test-unit", "~> 3.0"
spec.add_development_dependency "rdoc"
spec.metadata["msys2_mingw_dependencies"] = "openssl"
end end

View file

@ -27,6 +27,7 @@
#include <openssl/hmac.h> #include <openssl/hmac.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/conf.h> #include <openssl/conf.h>
#include <openssl/conf_api.h>
#include <openssl/crypto.h> #include <openssl/crypto.h>
#if !defined(OPENSSL_NO_ENGINE) #if !defined(OPENSSL_NO_ENGINE)
# include <openssl/engine.h> # include <openssl/engine.h>

View file

@ -400,7 +400,7 @@ ossl_bn_is_negative(VALUE self)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func(result, bn, ossl_bn_ctx)) { \ if (BN_##func(result, bn, ossl_bn_ctx) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -426,7 +426,7 @@ BIGNUM_1c(sqr)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func(result, bn1, bn2)) { \ if (BN_##func(result, bn1, bn2) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -459,7 +459,7 @@ BIGNUM_2(sub)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ 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); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -503,11 +503,21 @@ BIGNUM_2c(gcd)
BIGNUM_2c(mod_sqr) BIGNUM_2c(mod_sqr)
/* /*
* Document-method: OpenSSL::BN#mod_inverse
* call-seq: * 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: * call-seq:
@ -556,7 +566,7 @@ ossl_bn_div(VALUE self, VALUE other)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ 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); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -598,7 +608,7 @@ BIGNUM_3c(mod_exp)
{ \ { \
BIGNUM *bn; \ BIGNUM *bn; \
GetBN(self, bn); \ GetBN(self, bn); \
if (!BN_##func(bn, NUM2INT(bit))) { \ if (BN_##func(bn, NUM2INT(bit)) <= 0) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
return self; \ return self; \
@ -658,7 +668,7 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func(result, bn, b)) { \ if (BN_##func(result, bn, b) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -688,7 +698,7 @@ BIGNUM_SHIFT(rshift)
int b; \ int b; \
b = NUM2INT(bits); \ b = NUM2INT(bits); \
GetBN(self, bn); \ GetBN(self, bn); \
if (!BN_##func(bn, bn, b)) \ if (BN_##func(bn, bn, b) <= 0) \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
return self; \ return self; \
} }
@ -727,7 +737,7 @@ BIGNUM_SELF_SHIFT(rshift)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func(result, b, top, bottom)) { \ if (BN_##func(result, b, top, bottom) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -756,7 +766,7 @@ BIGNUM_RAND(pseudo_rand)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func##_range(result, bn)) { \ if (BN_##func##_range(result, bn) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \

View file

@ -313,8 +313,6 @@ ossl_digest_block_length(VALUE self)
void void
Init_ossl_digest(void) Init_ossl_digest(void)
{ {
rb_require("digest");
#if 0 #if 0
mOSSL = rb_define_module("OpenSSL"); mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
@ -433,6 +431,12 @@ Init_ossl_digest(void)
* digest2 = sha256.digest(data2) * 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")); cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
/* Document-class: OpenSSL::Digest::DigestError /* Document-class: OpenSSL::Digest::DigestError
* *

View file

@ -803,9 +803,9 @@ ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self)
BIO *out; BIO *out;
VALUE str; VALUE str;
rb_scan_args(argc, argv, "12", &pkey, &cert, &flags); rb_scan_args(argc, argv, "21", &pkey, &cert, &flags);
key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */ key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */
x509 = NIL_P(cert) ? NULL : GetX509CertPtr(cert); /* NO NEED TO DUP */ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
flg = NIL_P(flags) ? 0 : NUM2INT(flags); flg = NIL_P(flags) ? 0 : NUM2INT(flags);
GetPKCS7(self, p7); GetPKCS7(self, p7);
if(!(out = BIO_new(BIO_s_mem()))) if(!(out = BIO_new(BIO_s_mem())))

View file

@ -653,15 +653,15 @@ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
StringValue(data); StringValue(data);
StringValue(sig); StringValue(sig);
switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) { switch (ECDSA_verify(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
case 1: return Qtrue; (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), ec)) {
case 0: return Qfalse; case 1:
default: break; return Qtrue;
case 0:
return Qfalse;
default:
ossl_raise(eECError, "ECDSA_verify");
} }
ossl_raise(eECError, "ECDSA_verify");
UNREACHABLE;
} }
/* /*

View file

@ -13,6 +13,12 @@
#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0])) #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 #ifdef _WIN32
# define TO_SOCKET(s) _get_osfhandle(s) # define TO_SOCKET(s) _get_osfhandle(s)
#else #else
@ -33,7 +39,7 @@ static VALUE eSSLErrorWaitReadable;
static VALUE eSSLErrorWaitWritable; static VALUE eSSLErrorWaitWritable;
static ID id_call, ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback, 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 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, 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;
static int ossl_sslctx_ex_store_p; static int ossl_sslctx_ex_store_p;
#endif #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 static void
ossl_sslctx_free(void *ptr) ossl_sslctx_free(void *ptr)
{ {
@ -67,7 +80,7 @@ ossl_sslctx_free(void *ptr)
static const rb_data_type_t ossl_sslctx_type = { static const rb_data_type_t ossl_sslctx_type = {
"OpenSSL/SSL/CTX", "OpenSSL/SSL/CTX",
{ {
0, ossl_sslctx_free, ossl_sslctx_mark, ossl_sslctx_free,
}, },
0, 0, RUBY_TYPED_FREE_IMMEDIATELY, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
}; };
@ -359,7 +372,14 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status)); rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
return 0; return 0;
} }
preverify_ok = ret == Qtrue; if (ret != Qtrue) {
preverify_ok = 0;
#if defined(X509_V_ERR_HOSTNAME_MISMATCH)
X509_STORE_CTX_set_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH);
#else
X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
#endif
}
} }
return ossl_verify_cb_call(cb, preverify_ok, ctx); return ossl_verify_cb_call(cb, preverify_ok, ctx);
@ -609,7 +629,7 @@ static VALUE
ssl_encode_npn_protocols(VALUE protocols) ssl_encode_npn_protocols(VALUE protocols)
{ {
VALUE encoded = rb_str_new(NULL, 0); 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; return encoded;
} }
@ -679,7 +699,7 @@ static int
ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
void *arg) void *arg)
{ {
VALUE protocols = (VALUE)arg; VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded);
*out = (const unsigned char *) RSTRING_PTR(protocols); *out = (const unsigned char *) RSTRING_PTR(protocols);
*outlen = RSTRING_LENINT(protocols); *outlen = RSTRING_LENINT(protocols);
@ -897,7 +917,7 @@ ossl_sslctx_setup(VALUE self)
if (!NIL_P(val)) { if (!NIL_P(val)) {
VALUE encoded = ssl_encode_npn_protocols(val); VALUE encoded = ssl_encode_npn_protocols(val);
rb_ivar_set(self, id_npn_protocols_encoded, encoded); 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"); OSSL_Debug("SSL NPN advertise callback added");
} }
if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) { if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
@ -1515,6 +1535,14 @@ ssl_started(SSL *ssl)
return SSL_get_fd(ssl) >= 0; return SSL_get_fd(ssl) >= 0;
} }
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 static void
ossl_ssl_free(void *ssl) ossl_ssl_free(void *ssl)
{ {
@ -1524,7 +1552,7 @@ ossl_ssl_free(void *ssl)
const rb_data_type_t ossl_ssl_type = { const rb_data_type_t ossl_ssl_type = {
"OpenSSL/SSL", "OpenSSL/SSL",
{ {
0, ossl_ssl_free, ossl_ssl_mark, ossl_ssl_free,
}, },
0, 0, RUBY_TYPED_FREE_IMMEDIATELY, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
}; };
@ -1680,6 +1708,11 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
rb_io_wait_readable(fptr->fd); rb_io_wait_readable(fptr->fd);
continue; continue;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
#ifdef __APPLE__
/* See ossl_ssl_write_internal() */
if (errno == EPROTOTYPE)
continue;
#endif
if (errno) rb_sys_fail(funcname); 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)); 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) #if defined(SSL_R_CERTIFICATE_VERIFY_FAILED)
@ -1836,26 +1869,36 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
io = rb_attr_get(self, id_i_io); io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr); GetOpenFile(io, fptr);
if (ssl_started(ssl)) { if (ssl_started(ssl)) {
for (;;){ rb_str_locktmp(str);
for (;;) {
nread = SSL_read(ssl, RSTRING_PTR(str), ilen); nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
switch(ssl_get_error(ssl, nread)){ switch(ssl_get_error(ssl, nread)){
case SSL_ERROR_NONE: case SSL_ERROR_NONE:
rb_str_unlocktmp(str);
goto end; goto end;
case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_ZERO_RETURN:
rb_str_unlocktmp(str);
if (no_exception_p(opts)) { return Qnil; } if (no_exception_p(opts)) { return Qnil; }
rb_eof_error(); rb_eof_error();
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
if (no_exception_p(opts)) { return sym_wait_writable; } if (nonblock) {
write_would_block(nonblock); rb_str_unlocktmp(str);
if (no_exception_p(opts)) { return sym_wait_writable; }
write_would_block(nonblock);
}
rb_io_wait_writable(fptr->fd); rb_io_wait_writable(fptr->fd);
continue; continue;
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
if (no_exception_p(opts)) { return sym_wait_readable; } if (nonblock) {
read_would_block(nonblock); rb_str_unlocktmp(str);
if (no_exception_p(opts)) { return sym_wait_readable; }
read_would_block(nonblock);
}
rb_io_wait_readable(fptr->fd); rb_io_wait_readable(fptr->fd);
continue; continue;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
if (!ERR_peek_error()) { if (!ERR_peek_error()) {
rb_str_unlocktmp(str);
if (errno) if (errno)
rb_sys_fail(0); rb_sys_fail(0);
else { else {
@ -1872,23 +1915,30 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
} }
/* fall through */ /* fall through */
default: default:
rb_str_unlocktmp(str);
ossl_raise(eSSLError, "SSL_read"); ossl_raise(eSSLError, "SSL_read");
} }
} }
} }
else { else {
ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread"); ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
rb_warning("SSL session is not started yet."); rb_warning("SSL session is not started yet.");
if (nonblock) { #if defined(RB_PASS_KEYWORDS)
if (nonblock) {
VALUE argv[3]; VALUE argv[3];
argv[0] = len; argv[0] = len;
argv[1] = str; argv[1] = str;
argv[2] = opts; argv[2] = opts;
return rb_funcallv_kw(io, meth, 3, argv, RB_PASS_KEYWORDS); return rb_funcallv_kw(io, meth, 3, argv, RB_PASS_KEYWORDS);
} }
else #else
return rb_funcall(io, meth, 2, len, str); if (nonblock) {
return rb_funcall(io, meth, 3, len, str, opts);
}
#endif
else
return rb_funcall(io, meth, 2, len, str);
} }
end: end:
@ -1936,21 +1986,21 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
int nwrite = 0; int nwrite = 0;
rb_io_t *fptr; rb_io_t *fptr;
int nonblock = opts != Qfalse; int nonblock = opts != Qfalse;
VALUE io; VALUE tmp, io;
StringValue(str); tmp = rb_str_new_frozen(StringValue(str));
GetSSL(self, ssl); GetSSL(self, ssl);
io = rb_attr_get(self, id_i_io); io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr); GetOpenFile(io, fptr);
if (ssl_started(ssl)) { if (ssl_started(ssl)) {
for (;;){ for (;;) {
int num = RSTRING_LENINT(str); int num = RSTRING_LENINT(tmp);
/* SSL_write(3ssl) manpage states num == 0 is undefined */ /* SSL_write(3ssl) manpage states num == 0 is undefined */
if (num == 0) if (num == 0)
goto end; goto end;
nwrite = SSL_write(ssl, RSTRING_PTR(str), num); nwrite = SSL_write(ssl, RSTRING_PTR(tmp), num);
switch(ssl_get_error(ssl, nwrite)){ switch(ssl_get_error(ssl, nwrite)){
case SSL_ERROR_NONE: case SSL_ERROR_NONE:
goto end; goto end;
@ -1965,6 +2015,16 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
rb_io_wait_readable(fptr->fd); rb_io_wait_readable(fptr->fd);
continue; continue;
case SSL_ERROR_SYSCALL: 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); if (errno) rb_sys_fail(0);
default: default:
ossl_raise(eSSLError, "SSL_write"); ossl_raise(eSSLError, "SSL_write");
@ -1975,15 +2035,21 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
ID meth = nonblock ? ID meth = nonblock ?
rb_intern("write_nonblock") : rb_intern("syswrite"); rb_intern("write_nonblock") : rb_intern("syswrite");
rb_warning("SSL session is not started yet."); rb_warning("SSL session is not started yet.");
if (nonblock) { #if defined(RB_PASS_KEYWORDS)
if (nonblock) {
VALUE argv[2]; VALUE argv[2];
argv[0] = str; argv[0] = str;
argv[1] = opts; argv[1] = opts;
return rb_funcallv_kw(io, meth, 2, argv, RB_PASS_KEYWORDS); return rb_funcallv_kw(io, meth, 2, argv, RB_PASS_KEYWORDS);
} }
else #else
return rb_funcall(io, meth, 1, str); if (nonblock) {
return rb_funcall(io, meth, 2, str, opts);
}
#endif
else
return rb_funcall(io, meth, 1, str);
} }
end: end:
@ -2926,6 +2992,7 @@ Init_ossl_ssl(void)
id_tmp_dh_callback = rb_intern("tmp_dh_callback"); id_tmp_dh_callback = rb_intern("tmp_dh_callback");
id_tmp_ecdh_callback = rb_intern("tmp_ecdh_callback"); id_tmp_ecdh_callback = rb_intern("tmp_ecdh_callback");
id_npn_protocols_encoded = rb_intern("npn_protocols_encoded"); id_npn_protocols_encoded = rb_intern("npn_protocols_encoded");
id_each = rb_intern_const("each");
#define DefIVarID(name) do \ #define DefIVarID(name) do \
id_i_##name = rb_intern("@"#name); while (0) id_i_##name = rb_intern("@"#name); while (0)

View file

@ -10,6 +10,6 @@
#if !defined(_OSSL_VERSION_H_) #if !defined(_OSSL_VERSION_H_)
#define _OSSL_VERSION_H_ #define _OSSL_VERSION_H_
#define OSSL_VERSION "2.1.2" #define OSSL_VERSION "2.1.3"
#endif /* _OSSL_VERSION_H_ */ #endif /* _OSSL_VERSION_H_ */

View file

@ -44,7 +44,13 @@ Init_ossl_x509(void)
Init_ossl_x509revoked(); Init_ossl_x509revoked();
Init_ossl_x509store(); Init_ossl_x509store();
/* Constants are up-to-date with 1.1.1. */
/* Certificate verification error code */
DefX509Const(V_OK); DefX509Const(V_OK);
#if defined(X509_V_ERR_UNSPECIFIED) /* 1.0.1r, 1.0.2f, 1.1.0 */
DefX509Const(V_ERR_UNSPECIFIED);
#endif
DefX509Const(V_ERR_UNABLE_TO_GET_ISSUER_CERT); DefX509Const(V_ERR_UNABLE_TO_GET_ISSUER_CERT);
DefX509Const(V_ERR_UNABLE_TO_GET_CRL); DefX509Const(V_ERR_UNABLE_TO_GET_CRL);
DefX509Const(V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE); DefX509Const(V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE);
@ -76,8 +82,73 @@ Init_ossl_x509(void)
DefX509Const(V_ERR_AKID_SKID_MISMATCH); DefX509Const(V_ERR_AKID_SKID_MISMATCH);
DefX509Const(V_ERR_AKID_ISSUER_SERIAL_MISMATCH); DefX509Const(V_ERR_AKID_ISSUER_SERIAL_MISMATCH);
DefX509Const(V_ERR_KEYUSAGE_NO_CERTSIGN); DefX509Const(V_ERR_KEYUSAGE_NO_CERTSIGN);
DefX509Const(V_ERR_UNABLE_TO_GET_CRL_ISSUER);
DefX509Const(V_ERR_UNHANDLED_CRITICAL_EXTENSION);
DefX509Const(V_ERR_KEYUSAGE_NO_CRL_SIGN);
DefX509Const(V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION);
DefX509Const(V_ERR_INVALID_NON_CA);
DefX509Const(V_ERR_PROXY_PATH_LENGTH_EXCEEDED);
DefX509Const(V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE);
DefX509Const(V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED);
DefX509Const(V_ERR_INVALID_EXTENSION);
DefX509Const(V_ERR_INVALID_POLICY_EXTENSION);
DefX509Const(V_ERR_NO_EXPLICIT_POLICY);
DefX509Const(V_ERR_DIFFERENT_CRL_SCOPE);
DefX509Const(V_ERR_UNSUPPORTED_EXTENSION_FEATURE);
DefX509Const(V_ERR_UNNESTED_RESOURCE);
DefX509Const(V_ERR_PERMITTED_VIOLATION);
DefX509Const(V_ERR_EXCLUDED_VIOLATION);
DefX509Const(V_ERR_SUBTREE_MINMAX);
DefX509Const(V_ERR_APPLICATION_VERIFICATION); DefX509Const(V_ERR_APPLICATION_VERIFICATION);
DefX509Const(V_ERR_UNSUPPORTED_CONSTRAINT_TYPE);
DefX509Const(V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX);
DefX509Const(V_ERR_UNSUPPORTED_NAME_SYNTAX);
DefX509Const(V_ERR_CRL_PATH_VALIDATION_ERROR);
#if defined(X509_V_ERR_PATH_LOOP)
DefX509Const(V_ERR_PATH_LOOP);
#endif
#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION)
DefX509Const(V_ERR_SUITE_B_INVALID_VERSION);
DefX509Const(V_ERR_SUITE_B_INVALID_ALGORITHM);
DefX509Const(V_ERR_SUITE_B_INVALID_CURVE);
DefX509Const(V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM);
DefX509Const(V_ERR_SUITE_B_LOS_NOT_ALLOWED);
DefX509Const(V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256);
#endif
#if defined(X509_V_ERR_HOSTNAME_MISMATCH)
DefX509Const(V_ERR_HOSTNAME_MISMATCH);
DefX509Const(V_ERR_EMAIL_MISMATCH);
DefX509Const(V_ERR_IP_ADDRESS_MISMATCH);
#endif
#if defined(X509_V_ERR_DANE_NO_MATCH)
DefX509Const(V_ERR_DANE_NO_MATCH);
#endif
#if defined(X509_V_ERR_EE_KEY_TOO_SMALL)
DefX509Const(V_ERR_EE_KEY_TOO_SMALL);
DefX509Const(V_ERR_CA_KEY_TOO_SMALL);
DefX509Const(V_ERR_CA_MD_TOO_WEAK);
#endif
#if defined(X509_V_ERR_INVALID_CALL)
DefX509Const(V_ERR_INVALID_CALL);
#endif
#if defined(X509_V_ERR_STORE_LOOKUP)
DefX509Const(V_ERR_STORE_LOOKUP);
#endif
#if defined(X509_V_ERR_NO_VALID_SCTS)
DefX509Const(V_ERR_NO_VALID_SCTS);
#endif
#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION)
DefX509Const(V_ERR_PROXY_SUBJECT_NAME_VIOLATION);
#endif
#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED)
DefX509Const(V_ERR_OCSP_VERIFY_NEEDED);
DefX509Const(V_ERR_OCSP_VERIFY_FAILED);
DefX509Const(V_ERR_OCSP_CERT_UNKNOWN);
#endif
/* Certificate verify flags */
/* Set by Store#flags= and StoreContext#flags=. */
DefX509Const(V_FLAG_USE_CHECK_TIME);
/* Set by Store#flags= and StoreContext#flags=. Enables CRL checking for the /* Set by Store#flags= and StoreContext#flags=. Enables CRL checking for the
* certificate chain leaf. */ * certificate chain leaf. */
DefX509Const(V_FLAG_CRL_CHECK); DefX509Const(V_FLAG_CRL_CHECK);
@ -122,6 +193,26 @@ Init_ossl_x509(void)
* Enabled by default in OpenSSL >= 1.1.0. */ * Enabled by default in OpenSSL >= 1.1.0. */
DefX509Const(V_FLAG_TRUSTED_FIRST); DefX509Const(V_FLAG_TRUSTED_FIRST);
#endif #endif
#if defined(X509_V_FLAG_SUITEB_128_LOS_ONLY)
/* Set by Store#flags= and StoreContext#flags=.
* Enables Suite B 128 bit only mode. */
DefX509Const(V_FLAG_SUITEB_128_LOS_ONLY);
#endif
#if defined(X509_V_FLAG_SUITEB_192_LOS)
/* Set by Store#flags= and StoreContext#flags=.
* Enables Suite B 192 bit only mode. */
DefX509Const(V_FLAG_SUITEB_192_LOS);
#endif
#if defined(X509_V_FLAG_SUITEB_128_LOS)
/* Set by Store#flags= and StoreContext#flags=.
* Enables Suite B 128 bit mode allowing 192 bit algorithms. */
DefX509Const(V_FLAG_SUITEB_128_LOS);
#endif
#if defined(X509_V_FLAG_PARTIAL_CHAIN)
/* Set by Store#flags= and StoreContext#flags=.
* Allows partial chains if at least one certificate is in trusted store. */
DefX509Const(V_FLAG_PARTIAL_CHAIN);
#endif
#if defined(X509_V_FLAG_NO_ALT_CHAINS) #if defined(X509_V_FLAG_NO_ALT_CHAINS)
/* Set by Store#flags= and StoreContext#flags=. Suppresses searching for /* Set by Store#flags= and StoreContext#flags=. Suppresses searching for
* a alternative chain. No effect in OpenSSL >= 1.1.0. */ * a alternative chain. No effect in OpenSSL >= 1.1.0. */

View file

@ -105,6 +105,13 @@ VALUE cX509Store;
VALUE cX509StoreContext; VALUE cX509StoreContext;
VALUE eX509StoreError; 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 static void
ossl_x509store_free(void *ptr) ossl_x509store_free(void *ptr)
{ {
@ -114,7 +121,7 @@ ossl_x509store_free(void *ptr)
static const rb_data_type_t ossl_x509store_type = { static const rb_data_type_t ossl_x509store_type = {
"OpenSSL/X509/STORE", "OpenSSL/X509/STORE",
{ {
0, ossl_x509store_free, ossl_x509store_mark, ossl_x509store_free,
}, },
0, 0, RUBY_TYPED_FREE_IMMEDIATELY, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
}; };
@ -456,23 +463,16 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
return result; return result;
} }
/*
* 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 * 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 static void
ossl_x509stctx_free(void *ptr) ossl_x509stctx_free(void *ptr)
{ {
@ -484,6 +484,14 @@ ossl_x509stctx_free(void *ptr)
X509_STORE_CTX_free(ctx); 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 static VALUE
ossl_x509stctx_alloc(VALUE klass) ossl_x509stctx_alloc(VALUE klass)
{ {
@ -517,7 +525,9 @@ static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
/* /*
* call-seq: * 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 static VALUE
ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) 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_STORE *x509st;
X509 *x509 = NULL; X509 *x509 = NULL;
STACK_OF(X509) *x509s = NULL; STACK_OF(X509) *x509s = NULL;
int state;
rb_scan_args(argc, argv, "12", &store, &cert, &chain); rb_scan_args(argc, argv, "12", &store, &cert, &chain);
GetX509StCtx(self, ctx); GetX509StCtx(self, ctx);
GetX509Store(store, x509st); GetX509Store(store, x509st);
if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */ if (!NIL_P(cert))
if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain); x509 = DupX509CertPtr(cert); /* NEED TO DUP */
if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){ 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); 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"))) if (!NIL_P(t = rb_iv_get(store, "@time")))
ossl_x509stctx_set_time(self, t); ossl_x509stctx_set_time(self, t);

View file

@ -635,11 +635,6 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
assert_equal data, seq.entries assert_equal data, seq.entries
end end
def test_gc_stress
skip "very time consuming test"
assert_ruby_status(['--disable-gems', '-eGC.stress=true', '-erequire "openssl.so"'])
end
private private
def B(ary) def B(ary)

View file

@ -272,11 +272,6 @@ class OpenSSL::TestBN < OpenSSL::TestCase
assert_equal(0, @e1.ucmp(-999)) assert_equal(0, @e1.ucmp(-999))
assert_instance_of(String, @e1.hash.to_s) assert_instance_of(String, @e1.hash.to_s)
end end
def test_type_error
bug15760 = '[ruby-core:92231] [Bug #15760]'
assert_raise(TypeError, bug15760) { OpenSSL::BN.new(nil, 2) }
end
end end
end end

View file

@ -133,8 +133,6 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase
assert_equal(@ca_cert.subject.to_s, recip[1].issuer.to_s) assert_equal(@ca_cert.subject.to_s, recip[1].issuer.to_s)
assert_equal(3, recip[1].serial) assert_equal(3, recip[1].serial)
assert_equal(data, p7.decrypt(@rsa1024, @ee2_cert)) assert_equal(data, p7.decrypt(@rsa1024, @ee2_cert))
assert_equal(data, p7.decrypt(@rsa1024))
end end
def test_graceful_parsing_failure #[ruby-core:43250] def test_graceful_parsing_failure #[ruby-core:43250]

View file

@ -155,21 +155,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
} }
end end
def test_sysread_nonblock_and_syswrite_nonblock_keywords
start_server(ignore_listener_error: true) do |port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
assert_warn ("") do
ssl.send(:syswrite_nonblock, "1", exception: false)
ssl.send(:sysread_nonblock, 1, exception: false) rescue nil
ssl.send(:sysread_nonblock, 1, String.new, exception: false) rescue nil
end
ensure
sock&.close
end
end
def test_sync_close def test_sync_close
start_server { |port| start_server { |port|
begin begin
@ -222,7 +207,10 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
def test_client_auth_success def test_client_auth_success
vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
start_server(verify_mode: vflag) { |port| start_server(verify_mode: vflag,
ctx_proc: proc { |ctx|
ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION if libressl?(3, 2, 0)
}) { |port|
ctx = OpenSSL::SSL::SSLContext.new ctx = OpenSSL::SSL::SSLContext.new
ctx.key = @cli_key ctx.key = @cli_key
ctx.cert = @cli_cert ctx.cert = @cli_cert
@ -268,6 +256,8 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end end
def test_client_ca def test_client_ca
pend "LibreSSL 3.2 has broken client CA support" if libressl?(3, 2, 0)
ctx_proc = Proc.new do |ctx| ctx_proc = Proc.new do |ctx|
ctx.client_ca = [@ca_cert] ctx.client_ca = [@ca_cert]
end end
@ -808,11 +798,13 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
def test_verify_hostname_on_connect def test_verify_hostname_on_connect
ctx_proc = proc { |ctx| ctx_proc = proc { |ctx|
san = "DNS:a.example.com,DNS:*.b.example.com"
san += ",DNS:c*.example.com,DNS:d.*.example.com" unless libressl?(3, 2, 2)
exts = [ exts = [
["keyUsage", "keyEncipherment,digitalSignature", true], ["keyUsage", "keyEncipherment,digitalSignature", true],
["subjectAltName", "DNS:a.example.com,DNS:*.b.example.com," \ ["subjectAltName", san],
"DNS:c*.example.com,DNS:d.*.example.com"],
] ]
ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key) ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key)
ctx.key = @svr_key ctx.key = @svr_key
} }
@ -833,6 +825,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
["cx.example.com", true], ["cx.example.com", true],
["d.x.example.com", false], ["d.x.example.com", false],
].each do |name, expected_ok| ].each do |name, expected_ok|
next if name.start_with?('cx') if libressl?(3, 2, 2)
begin begin
sock = TCPSocket.new("127.0.0.1", port) sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
@ -851,6 +844,46 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end end
end end
def test_verify_hostname_failure_error_code
ctx_proc = proc { |ctx|
exts = [
["keyUsage", "keyEncipherment,digitalSignature", true],
["subjectAltName", "DNS:a.example.com"],
]
ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key)
ctx.key = @svr_key
}
start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port|
verify_callback_ok = verify_callback_err = nil
ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_hostname = true
ctx.cert_store = OpenSSL::X509::Store.new
ctx.cert_store.add_cert(@ca_cert)
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
ctx.verify_callback = -> (preverify_ok, store_ctx) {
verify_callback_ok = preverify_ok
verify_callback_err = store_ctx.error
preverify_ok
}
begin
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
ssl.hostname = "b.example.com"
assert_handshake_error { ssl.connect }
assert_equal false, verify_callback_ok
code_expected = openssl?(1, 0, 2) || defined?(OpenSSL::X509::V_ERR_HOSTNAME_MISMATCH) ?
OpenSSL::X509::V_ERR_HOSTNAME_MISMATCH :
OpenSSL::X509::V_ERR_CERT_REJECTED
assert_equal code_expected, verify_callback_err
ensure
sock&.close
end
end
end
def test_connect_certificate_verify_failed_exception_message def test_connect_certificate_verify_failed_exception_message
start_server(ignore_listener_error: true) { |port| start_server(ignore_listener_error: true) { |port|
ctx = OpenSSL::SSL::SSLContext.new ctx = OpenSSL::SSL::SSLContext.new
@ -1476,12 +1509,13 @@ end
end end
end end
def test_ecdh_curves def test_ecdh_curves_tls12
pend "EC is disabled" unless defined?(OpenSSL::PKey::EC) pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
ctx_proc = -> ctx { ctx_proc = -> ctx {
# Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3 # Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3
ctx.ciphers = "DEFAULT:!kRSA:!kEDH" ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
ctx.ciphers = "kEECDH"
ctx.ecdh_curves = "P-384:P-521" ctx.ecdh_curves = "P-384:P-521"
} }
start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port|
@ -1490,13 +1524,9 @@ end
server_connect(port, ctx) { |ssl| server_connect(port, ctx) { |ssl|
cs = ssl.cipher[0] cs = ssl.cipher[0]
if /\ATLS/ =~ cs # Is TLS 1.3 is used? assert_match (/\AECDH/), cs
if ssl.respond_to?(:tmp_key)
assert_equal "secp384r1", ssl.tmp_key.group.curve_name assert_equal "secp384r1", ssl.tmp_key.group.curve_name
else
assert_match (/\AECDH/), cs
if ssl.respond_to?(:tmp_key)
assert_equal "secp384r1", ssl.tmp_key.group.curve_name
end
end end
ssl.puts "abc"; assert_equal "abc\n", ssl.gets ssl.puts "abc"; assert_equal "abc\n", ssl.gets
} }
@ -1520,6 +1550,26 @@ end
end end
end end
def test_ecdh_curves_tls13
pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
pend "TLS 1.3 not supported" unless tls13_supported?
ctx_proc = -> ctx {
# Assume TLS 1.3 is enabled and chosen by default
ctx.ecdh_curves = "P-384:P-521"
}
start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.ecdh_curves = "P-256:P-384" # disable P-521
server_connect(port, ctx) { |ssl|
assert_equal "TLSv1.3", ssl.ssl_version
assert_equal "secp384r1", ssl.tmp_key.group.curve_name
ssl.puts "abc"; assert_equal "abc\n", ssl.gets
}
end
end
def test_security_level def test_security_level
ctx = OpenSSL::SSL::SSLContext.new ctx = OpenSSL::SSL::SSLContext.new
begin begin

View file

@ -122,6 +122,7 @@ __EOS__
ctx.options &= ~OpenSSL::SSL::OP_NO_TICKET ctx.options &= ~OpenSSL::SSL::OP_NO_TICKET
# Disable server-side session cache which is enabled by default # Disable server-side session cache which is enabled by default
ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_OFF ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_OFF
ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION if libressl?(3, 2, 0)
} }
start_server(ctx_proc: ctx_proc) do |port| start_server(ctx_proc: ctx_proc) do |port|
sess1 = server_connect_with_session(port, nil, nil) { |ssl| sess1 = server_connect_with_session(port, nil, nil) { |ssl|

View file

@ -242,16 +242,15 @@ class OpenSSL::TestX509Name < OpenSSL::TestCase
assert_match(/^multi-valued RDN is not supported: #{dn_r}/, ex.message) assert_match(/^multi-valued RDN is not supported: #{dn_r}/, ex.message)
} }
bad_dc = "exa#{"pm"}le" # <- typo of "example"
[ [
["DC=org,DC=#{bad_dc},CN", "CN"], ["DC=org,DC=exapmle,CN", "CN"],
["DC=org,DC=example,", ""], ["DC=org,DC=example,", ""],
["DC=org,DC=#{bad_dc},CN=www.example.org;", "CN=www.example.org;"], ["DC=org,DC=exapmle,CN=www.example.org;", "CN=www.example.org;"],
["DC=org,DC=#{bad_dc},CN=#www.example.org", "CN=#www.example.org"], ["DC=org,DC=exapmle,CN=#www.example.org", "CN=#www.example.org"],
["DC=org,DC=#{bad_dc},CN=#777777.example.org", "CN=#777777.example.org"], ["DC=org,DC=exapmle,CN=#777777.example.org", "CN=#777777.example.org"],
["DC=org,DC=#{bad_dc},CN=\"www.example\".org", "CN=\"www.example\".org"], ["DC=org,DC=exapmle,CN=\"www.example\".org", "CN=\"www.example\".org"],
["DC=org,DC=#{bad_dc},CN=www.\"example.org\"", "CN=www.\"example.org\""], ["DC=org,DC=exapmle,CN=www.\"example.org\"", "CN=www.\"example.org\""],
["DC=org,DC=#{bad_dc},CN=www.\"example\".org", "CN=www.\"example\".org"], ["DC=org,DC=exapmle,CN=www.\"example\".org", "CN=www.\"example\".org"],
].each{|dn, msg| ].each{|dn, msg|
ex = scanner.call(dn) rescue $! ex = scanner.call(dn) rescue $!
assert_match(/^malformed RDN: .*=>#{Regexp.escape(msg)}/, ex.message) assert_match(/^malformed RDN: .*=>#{Regexp.escape(msg)}/, ex.message)

View file

@ -181,6 +181,14 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
rescue rescue
end end
def tls13_supported?
return false unless defined?(OpenSSL::SSL::TLS1_3_VERSION)
ctx = OpenSSL::SSL::SSLContext.new
ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_3_VERSION
true
rescue
end
def readwrite_loop(ctx, ssl) def readwrite_loop(ctx, ssl)
while line = ssl.gets while line = ssl.gets
ssl.write(line) ssl.write(line)