From e4a26cd4f8e74e5d29de10a3a0ce5829829301b0 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 9 Mar 2020 18:26:19 +0900 Subject: openssl: sync with upstream repository Import current master (2c43241dc0ed) of ruby/openssl.git. Below are the commits that were made since the last batch at commit b99775b163ce (ruby/openssl.git commit f49e7110ca1e). Note that some of them have been applied already. ---------------------------------------------------------------- Benoit Daloze (1): Remove redundant and ignored workflow file DBL-Lee (1): add support for SHA512_256/SHA512_224 Hiroshi SHIBATA (2): Guard for OpenSSL::PKey::EC::Group::Error with unsupported platforms Fixed inconsistency directory structure with ruby/ruby repo Jeremy Evans (2): Fix keyword argument separation issues in OpenSSL::SSL::SSLSocket#sys{read,write}_nonblock Remove taint support Kazuki Yamaguchi (26): config: support .include directive random: make OpenSSL::Random.pseudo_bytes alias of .random_bytes extconf.rb: get rid of -Werror=deprecated-declarations test/openssl/test_ssl: skip test_fallback_scsv if necessary ts: simplify OpenSSL::Timestamp::Request#algorithm History.md: add missing references to GitHub issues config: deprecate OpenSSL::Config#add_value and #[]= test/openssl/test_ssl: remove sleep from test_finished_messages test/openssl/test_ssl: fix random failure in SSLSocket.open test test/openssl/test_ssl: avoid explicitly-sized private keys test/openssl/test_ssl: remove commented-out test case test/openssl/test_ssl: allow kRSA tests to fail ssl: avoid declarations after statements engine: revert OpenSSL::Engine.load changes for cloudhsm engine: remove really outdated static engines engine: do not check for ENGINE_load_builtin_engines() engine: fix guards for 'dynamic' and 'cryptodev' engines lib/openssl.rb: require openssl/version.rb x509: add error code and verify flags constants ssl: set verify error code in the case of verify_hostname failure .github/workflows: merge CI jobs into a single workflow .github/workflows: test against different OpenSSL versions .travis.yml: fully migrate to GitHub Actions ssl: suppress test failure with SSLContext#add_certificate_chain_file ssl: remove test case test_puts_meta from test_pair Revert "Use version.rb in gemspec" MSP-Greg (2): .travis.yml - remove 2.3/1.0.2, 2.5/1.1.1, head/1.0.2 Use version.rb in gemspec Samuel Williams (1): Restore compatibility with older versions of Ruby. Yusuke Endoh (1): Make OpenSSL::OSSL#test_memcmp_timing robust --- ext/openssl/History.md | 43 ++++++--- ext/openssl/deprecation.rb | 27 ------ ext/openssl/extconf.rb | 23 ++--- ext/openssl/lib/openssl.rb | 1 + ext/openssl/lib/openssl/config.rb | 72 ++++++++++----- ext/openssl/lib/openssl/digest.rb | 2 +- ext/openssl/lib/openssl/version.rb | 2 +- ext/openssl/ossl_engine.c | 17 +--- ext/openssl/ossl_rand.c | 34 +------ ext/openssl/ossl_ssl.c | 43 +++++---- ext/openssl/ossl_x509.c | 91 +++++++++++++++++++ test/openssl/fixtures/chain/dh512.pem | 4 - test/openssl/fixtures/chain/server.crt | 13 --- test/openssl/fixtures/chain/server.csr | 11 --- test/openssl/fixtures/chain/server.key | 15 ---- test/openssl/test_config.rb | 160 +++++++++++++++++++++++---------- test/openssl/test_digest.rb | 12 +++ test/openssl/test_pair.rb | 14 --- test/openssl/test_ssl.rb | 106 +++++++++++++++++----- 19 files changed, 426 insertions(+), 264 deletions(-) delete mode 100644 ext/openssl/deprecation.rb delete mode 100644 test/openssl/fixtures/chain/dh512.pem delete mode 100644 test/openssl/fixtures/chain/server.crt delete mode 100644 test/openssl/fixtures/chain/server.csr delete mode 100644 test/openssl/fixtures/chain/server.key diff --git a/ext/openssl/History.md b/ext/openssl/History.md index cdb44b1293..929d91961d 100644 --- a/ext/openssl/History.md +++ b/ext/openssl/History.md @@ -1,34 +1,55 @@ Version 2.2.0 (not yet released) ============= +Compatibility notes +------------------- + +* Remove unsupported MDC2, DSS, DSS1, and SHA algorithms. +* Remove `OpenSSL::PKCS7::SignerInfo#name` alias for `#issuer`. + [[GitHub #266]](https://github.com/ruby/openssl/pull/266) +* Deprecate `OpenSSL::Config#add_value` and `#[]=` for future removal. + [[GitHub #322]](https://github.com/ruby/openssl/pull/322) + + +Notable changes +--------------- + * Change default `OpenSSL::SSL::SSLServer#listen` backlog argument from 5 to `Socket::SOMAXCONN`. + [[GitHub #286]](https://github.com/ruby/openssl/issues/286) * Make `OpenSSL::HMAC#==` use a timing safe string comparison. -* Remove unsupported MDC2, DSS, DSS1, and SHA algorithms. + [[GitHub #284]](https://github.com/ruby/openssl/pull/284) * Add support for SHA3 and BLAKE digests. + [[GitHub #282]](https://github.com/ruby/openssl/pull/282) * Add `OpenSSL::SSL::SSLSocket.open` for opening a `TCPSocket` and returning an `OpenSSL::SSL::SSLSocket` for it. + [[GitHub #225]](https://github.com/ruby/openssl/issues/225) * Support marshalling of `OpenSSL::X509` objects. + [[GitHub #281]](https://github.com/ruby/openssl/pull/281) * Add `OpenSSL.secure_compare` for timing safe string comparison for strings of possibly unequal length. + [[GitHub #280]](https://github.com/ruby/openssl/pull/280) * Add `OpenSSL.fixed_length_secure_compare` for timing safe string comparison for strings of equal length. + [[GitHub #269]](https://github.com/ruby/openssl/pull/269) * Add `OpenSSL::SSL::SSLSocket#{finished_message,peer_finished_message}` for last finished message sent and received. + [[GitHub #250]](https://github.com/ruby/openssl/pull/250) * Add `OpenSSL::Timestamp` module for handing timestamp requests and responses. + [[GitHub #204]](https://github.com/ruby/openssl/pull/204) * Add helper methods for `OpenSSL::X509::Certificate`: `find_extension`, `subject_key_identifier`, `authority_key_identifier`, `crl_uris`, `ca_issuer_uris` and - `ocsp_uris`. -* Add helper methods for `OpenSSL::X509::CRL`: + `ocsp_uris`, and for `OpenSSL::X509::CRL`: `find_extension` and `subject_key_identifier`. -* Remove `OpenSSL::PKCS7::SignerInfo#name` alias for `#issuer`. -* Add `OpenSSL::ECPoint#add` for adding points to an elliptic curve - group. + [[GitHub #260]](https://github.com/ruby/openssl/pull/260) + [[GitHub #275]](https://github.com/ruby/openssl/pull/275) + [[GitHub #293]](https://github.com/ruby/openssl/pull/293) +* Add `OpenSSL::ECPoint#add` for performing elliptic curve point addition. [[GitHub #261]](https://github.com/ruby/openssl/pull/261) -* Make `OpenSSL::PKey::RSA#{export,to_der}` correctly check `key`, - `factors`, and `crt_params`. +* Make `OpenSSL::PKey::RSA#{export,to_der}` check `key`, `factors`, and + `crt_params` to do proper private key serialization. [[GitHub #258]](https://github.com/ruby/openssl/pull/258) * Add `OpenSSL::SSL::{SSLSocket,SSLServer}#fileno`, returning the underlying socket file descriptor number. @@ -40,16 +61,18 @@ Version 2.2.0 (not yet released) * Add `OpenSSL::X509::Extension#value_der` for the raw value of the extension. [[GitHub #234]](https://github.com/ruby/openssl/pull/234) -* Signficantly reduce allocated memory in `OpenSSL::Buffering#do_write`. +* Significantly reduce allocated memory in `OpenSSL::Buffering#do_write`. [[GitHub #212]](https://github.com/ruby/openssl/pull/212) * Ensure all valid IPv6 addresses are considered valid as elements of subjectAlternativeName in certificates. [[GitHub #185]](https://github.com/ruby/openssl/pull/185) * Allow recipient's certificate to be omitted in PCKS7#decrypt. [[GitHub #183]](https://github.com/ruby/openssl/pull/183) -* Add support for reading keys in PKCS8 format and export via instance methods +* Add support for reading keys in PKCS #8 format and export via instance methods added to `OpenSSL::PKey` classes: `private_to_der`, `private_to_pem`, `public_to_der` and `public_to_pem`. + [[GitHub #297]](https://github.com/ruby/openssl/pull/297) + Version 2.1.2 ============= diff --git a/ext/openssl/deprecation.rb b/ext/openssl/deprecation.rb deleted file mode 100644 index fdf2d30ed0..0000000000 --- a/ext/openssl/deprecation.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true -module OpenSSL - def self.deprecated_warning_flag - unless flag = (@deprecated_warning_flag ||= nil) - if try_compile("", flag = "-Werror=deprecated-declarations") - $warnflags << " #{flag}" - else - flag = "" - end - @deprecated_warning_flag = flag - end - flag - end - - def self.restore_warning_flag - $warnflags = @warnflags - end - - def self.check_func(func, header) - have_func(func, header, deprecated_warning_flag) - end - - def self.check_func_or_macro(func, header) - check_func(func, header) or - have_macro(func, header) && $defs.push("-DHAVE_#{func.upcase}") - end -end diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 87a682b4ab..693e55cd97 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -12,16 +12,12 @@ =end require "mkmf" -require File.expand_path('../deprecation', __FILE__) dir_config("openssl") dir_config("kerberos") Logging::message "=== OpenSSL for Ruby configurator ===\n" -# Check with -Werror=deprecated-declarations if available -OpenSSL.deprecated_warning_flag - ## # Adds -DOSSL_DEBUG for compilation and some more targets when GCC is used # To turn it on, use: --with-debug or --enable-debug @@ -114,11 +110,10 @@ end Logging::message "=== Checking for OpenSSL features... ===\n" # compile options have_func("RAND_egd") -engines = %w{builtin_engines openbsd_dev_crypto dynamic 4758cca aep atalla chil - cswift nuron sureware ubsec padlock capi gmp gost cryptodev aesni - cloudhsm} +engines = %w{dynamic 4758cca aep atalla chil + cswift nuron sureware ubsec padlock capi gmp gost cryptodev} engines.each { |name| - OpenSSL.check_func_or_macro("ENGINE_load_#{name}", "openssl/engine.h") + have_func("ENGINE_load_#{name}()", "openssl/engine.h") } if ($mswin || $mingw) && have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h") @@ -130,9 +125,9 @@ have_func("EC_curve_nist2nid") have_func("X509_REVOKED_dup") have_func("X509_STORE_CTX_get0_store") have_func("SSL_CTX_set_alpn_select_cb") -OpenSSL.check_func_or_macro("SSL_CTX_set1_curves_list", "openssl/ssl.h") -OpenSSL.check_func_or_macro("SSL_CTX_set_ecdh_auto", "openssl/ssl.h") -OpenSSL.check_func_or_macro("SSL_get_server_tmp_key", "openssl/ssl.h") +have_func("SSL_CTX_set1_curves_list(NULL, NULL)", "openssl/ssl.h") +have_func("SSL_CTX_set_ecdh_auto(NULL, 0)", "openssl/ssl.h") +have_func("SSL_get_server_tmp_key(NULL, NULL)", "openssl/ssl.h") have_func("SSL_is_server") # added in 1.1.0 @@ -148,7 +143,6 @@ have_func("EVP_MD_CTX_new") have_func("EVP_MD_CTX_free") have_func("HMAC_CTX_new") have_func("HMAC_CTX_free") -OpenSSL.check_func("RAND_pseudo_bytes", "openssl/rand.h") # deprecated have_func("X509_STORE_get_ex_data") have_func("X509_STORE_set_ex_data") have_func("X509_STORE_get_ex_new_index") @@ -167,8 +161,8 @@ have_func("X509_CRL_up_ref") have_func("X509_STORE_up_ref") have_func("SSL_SESSION_up_ref") have_func("EVP_PKEY_up_ref") -OpenSSL.check_func_or_macro("SSL_CTX_set_tmp_ecdh_callback", "openssl/ssl.h") # removed -OpenSSL.check_func_or_macro("SSL_CTX_set_min_proto_version", "openssl/ssl.h") +have_func("SSL_CTX_set_tmp_ecdh_callback(NULL, NULL)", "openssl/ssl.h") # removed +have_func("SSL_CTX_set_min_proto_version(NULL, 0)", "openssl/ssl.h") have_func("SSL_CTX_get_security_level") have_func("X509_get0_notBefore") have_func("SSL_SESSION_get_protocol_version") @@ -185,6 +179,5 @@ have_func("SSL_CTX_set_post_handshake_auth") Logging::message "=== Checking done. ===\n" create_header -OpenSSL.restore_warning_flag create_makefile("openssl") Logging::message "Done.\n" diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb index 7ba2229a1b..00e2db1f40 100644 --- a/ext/openssl/lib/openssl.rb +++ b/ext/openssl/lib/openssl.rb @@ -21,6 +21,7 @@ require_relative 'openssl/hmac' require_relative 'openssl/x509' require_relative 'openssl/ssl' require_relative 'openssl/pkcs5' +require_relative 'openssl/version' module OpenSSL # call-seq: diff --git a/ext/openssl/lib/openssl/config.rb b/ext/openssl/lib/openssl/config.rb index ef83c57b20..9a0b787420 100644 --- a/ext/openssl/lib/openssl/config.rb +++ b/ext/openssl/lib/openssl/config.rb @@ -37,7 +37,7 @@ module OpenSSL def parse(string) c = new() parse_config(StringIO.new(string)).each do |section, hash| - c[section] = hash + c.set_section(section, hash) end c end @@ -76,29 +76,44 @@ module OpenSSL def parse_config_lines(io) section = 'default' data = {section => {}} - while definition = get_definition(io) + io_stack = [io] + while definition = get_definition(io_stack) definition = clear_comments(definition) next if definition.empty? - if definition[0] == ?[ + case definition + when /\A\[/ if /\[([^\]]*)\]/ =~ definition section = $1.strip data[section] ||= {} else raise ConfigError, "missing close square bracket" end - else - if /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ =~ definition - if $2 - section = $1 - key = $2 - else - key = $1 + when /\A\.include (\s*=\s*)?(.+)\z/ + path = $2 + if File.directory?(path) + files = Dir.glob(File.join(path, "*.{cnf,conf}"), File::FNM_EXTGLOB) + else + files = [path] + end + + files.each do |filename| + begin + io_stack << StringIO.new(File.read(filename)) + rescue + raise ConfigError, "could not include file '%s'" % filename end - value = unescape_value(data, section, $3) - (data[section] ||= {})[key] = value.strip + end + when /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ + if $2 + section = $1 + key = $2 else - raise ConfigError, "missing equal sign" + key = $1 end + value = unescape_value(data, section, $3) + (data[section] ||= {})[key] = value.strip + else + raise ConfigError, "missing equal sign" end end data @@ -211,10 +226,10 @@ module OpenSSL scanned.join end - def get_definition(io) - if line = get_line(io) + def get_definition(io_stack) + if line = get_line(io_stack) while /[^\\]\\\z/ =~ line - if extra = get_line(io) + if extra = get_line(io_stack) line += extra else break @@ -224,9 +239,12 @@ module OpenSSL end end - def get_line(io) - if line = io.gets - line.gsub(/[\r\n]*/, '') + def get_line(io_stack) + while io = io_stack.last + if line = io.gets + return line.gsub(/[\r\n]*/, '') + end + io_stack.pop end end end @@ -248,7 +266,7 @@ module OpenSSL if filename File.open(filename.to_s) do |file| Config.parse_config(file).each do |section, hash| - self[section] = hash + set_section(section, hash) end end end @@ -297,6 +315,8 @@ module OpenSSL end ## + # *Deprecated in v2.2.0*. This method will be removed in a future release. + # # Set the target _key_ with a given _value_ under a specific _section_. # # Given the following configurating file being loaded: @@ -351,6 +371,8 @@ module OpenSSL end ## + # *Deprecated in v2.2.0*. This method will be removed in a future release. + # # Sets a specific _section_ name with a Hash _pairs_. # # Given the following configuration being created: @@ -376,9 +398,13 @@ module OpenSSL # def []=(section, pairs) check_modify - @data[section] ||= {} + set_section(section, pairs) + end + + def set_section(section, pairs) # :nodoc: + hash = @data[section] ||= {} pairs.each do |key, value| - self.add_value(section, key, value) + hash[key] = value end end @@ -463,6 +489,8 @@ module OpenSSL end def check_modify + warn "#{caller(2, 1)[0]}: warning: do not modify OpenSSL::Config; this " \ + "method is deprecated and will be removed in a future release." raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen? end diff --git a/ext/openssl/lib/openssl/digest.rb b/ext/openssl/lib/openssl/digest.rb index c953911954..92d358d241 100644 --- a/ext/openssl/lib/openssl/digest.rb +++ b/ext/openssl/lib/openssl/digest.rb @@ -21,7 +21,7 @@ module OpenSSL ALGORITHMS = %w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512) if !OPENSSL_VERSION.include?("LibreSSL") && OPENSSL_VERSION_NUMBER > 0x10101000 - ALGORITHMS.concat %w(BLAKE2b512 BLAKE2s256 SHA3-224 SHA3-256 SHA3-384 SHA3-512) + ALGORITHMS.concat %w(BLAKE2b512 BLAKE2s256 SHA3-224 SHA3-256 SHA3-384 SHA3-512 SHA512-224 SHA512-256) end ALGORITHMS.freeze diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb index b07bb33009..9c7515ba0f 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" unless defined?(VERSION) + VERSION = "2.2.0" end diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c index f90bf061df..90546934d1 100644 --- a/ext/openssl/ossl_engine.c +++ b/ext/openssl/ossl_engine.c @@ -93,9 +93,6 @@ static const rb_data_type_t ossl_engine_type = { static VALUE ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) { -#if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES) - return Qnil; -#else VALUE name; rb_scan_args(argc, argv, "01", &name); @@ -104,10 +101,10 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) return Qtrue; } StringValueCStr(name); -#ifndef OPENSSL_NO_STATIC_ENGINE #if HAVE_ENGINE_LOAD_DYNAMIC OSSL_ENGINE_LOAD_IF_MATCH(dynamic, DYNAMIC); #endif +#ifndef OPENSSL_NO_STATIC_ENGINE #if HAVE_ENGINE_LOAD_4758CCA OSSL_ENGINE_LOAD_IF_MATCH(4758cca, 4758CCA); #endif @@ -144,23 +141,13 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) #if HAVE_ENGINE_LOAD_GOST OSSL_ENGINE_LOAD_IF_MATCH(gost, GOST); #endif +#endif #if HAVE_ENGINE_LOAD_CRYPTODEV OSSL_ENGINE_LOAD_IF_MATCH(cryptodev, CRYPTODEV); -#endif -#if HAVE_ENGINE_LOAD_AESNI - OSSL_ENGINE_LOAD_IF_MATCH(aesni, AESNI); -#endif -#if HAVE_ENGINE_LOAD_CLOUDHSM - OSSL_ENGINE_LOAD_IF_MATCH(cloudhsm, CLOUDHSM); -#endif -#endif -#ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO - OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto, OPENBSD_DEV_CRYPTO); #endif OSSL_ENGINE_LOAD_IF_MATCH(openssl, OPENSSL); rb_warning("no such builtin loader for `%"PRIsVALUE"'", name); return Qnil; -#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ } /* diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c index 4a4f9dd5bf..659dc818b6 100644 --- a/ext/openssl/ossl_rand.c +++ b/ext/openssl/ossl_rand.c @@ -120,36 +120,6 @@ ossl_rand_bytes(VALUE self, VALUE len) return str; } -#if defined(HAVE_RAND_PSEUDO_BYTES) -/* - * call-seq: - * pseudo_bytes(length) -> string - * - * Generates a String with _length_ number of pseudo-random bytes. - * - * Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if - * they are of sufficient length, but are not necessarily unpredictable. - * - * === Example - * - * OpenSSL::Random.pseudo_bytes(12) - * #=> "..." - */ -static VALUE -ossl_rand_pseudo_bytes(VALUE self, VALUE len) -{ - VALUE str; - int n = NUM2INT(len); - - str = rb_str_new(0, n); - if (RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n) < 1) { - ossl_raise(eRandomError, NULL); - } - - return str; -} -#endif - #ifdef HAVE_RAND_EGD /* * call-seq: @@ -219,8 +189,8 @@ Init_ossl_rand(void) rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1); rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1); rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1); -#if defined(HAVE_RAND_PSEUDO_BYTES) - rb_define_module_function(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1); +#if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER) + rb_define_alias(rb_singleton_class(mRandom), "pseudo_bytes", "random_bytes"); #endif #ifdef HAVE_RAND_EGD rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1); diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index dfbfbb22ee..34bb636ead 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -359,7 +359,14 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status)); 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); @@ -1325,12 +1332,16 @@ ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self) static VALUE ossl_sslctx_add_certificate_chain_file(VALUE self, VALUE path) { - StringValue(path); - SSL_CTX *ctx = NULL; + SSL_CTX *ctx; + int ret; GetSSLCTX(self, ctx); + StringValueCStr(path); + ret = SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(path)); + if (ret != 1) + ossl_raise(eSSLError, "SSL_CTX_use_certificate_chain_file"); - return SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(path)) == 1 ? Qtrue : Qfalse; + return Qtrue; } /* @@ -2327,16 +2338,16 @@ static VALUE ossl_ssl_get_finished(VALUE self) { SSL *ssl; + char sizer[1], *buf; + size_t len; GetSSL(self, ssl); - char sizer[1]; - size_t len = SSL_get_finished(ssl, sizer, 0); - - if(len == 0) - return Qnil; + len = SSL_get_finished(ssl, sizer, 0); + if (len == 0) + return Qnil; - char* buf = ALLOCA_N(char, len); + buf = ALLOCA_N(char, len); SSL_get_finished(ssl, buf, len); return rb_str_new(buf, len); } @@ -2352,16 +2363,16 @@ static VALUE ossl_ssl_get_peer_finished(VALUE self) { SSL *ssl; + char sizer[1], *buf; + size_t len; GetSSL(self, ssl); - char sizer[1]; - size_t len = SSL_get_peer_finished(ssl, sizer, 0); - - if(len == 0) - return Qnil; + len = SSL_get_peer_finished(ssl, sizer, 0); + if (len == 0) + return Qnil; - char* buf = ALLOCA_N(char, len); + buf = ALLOCA_N(char, len); SSL_get_peer_finished(ssl, buf, len); return rb_str_new(buf, len); } diff --git a/ext/openssl/ossl_x509.c b/ext/openssl/ossl_x509.c index 8a061b0687..4fc0648614 100644 --- a/ext/openssl/ossl_x509.c +++ b/ext/openssl/ossl_x509.c @@ -44,7 +44,13 @@ Init_ossl_x509(void) Init_ossl_x509revoked(); Init_ossl_x509store(); + /* Constants are up-to-date with 1.1.1. */ + + /* Certificate verification error code */ 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_CRL); 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_ISSUER_SERIAL_MISMATCH); 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_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 * certificate chain leaf. */ DefX509Const(V_FLAG_CRL_CHECK); @@ -122,6 +193,26 @@ Init_ossl_x509(void) * Enabled by default in OpenSSL >= 1.1.0. */ DefX509Const(V_FLAG_TRUSTED_FIRST); #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) /* Set by Store#flags= and StoreContext#flags=. Suppresses searching for * a alternative chain. No effect in OpenSSL >= 1.1.0. */ diff --git a/test/openssl/fixtures/chain/dh512.pem b/test/openssl/fixtures/chain/dh512.pem deleted file mode 100644 index fec138c7a9..0000000000 --- a/test/openssl/fixtures/chain/dh512.pem +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN DH PARAMETERS----- -MEYCQQCjDVzTg9C4u43MV0TKDGsBuYdChrPMczr4IYjy+jHQvXm2DDadNNWBIDau -4zNtwfLCg2gMwOc7t18m4Ten/NOLAgEC ------END DH PARAMETERS----- diff --git a/test/openssl/fixtures/chain/server.crt b/test/openssl/fixtures/chain/server.crt deleted file mode 100644 index d6b814f450..0000000000 --- a/test/openssl/fixtures/chain/server.crt +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICATCCAWoCCQDbxIRGgXeWaDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJO -WjETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTE5MDYxMzA1MDU0MloXDTI5MDYxMDA1MDU0MlowRTELMAkG -A1UEBhMCTloxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA29Vu -Y6m8pRrsXxUhlK2BX48CDChr8D53SqZozcQI26BCm+05TBnQxKAHOknR3y/ige2U -2zftSwbSoK/zKUC8o5pKVL+l36anDEnZ6RWc9Z9CvmaCFjlcP4nXZO+yD1Is/jCy -KqGGC8lQ920VXOCFflJj6AWg88+4C3GLjxJe6bMCAwEAATANBgkqhkiG9w0BAQsF -AAOBgQCDaqKGBkYxNxnv37vEKp7zi/cov8LvEsZaAD1pcSU+ysBiBes/B7a/Qjcj -PTZsH/hedn9mVynLkjc7LrztUWngTeW9gk5EB9YSwJdPhwLntV1TdaBlf/tu0n/c -s7QxaZhFMUyo1Eof28zXVHhs1OEhlSjwJ8lxuC3vBE4F1BjSNQ== ------END CERTIFICATE----- diff --git a/test/openssl/fixtures/chain/server.csr b/test/openssl/fixtures/chain/server.csr deleted file mode 100644 index 51b38e33f2..0000000000 --- a/test/openssl/fixtures/chain/server.csr +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIIBhDCB7gIBADBFMQswCQYDVQQGEwJOWjETMBEGA1UECAwKU29tZS1TdGF0ZTEh -MB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQDb1W5jqbylGuxfFSGUrYFfjwIMKGvwPndKpmjNxAjboEKb -7TlMGdDEoAc6SdHfL+KB7ZTbN+1LBtKgr/MpQLyjmkpUv6XfpqcMSdnpFZz1n0K+ -ZoIWOVw/iddk77IPUiz+MLIqoYYLyVD3bRVc4IV+UmPoBaDzz7gLcYuPEl7pswID -AQABoAAwDQYJKoZIhvcNAQELBQADgYEAONaTWYVfyMmd8irCtognRoM4tFF4xvDg -PTcnHjVb/6oPPMU+mtQVD9qNf8SOdhNuYVTZ61mDLQGeq45CLM5qWjZkqFPHnngf -ajfZRE7Y3vA8ZaWFvsTJYcU+R3/FRS0XnFYj99+q9Yi3JExSY+arElyAW3tFYlcs -RWOCk1pT2Yc= ------END CERTIFICATE REQUEST----- diff --git a/test/openssl/fixtures/chain/server.key b/test/openssl/fixtures/chain/server.key deleted file mode 100644 index 9590235db8..0000000000 --- a/test/openssl/fixtures/chain/server.key +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDb1W5jqbylGuxfFSGUrYFfjwIMKGvwPndKpmjNxAjboEKb7TlM -GdDEoAc6SdHfL+KB7ZTbN+1LBtKgr/MpQLyjmkpUv6XfpqcMSdnpFZz1n0K+ZoIW -OVw/iddk77IPUiz+MLIqoYYLyVD3bRVc4IV+UmPoBaDzz7gLcYuPEl7pswIDAQAB -AoGAGO+q5+83ENtu+JIjDwRnanmEV/C13biYO4WI2d5kytTw+VL9bt52yfcFGt2I -yvJZlTdn7T340svhVIzg3ksTmp1xQk3zh6zR00zQy45kYwY8uyd8Xfh2IsnpByoc -h2jWVX6LSqi1Iy3RxanHmMYPSMy15otsjwlwnnTAHLnnvzECQQDvw3TL90DucQSD -S0h6DWAGakaiOMhY/PpFbTsjzw+uG+Up65tpz4QqPbsXfoReeK0CQIuyE/LlYoJl -VOlIsL6HAkEA6rh4zsWi6KVTGa7qd5x70TEgxeMMAW1qUbak1THxeZTFYnyvucBz -i+VQvHEVnCadhVpHIwbBNUeOyS5DXjj6dQJAA0Caf/3Noq5jykgmJomx6MReSusM -RLDB0FlH+Rdg9hKozCXHCOtoto350LrFnuZyKlqnynWc0OHCNQ+uzm6fVwJAbtyW -YsNCQLPlXhoZsEj+yj10B0NH5lyxfMrRa8jdDtnPqMbPkOJvMMIssfSPimNKvzN2 -qfqEww97R1ZMh3JOCQJBAIIwGHBN5rDGIb4CgR+PLsh8bve1X+gO8UnOYJXa/Uzx -gAXE0uzHNH6rNSG0V/IQnFYlSHpNJGgcdSl+MZNLldQ= ------END RSA PRIVATE KEY----- diff --git a/test/openssl/test_config.rb b/test/openssl/test_config.rb index dba66b0802..f65392c18d 100644 --- a/test/openssl/test_config.rb +++ b/test/openssl/test_config.rb @@ -120,6 +120,49 @@ __EOC__ assert_equal("error in line 7: missing close square bracket", excn.message) end + def test_s_parse_include + in_tmpdir("ossl-config-include-test") do |dir| + Dir.mkdir("child") + File.write("child/a.conf", <<~__EOC__) + [default] + file-a = a.conf + [sec-a] + a = 123 + __EOC__ + File.write("child/b.cnf", <<~__EOC__) + [default] + file-b = b.cnf + [sec-b] + b = 123 + __EOC__ + File.write("include-child.conf", <<~__EOC__) + key_outside_section = value_a + .include child + __EOC__ + + include_file = <<~__EOC__ + [default] + file-main = unnamed + [sec-main] + main = 123 + .include = include-child.conf + __EOC__ + + # Include a file by relative path + c1 = OpenSSL::Config.parse(include_file) + assert_equal(["default", "sec-a", "sec-b", "sec-main"], c1.sections.sort) + assert_equal(["file-main", "file-a", "file-b"], c1["default"].keys) + assert_equal({"a" => "123"}, c1["sec-a"]) + assert_equal({"b" => "123"}, c1["sec-b"]) + assert_equal({"main" => "123", "key_outside_section" => "value_a"}, c1["sec-main"]) + + # Relative paths are from the working directory + assert_raise(OpenSSL::ConfigError) do + Dir.chdir("child") { OpenSSL::Config.parse(include_file) } + end + end + end + def test_s_load # alias of new c = OpenSSL::Config.load @@ -211,45 +254,54 @@ __EOC__ def test_sections assert_equal(['CA_default', 'ca', 'default'], @it.sections.sort) - @it['new_section'] = {'foo' => 'bar'} - assert_equal(['CA_default', 'ca', 'default', 'new_section'], @it.sections.sort) - @it['new_section'] = {} - assert_equal(['CA_default', 'ca', 'default', 'new_section'], @it.sections.sort) + # OpenSSL::Config#[]= is deprecated + EnvUtil.suppress_warning do + @it['new_section'] = {'foo' => 'bar'} + assert_equal(['CA_default', 'ca', 'default', 'new_section'], @it.sections.sort) + @it['new_section'] = {} + assert_equal(['CA_default', 'ca', 'default', 'new_section'], @it.sections.sort) + end end def test_add_value - c = OpenSSL::Config.new - assert_equal("", c.to_s) - # add key - c.add_value('default', 'foo', 'bar') - assert_equal("[ default ]\nfoo=bar\n\n", c.to_s) - # add another key - c.add_value('default', 'baz', 'qux') - assert_equal('bar', c['default']['foo']) - assert_equal('qux', c['default']['baz']) - # update the value - c.add_value('default', 'baz', 'quxxx') - assert_equal('bar', c['default']['foo']) - assert_equal('quxxx', c['default']['baz']) - # add section and key - c.add_value('section', 'foo', 'bar') - assert_equal('bar', c['default']['foo']) - assert_equal('quxxx', c['default']['baz']) - assert_equal('bar', c['section']['foo']) + # OpenSSL::Config#add_value is deprecated + EnvUtil.suppress_warning do + c = OpenSSL::Config.new + assert_equal("", c.to_s) + # add key + c.add_value('default', 'foo', 'bar') + assert_equal("[ default ]\nfoo=bar\n\n", c.to_s) + # add another key + c.add_value('default', 'baz', 'qux') + assert_equal('bar', c['default']['foo']) + assert_equal('qux', c['default']['baz']) + # update the value + c.add_value('default', 'baz', 'quxxx') + assert_equal('bar', c['default']['foo']) + assert_equal('quxxx', c['default']['baz']) + # add section and key + c.add_value('section', 'foo', 'bar') + assert_equal('bar', c['default']['foo']) + assert_equal('quxxx', c['default']['baz']) + assert_equal('bar', c['section']['foo']) + end end def test_aset - @it['foo'] = {'bar' => 'baz'} - assert_equal({'bar' => 'baz'}, @it['foo']) - @it['foo'] = {'bar' => 'qux', 'baz' => 'quxx'} - assert_equal({'bar' => 'qux', 'baz' => 'quxx'}, @it['foo']) - - # OpenSSL::Config is add only for now. - @it['foo'] = {'foo' => 'foo'} - assert_equal({'foo' => 'foo', 'bar' => 'qux', 'baz' => 'quxx'}, @it['foo']) - # you cannot override or remove any section and key. - @it['foo'] = {} - assert_equal({'foo' => 'foo', 'bar' => 'qux', 'baz' => 'quxx'}, @it['foo']) + # OpenSSL::Config#[]= is deprecated + EnvUtil.suppress_warning do + @it['foo'] = {'bar' => 'baz'} + assert_equal({'bar' => 'baz'}, @it['foo']) + @it['foo'] = {'bar' => 'qux', 'baz' => 'quxx'} + assert_equal({'bar' => 'qux', 'baz' => 'quxx'}, @it['foo']) + + # OpenSSL::Config is add only for now. + @it['foo'] = {'foo' => 'foo'} + assert_equal({'foo' => 'foo', 'bar' => 'qux', 'baz' => 'quxx'}, @it['foo']) + # you cannot override or remove any section and key. + @it['foo'] = {} + assert_equal({'foo' => 'foo', 'bar' => 'qux', 'baz' => 'quxx'}, @it['foo']) + end end def test_each @@ -272,32 +324,50 @@ __EOC__ end def test_freeze - c = OpenSSL::Config.new - c['foo'] = [['key', 'value']] - c.freeze + @it.freeze - bug = '[ruby-core:18377]' - # RuntimeError for 1.9, TypeError for 1.8 - e = assert_raise(TypeError, bug) do - c['foo'] = [['key', 'wrong']] + # Modifying OpenSSL::Config produces a warning + EnvUtil.suppress_warning do + bug = '[ruby-core:18377]' + # RuntimeError for 1.9, TypeError for 1.8 + e = assert_raise(TypeError, bug) do + @it['foo'] = [['key', 'wrong']] + end + assert_match(/can't modify/, e.message, bug) end - assert_match(/can't modify/, e.message, bug) end def test_dup assert(!@it.sections.empty?) c = @it.dup assert_equal(@it.sections.sort, c.sections.sort) - @it['newsection'] = {'a' => 'b'} - assert_not_equal(@it.sections.sort, c.sections.sort) + # OpenSSL::Config#[]= is deprecated + EnvUtil.suppress_warning do + @it['newsection'] = {'a' => 'b'} + assert_not_equal(@it.sections.sort, c.sections.sort) + end end def test_clone assert(!@it.sections.empty?) c = @it.clone assert_equal(@it.sections.sort, c.sections.sort) - @it['newsection'] = {'a' => 'b'} - assert_not_equal(@it.sections.sort, c.sections.sort) + # OpenSSL::Config#[]= is deprecated + EnvUtil.suppress_warning do + @it['newsection'] = {'a' => 'b'} + assert_not_equal(@it.sections.sort, c.sections.sort) + end + end + + private + + def in_tmpdir(*args) + Dir.mktmpdir(*args) do |dir| + dir = File.realpath(dir) + Dir.chdir(dir) do + yield dir + end + end end end diff --git a/test/openssl/test_digest.rb b/test/openssl/test_digest.rb index e47fc0a356..0bf66b826a 100644 --- a/test/openssl/test_digest.rb +++ b/test/openssl/test_digest.rb @@ -98,6 +98,18 @@ class OpenSSL::TestDigest < OpenSSL::TestCase assert_equal(sha512_a, encode16(OpenSSL::Digest::SHA512.digest("a"))) end + def test_sha512_truncate + pend "SHA512_224 is not implemented" unless OpenSSL::Digest.const_defined?(:SHA512_224) + sha512_224_a = "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327" + sha512_256_a = "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8" + + assert_equal(sha512_224_a, OpenSSL::Digest::SHA512_224.hexdigest("a")) + assert_equal(sha512_256_a, OpenSSL::Digest::SHA512_256.hexdigest("a")) + + assert_equal(sha512_224_a, encode16(OpenSSL::Digest::SHA512_224.digest("a"))) + assert_equal(sha512_256_a, encode16(OpenSSL::Digest::SHA512_256.digest("a"))) + end + def test_sha3 pend "SHA3 is not implemented" unless OpenSSL::Digest.const_defined?(:SHA3_224) s224 = '6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7' diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb index a77abfd923..8316ec2a9c 100644 --- a/test/openssl/test_pair.rb +++ b/test/openssl/test_pair.rb @@ -156,20 +156,6 @@ module OpenSSL::TestPairM } end - def test_puts_meta - ssl_pair {|s1, s2| - begin - old = $/ - EnvUtil.suppress_warning {$/ = '*'} - s1.puts 'a' - ensure - EnvUtil.suppress_warning {$/ = old} - end - s1.close - assert_equal("a\n", s2.read) - } - end - def test_puts_empty ssl_pair {|s1, s2| s1.puts diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index cce1a4472e..ce899ba085 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -89,13 +89,17 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase def test_socket_open_with_local_address_port_context start_server { |port| begin + # Guess a free port number + random_port = rand(49152..65535) ctx = OpenSSL::SSL::SSLContext.new - ssl = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port, "127.0.0.1", 8000, context: ctx) + ssl = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port, "127.0.0.1", random_port, context: ctx) ssl.sync_close = true ssl.connect - assert_equal ssl.context, ctx + assert_equal ctx, ssl.context + assert_equal random_port, ssl.io.local_address.ip_port ssl.puts "abc"; assert_equal "abc\n", ssl.gets + rescue Errno::EADDRINUSE ensure ssl&.close end @@ -127,7 +131,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase add0_chain_supported = openssl?(1, 0, 2) if add0_chain_supported - ca2_key = Fixtures.pkey("rsa2048") + ca2_key = Fixtures.pkey("rsa-3") ca2_exts = [ ["basicConstraints", "CA:TRUE", true], ["keyUsage", "cRLSign, keyCertSign", true], @@ -186,9 +190,31 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end def test_add_certificate_chain_file - pend "The current server.crt seems too short for OpenSSL 1.1.1d or later" if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10101040 - ctx = OpenSSL::SSL::SSLContext.new - assert ctx.add_certificate_chain_file(Fixtures.file_path("chain", "server.crt")) + # Create chain certificates file + certs = Tempfile.open { |f| f << @svr_cert.to_pem << @ca_cert.to_pem; f } + pkey = Tempfile.open { |f| f << @svr_key.to_pem; f } + + ctx_proc = -> ctx { + # FIXME: This is a temporary test case written just to match the current + # state. ctx.add_certificate_chain_file should take two arguments. + ctx.add_certificate_chain_file(certs.path) + # # Unset values set by start_server + # ctx.cert = ctx.key = ctx.extra_chain_cert = nil + # assert_nothing_raised { ctx.add_certificate_chain_file(certs.path, pkey.path) } + } + + start_server(ctx_proc: ctx_proc) { |port| + server_connect(port) { |ssl| + assert_equal @svr_cert.subject, ssl.peer_cert.subject + assert_equal [@svr_cert.subject, @ca_cert.subject], + ssl.peer_cert_chain.map(&:subject) + + ssl.puts "abc"; assert_equal "abc\n", ssl.gets + } + } + ensure + certs&.unlink + pkey&.unlink end def test_sysread_and_syswrite @@ -207,19 +233,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase } end - # TODO fix this test - # def test_sysread_nonblock_and_syswrite_nonblock_keywords - # start_server do |port| - # server_connect(port) do |ssl| - # assert_warning("") do - # ssl.send(:syswrite_nonblock, "12", exception: false) - # ssl.send(:sysread_nonblock, 1, exception: false) rescue nil - # ssl.send(:sysread_nonblock, 1, String.new, exception: false) rescue nil - # end - # end - # end - # end - def test_sync_close start_server do |port| begin @@ -497,12 +510,14 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx = OpenSSL::SSL::SSLContext.new ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE server_connect(port, ctx) { |ssl| + ssl.puts "abc"; ssl.gets + client_finished = ssl.finished_message client_peer_finished = ssl.peer_finished_message - sleep 0.05 - ssl.send :stop } } + assert_not_nil(server_finished) + assert_not_nil(client_finished) assert_equal(server_finished, client_peer_finished) assert_equal(server_peer_finished, client_finished) end @@ -924,6 +939,46 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 start_server(ignore_listener_error: true) { |port| ctx = OpenSSL::SSL::SSLContext.new @@ -1377,11 +1432,16 @@ end ctx.ssl_version = :TLSv1_2 ctx.ciphers = "kRSA" } - start_server(ctx_proc: ctx_proc1) do |port| + start_server(ctx_proc: ctx_proc1, ignore_listener_error: true) do |port| ctx = OpenSSL::SSL::SSLContext.new ctx.ssl_version = :TLSv1_2 ctx.ciphers = "kRSA" - server_connect(port, ctx) { |ssl| assert_nil ssl.tmp_key } + begin + server_connect(port, ctx) { |ssl| assert_nil ssl.tmp_key } + rescue OpenSSL::SSL::SSLError + # kRSA seems disabled + raise unless $!.message =~ /no cipher/ + end end end -- cgit v1.2.3