summaryrefslogtreecommitdiff
path: root/test/openssl/test_ssl.rb
diff options
context:
space:
mode:
authorrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-03 12:35:27 +0000
committerrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-03 12:35:27 +0000
commit609103dbb5fb182eec12f052226c43e39b907682 (patch)
tree881cdacc3312e65261ebd34a807c75ee09fdb303 /test/openssl/test_ssl.rb
parentb9801bb8b2f5ce91755e0076d79140a72ff94d6a (diff)
openssl: import v2.1.0.beta1
Import Ruby/OpenSSL 2.1.0.beta1. The full commit log since v2.0.5 (imported by r59567) can be found at: https://github.com/ruby/openssl/compare/v2.0.5...v2.1.0.beta1 ---------------------------------------------------------------- Antonio Terceiro (1): test/test_ssl: explicitly accept TLS 1.1 in corresponding test Colby Swandale (1): document using secure protocol to fetch git master in Bundler Colton Jenkins (1): Add fips_mode_get to return fips_mode Kazuki Yamaguchi (85): Start preparing for 2.1.0 Remove support for OpenSSL 0.9.8 and 1.0.0 bn: refine tests bn: implement unary {plus,minus} operators for OpenSSL::BN bn: implement OpenSSL::BN#negative? Don't define main() when built with --enable-debug test: let OpenSSL::TestCase include OpenSSL::TestUtils test: prepare test PKey instances on demand Add OpenSSL.print_mem_leaks Enable OSSL_MDEBUG on CI builds ssl: move default DH parameters from OpenSSL::PKey::DH Make exceptions with the same format regardless of OpenSSL.debug ssl: show reason of 'certificate verify error' in exception message ssl: remove OpenSSL::ExtConfig::TLS_DH_anon_WITH_AES_256_GCM_SHA384 ssl: do not confuse different ex_data index registries ssl: assume SSL/SSL_CTX always have a valid reference to the Ruby object Fix RDoc markup ssl: suppress compiler warning ext/openssl/deprecation.rb: remove broken-apple-openssl extconf.rb: print informative message if OpenSSL can't be found Rakefile: compile the extension before test kdf: introduce OpenSSL::KDF module ossl.h: add NUM2UINT64T() macro kdf: add scrypt Expand rb_define_copy_func() macro Expand FPTR_TO_FD() macro Remove SafeGet*() macros cipher: rename GetCipherPtr() to ossl_evp_get_cipherbyname() digest: rename GetDigestPtr() to ossl_evp_get_digestbyname() Add ossl_str_new(), an exception-safe rb_str_new() bio: simplify ossl_membio2str() using ossl_str_new() Remove unused functions and macros Drop support for LibreSSL 2.3 ocsp: add OpenSSL::OCSP::Request#signed? asn1: infinite length -> indefinite length asn1: rearrange tests ssl: remove a needless NULL check in SSL::SSLContext#ciphers ssl: return nil in SSL::SSLSocket#cipher if session is not started asn1: remove an unnecessary function prototype asn1: require tag information when instantiating generic type asn1: initialize 'unused_bits' attribute of BitString with 0 asn1: check for illegal 'unused_bits' value of BitString asn1: disallow NULL to be passed to asn1time_to_time() asn1: avoid truncating OID in OpenSSL::ASN1::ObjectId#oid asn1: allow constructed encoding with definite length form asn1: prohibit indefinite length form for primitive encoding asn1: allow tag number to be >= 32 for universal tag class asn1: use ossl_asn1_tag() asn1: clean up OpenSSL::ASN1::Constructive#to_der asn1: harmonize OpenSSL::ASN1::*#to_der asn1: prevent EOC octets from being in the middle of the content asn1: do not treat EOC octets as part of content octets x509name: add 'loc' and 'set' kwargs to OpenSSL::X509::Name#add_entry ssl: do not call session_remove_cb during GC Backport "Merge branch 'topic/test-memory-leak'" to maint cipher: update the documentation for Cipher#auth_tag= Rakefile: let sync:to_ruby know about test/openssl/fixtures test: fix formatting test/utils: remove OpenSSL::TestUtils.silent test/utils: add SSLTestCase#tls12_supported? test/utils: have start_server yield only the port number test/utils: do not set ecdh_curves in start_server test/utils: let server_loop close socket test/utils: improve error handling in start_server test/utils: add OpenSSL::TestUtils.openssl? and .libressl? test/utils: do not use DSA certificates in SSL tests test/test_ssl: remove test_invalid_shutdown_by_gc test/test_ssl: move test_multibyte_read_write to test_pair test/test_ssl_session: rearrange tests test/test_pair, test/test_ssl: fix for TLS 1.3 ssl: remove useless call to rb_thread_wait_fd() ssl: fix NPN support ssl: mark OpenSSL::SSL::SSLContext::DEFAULT_{1024,2048} as private ssl: use 2048-bit group in the default tmp_dh_cb ssl: ensure that SSL option flags are non-negative ssl: update OpenSSL::SSL::OP_* flags ssl: prefer TLS_method() over SSLv23_method() ssl: add SSLContext#min_version= and #max_version= ssl: rework SSLContext#ssl_version= test/test_x509name: change script encoding to ASCII-8BIT x509name: refactor OpenSSL::X509::Name#to_s x509name: add OpenSSL::X509::Name#to_utf8 x509name: add OpenSSL::X509::Name#inspect x509name: update regexp in OpenSSL::X509::Name.parse Ruby/OpenSSL 2.1.0.beta1 Marcus Stollsteimer (1): Fix rdoc for core Integer class nobu (4): [DOC] {read,write}_nonblock with exception: false [DOC] keyword argument _exception_ [DOC] mark up literals Revert r57690 except for read_nonblock git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59734 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test/openssl/test_ssl.rb')
-rw-r--r--test/openssl/test_ssl.rb694
1 files changed, 389 insertions, 305 deletions
diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb
index 8c65df953d..3f17ab0d38 100644
--- a/test/openssl/test_ssl.rb
+++ b/test/openssl/test_ssl.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: false
require_relative "utils"
-if defined?(OpenSSL::TestUtils)
+if defined?(OpenSSL)
class OpenSSL::TestSSL < OpenSSL::SSLTestCase
-
def test_ctx_options
ctx = OpenSSL::SSL::SSLContext.new
@@ -35,7 +34,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
readwrite_loop(ctx, ssl)
}
- start_server(ctx_proc: ctx_proc, server_proc: server_proc) { |server, port|
+ start_server(ctx_proc: ctx_proc, server_proc: server_proc) { |port|
begin
sock = TCPSocket.new("127.0.0.1", port)
ctx = OpenSSL::SSL::SSLContext.new
@@ -56,7 +55,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_sysread_and_syswrite
- start_server { |server, port|
+ start_server { |port|
server_connect(port) { |ssl|
str = "x" * 100 + "\n"
ssl.syswrite(str)
@@ -72,7 +71,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_sync_close
- start_server { |server, port|
+ start_server { |port|
begin
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
@@ -97,7 +96,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_copy_stream
- start_server do |server, port|
+ start_server do |port|
server_connect(port) do |ssl|
IO.pipe do |r, w|
str = "hello world\n"
@@ -112,21 +111,16 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
def test_client_auth_failure
vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
- start_server(verify_mode: vflag, ignore_listener_error: true) { |server, port|
- sock = TCPSocket.new("127.0.0.1", port)
- ssl = OpenSSL::SSL::SSLSocket.new(sock)
- ssl.sync_close = true
- begin
- assert_handshake_error { ssl.connect }
- ensure
- ssl.close
- end
+ start_server(verify_mode: vflag, ignore_listener_error: true) { |port|
+ assert_handshake_error {
+ server_connect(port) { |ssl| ssl.puts("abc"); ssl.gets }
+ }
}
end
def test_client_auth_success
vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
- start_server(verify_mode: vflag) { |server, port|
+ start_server(verify_mode: vflag) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.key = @cli_key
ctx.cert = @cli_cert
@@ -153,19 +147,21 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
def test_client_auth_public_key
vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
- start_server(verify_mode: vflag, ignore_listener_error: true) do |server, port|
+ start_server(verify_mode: vflag, ignore_listener_error: true) do |port|
assert_raise(ArgumentError) {
ctx = OpenSSL::SSL::SSLContext.new
ctx.key = @cli_key.public_key
ctx.cert = @cli_cert
- server_connect(port, ctx) { }
+ server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets }
}
ctx = OpenSSL::SSL::SSLContext.new
ctx.client_cert_cb = Proc.new{ |ssl|
[@cli_cert, @cli_key.public_key]
}
- assert_handshake_error { server_connect(port, ctx) }
+ assert_handshake_error {
+ server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets }
+ }
end
end
@@ -175,7 +171,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
- start_server(verify_mode: vflag, ctx_proc: ctx_proc) { |server, port|
+ start_server(verify_mode: vflag, ctx_proc: ctx_proc) { |port|
ctx = OpenSSL::SSL::SSLContext.new
client_ca_from_server = nil
ctx.client_cert_cb = Proc.new do |sslconn|
@@ -187,8 +183,8 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_read_nonblock_without_session
- OpenSSL::TestUtils.silent do
- start_server(start_immediately: false) { |server, port|
+ EnvUtil.suppress_warning do
+ start_server(start_immediately: false) { |port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.sync_close = true
@@ -206,26 +202,21 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
def test_starttls
server_proc = -> (ctx, ssl) {
- begin
- while line = ssl.gets
- if line =~ /^STARTTLS$/
- ssl.write("x")
- ssl.flush
- ssl.accept
- next
- end
- ssl.write(line)
+ while line = ssl.gets
+ if line =~ /^STARTTLS$/
+ ssl.write("x")
+ ssl.flush
+ ssl.accept
+ break
end
- rescue OpenSSL::SSL::SSLError
- rescue IOError
- ensure
- ssl.close rescue nil
+ ssl.write(line)
end
+ readwrite_loop(ctx, ssl)
}
EnvUtil.suppress_warning do # read/write on not started session
start_server(start_immediately: false,
- server_proc: server_proc) { |server, port|
+ server_proc: server_proc) { |port|
begin
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
@@ -248,7 +239,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_parallel
- start_server { |server, port|
+ start_server { |port|
ssls = []
10.times{
sock = TCPSocket.new("127.0.0.1", port)
@@ -269,7 +260,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_verify_result
- start_server(ignore_listener_error: true) { |server, port|
+ start_server(ignore_listener_error: true) { |port|
sock = TCPSocket.new("127.0.0.1", port)
ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -283,7 +274,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
}
- start_server { |server, port|
+ start_server { |port|
sock = TCPSocket.new("127.0.0.1", port)
ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -301,7 +292,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
}
- start_server(ignore_listener_error: true) { |server, port|
+ start_server(ignore_listener_error: true) { |port|
sock = TCPSocket.new("127.0.0.1", port)
ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -321,7 +312,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_exception_in_verify_callback_is_ignored
- start_server(ignore_listener_error: true) { |server, port|
+ start_server(ignore_listener_error: true) { |port|
sock = TCPSocket.new("127.0.0.1", port)
ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -332,7 +323,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
ssl.sync_close = true
begin
- OpenSSL::TestUtils.silent do
+ EnvUtil.suppress_warning do
# SSLError, not RuntimeError
assert_raise(OpenSSL::SSL::SSLError) { ssl.connect }
end
@@ -352,20 +343,22 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
assert ciphers_names.all?{|v| /A(EC)?DH/ !~ v }, "anon ciphers are disabled"
assert ciphers_names.all?{|v| /(RC4|MD5|EXP|DES(?!-EDE|-CBC3))/ !~ v }, "weak ciphers are disabled"
assert_equal 0, ctx.options & OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
- if defined?(OpenSSL::SSL::OP_NO_COMPRESSION) # >= 1.0.0
- assert_equal OpenSSL::SSL::OP_NO_COMPRESSION,
- ctx.options & OpenSSL::SSL::OP_NO_COMPRESSION
- end
+ assert_equal OpenSSL::SSL::OP_NO_COMPRESSION,
+ ctx.options & OpenSSL::SSL::OP_NO_COMPRESSION
end
def test_post_connect_check_with_anon_ciphers
+ pend "TLS 1.2 is not supported" unless tls12_supported?
+
ctx_proc = -> ctx {
+ ctx.ssl_version = :TLSv1_2
ctx.ciphers = "aNULL"
ctx.security_level = 0
}
- start_server(ctx_proc: ctx_proc) { |server, port|
+ start_server(ctx_proc: ctx_proc) { |port|
ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ssl_version = :TLSv1_2
ctx.ciphers = "aNULL"
ctx.security_level = 0
server_connect(port, ctx) { |ssl|
@@ -379,7 +372,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
def test_post_connection_check
sslerr = OpenSSL::SSL::SSLError
- start_server { |server, port|
+ start_server { |port|
server_connect(port) { |ssl|
assert_raise(sslerr){ssl.post_connection_check("localhost.localdomain")}
assert_raise(sslerr){ssl.post_connection_check("127.0.0.1")}
@@ -400,7 +393,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
["subjectAltName","IP:127.0.0.1",false],
]
@svr_cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key)
- start_server { |server, port|
+ start_server { |port|
server_connect(port) { |ssl|
assert(ssl.post_connection_check("localhost.localdomain"))
assert(ssl.post_connection_check("127.0.0.1"))
@@ -420,7 +413,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
["subjectAltName","DNS:*.localdomain",false],
]
@svr_cert = issue_cert(@svr, @svr_key, 5, exts, @ca_cert, @ca_key)
- start_server { |server, port|
+ start_server { |port|
server_connect(port) { |ssl|
assert(ssl.post_connection_check("localhost.localdomain"))
assert_raise(sslerr){ssl.post_connection_check("127.0.0.1")}
@@ -623,48 +616,44 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_tlsext_hostname
- ctx3 = OpenSSL::SSL::SSLContext.new
- ctx3.ciphers = "ADH"
- ctx3.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
- ctx3.security_level = 0
- assert_not_predicate ctx3, :frozen?
+ fooctx = OpenSSL::SSL::SSLContext.new
+ fooctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") }
+ fooctx.cert = @cli_cert
+ fooctx.key = @cli_key
- ctx_proc = -> ctx {
- ctx.ciphers = "ALL:!aNULL"
+ ctx_proc = proc { |ctx|
ctx.servername_cb = proc { |ssl, servername|
case servername
when "foo.example.com"
- ctx3
+ fooctx
when "bar.example.com"
nil
else
- raise "unknown hostname"
+ raise "unreachable"
end
}
}
- start_server(ctx_proc: ctx_proc) do |server, port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ciphers = "ALL"
- ctx.security_level = 0
-
+ start_server(ctx_proc: ctx_proc) do |port|
sock = TCPSocket.new("127.0.0.1", port)
begin
- ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.hostname = "foo.example.com"
ssl.connect
- assert_match (/^ADH-/), ssl.cipher[0], "the context returned by servername_cb is used"
- assert_predicate ctx3, :frozen?
+ assert_equal @cli_cert.serial, ssl.peer_cert.serial
+ assert_predicate fooctx, :frozen?
ensure
+ ssl&.close
sock.close
end
sock = TCPSocket.new("127.0.0.1", port)
begin
- ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.hostname = "bar.example.com"
ssl.connect
- assert_not_match (/^A(EC)?DH-/), ssl.cipher[0], "the original context is used"
+ assert_equal @svr_cert.serial, ssl.peer_cert.serial
ensure
+ ssl&.close
sock.close
end
end
@@ -674,9 +663,9 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
hostname = 'example.org'
ctx2 = OpenSSL::SSL::SSLContext.new
- ctx2.ciphers = "aNULL"
- ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
- ctx2.security_level = 0
+ ctx2.cert = @svr_cert
+ ctx2.key = @svr_key
+ ctx2.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") }
ctx2.servername_cb = lambda { |args| Object.new }
sock1, sock2 = socketpair
@@ -684,8 +673,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
ctx1 = OpenSSL::SSL::SSLContext.new
- ctx1.ciphers = "aNULL"
- ctx1.security_level = 0
s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
s1.hostname = hostname
@@ -716,7 +703,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
ctx.key = @svr_key
}
- start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |server, port|
+ start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_hostname = true
ctx.cert_store = OpenSSL::X509::Store.new
@@ -749,27 +736,26 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
- def test_multibyte_read_write
- #German a umlaut
- auml = [%w{ C3 A4 }.join('')].pack('H*')
- auml.force_encoding(Encoding::UTF_8)
-
- [10, 1000, 100000].each {|i|
- str = nil
- num_written = nil
- server_proc = Proc.new {|ctx, ssl|
- cmp = ssl.read
- raw_size = cmp.size
- cmp.force_encoding(Encoding::UTF_8)
- assert_equal(str, cmp)
- assert_equal(num_written, raw_size)
- ssl.close
+ def test_connect_certificate_verify_failed_exception_message
+ start_server(ignore_listener_error: true) { |port|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params
+ assert_raise_with_message(OpenSSL::SSL::SSLError, /self signed/) {
+ server_connect(port, ctx)
}
- start_server(server_proc: server_proc) { |server, port|
- server_connect(port) { |ssl|
- str = auml * i
- num_written = ssl.write(str)
- }
+ }
+
+ ctx_proc = proc { |ctx|
+ ctx.cert = issue_cert(@svr, @svr_key, 30, [], @ca_cert, @ca_key,
+ not_before: Time.now-100, not_after: Time.now-10)
+ }
+ start_server(ignore_listener_error: true, ctx_proc: ctx_proc) { |port|
+ store = OpenSSL::X509::Store.new
+ store.add_cert(@ca_cert)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params(cert_store: store)
+ assert_raise_with_message(OpenSSL::SSL::SSLError, /expired/) {
+ server_connect(port, ctx)
}
}
end
@@ -781,7 +767,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
# But it also degrades gracefully, so keep it
ctx.options = OpenSSL::SSL::OP_ALL
}
- start_server(ctx_proc: ctx_proc) { |server, port|
+ start_server(ctx_proc: ctx_proc) { |port|
server_connect(port) { |ssl|
ssl.puts('hello')
assert_equal("hello\n", ssl.gets)
@@ -789,112 +775,223 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
-if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1) && OpenSSL::SSL::SSLContext::METHODS.include?(:SSLv3)
+ def check_supported_protocol_versions
+ possible_versions = [
+ OpenSSL::SSL::SSL3_VERSION,
+ OpenSSL::SSL::TLS1_VERSION,
+ OpenSSL::SSL::TLS1_1_VERSION,
+ OpenSSL::SSL::TLS1_2_VERSION,
+ # OpenSSL 1.1.1
+ defined?(OpenSSL::SSL::TLS1_3_VERSION) && OpenSSL::SSL::TLS1_3_VERSION,
+ ].compact
+
+ # Prepare for testing & do sanity check
+ supported = []
+ possible_versions.each do |ver|
+ catch(:unsupported) {
+ ctx_proc = proc { |ctx|
+ begin
+ ctx.min_version = ctx.max_version = ver
+ rescue ArgumentError, OpenSSL::SSL::SSLError
+ throw :unsupported
+ end
+ }
+ start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port|
+ begin
+ server_connect(port) { }
+ rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET
+ else
+ supported << ver
+ end
+ end
+ }
+ end
+ assert_not_empty supported
- def test_forbid_ssl_v3_for_client
- ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv3 }
- start_server_version(:SSLv23, ctx_proc) { |server, port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ssl_version = :SSLv3
- assert_handshake_error { server_connect(port, ctx) }
- }
+ supported
end
- def test_forbid_ssl_v3_from_server
- start_server_version(:SSLv3) { |server, port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv3
- assert_handshake_error { server_connect(port, ctx) }
+ def test_minmax_version
+ supported = check_supported_protocol_versions
+
+ # name: The string that would be returned by SSL_get_version()
+ # method: The version-specific method name (if any)
+ vmap = {
+ OpenSSL::SSL::SSL3_VERSION => { name: "SSLv3", method: "SSLv3" },
+ OpenSSL::SSL::SSL3_VERSION => { name: "SSLv3", method: "SSLv3" },
+ OpenSSL::SSL::TLS1_VERSION => { name: "TLSv1", method: "TLSv1" },
+ OpenSSL::SSL::TLS1_1_VERSION => { name: "TLSv1.1", method: "TLSv1_1" },
+ OpenSSL::SSL::TLS1_2_VERSION => { name: "TLSv1.2", method: "TLSv1_2" },
+ # OpenSSL 1.1.1
+ defined?(OpenSSL::SSL::TLS1_3_VERSION) && OpenSSL::SSL::TLS1_3_VERSION =>
+ { name: "TLSv1.3", method: nil },
}
- end
-end
+ # Server enables a single version
+ supported.each do |ver|
+ ctx_proc = proc { |ctx| ctx.min_version = ctx.max_version = ver }
+ start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
+ supported.each do |cver|
+ # Client enables a single version
+ ctx1 = OpenSSL::SSL::SSLContext.new
+ ctx1.min_version = ctx1.max_version = cver
+ if ver == cver
+ server_connect(port, ctx1) { |ssl|
+ assert_equal vmap[cver][:name], ssl.ssl_version
+ }
+ else
+ assert_handshake_error { server_connect(port, ctx1) { } }
+ end
-if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_1) && OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1)
+ # There is no version-specific SSL methods for TLS 1.3
+ if cver <= OpenSSL::SSL::TLS1_2_VERSION
+ # Client enables a single version using #ssl_version=
+ ctx2 = OpenSSL::SSL::SSLContext.new
+ ctx2.ssl_version = vmap[cver][:method]
+ if ver == cver
+ server_connect(port, ctx2) { |ssl|
+ assert_equal vmap[cver][:name], ssl.ssl_version
+ }
+ else
+ assert_handshake_error { server_connect(port, ctx2) { } }
+ end
+ end
+ end
- def test_tls_v1_1
- start_server_version(:TLSv1_1) { |server, port|
- server_connect(port) { |ssl| assert_equal("TLSv1.1", ssl.ssl_version) }
- }
- end
+ # Client enables all supported versions
+ ctx3 = OpenSSL::SSL::SSLContext.new
+ ctx3.min_version = ctx3.max_version = nil
+ server_connect(port, ctx3) { |ssl|
+ assert_equal vmap[ver][:name], ssl.ssl_version
+ }
+ }
+ end
- def test_forbid_tls_v1_for_client
- ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1 }
- start_server_version(:SSLv23, ctx_proc) { |server, port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ssl_version = :TLSv1
- assert_handshake_error { server_connect(port, ctx) }
+ if supported.size == 1
+ pend "More than one protocol version must be supported"
+ end
+
+ # Server sets min_version (earliest is disabled)
+ sver = supported[1]
+ ctx_proc = proc { |ctx| ctx.min_version = sver }
+ start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
+ supported.each do |cver|
+ # Client sets min_version
+ ctx1 = OpenSSL::SSL::SSLContext.new
+ ctx1.min_version = cver
+ server_connect(port, ctx1) { |ssl|
+ assert_equal vmap[supported.last][:name], ssl.ssl_version
+ }
+
+ # Client sets max_version
+ ctx2 = OpenSSL::SSL::SSLContext.new
+ ctx2.max_version = cver
+ if cver >= sver
+ server_connect(port, ctx2) { |ssl|
+ assert_equal vmap[cver][:name], ssl.ssl_version
+ }
+ else
+ assert_handshake_error { server_connect(port, ctx2) { } }
+ end
+ end
}
- end
- def test_forbid_tls_v1_from_server
- start_server_version(:TLSv1) { |server, port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1
- assert_handshake_error { server_connect(port, ctx) }
+ # Server sets max_version (latest is disabled)
+ sver = supported[-2]
+ ctx_proc = proc { |ctx| ctx.max_version = sver }
+ start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
+ supported.each do |cver|
+ # Client sets min_version
+ ctx1 = OpenSSL::SSL::SSLContext.new
+ ctx1.min_version = cver
+ if cver <= sver
+ server_connect(port, ctx1) { |ssl|
+ assert_equal vmap[sver][:name], ssl.ssl_version
+ }
+ else
+ assert_handshake_error { server_connect(port, ctx1) { } }
+ end
+
+ # Client sets max_version
+ ctx2 = OpenSSL::SSL::SSLContext.new
+ ctx2.max_version = cver
+ server_connect(port, ctx2) { |ssl|
+ if cver >= sver
+ assert_equal vmap[sver][:name], ssl.ssl_version
+ else
+ assert_equal vmap[cver][:name], ssl.ssl_version
+ end
+ }
+ end
}
end
-end
-
-if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) && OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_1)
+ def test_options_disable_versions
+ # Note: Use of these OP_* flags has been deprecated since OpenSSL 1.1.0.
+ supported = check_supported_protocol_versions
- def test_tls_v1_2
- start_server_version(:TLSv1_2) { |server, port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ssl_version = :TLSv1_2_client
- server_connect(port, ctx) { |ssl| assert_equal("TLSv1.2", ssl.ssl_version) }
- }
- end if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000
+ if supported.include?(OpenSSL::SSL::TLS1_1_VERSION) &&
+ supported.include?(OpenSSL::SSL::TLS1_2_VERSION)
+ # Server disables ~ TLS 1.1
+ ctx_proc = proc { |ctx|
+ ctx.options |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 |
+ OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1
+ }
+ start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
+ # Client only supports TLS 1.1
+ ctx1 = OpenSSL::SSL::SSLContext.new
+ ctx1.min_version = ctx1.max_version = OpenSSL::SSL::TLS1_1_VERSION
+ assert_handshake_error { server_connect(port, ctx1) { } }
- def test_forbid_tls_v1_1_for_client
- ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_1 }
- start_server_version(:SSLv23, ctx_proc) { |server, port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ssl_version = :TLSv1_1
- assert_handshake_error { server_connect(port, ctx) }
- }
- end if defined?(OpenSSL::SSL::OP_NO_TLSv1_1)
+ # Client only supports TLS 1.2
+ ctx2 = OpenSSL::SSL::SSLContext.new
+ ctx2.min_version = ctx2.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ assert_nothing_raised { server_connect(port, ctx2) { } }
+ }
- def test_forbid_tls_v1_1_from_server
- start_server_version(:TLSv1_1) { |server, port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_1
- assert_handshake_error { server_connect(port, ctx) }
- }
- end if defined?(OpenSSL::SSL::OP_NO_TLSv1_1)
+ # Server only supports TLS 1.1
+ ctx_proc = proc { |ctx|
+ ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION
+ }
+ start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
+ # Client disables TLS 1.1
+ ctx1 = OpenSSL::SSL::SSLContext.new
+ ctx1.options |= OpenSSL::SSL::OP_NO_TLSv1_1
+ assert_handshake_error { server_connect(port, ctx1) { } }
- def test_forbid_tls_v1_2_for_client
- ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_2 }
- start_server_version(:SSLv23, ctx_proc) { |server, port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ssl_version = :TLSv1_2
- assert_handshake_error { server_connect(port, ctx) }
- }
- end if defined?(OpenSSL::SSL::OP_NO_TLSv1_2)
+ # Client disables TLS 1.2
+ ctx2 = OpenSSL::SSL::SSLContext.new
+ ctx2.options |= OpenSSL::SSL::OP_NO_TLSv1_2
+ assert_nothing_raised { server_connect(port, ctx2) { } }
+ }
+ else
+ pend "TLS 1.1 and TLS 1.2 must be supported; skipping"
+ end
+ end
- def test_forbid_tls_v1_2_from_server
- start_server_version(:TLSv1_2) { |server, port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_2
- assert_handshake_error { server_connect(port, ctx) }
+ def test_ssl_methods_constant
+ EnvUtil.suppress_warning { # Deprecated in v2.1.0
+ base = [:TLSv1_2, :TLSv1_1, :TLSv1, :SSLv3, :SSLv2, :SSLv23]
+ base.each do |name|
+ assert_include OpenSSL::SSL::SSLContext::METHODS, name
+ assert_include OpenSSL::SSL::SSLContext::METHODS, :"#{name}_client"
+ assert_include OpenSSL::SSL::SSLContext::METHODS, :"#{name}_server"
+ end
}
- end if defined?(OpenSSL::SSL::OP_NO_TLSv1_2)
-
-end
+ end
def test_renegotiation_cb
num_handshakes = 0
renegotiation_cb = Proc.new { |ssl| num_handshakes += 1 }
ctx_proc = Proc.new { |ctx| ctx.renegotiation_cb = renegotiation_cb }
- start_server_version(:SSLv23, ctx_proc) { |server, port|
+ start_server_version(:SSLv23, ctx_proc) { |port|
server_connect(port) { |ssl|
assert_equal(1, num_handshakes)
}
}
end
-if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000
+if openssl?(1, 0, 2) || libressl?
def test_alpn_protocol_selection_ary
advertised = ["http/1.1", "spdy/2"]
ctx_proc = Proc.new { |ctx|
@@ -903,7 +1000,7 @@ if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000
}
ctx.alpn_protocols = advertised
}
- start_server_version(:SSLv23, ctx_proc) { |server, port|
+ start_server_version(:SSLv23, ctx_proc) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.alpn_protocols = advertised
server_connect(port, ctx) { |ssl|
@@ -916,14 +1013,12 @@ if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000
sock1, sock2 = socketpair
ctx1 = OpenSSL::SSL::SSLContext.new
- ctx1.ciphers = "aNULL"
- ctx1.security_level = 0
+ ctx1.cert = @svr_cert
+ ctx1.key = @svr_key
ctx1.alpn_select_cb = -> (protocols) { nil }
ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
ctx2 = OpenSSL::SSL::SSLContext.new
- ctx2.ciphers = "aNULL"
- ctx2.security_level = 0
ctx2.alpn_protocols = ["http/1.1"]
ssl2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
@@ -942,14 +1037,14 @@ if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000
end
end
-if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 &&
- OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
- # NPN may be disabled by OpenSSL configure option
-
def test_npn_protocol_selection_ary
+ pend "TLS 1.2 is not supported" unless tls12_supported?
+ pend "NPN is not supported" unless \
+ OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
+
advertised = ["http/1.1", "spdy/2"]
- ctx_proc = Proc.new { |ctx| ctx.npn_protocols = advertised }
- start_server_version(:SSLv23, ctx_proc) { |server, port|
+ ctx_proc = proc { |ctx| ctx.npn_protocols = advertised }
+ start_server_version(:TLSv1_2, ctx_proc) { |port|
selector = lambda { |which|
ctx = OpenSSL::SSL::SSLContext.new
ctx.npn_select_cb = -> (protocols) { protocols.send(which) }
@@ -963,13 +1058,17 @@ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 &&
end
def test_npn_protocol_selection_enum
+ pend "TLS 1.2 is not supported" unless tls12_supported?
+ pend "NPN is not supported" unless \
+ OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
+
advertised = Object.new
def advertised.each
yield "http/1.1"
yield "spdy/2"
end
ctx_proc = Proc.new { |ctx| ctx.npn_protocols = advertised }
- start_server_version(:SSLv23, ctx_proc) { |server, port|
+ start_server_version(:TLSv1_2, ctx_proc) { |port|
selector = lambda { |selected, which|
ctx = OpenSSL::SSL::SSLContext.new
ctx.npn_select_cb = -> (protocols) { protocols.to_a.send(which) }
@@ -983,8 +1082,12 @@ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 &&
end
def test_npn_protocol_selection_cancel
+ pend "TLS 1.2 is not supported" unless tls12_supported?
+ pend "NPN is not supported" unless \
+ OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
+
ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] }
- start_server_version(:SSLv23, ctx_proc) { |server, port|
+ start_server_version(:TLSv1_2, ctx_proc) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.npn_select_cb = -> (protocols) { raise RuntimeError.new }
assert_raise(RuntimeError) { server_connect(port, ctx) }
@@ -992,8 +1095,12 @@ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 &&
end
def test_npn_advertised_protocol_too_long
+ pend "TLS 1.2 is not supported" unless tls12_supported?
+ pend "NPN is not supported" unless \
+ OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
+
ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["a" * 256] }
- start_server_version(:SSLv23, ctx_proc) { |server, port|
+ start_server_version(:TLSv1_2, ctx_proc) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.npn_select_cb = -> (protocols) { protocols.first }
assert_handshake_error { server_connect(port, ctx) }
@@ -1001,32 +1108,23 @@ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 &&
end
def test_npn_selected_protocol_too_long
+ pend "TLS 1.2 is not supported" unless tls12_supported?
+ pend "NPN is not supported" unless \
+ OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
+
ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] }
- start_server_version(:SSLv23, ctx_proc) { |server, port|
+ start_server_version(:TLSv1_2, ctx_proc) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.npn_select_cb = -> (protocols) { "a" * 256 }
assert_handshake_error { server_connect(port, ctx) }
}
end
-end
-
- def test_invalid_shutdown_by_gc
- assert_nothing_raised {
- start_server { |server, port|
- 10.times {
- sock = TCPSocket.new("127.0.0.1", port)
- ssl = OpenSSL::SSL::SSLSocket.new(sock)
- GC.start
- ssl.connect
- sock.close
- }
- }
- }
- end
-
def test_close_after_socket_close
- start_server { |server, port|
+ server_proc = proc { |ctx, ssl|
+ # Do nothing
+ }
+ start_server(server_proc: server_proc) { |port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.sync_close = true
@@ -1047,84 +1145,90 @@ end
}
end
- def test_close_and_socket_close_while_connecting
- # test it doesn't cause a segmentation fault
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ciphers = "aNULL"
- ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
- ctx.security_level = 0
-
- sock1, sock2 = socketpair
- ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx)
- ssl2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx)
+ def test_get_ephemeral_key
+ # OpenSSL >= 1.0.2
+ unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key)
+ pend "SSL_get_server_tmp_key() is not supported"
+ end
- t = Thread.new { ssl1.connect }
- ssl2.accept
+ if tls12_supported?
+ # kRSA
+ ctx_proc1 = proc { |ctx|
+ ctx.ssl_version = :TLSv1_2
+ ctx.ciphers = "kRSA"
+ }
+ start_server(ctx_proc: ctx_proc1) 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 }
+ end
+ end
- ssl1.close
- sock1.close
- t.value rescue nil
- ensure
- ssl1.close if ssl1
- ssl2.close if ssl2
- sock1.close if sock1
- sock2.close if sock2
- end
+ if defined?(OpenSSL::PKey::DH) && tls12_supported?
+ # DHE
+ # TODO: How to test this with TLS 1.3?
+ ctx_proc2 = proc { |ctx|
+ ctx.ssl_version = :TLSv1_2
+ ctx.ciphers = "EDH"
+ }
+ start_server(ctx_proc: ctx_proc2) do |port|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ssl_version = :TLSv1_2
+ ctx.ciphers = "EDH"
+ server_connect(port, ctx) { |ssl|
+ assert_instance_of OpenSSL::PKey::DH, ssl.tmp_key
+ }
+ end
+ end
- def test_get_ephemeral_key
- return unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key)
- pkey = OpenSSL::PKey
- ciphers = {
- 'ECDHE-RSA-AES128-SHA' => (pkey::EC if defined?(pkey::EC)),
- 'DHE-RSA-AES128-SHA' => (pkey::DH if defined?(pkey::DH)),
- 'AES128-SHA' => nil
- }
- conf_proc = Proc.new { |ctx| ctx.ciphers = 'ALL' }
- start_server(ctx_proc: conf_proc) do |server, port|
- ciphers.each do |cipher, ephemeral|
+ if defined?(OpenSSL::PKey::EC)
+ # ECDHE
+ ctx_proc3 = proc { |ctx|
+ ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
+ ctx.ecdh_curves = "P-256"
+ }
+ start_server(ctx_proc: ctx_proc3) do |port|
ctx = OpenSSL::SSL::SSLContext.new
- begin
- ctx.ciphers = cipher
- rescue OpenSSL::SSL::SSLError => e
- next if /no cipher match/ =~ e.message
- raise
- end
- server_connect(port, ctx) do |ssl|
- if ephemeral
- assert_instance_of(ephemeral, ssl.tmp_key)
- else
- assert_nil(ssl.tmp_key)
- end
- end
+ ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
+ server_connect(port, ctx) { |ssl|
+ assert_instance_of OpenSSL::PKey::EC, ssl.tmp_key
+ }
end
end
end
def test_dh_callback
+ pend "TLS 1.2 is not supported" unless tls12_supported?
+
called = false
ctx_proc = -> ctx {
+ ctx.ssl_version = :TLSv1_2
ctx.ciphers = "DH:!NULL"
ctx.tmp_dh_callback = ->(*args) {
called = true
- OpenSSL::TestUtils::TEST_KEY_DH1024
+ Fixtures.pkey_dh("dh1024")
}
}
- start_server(ctx_proc: ctx_proc) do |server, port|
+ start_server(ctx_proc: ctx_proc) do |port|
server_connect(port) { |ssl|
assert called, "dh callback should be called"
if ssl.respond_to?(:tmp_key)
- assert_equal OpenSSL::TestUtils::TEST_KEY_DH1024.to_der, ssl.tmp_key.to_der
+ assert_equal Fixtures.pkey_dh("dh1024").to_der, ssl.tmp_key.to_der
end
}
end
end
def test_connect_works_when_setting_dh_callback_to_nil
+ pend "TLS 1.2 is not supported" unless tls12_supported?
+
ctx_proc = -> ctx {
+ ctx.ssl_version = :TLSv1_2
ctx.ciphers = "DH:!NULL" # use DH
ctx.tmp_dh_callback = nil
}
- start_server(ctx_proc: ctx_proc) do |server, port|
+ start_server(ctx_proc: ctx_proc) do |port|
EnvUtil.suppress_warning { # uses default callback
assert_nothing_raised {
server_connect(port) { }
@@ -1133,73 +1237,53 @@ end
end
end
- def test_ecdh_callback
- return unless OpenSSL::SSL::SSLContext.instance_methods.include?(:tmp_ecdh_callback)
+ def test_tmp_ecdh_callback
+ pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
+ pend "tmp_ecdh_callback is not supported" unless \
+ OpenSSL::SSL::SSLContext.method_defined?(:tmp_ecdh_callback)
+
EnvUtil.suppress_warning do # tmp_ecdh_callback is deprecated (2016-05)
- begin
- called = false
- ctx2 = OpenSSL::SSL::SSLContext.new
- ctx2.ciphers = "ECDH"
- # OpenSSL 1.1.0 doesn't have tmp_ecdh_callback so this shouldn't be required
- ctx2.security_level = 0
- ctx2.tmp_ecdh_callback = ->(*args) {
+ called = false
+ ctx_proc = -> ctx {
+ ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
+ ctx.tmp_ecdh_callback = -> (*args) {
called = true
OpenSSL::PKey::EC.new "prime256v1"
}
-
- sock1, sock2 = socketpair
-
- s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
- ctx1 = OpenSSL::SSL::SSLContext.new
- ctx1.ciphers = "ECDH"
- ctx1.security_level = 0
-
- s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
- th = Thread.new do
- s1.connect
- end
-
- s2.accept
- assert called, 'ecdh callback should be called'
- rescue OpenSSL::SSL::SSLError => e
- if e.message =~ /no cipher match/
- pend "ECDH cipher not supported."
- else
- raise e
- end
- ensure
- th.join if th
- s1.close if s1
- s2.close if s2
- sock1.close if sock1
- sock2.close if sock2
+ }
+ start_server(ctx_proc: ctx_proc) do |port|
+ server_connect(port) { |s|
+ assert called, "tmp_ecdh_callback should be called"
+ }
end
end
end
def test_ecdh_curves
+ pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
+
ctx_proc = -> ctx {
- begin
- ctx.ciphers = "ECDH:!NULL"
- rescue OpenSSL::SSL::SSLError
- pend "ECDH is not enabled in this OpenSSL" if $!.message =~ /no cipher match/
- raise
- end
+ # Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3
+ ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
ctx.ecdh_curves = "P-384:P-521"
}
- start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |server, port|
+ 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 for OpenSSL >= 1.0.2
server_connect(port, ctx) { |ssl|
- assert ssl.cipher[0].start_with?("ECDH"), "ECDH should be used"
- if ssl.respond_to?(:tmp_key)
+ cs = ssl.cipher[0]
+ if /\ATLS/ =~ cs # Is TLS 1.3 is used?
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
}
- if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000 &&
- !OpenSSL::OPENSSL_VERSION.include?("LibreSSL")
+ if openssl?(1, 0, 2) || libressl?(2, 5, 1)
ctx = OpenSSL::SSL::SSLContext.new
ctx.ecdh_curves = "P-256"
@@ -1226,10 +1310,10 @@ end
return
end
assert_equal(1, ctx.security_level)
- # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = OpenSSL::TestUtils::TEST_KEY_DSA512 }
- # ctx.key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = Fixtures.pkey("dsa512") }
+ # ctx.key = Fixtures.pkey("rsa1024")
# ctx.security_level = 2
- # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = OpenSSL::TestUtils::TEST_KEY_RSA1024 }
+ # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = Fixtures.pkey("rsa1024") }
pend "FIXME: SSLContext#key= currently does not raise because SSL_CTX_use_certificate() is delayed"
end
@@ -1248,7 +1332,7 @@ end
def test_freeze_calls_setup
bug = "[ruby/openssl#85]"
- start_server(ignore_listener_error: true) { |server, port|
+ start_server(ignore_listener_error: true) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
ctx.freeze
@@ -1274,7 +1358,7 @@ end
)
end
- def server_connect(port, ctx=nil)
+ def server_connect(port, ctx = nil)
sock = TCPSocket.new("127.0.0.1", port)
ssl = ctx ? OpenSSL::SSL::SSLSocket.new(sock, ctx) : OpenSSL::SSL::SSLSocket.new(sock)
ssl.sync_close = true