summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2017-08-26 10:07:58 +0900
committerKazuki Yamaguchi <k@rhe.jp>2017-08-26 10:07:58 +0900
commitd05a1a9120b6870e19b20d7a6c367482ac96e1cc (patch)
treea0634b37822d6033bfffdfcac21878bf8897e906
parent3ed3fc5dde962615fcf42d0cfa4feba6cb8af9d5 (diff)
parent230467d23c2b70f2f8f1af1e5b28243e0e119cf6 (diff)
downloadruby-openssl-d05a1a9120b6870e19b20d7a6c367482ac96e1cc.tar.gz
Merge branch 'maint'
This also restores 'if defined?(OpenSSL)-end' wrapping the test code. They have been removed erroneously by commit 4eb4b3297a92 ("Remove support for OpenSSL 0.9.8 and 1.0.0", 2016-11-30). * maint: test/test_ssl: explicitly accept TLS 1.1 in corresponding test ssl: remove useless call to rb_thread_wait_fd() test/test_pair, test/test_ssl: fix for TLS 1.3 test/test_ssl_session: rearrange tests test/test_ssl: move test_multibyte_read_write to test_pair test/test_ssl: remove test_invalid_shutdown_by_gc test/utils: do not use DSA certificates in SSL tests test/utils: add OpenSSL::TestUtils.openssl? and .libressl? test/utils: improve error handling in start_server test/utils: let server_loop close socket test/utils: do not set ecdh_curves in start_server test/utils: have start_server yield only the port number test/utils: add SSLTestCase#tls12_supported? test/utils: remove OpenSSL::TestUtils.silent test: fix formatting Rakefile: let sync:to_ruby know about test/openssl/fixtures cipher: update the documentation for Cipher#auth_tag= Backport "Merge branch 'topic/test-memory-leak'" to maint ssl: do not call session_remove_cb during GC
-rw-r--r--Rakefile5
-rw-r--r--ext/openssl/ossl_cipher.c12
-rw-r--r--ext/openssl/ossl_ssl.c9
-rw-r--r--test/test_asn1.rb3
-rw-r--r--test/test_bn.rb4
-rw-r--r--test/test_buffering.rb5
-rw-r--r--test/test_cipher.rb3
-rw-r--r--test/test_config.rb10
-rw-r--r--test/test_digest.rb6
-rw-r--r--test/test_engine.rb6
-rw-r--r--test/test_fips.rb5
-rw-r--r--test/test_hmac.rb4
-rw-r--r--test/test_kdf.rb4
-rw-r--r--test/test_ns_spki.rb4
-rw-r--r--test/test_ocsp.rb6
-rw-r--r--test/test_pair.rb129
-rw-r--r--test/test_pkcs12.rb5
-rw-r--r--test/test_pkcs7.rb4
-rw-r--r--test/test_pkey_dh.rb4
-rw-r--r--test/test_pkey_dsa.rb5
-rw-r--r--test/test_pkey_ec.rb2
-rw-r--r--test/test_pkey_rsa.rb7
-rw-r--r--test/test_random.rb4
-rw-r--r--test/test_ssl.rb431
-rw-r--r--test/test_ssl_session.rb403
-rw-r--r--test/test_x509attr.rb4
-rw-r--r--test/test_x509cert.rb4
-rw-r--r--test/test_x509crl.rb4
-rw-r--r--test/test_x509ext.rb4
-rw-r--r--test/test_x509name.rb4
-rw-r--r--test/test_x509req.rb4
-rw-r--r--test/test_x509store.rb6
-rw-r--r--test/ut_eof.rb4
-rw-r--r--test/utils.rb312
34 files changed, 746 insertions, 680 deletions
diff --git a/Rakefile b/Rakefile
index 8ba95aa9..d63267d7 100644
--- a/Rakefile
+++ b/Rakefile
@@ -58,11 +58,12 @@ namespace :sync do
paths = [
["ext/openssl/", "ext/openssl/"],
+ ["lib/", "ext/openssl/lib/"],
+ ["sample/", "sample/openssl/"],
+ ["test/fixtures/", "test/openssl/fixtures/"],
["test/utils.rb", "test/openssl/"],
["test/ut_eof.rb", "test/openssl/"],
["test/test_*", "test/openssl/"],
- ["lib/", "ext/openssl/lib/"],
- ["sample/", "sample/openssl/"],
["History.md", "ext/openssl/"],
]
paths.each do |src, dst|
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 21fcb1b6..bfa76c1a 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -620,13 +620,11 @@ ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self)
* call-seq:
* cipher.auth_tag = string -> string
*
- * Sets the authentication tag to verify the contents of the
- * ciphertext. The tag must be set after calling Cipher#decrypt,
- * Cipher#key= and Cipher#iv=, but before assigning the associated
- * authenticated data using Cipher#auth_data= and of course, before
- * decrypting any of the ciphertext. After all decryption is
- * performed, the tag is verified automatically in the call to
- * Cipher#final.
+ * Sets the authentication tag to verify the integrity of the ciphertext.
+ * This can be called only when the cipher supports AE. The tag must be set
+ * after calling Cipher#decrypt, Cipher#key= and Cipher#iv=, but before
+ * calling Cipher#final. After all decryption is performed, the tag is
+ * verified automatically in the call to Cipher#final.
*
* For OCB mode, the tag length must be supplied with #auth_tag_len=
* beforehand.
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 51418410..cd575a13 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -470,6 +470,13 @@ ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
VALUE ary, sslctx_obj, sess_obj;
int state = 0;
+ /*
+ * This callback is also called for all sessions in the internal store
+ * when SSL_CTX_free() is called.
+ */
+ if (rb_during_gc())
+ return;
+
OSSL_Debug("SSL SESSION remove callback entered");
sslctx_obj = (VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx);
@@ -1689,8 +1696,6 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr);
if (ssl_started(ssl)) {
- if(!nonblock && SSL_pending(ssl) <= 0)
- rb_thread_wait_fd(fptr->fd);
for (;;){
nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LENINT(str));
switch(ssl_get_error(ssl, nread)){
diff --git a/test/test_asn1.rb b/test/test_asn1.rb
index 9ac6b9be..3e7f8c13 100644
--- a/test/test_asn1.rb
+++ b/test/test_asn1.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative 'utils'
+if defined?(OpenSSL)
+
class OpenSSL::TestASN1 < OpenSSL::TestCase
def test_decode_x509_certificate
subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA")
@@ -677,5 +679,6 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
end
assert_equal(:UNIVERSAL, asn1.tag_class)
end
+end
end
diff --git a/test/test_bn.rb b/test/test_bn.rb
index 02c53f39..77390286 100644
--- a/test/test_bn.rb
+++ b/test/test_bn.rb
@@ -3,6 +3,8 @@
require_relative 'utils'
require "prime"
+if defined?(OpenSSL)
+
class OpenSSL::TestBN < OpenSSL::TestCase
def setup
super
@@ -270,3 +272,5 @@ class OpenSSL::TestBN < OpenSSL::TestCase
assert_equal(0, @e1.ucmp(-999))
end
end
+
+end
diff --git a/test/test_buffering.rb b/test/test_buffering.rb
index 73cfa9d8..c85a6f02 100644
--- a/test/test_buffering.rb
+++ b/test/test_buffering.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: false
require_relative 'utils'
-require 'stringio'
-class OpenSSL::TestBuffering < OpenSSL::TestCase
+if defined?(OpenSSL)
+class OpenSSL::TestBuffering < OpenSSL::TestCase
class IO
include OpenSSL::Buffering
@@ -85,5 +85,6 @@ class OpenSSL::TestBuffering < OpenSSL::TestCase
end
assert_equal([97, 98, 99], res)
end
+end
end
diff --git a/test/test_cipher.rb b/test/test_cipher.rb
index ce64fbb9..d87dedf7 100644
--- a/test/test_cipher.rb
+++ b/test/test_cipher.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative 'utils'
+if defined?(OpenSSL)
+
class OpenSSL::TestCipher < OpenSSL::TestCase
module Helper
def has_cipher?(name)
@@ -308,5 +310,6 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
kwargs.each {|k, v| cipher.send(:"#{k}=", v) }
end
end
+end
end
diff --git a/test/test_config.rb b/test/test_config.rb
index 42f9d3c5..8096375c 100644
--- a/test/test_config.rb
+++ b/test/test_config.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative 'utils'
+if defined?(OpenSSL)
+
class OpenSSL::TestConfig < OpenSSL::TestCase
def setup
super
@@ -171,7 +173,7 @@ __EOC__
def test_value
# suppress deprecation warnings
- OpenSSL::TestUtils.silent do
+ EnvUtil.suppress_warning do
assert_equal('CA_default', @it.value('ca', 'default_ca'))
assert_equal(nil, @it.value('ca', 'no such key'))
assert_equal(nil, @it.value('no such section', 'no such key'))
@@ -184,7 +186,7 @@ __EOC__
end
def test_value_ENV
- OpenSSL::TestUtils.silent do
+ EnvUtil.suppress_warning do
key = ENV.keys.first
assert_not_nil(key) # make sure we have at least one ENV var.
assert_equal(ENV[key], @it.value('ENV', key))
@@ -199,7 +201,7 @@ __EOC__
end
def test_section
- OpenSSL::TestUtils.silent do
+ EnvUtil.suppress_warning do
assert_equal({'HOME' => '.'}, @it.section('default'))
assert_equal({'dir' => './demoCA', 'certs' => './certs'}, @it.section('CA_default'))
assert_equal({}, @it.section('no_such_section'))
@@ -298,3 +300,5 @@ __EOC__
assert_not_equal(@it.sections.sort, c.sections.sort)
end
end
+
+end
diff --git a/test/test_digest.rb b/test/test_digest.rb
index e81d618d..2cb878b6 100644
--- a/test/test_digest.rb
+++ b/test/test_digest.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative 'utils'
+if defined?(OpenSSL)
+
class OpenSSL::TestDigest < OpenSSL::TestCase
def setup
super
@@ -53,7 +55,7 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
def test_digest_constants
algs = %w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512)
- if OpenSSL::OPENSSL_VERSION_NUMBER < 0x10100000
+ if !libressl? && !openssl?(1, 1, 0)
algs += %w(DSS1 SHA)
end
algs.each do |alg|
@@ -115,3 +117,5 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
assert_not_nil(d)
end
end
+
+end
diff --git a/test/test_engine.rb b/test/test_engine.rb
index a987f267..4f3973a7 100644
--- a/test/test_engine.rb
+++ b/test/test_engine.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: false
require_relative 'utils'
-class OpenSSL::TestEngine < OpenSSL::TestCase
+if defined?(OpenSSL) && defined?(OpenSSL::Engine)
+class OpenSSL::TestEngine < OpenSSL::TestCase
def test_engines_free # [ruby-dev:44173]
with_openssl <<-'end;'
OpenSSL::Engine.load("openssl")
@@ -95,5 +96,6 @@ class OpenSSL::TestEngine < OpenSSL::TestCase
cipher.update(data) + cipher.final
end
end
+end
-end if defined?(OpenSSL::Engine)
+end
diff --git a/test/test_fips.rb b/test/test_fips.rb
index e96c5c07..a4ab87f3 100644
--- a/test/test_fips.rb
+++ b/test/test_fips.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: false
require_relative 'utils'
-class OpenSSL::TestFIPS < OpenSSL::TestCase
+if defined?(OpenSSL)
+class OpenSSL::TestFIPS < OpenSSL::TestCase
def test_fips_mode_is_reentrant
OpenSSL.fips_mode = false
OpenSSL.fips_mode = false
@@ -18,3 +19,5 @@ class OpenSSL::TestFIPS < OpenSSL::TestCase
end
end
end
+
+end
diff --git a/test/test_hmac.rb b/test/test_hmac.rb
index 86857ba0..831a5b6b 100644
--- a/test/test_hmac.rb
+++ b/test/test_hmac.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative 'utils'
+if defined?(OpenSSL)
+
class OpenSSL::TestHMAC < OpenSSL::TestCase
def test_hmac
# RFC 2202 2. Test Cases for HMAC-MD5
@@ -38,3 +40,5 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase
assert_equal first, second
end
end
+
+end
diff --git a/test/test_kdf.rb b/test/test_kdf.rb
index 9346be7c..d91fa3cf 100644
--- a/test/test_kdf.rb
+++ b/test/test_kdf.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: false
require_relative 'utils'
-class OpenSSL::TestKDF < OpenSSL::TestCase
+if defined?(OpenSSL)
+class OpenSSL::TestKDF < OpenSSL::TestCase
def test_pkcs5_pbkdf2_hmac_compatibility
expected = OpenSSL::KDF.pbkdf2_hmac("password", salt: "salt", iterations: 1, length: 20, hash: "sha1")
assert_equal(expected, OpenSSL::PKCS5.pbkdf2_hmac("password", "salt", 1, 20, "sha1"))
@@ -135,5 +136,6 @@ class OpenSSL::TestKDF < OpenSSL::TestCase
def B(ary)
[Array(ary).join].pack("H*")
end
+end
end
diff --git a/test/test_ns_spki.rb b/test/test_ns_spki.rb
index 4905fba4..aa1e6182 100644
--- a/test/test_ns_spki.rb
+++ b/test/test_ns_spki.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative 'utils'
+if defined?(OpenSSL)
+
class OpenSSL::TestNSSPI < OpenSSL::TestCase
def setup
super
@@ -47,3 +49,5 @@ class OpenSSL::TestNSSPI < OpenSSL::TestCase
assert_equal(OpenSSL::PKey::RSA, spki.public_key.class)
end
end
+
+end
diff --git a/test/test_ocsp.rb b/test/test_ocsp.rb
index 25e052ae..9d48496d 100644
--- a/test/test_ocsp.rb
+++ b/test/test_ocsp.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative "utils"
+if defined?(OpenSSL)
+
class OpenSSL::TestOCSP < OpenSSL::TestCase
def setup
super
@@ -120,7 +122,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
assert_equal true, req.verify([@cert], store, OpenSSL::OCSP::NOINTERN)
ret = req.verify([@cert], store)
- if ret || OpenSSL::OPENSSL_VERSION =~ /OpenSSL/ && OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000
+ if ret || openssl?(1, 0, 2) || libressl?(2, 4, 2)
assert_equal true, ret
else
# RT2560; OCSP_request_verify() does not find signer cert from 'certs' when
@@ -307,3 +309,5 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
assert_equal res.to_der, res.dup.to_der
end
end
+
+end
diff --git a/test/test_pair.rb b/test/test_pair.rb
index a462891d..89cf41a8 100644
--- a/test/test_pair.rb
+++ b/test/test_pair.rb
@@ -1,59 +1,45 @@
# frozen_string_literal: false
require_relative 'utils'
-
-require 'socket'
require_relative 'ut_eof'
+if defined?(OpenSSL)
+
module OpenSSL::SSLPairM
- def server
- host = "127.0.0.1"
- port = 0
- ctx = OpenSSL::SSL::SSLContext.new()
- ctx.ciphers = "ADH"
- ctx.security_level = 0
- ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") }
- tcps = create_tcp_server(host, port)
- ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
- return ssls
+ def setup
+ svr_dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
+ ee_exts = [
+ ["keyUsage", "keyEncipherment,digitalSignature", true],
+ ]
+ @svr_key = OpenSSL::TestUtils::Fixtures.pkey("rsa1024")
+ @svr_cert = issue_cert(svr_dn, @svr_key, 1, ee_exts, nil, nil)
end
- def client(port)
+ def ssl_pair
host = "127.0.0.1"
- ctx = OpenSSL::SSL::SSLContext.new()
- ctx.ciphers = "ADH"
- ctx.security_level = 0
- s = create_tcp_client(host, port)
- ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
- ssl.connect
- ssl.sync_close = true
- ssl
- end
+ tcps = create_tcp_server(host, 0)
+ port = tcps.connect_address.ip_port
- def ssl_pair
- ssls = server
th = Thread.new {
+ sctx = OpenSSL::SSL::SSLContext.new
+ sctx.cert = @svr_cert
+ sctx.key = @svr_key
+ sctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") }
+ ssls = OpenSSL::SSL::SSLServer.new(tcps, sctx)
ns = ssls.accept
ssls.close
ns
}
- port = ssls.to_io.local_address.ip_port
- c = client(port)
+
+ tcpc = create_tcp_client(host, port)
+ c = OpenSSL::SSL::SSLSocket.new(tcpc)
+ c.connect
s = th.value
- if block_given?
- begin
- yield c, s
- ensure
- c.close unless c.closed?
- s.close unless s.closed?
- end
- else
- return c, s
- end
+
+ yield c, s
ensure
- if th&.alive?
- th.kill
- th.join
- end
+ tcpc&.close
+ tcps&.close
+ s&.close
end
end
@@ -83,23 +69,27 @@ end
module OpenSSL::TestEOF1M
def open_file(content)
- s1, s2 = ssl_pair
- th = Thread.new { s2 << content; s2.close }
- yield s1
- ensure
- th.join if th
- s1.close
+ ssl_pair { |s1, s2|
+ begin
+ th = Thread.new { s2 << content; s2.close }
+ yield s1
+ ensure
+ th&.join
+ end
+ }
end
end
module OpenSSL::TestEOF2M
def open_file(content)
- s1, s2 = ssl_pair
- th = Thread.new { s1 << content; s1.close }
- yield s2
- ensure
- th.join if th
- s2.close
+ ssl_pair { |s1, s2|
+ begin
+ th = Thread.new { s1 << content; s1.close }
+ yield s2
+ ensure
+ th&.join
+ end
+ }
end
end
@@ -187,6 +177,27 @@ module OpenSSL::TestPairM
}
end
+ def test_multibyte_read_write
+ # German a umlaut
+ auml = [%w{ C3 A4 }.join('')].pack('H*')
+ auml.force_encoding(Encoding::UTF_8)
+ bsize = auml.bytesize
+
+ ssl_pair { |s1, s2|
+ assert_equal bsize, s1.write(auml)
+ read = s2.read(bsize)
+ assert_equal Encoding::ASCII_8BIT, read.encoding
+ assert_equal bsize, read.bytesize
+ assert_equal auml, read.force_encoding(Encoding::UTF_8)
+
+ s1.puts(auml)
+ read = s2.gets
+ assert_equal Encoding::ASCII_8BIT, read.encoding
+ assert_equal bsize + 1, read.bytesize
+ assert_equal auml + "\n", read.force_encoding(Encoding::UTF_8)
+ }
+ end
+
def test_read_nonblock
ssl_pair {|s1, s2|
err = nil
@@ -352,8 +363,8 @@ module OpenSSL::TestPairM
def test_connect_accept_nonblock_no_exception
ctx2 = OpenSSL::SSL::SSLContext.new
- ctx2.ciphers = "ADH"
- ctx2.security_level = 0
+ ctx2.cert = @svr_cert
+ ctx2.key = @svr_key
ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") }
sock1, sock2 = tcp_pair
@@ -363,8 +374,6 @@ module OpenSSL::TestPairM
assert_equal :wait_readable, accepted
ctx1 = OpenSSL::SSL::SSLContext.new
- ctx1.ciphers = "ADH"
- ctx1.security_level = 0
s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
th = Thread.new do
rets = []
@@ -402,8 +411,8 @@ module OpenSSL::TestPairM
def test_connect_accept_nonblock
ctx = OpenSSL::SSL::SSLContext.new()
- ctx.ciphers = "ADH"
- ctx.security_level = 0
+ ctx.cert = @svr_cert
+ ctx.key = @svr_key
ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") }
sock1, sock2 = tcp_pair
@@ -426,8 +435,6 @@ module OpenSSL::TestPairM
sleep 0.1
ctx = OpenSSL::SSL::SSLContext.new()
- ctx.ciphers = "ADH"
- ctx.security_level = 0
s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx)
begin
sleep 0.2
@@ -487,3 +494,5 @@ class OpenSSL::TestPairLowlevelSocket < OpenSSL::TestCase
include OpenSSL::SSLPairLowlevelSocket
include OpenSSL::TestPairM
end
+
+end
diff --git a/test/test_pkcs12.rb b/test/test_pkcs12.rb
index 2a3b47f4..de8e35ed 100644
--- a/test/test_pkcs12.rb
+++ b/test/test_pkcs12.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative "utils"
+if defined?(OpenSSL)
+
module OpenSSL
class TestPKCS12 < OpenSSL::TestCase
def setup
@@ -305,6 +307,7 @@ Kw4DAhoFAAQUYAuwVtGD1TdgbFK4Yal2XBgwUR4ECEawsN3rNaa6AgIIAA==
end
false
end
-
end
end
+
+end
diff --git a/test/test_pkcs7.rb b/test/test_pkcs7.rb
index 5320cc38..149d3b9b 100644
--- a/test/test_pkcs7.rb
+++ b/test/test_pkcs7.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative 'utils'
+if defined?(OpenSSL)
+
class OpenSSL::TestPKCS7 < OpenSSL::TestCase
def setup
super
@@ -279,3 +281,5 @@ END
assert_equal(pki_message_content_pem, p7enc.to_pem)
end
end
+
+end
diff --git a/test/test_pkey_dh.rb b/test/test_pkey_dh.rb
index e7e76f97..77cdb0ab 100644
--- a/test/test_pkey_dh.rb
+++ b/test/test_pkey_dh.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative 'utils'
+if defined?(OpenSSL) && defined?(OpenSSL::PKey::DH)
+
class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
NEW_KEYLEN = 256
@@ -97,3 +99,5 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
check_component(expected, key, [:p, :q, :g, :pub_key, :priv_key])
end
end
+
+end
diff --git a/test/test_pkey_dsa.rb b/test/test_pkey_dsa.rb
index 52ff8579..d6519498 100644
--- a/test/test_pkey_dsa.rb
+++ b/test/test_pkey_dsa.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: false
require_relative 'utils'
-require 'base64'
+
+if defined?(OpenSSL) && defined?(OpenSSL::PKey::DSA)
class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
def test_private
@@ -195,3 +196,5 @@ fWLOqqkzFeRrYMDzUpl36XktY6Yq8EJYlW9pCMmBVNy/dQ==
check_component(expected, key, [:p, :q, :g, :pub_key, :priv_key])
end
end
+
+end
diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb
index 2944f5c2..713c649a 100644
--- a/test/test_pkey_ec.rb
+++ b/test/test_pkey_ec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'utils'
-if defined?(OpenSSL::PKey::EC)
+if defined?(OpenSSL) && defined?(OpenSSL::PKey::EC)
class OpenSSL::TestEC < OpenSSL::PKeyTestCase
def test_ec_key
diff --git a/test/test_pkey_rsa.rb b/test/test_pkey_rsa.rb
index fed5aa9d..49ab3792 100644
--- a/test/test_pkey_rsa.rb
+++ b/test/test_pkey_rsa.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: false
-require_relative 'utils'
-require 'base64'
+require_relative "utils"
+
+if defined?(OpenSSL)
class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
def test_padding
@@ -267,3 +268,5 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
check_component(expected, key, [:n, :e, :d, :p, :q, :dmp1, :dmq1, :iqmp])
end
end
+
+end
diff --git a/test/test_random.rb b/test/test_random.rb
index dd72d84d..d5a37454 100644
--- a/test/test_random.rb
+++ b/test/test_random.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative "utils"
+if defined?(OpenSSL)
+
class OpenSSL::TestRandom < OpenSSL::TestCase
def test_random_bytes
assert_equal("", OpenSSL::Random.random_bytes(0))
@@ -13,3 +15,5 @@ class OpenSSL::TestRandom < OpenSSL::TestCase
assert_equal(12, OpenSSL::Random.pseudo_bytes(12).bytesize)
end if OpenSSL::Random.methods.include?(:pseudo_bytes)
end
+
+end
diff --git a/test/test_ssl.rb b/test/test_ssl.rb
index a519c6af..fd4afa69 100644
--- a/test/test_ssl.rb
+++ b/test/test_ssl.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: false
require_relative "utils"
-class OpenSSL::TestSSL < OpenSSL::SSLTestCase
+if defined?(OpenSSL)
+class OpenSSL::TestSSL < OpenSSL::SSLTestCase
def test_ctx_options
ctx = OpenSSL::SSL::SSLContext.new
@@ -33,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
@@ -54,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)
@@ -70,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)
@@ -95,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"
@@ -110,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
@@ -151,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
@@ -173,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|
@@ -185,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
@@ -204,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)
@@ -246,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)
@@ -267,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
@@ -281,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
@@ -299,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
@@ -319,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
@@ -330,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
@@ -355,13 +348,17 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
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|
@@ -375,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")}
@@ -396,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"))
@@ -416,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")}
@@ -619,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 { Fixtures.pkey_dh("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
@@ -670,9 +663,9 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
hostname = 'example.org'
ctx2 = OpenSSL::SSL::SSLContext.new
- ctx2.ciphers = "aNULL"
+ ctx2.cert = @svr_cert
+ ctx2.key = @svr_key
ctx2.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") }
- ctx2.security_level = 0
ctx2.servername_cb = lambda { |args| Object.new }
sock1, sock2 = socketpair
@@ -680,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
@@ -712,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
@@ -746,7 +737,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_connect_certificate_verify_failed_exception_message
- start_server(ignore_listener_error: true) { |server, port|
+ start_server(ignore_listener_error: true) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.set_params
assert_raise_with_message(OpenSSL::SSL::SSLError, /self signed/) {
@@ -758,7 +749,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
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) { |server, port|
+ 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
@@ -769,31 +760,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
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
- }
- start_server(server_proc: server_proc) { |server, port|
- server_connect(port) { |ssl|
- str = auml * i
- num_written = ssl.write(str)
- }
- }
- }
- end
-
def test_unset_OP_ALL
ctx_proc = Proc.new { |ctx|
# If OP_DONT_INSERT_EMPTY_FRAGMENTS is not defined, this test is
@@ -801,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)
@@ -813,7 +779,7 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1) && OpenSSL::SSL::SSLContex
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|
+ start_server_version(:SSLv23, ctx_proc) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.ssl_version = :SSLv3
assert_handshake_error { server_connect(port, ctx) }
@@ -821,7 +787,7 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1) && OpenSSL::SSL::SSLContex
end
def test_forbid_ssl_v3_from_server
- start_server_version(:SSLv3) { |server, port|
+ start_server_version(:SSLv3) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv3
assert_handshake_error { server_connect(port, ctx) }
@@ -833,14 +799,15 @@ end
if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_1) && OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1)
def test_tls_v1_1
- start_server_version(:TLSv1_1) { |server, port|
- server_connect(port) { |ssl| assert_equal("TLSv1.1", ssl.ssl_version) }
+ start_server_version(:TLSv1_1) { |port|
+ ctx = OpenSSL::SSL::SSLContext.new(:TLSv1_1)
+ server_connect(port, ctx) { |ssl| assert_equal("TLSv1.1", 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|
+ start_server_version(:SSLv23, ctx_proc) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.ssl_version = :TLSv1
assert_handshake_error { server_connect(port, ctx) }
@@ -848,7 +815,7 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_1) && OpenSSL::SSL::SSLCont
end
def test_forbid_tls_v1_from_server
- start_server_version(:TLSv1) { |server, port|
+ start_server_version(:TLSv1) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1
assert_handshake_error { server_connect(port, ctx) }
@@ -860,7 +827,7 @@ end
if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) && OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_1)
def test_tls_v1_2
- start_server_version(:TLSv1_2) { |server, port|
+ start_server_version(:TLSv1_2) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.ssl_version = :TLSv1_2_client
server_connect(port, ctx) { |ssl| assert_equal("TLSv1.2", ssl.ssl_version) }
@@ -869,7 +836,7 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) && OpenSSL::SSL::SSLCont
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|
+ start_server_version(:SSLv23, ctx_proc) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.ssl_version = :TLSv1_1
assert_handshake_error { server_connect(port, ctx) }
@@ -877,7 +844,7 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) && OpenSSL::SSL::SSLCont
end
def test_forbid_tls_v1_1_from_server
- start_server_version(:TLSv1_1) { |server, port|
+ start_server_version(:TLSv1_1) { |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) }
@@ -886,7 +853,7 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) && OpenSSL::SSL::SSLCont
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|
+ start_server_version(:SSLv23, ctx_proc) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.ssl_version = :TLSv1_2
assert_handshake_error { server_connect(port, ctx) }
@@ -894,7 +861,7 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) && OpenSSL::SSL::SSLCont
end
def test_forbid_tls_v1_2_from_server
- start_server_version(:TLSv1_2) { |server, port|
+ start_server_version(:TLSv1_2) { |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) }
@@ -907,14 +874,14 @@ end
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|
@@ -923,7 +890,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|
@@ -936,14 +903,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)
@@ -962,13 +927,14 @@ if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000
end
end
-if 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) }
@@ -982,13 +948,17 @@ if OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
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) }
@@ -1002,8 +972,12 @@ if OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
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) }
@@ -1011,8 +985,12 @@ if OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
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) }
@@ -1020,32 +998,23 @@ if OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
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
@@ -1066,69 +1035,72 @@ 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 { Fixtures.pkey_dh("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
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)
@@ -1139,11 +1111,14 @@ 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) { }
@@ -1152,73 +1127,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"
@@ -1267,7 +1222,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
@@ -1293,7 +1248,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
@@ -1315,3 +1270,5 @@ end
}
end
end
+
+end
diff --git a/test/test_ssl_session.rb b/test/test_ssl_session.rb
index f89732ab..199f722e 100644
--- a/test/test_ssl_session.rb
+++ b/test/test_ssl_session.rb
@@ -1,55 +1,15 @@
# frozen_string_literal: false
require_relative "utils"
-class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase
- def test_session_equals
- session = OpenSSL::SSL::Session.new <<-SESSION
------BEGIN SSL SESSION PARAMETERS-----
-MIIDFgIBAQICAwEEAgA5BCCY3pW6iTkPoD5SENuztz/gZjhvey6XnHbsxd22k0Ol
-dgQw8uaN3hCRnlhoIKPWInCFzrp/tQsDRFs9jDjc9pwpy/oKHmJdQQMQA1g8FYnO
-gpdVoQYCBE52ikKiBAICASyjggKOMIICijCCAXKgAwIBAgIBAjANBgkqhkiG9w0B
-AQUFADA9MRMwEQYKCZImiZPyLGQBGRYDb3JnMRkwFwYKCZImiZPyLGQBGRYJcnVi
-eS1sYW5nMQswCQYDVQQDDAJDQTAeFw0xMTA5MTkwMDE4MTBaFw0xMTA5MTkwMDQ4
-MTBaMEQxEzARBgoJkiaJk/IsZAEZFgNvcmcxGTAXBgoJkiaJk/IsZAEZFglydWJ5
-LWxhbmcxEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAy8LEsNRApz7U/j5DoB4XBgO9Z8Atv5y/OVQRp0ag8Tqo1YewsWijxEWB
-7JOATwpBN267U4T1nPZIxxEEO7n/WNa2ws9JWsjah8ssEBFSxZqdXKSLf0N4Hi7/
-GQ/aYoaMCiQ8jA4jegK2FJmXM71uPe+jFN/peeBOpRfyXxRFOYcCAwEAAaMSMBAw
-DgYDVR0PAQH/BAQDAgWgMA0GCSqGSIb3DQEBBQUAA4IBAQARC7GP7InX1t7VEXz2
-I8RI57S0/HSJL4fDIYP3zFpitHX1PZeo+7XuzMilvPjjBo/ky9Jzo8TYiY+N+JEz
-mY/A/zPA4ZsJ7KYj6/FEdIc/vRlS0CvsbClbNjw1jl/PoB2FLr2b3uuBcZEsyZeP
-yq154ijq37Ajf8K5Mi5FgshoP41BPtRPj+VVf61rv1IcEnNWdDCS6DR4XsaNC+zt
-G6AqCqkytIXWRuDw6n6vYLF3A/tn2sldLo7/scY0PMDNbo63O/LTxkDHmPhSkD68
-8m9SsMeTR+RCiDEZWFPVcAH/8mDfi+5k8uN3qS+gOU/PPrmHGgl5ykiSFgqs4v61
-tddwpBAEDjcwMzA5NTYzMTU1MzAwpQMCARM=
------END SSL SESSION PARAMETERS-----
- SESSION
-
- start_server(ignore_listener_error: true) { |_, port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT
- ctx.session_id_context = self.object_id.to_s
-
- sock = TCPSocket.new '127.0.0.1', port
- begin
- ssl = OpenSSL::SSL::SSLSocket.new sock, ctx
- ssl.session = session
-
- assert_equal session, ssl.session
- ensure
- sock.close
- end
- }
- end
+if defined?(OpenSSL)
+class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase
def test_session
- Timeout.timeout(5) do
- start_server do |server, port|
- sock = TCPSocket.new("127.0.0.1", port)
- ctx = OpenSSL::SSL::SSLContext.new
- ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
- ssl.sync_close = true
- ssl.connect
+ pend "TLS 1.2 is not supported" unless tls12_supported?
+
+ ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 }
+ start_server(ctx_proc: ctx_proc) do |port|
+ server_connect_with_session(port, nil, nil) { |ssl|
session = ssl.session
assert(session == OpenSSL::SSL::Session.new(session.to_pem))
assert(session == OpenSSL::SSL::Session.new(ssl))
@@ -66,8 +26,7 @@ tddwpBAEDjcwMzA5NTYzMTU1MzAwpQMCARM=
pem.gsub!(/-----(BEGIN|END) SSL SESSION PARAMETERS-----/, '').gsub!(/[\r\n]+/m, '')
assert_equal(session.to_der, pem.unpack('m*')[0])
assert_not_nil(session.to_text)
- ssl.close
- end
+ }
end
end
@@ -150,220 +109,243 @@ __EOS__
assert(OpenSSL::SSL::Session.new(DUMMY_SESSION))
end
- def test_client_session
- last_session = nil
- start_server do |server, port|
- 2.times do
- sock = TCPSocket.new("127.0.0.1", port)
- ctx = OpenSSL::SSL::SSLContext.new
- ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
- ssl.sync_close = true
- ssl.session = last_session if last_session
- ssl.connect
+ def test_resumption
+ non_resumable = nil
+ start_server { |port|
+ server_connect_with_session(port, nil, nil) { |ssl|
+ non_resumable = ssl.session
+ }
+ }
- session = ssl.session
- if last_session
- assert(ssl.session_reused?)
- assert_equal(session.id, last_session.id)
- assert_equal(session.to_pem, last_session.to_pem)
- assert_equal(session.to_der, last_session.to_der)
- # Older version of OpenSSL may not be consistent. Look up which versions later.
- assert_equal(session.to_text, last_session.to_text)
- else
- assert(!ssl.session_reused?)
- end
- last_session = session
+ ctx_proc = proc { |ctx|
+ ctx.options &= ~OpenSSL::SSL::OP_NO_TICKET
+ # Disable server-side session cache which is enabled by default
+ ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_OFF
+ }
+ start_server(ctx_proc: ctx_proc) do |port|
+ sess1 = server_connect_with_session(port, nil, nil) { |ssl|
+ ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+ assert_equal false, ssl.session_reused?
+ ssl.session
+ }
- str = "x" * 100 + "\n"
- ssl.puts(str)
- assert_equal(str, ssl.gets)
+ server_connect_with_session(port, nil, non_resumable) { |ssl|
+ ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+ assert_equal false, ssl.session_reused?
+ }
- ssl.close
- end
+ server_connect_with_session(port, nil, sess1) { |ssl|
+ ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+ assert_equal true, ssl.session_reused?
+ }
end
end
- def test_server_session
- connections = 0
- saved_session = nil
+ def test_server_session_cache
+ pend "TLS 1.2 is not supported" unless tls12_supported?
- ctx_proc = Proc.new do |ctx, ssl|
-# add test for session callbacks here
+ ctx_proc = Proc.new do |ctx|
+ ctx.ssl_version = :TLSv1_2
+ ctx.options |= OpenSSL::SSL::OP_NO_TICKET
end
+ connections = nil
+ saved_session = nil
server_proc = Proc.new do |ctx, ssl|
- session = ssl.session
stats = ctx.session_cache_stats
case connections
when 0
- assert_equal(stats[:cache_num], 1)
- assert_equal(stats[:cache_hits], 0)
- assert_equal(stats[:cache_misses], 0)
- assert(!ssl.session_reused?)
+ assert_equal false, ssl.session_reused?
+ assert_equal 1, stats[:cache_num]
+ assert_equal 0, stats[:cache_hits]
+ assert_equal 0, stats[:cache_misses]
when 1
- assert_equal(stats[:cache_num], 1)
- assert_equal(stats[:cache_hits], 1)
- assert_equal(stats[:cache_misses], 0)
- assert(ssl.session_reused?)
- ctx.session_remove(session)
- saved_session = session.to_der
+ assert_equal true, ssl.session_reused?
+ assert_equal 1, stats[:cache_num]
+ assert_equal 1, stats[:cache_hits]
+ assert_equal 0, stats[:cache_misses]
+
+ saved_session = ssl.session
+ assert_equal true, ctx.session_remove(ssl.session)
when 2
- assert_equal(stats[:cache_num], 1)
- assert_equal(stats[:cache_hits], 1)
- assert_equal(stats[:cache_misses], 1)
- assert(!ssl.session_reused?)
- ctx.session_add(OpenSSL::SSL::Session.new(saved_session))
+ assert_equal false, ssl.session_reused?
+ assert_equal 1, stats[:cache_num]
+ assert_equal 1, stats[:cache_hits]
+ assert_equal 1, stats[:cache_misses]
+
+ assert_equal true, ctx.session_add(saved_session.dup)
when 3
- assert_equal(stats[:cache_num], 2)
- assert_equal(stats[:cache_hits], 2)
- assert_equal(stats[:cache_misses], 1)
- assert(ssl.session_reused?)
+ assert_equal true, ssl.session_reused?
+ assert_equal 2, stats[:cache_num]
+ assert_equal 2, stats[:cache_hits]
+ assert_equal 1, stats[:cache_misses]
+
ctx.flush_sessions(Time.now + 10000)
when 4
- assert_equal(stats[:cache_num], 1)
- assert_equal(stats[:cache_hits], 2)
- assert_equal(stats[:cache_misses], 2)
- assert(!ssl.session_reused?)
- ctx.session_add(OpenSSL::SSL::Session.new(saved_session))
+ assert_equal false, ssl.session_reused?
+ assert_equal 1, stats[:cache_num]
+ assert_equal 2, stats[:cache_hits]
+ assert_equal 2, stats[:cache_misses]
+
+ assert_equal true, ctx.session_add(saved_session.dup)
end
- connections += 1
readwrite_loop(ctx, ssl)
end
- first_session = nil
- start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |server, port|
+ start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |port|
+ first_session = nil
10.times do |i|
- sock = TCPSocket.new("127.0.0.1", port)
- ctx = OpenSSL::SSL::SSLContext.new
- # disable RFC4507 support
- ctx.options = OpenSSL::SSL::OP_NO_TICKET
- ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
- ssl.sync_close = true
- ssl.session = first_session if first_session
- ssl.connect
-
- session = ssl.session
- if first_session
- case i
- when 1; assert(ssl.session_reused?)
- when 2; assert(!ssl.session_reused?)
- when 3; assert(ssl.session_reused?)
- when 4; assert(!ssl.session_reused?)
- when 5..10; assert(ssl.session_reused?)
+ connections = i
+ server_connect_with_session(port, nil, first_session) { |ssl|
+ ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+ first_session ||= ssl.session
+
+ case connections
+ when 0;
+ when 1; assert_equal true, ssl.session_reused?
+ when 2; assert_equal false, ssl.session_reused?
+ when 3; assert_equal true, ssl.session_reused?
+ when 4; assert_equal false, ssl.session_reused?
+ when 5..9; assert_equal true, ssl.session_reused?
end
- end
- first_session ||= session
-
- str = "x" * 100 + "\n"
- ssl.puts(str)
- assert_equal(str, ssl.gets)
-
- ssl.close
+ }
end
end
end
def test_ctx_client_session_cb
- called = {}
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT
-
- ctx.session_new_cb = lambda { |ary|
- sock, sess = ary
- called[:new] = [sock, sess]
- }
+ pend "TLS 1.2 is not supported" unless tls12_supported?
- ctx.session_remove_cb = lambda { |ary|
- ctx, sess = ary
- called[:remove] = [ctx, sess]
- # any resulting value is OK (ignored)
- }
+ ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 }
+ start_server(ctx_proc: ctx_proc) do |port|
+ called = {}
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT
+ ctx.session_new_cb = lambda { |ary|
+ sock, sess = ary
+ called[:new] = [sock, sess]
+ }
+ ctx.session_remove_cb = lambda { |ary|
+ ctx, sess = ary
+ called[:remove] = [ctx, sess]
+ # any resulting value is OK (ignored)
+ }
- start_server do |server, port|
- sock = TCPSocket.new("127.0.0.1", port)
- begin
- ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
- ssl.sync_close = true
- ssl.connect
+ server_connect_with_session(port, ctx, nil) { |ssl|
assert_equal(1, ctx.session_cache_stats[:cache_num])
assert_equal(1, ctx.session_cache_stats[:connect_good])
assert_equal([ssl, ssl.session], called[:new])
assert(ctx.session_remove(ssl.session))
assert(!ctx.session_remove(ssl.session))
assert_equal([ctx, ssl.session], called[:remove])
- ssl.close
- ensure
- sock.close if !sock.closed?
- end
+ }
end
end
def test_ctx_server_session_cb
- called = {}
+ pend "TLS 1.2 is not supported" unless tls12_supported?
- ctx_proc = Proc.new { |ctx, ssl|
- ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_SERVER
- ctx.options = OpenSSL::SSL::OP_NO_TICKET
- last_server_session = nil
+ connections = nil
+ called = {}
+ sctx = nil
+ ctx_proc = Proc.new { |ctx|
+ sctx = ctx
+ ctx.ssl_version = :TLSv1_2
+ ctx.options |= OpenSSL::SSL::OP_NO_TICKET
# get_cb is called whenever a client proposed to resume a session but
# the session could not be found in the internal session cache.
+ last_server_session = nil
ctx.session_get_cb = lambda { |ary|
- sess, data = ary
- if last_server_session
- called[:get2] = [sess, data]
- last_server_session
+ _sess, data = ary
+ called[:get] = data
+
+ if connections == 2
+ last_server_session.dup
else
- called[:get1] = [sess, data]
- last_server_session = sess
nil
end
}
ctx.session_new_cb = lambda { |ary|
- sock, sess = ary
- called[:new] = [sock, sess]
- # SSL server doesn't cache sessions so get_cb is called next time.
- ctx.session_remove(sess)
+ _sock, sess = ary
+ called[:new] = sess
+ last_server_session = sess
}
ctx.session_remove_cb = lambda { |ary|
- ctx, sess = ary
- called[:remove] = [ctx, sess]
+ _ctx, sess = ary
+ called[:remove] = sess
}
}
-
- server_proc = Proc.new { |c, ssl|
- ssl.session
- c.session_cache_stats
- readwrite_loop(c, ssl)
- }
- start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |server, port|
- last_client_session = nil
- 3.times do
- sock = TCPSocket.new("127.0.0.1", port)
- begin
- ssl = OpenSSL::SSL::SSLSocket.new(sock, OpenSSL::SSL::SSLContext.new())
- ssl.sync_close = true
- ssl.session = last_client_session if last_client_session
- ssl.connect
- last_client_session = ssl.session
- ssl.close
- Timeout.timeout(5) do
- Thread.pass until called.key?(:new)
- assert(called.delete(:new))
- Thread.pass until called.key?(:remove)
- assert(called.delete(:remove))
- end
- ensure
- sock.close if !sock.closed?
+ start_server(ctx_proc: ctx_proc) do |port|
+ connections = 0
+ sess0 = server_connect_with_session(port, nil, nil) { |ssl|
+ ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+ assert_equal false, ssl.session_reused?
+ ssl.session
+ }
+ assert_nil called[:get]
+ assert_not_nil called[:new]
+ assert_equal sess0.id, called[:new].id
+ assert_nil called[:remove]
+ called.clear
+
+ # Internal cache hit
+ connections = 1
+ server_connect_with_session(port, nil, sess0.dup) { |ssl|
+ ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+ assert_equal true, ssl.session_reused?
+ ssl.session
+ }
+ assert_nil called[:get]
+ assert_nil called[:new]
+ assert_nil called[:remove]
+ called.clear
+
+ sctx.flush_sessions(Time.now + 10000)
+ assert_not_nil called[:remove]
+ assert_equal sess0.id, called[:remove].id
+ called.clear
+
+ # External cache hit
+ connections = 2
+ sess2 = server_connect_with_session(port, nil, sess0.dup) { |ssl|
+ ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+ if !ssl.session_reused? && openssl?(1, 1, 0) && !openssl?(1, 1, 0, 7)
+ # OpenSSL >= 1.1.0, < 1.1.0g
+ pend "External session cache is not working; " \
+ "see https://github.com/openssl/openssl/pull/4014"
end
- end
+ assert_equal true, ssl.session_reused?
+ ssl.session
+ }
+ assert_equal sess0.id, sess2.id
+ assert_equal sess0.id, called[:get]
+ assert_nil called[:new]
+ assert_nil called[:remove]
+ called.clear
+
+ sctx.flush_sessions(Time.now + 10000)
+ assert_not_nil called[:remove]
+ assert_equal sess0.id, called[:remove].id
+ called.clear
+
+ # Cache miss
+ connections = 3
+ sess3 = server_connect_with_session(port, nil, sess0.dup) { |ssl|
+ ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+ assert_equal false, ssl.session_reused?
+ ssl.session
+ }
+ assert_not_equal sess0.id, sess3.id
+ assert_equal sess0.id, called[:get]
+ assert_not_nil called[:new]
+ assert_equal sess3.id, called[:new].id
+ assert_nil called[:remove]
end
- assert(called[:get1])
- assert(called[:get2])
end
def test_dup
@@ -371,4 +353,21 @@ __EOS__
sess_dup = sess_orig.dup
assert_equal(sess_orig.to_der, sess_dup.to_der)
end
+
+ private
+
+ def server_connect_with_session(port, ctx = nil, sess = nil)
+ sock = TCPSocket.new("127.0.0.1", port)
+ ctx ||= OpenSSL::SSL::SSLContext.new
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ ssl.session = sess if sess
+ ssl.sync_close = true
+ ssl.connect
+ yield ssl if block_given?
+ ensure
+ ssl&.close
+ sock&.close
+ end
+end
+
end
diff --git a/test/test_x509attr.rb b/test/test_x509attr.rb
index 249c1593..108162f4 100644
--- a/test/test_x509attr.rb
+++ b/test/test_x509attr.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative "utils"
+if defined?(OpenSSL)
+
class OpenSSL::TestX509Attribute < OpenSSL::TestCase
def test_new
ef = OpenSSL::X509::ExtensionFactory.new
@@ -61,3 +63,5 @@ class OpenSSL::TestX509Attribute < OpenSSL::TestCase
assert_equal(attr.to_der, attr.dup.to_der)
end
end
+
+end
diff --git a/test/test_x509cert.rb b/test/test_x509cert.rb
index 5a992119..289994d1 100644
--- a/test/test_x509cert.rb
+++ b/test/test_x509cert.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative "utils"
+if defined?(OpenSSL)
+
class OpenSSL::TestX509Certificate < OpenSSL::TestCase
def setup
super
@@ -175,3 +177,5 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
false
end
end
+
+end
diff --git a/test/test_x509crl.rb b/test/test_x509crl.rb
index fd7b562a..1914a651 100644
--- a/test/test_x509crl.rb
+++ b/test/test_x509crl.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative "utils"
+if defined?(OpenSSL)
+
class OpenSSL::TestX509CRL < OpenSSL::TestCase
def setup
super
@@ -203,3 +205,5 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
false
end
end
+
+end
diff --git a/test/test_x509ext.rb b/test/test_x509ext.rb
index d9cde1bd..f384a25e 100644
--- a/test/test_x509ext.rb
+++ b/test/test_x509ext.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative 'utils'
+if defined?(OpenSSL)
+
class OpenSSL::TestX509Extension < OpenSSL::TestCase
def setup
super
@@ -74,3 +76,5 @@ class OpenSSL::TestX509Extension < OpenSSL::TestCase
assert_equal(ext.to_der, ext.dup.to_der)
end
end
+
+end
diff --git a/test/test_x509name.rb b/test/test_x509name.rb
index b2196628..2f77f20b 100644
--- a/test/test_x509name.rb
+++ b/test/test_x509name.rb
@@ -2,6 +2,8 @@
# frozen_string_literal: false
require_relative 'utils'
+if defined?(OpenSSL)
+
class OpenSSL::TestX509Name < OpenSSL::TestCase
def setup
super
@@ -403,3 +405,5 @@ class OpenSSL::TestX509Name < OpenSSL::TestCase
assert_equal(name.to_der, name.dup.to_der)
end
end
+
+end
diff --git a/test/test_x509req.rb b/test/test_x509req.rb
index 88156220..a21d45da 100644
--- a/test/test_x509req.rb
+++ b/test/test_x509req.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative "utils"
+if defined?(OpenSSL)
+
class OpenSSL::TestX509Request < OpenSSL::TestCase
def setup
super
@@ -147,3 +149,5 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
false
end
end
+
+end
diff --git a/test/test_x509store.rb b/test/test_x509store.rb
index 0009813d..6412249b 100644
--- a/test/test_x509store.rb
+++ b/test/test_x509store.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require_relative "utils"
+if defined?(OpenSSL)
+
class OpenSSL::TestX509Store < OpenSSL::TestCase
def setup
super
@@ -207,7 +209,7 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase
end
def test_set_errors
- return if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000
+ return if openssl?(1, 1, 0) || libressl?
now = Time.now
ca1_cert = issue_cert(@ca1, @rsa2048, 1, [], nil, nil)
store = OpenSSL::X509::Store.new
@@ -235,3 +237,5 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase
assert_raise(NoMethodError) { ctx.dup }
end
end
+
+end
diff --git a/test/ut_eof.rb b/test/ut_eof.rb
index 6de41c4a..bd62fd50 100644
--- a/test/ut_eof.rb
+++ b/test/ut_eof.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require 'test/unit'
+if defined?(OpenSSL)
+
module OpenSSL::TestEOF
def test_eof_0
open_file("") {|f|
@@ -127,3 +129,5 @@ module OpenSSL::TestEOF
end
end
end
+
+end
diff --git a/test/utils.rb b/test/utils.rb
index 54f75f25..a5dd38c2 100644
--- a/test/utils.rb
+++ b/test/utils.rb
@@ -30,11 +30,12 @@ if ENV["OSSL_MDEBUG"] == "1"
end
require "test/unit"
-require 'tempfile'
-require "rbconfig"
+require "tempfile"
require "socket"
require "envutil"
+if defined?(OpenSSL)
+
module OpenSSL::TestUtils
module Fixtures
module_function
@@ -117,183 +118,188 @@ module OpenSSL::TestUtils
OpenSSL::Digest::SHA1.hexdigest(pkvalue).scan(/../).join(":").upcase
end
- def silent
- begin
- back, $VERBOSE = $VERBOSE, nil
- yield
- ensure
- $VERBOSE = back
- end
+ def openssl?(major = nil, minor = nil, fix = nil, patch = 0)
+ return false if OpenSSL::OPENSSL_VERSION.include?("LibreSSL")
+ return true unless major
+ OpenSSL::OPENSSL_VERSION_NUMBER >=
+ major * 0x10000000 + minor * 0x100000 + fix * 0x1000 + patch * 0x10
end
- class OpenSSL::TestCase < Test::Unit::TestCase
- include OpenSSL::TestUtils
- extend OpenSSL::TestUtils
+ def libressl?(major = nil, minor = nil, fix = nil)
+ version = OpenSSL::OPENSSL_VERSION.scan(/LibreSSL (\d+)\.(\d+)\.(\d+).*/)[0]
+ return false unless version
+ !major || (version.map(&:to_i) <=> [major, minor, fix]) >= 0
+ end
+end
- def setup
- if ENV["OSSL_GC_STRESS"] == "1"
- GC.stress = true
- end
- end
+class OpenSSL::TestCase < Test::Unit::TestCase
+ include OpenSSL::TestUtils
+ extend OpenSSL::TestUtils
- def teardown
- if ENV["OSSL_GC_STRESS"] == "1"
- GC.stress = false
- end
- # OpenSSL error stack must be empty
- assert_equal([], OpenSSL.errors)
+ def setup
+ if ENV["OSSL_GC_STRESS"] == "1"
+ GC.stress = true
end
end
- class OpenSSL::SSLTestCase < OpenSSL::TestCase
- RUBY = EnvUtil.rubybin
- ITERATIONS = ($0 == __FILE__) ? 100 : 10
-
- def setup
- super
- @ca_key = Fixtures.pkey("rsa2048")
- @svr_key = Fixtures.pkey("rsa1024")
- @cli_key = Fixtures.pkey("dsa1024")
- @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
- @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
- @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
- ca_exts = [
- ["basicConstraints","CA:TRUE",true],
- ["keyUsage","cRLSign,keyCertSign",true],
- ]
- ee_exts = [
- ["keyUsage","keyEncipherment,digitalSignature",true],
- ]
- @ca_cert = issue_cert(@ca, @ca_key, 1, ca_exts, nil, nil)
- @svr_cert = issue_cert(@svr, @svr_key, 2, ee_exts, @ca_cert, @ca_key)
- @cli_cert = issue_cert(@cli, @cli_key, 3, ee_exts, @ca_cert, @ca_key)
- @server = nil
+ def teardown
+ if ENV["OSSL_GC_STRESS"] == "1"
+ GC.stress = false
end
+ # OpenSSL error stack must be empty
+ assert_equal([], OpenSSL.errors)
+ end
+end
- def readwrite_loop(ctx, ssl)
- while line = ssl.gets
- ssl.write(line)
- end
- rescue OpenSSL::SSL::SSLError
- rescue IOError
- ensure
- ssl.close rescue nil
- end
+class OpenSSL::SSLTestCase < OpenSSL::TestCase
+ RUBY = EnvUtil.rubybin
+ ITERATIONS = ($0 == __FILE__) ? 100 : 10
- def server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads)
- loop do
- ssl = nil
- begin
- readable, = IO.select([ssls, stop_pipe_r])
- if readable.include? stop_pipe_r
- return
- end
- ssl = ssls.accept
- rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET
- if ignore_listener_error
- retry
- else
- raise
- end
- end
+ def setup
+ super
+ @ca_key = Fixtures.pkey("rsa2048")
+ @svr_key = Fixtures.pkey("rsa1024")
+ @cli_key = Fixtures.pkey("rsa2048")
+ @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
+ @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
+ @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
+ ca_exts = [
+ ["basicConstraints","CA:TRUE",true],
+ ["keyUsage","cRLSign,keyCertSign",true],
+ ]
+ ee_exts = [
+ ["keyUsage","keyEncipherment,digitalSignature",true],
+ ]
+ @ca_cert = issue_cert(@ca, @ca_key, 1, ca_exts, nil, nil)
+ @svr_cert = issue_cert(@svr, @svr_key, 2, ee_exts, @ca_cert, @ca_key)
+ @cli_cert = issue_cert(@cli, @cli_key, 3, ee_exts, @ca_cert, @ca_key)
+ @server = nil
+ end
- th = Thread.start do
- server_proc.call(ctx, ssl)
- end
- threads << th
- end
- rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET
- if !ignore_listener_error
- raise
- end
+ def tls12_supported?
+ OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2)
+ end
+
+ def readwrite_loop(ctx, ssl)
+ while line = ssl.gets
+ ssl.write(line)
end
+ end
- def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true,
- ctx_proc: nil, server_proc: method(:readwrite_loop),
- ignore_listener_error: false, &block)
- IO.pipe {|stop_pipe_r, stop_pipe_w|
- store = OpenSSL::X509::Store.new
- store.add_cert(@ca_cert)
- store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.cert_store = store
- ctx.cert = @svr_cert
- ctx.key = @svr_key
- ctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") }
- begin
- ctx.ecdh_curves = "P-256"
- rescue NotImplementedError
- end
- ctx.verify_mode = verify_mode
- ctx_proc.call(ctx) if ctx_proc
+ def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true,
+ ctx_proc: nil, server_proc: method(:readwrite_loop),
+ ignore_listener_error: false, &block)
+ IO.pipe {|stop_pipe_r, stop_pipe_w|
+ store = OpenSSL::X509::Store.new
+ store.add_cert(@ca_cert)
+ store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.cert_store = store
+ ctx.cert = @svr_cert
+ ctx.key = @svr_key
+ ctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") }
+ ctx.verify_mode = verify_mode
+ ctx_proc.call(ctx) if ctx_proc
+
+ Socket.do_not_reverse_lookup = true
+ tcps = TCPServer.new("127.0.0.1", 0)
+ port = tcps.connect_address.ip_port
- Socket.do_not_reverse_lookup = true
- tcps = nil
- tcps = TCPServer.new("127.0.0.1", 0)
- port = tcps.connect_address.ip_port
+ ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
+ ssls.start_immediately = start_immediately
- ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
- ssls.start_immediately = start_immediately
+ threads = []
+ begin
+ server_thread = Thread.new do
+ begin
+ loop do
+ begin
+ readable, = IO.select([ssls, stop_pipe_r])
+ break if readable.include? stop_pipe_r
+ ssl = ssls.accept
+ rescue OpenSSL::SSL::SSLError, IOError, Errno::EBADF, Errno::EINVAL,
+ Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET
+ retry if ignore_listener_error
+ raise
+ end
- threads = []
- begin
- server = Thread.new do
- begin
- server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads)
- ensure
- tcps.close
+ th = Thread.new do
+ begin
+ server_proc.call(ctx, ssl)
+ ensure
+ ssl.close
+ end
+ true
+ end
+ threads << th
end
+ ensure
+ tcps.close
end
- threads.unshift server
-
- $stderr.printf("SSL server started: pid=%d port=%d\n", $$, port) if $DEBUG
+ end
- client = Thread.new do
- begin
- block.call(server, port.to_i)
- ensure
- stop_pipe_w.close
- end
+ client_thread = Thread.new do
+ begin
+ block.call(port)
+ ensure
+ # Stop accepting new connection
+ stop_pipe_w.close
+ server_thread.join
end
- threads.unshift client
- ensure
- assert_join_threads(threads)
end
- }
- end
+ threads.unshift client_thread
+ ensure
+ # Terminate existing connections. If a thread did 'pend', re-raise it.
+ pend = nil
+ threads.each { |th|
+ begin
+ th.join(10) or
+ th.raise(RuntimeError, "[start_server] thread did not exit in 10 secs")
+ rescue (defined?(MiniTest::Skip) ? MiniTest::Skip : Test::Unit::PendedError)
+ # MiniTest::Skip is for the Ruby tree
+ pend = $!
+ rescue Exception
+ end
+ }
+ raise pend if pend
+ assert_join_threads(threads)
+ end
+ }
end
+end
- class OpenSSL::PKeyTestCase < OpenSSL::TestCase
- def check_component(base, test, keys)
- keys.each { |comp|
- assert_equal base.send(comp), test.send(comp)
- }
- end
+class OpenSSL::PKeyTestCase < OpenSSL::TestCase
+ def check_component(base, test, keys)
+ keys.each { |comp|
+ assert_equal base.send(comp), test.send(comp)
+ }
+ end
- def dup_public(key)
- case key
- when OpenSSL::PKey::RSA
- rsa = OpenSSL::PKey::RSA.new
- rsa.set_key(key.n, key.e, nil)
- rsa
- when OpenSSL::PKey::DSA
- dsa = OpenSSL::PKey::DSA.new
- dsa.set_pqg(key.p, key.q, key.g)
- dsa.set_key(key.pub_key, nil)
- dsa
- when OpenSSL::PKey::DH
- dh = OpenSSL::PKey::DH.new
- dh.set_pqg(key.p, nil, key.g)
- dh
+ def dup_public(key)
+ case key
+ when OpenSSL::PKey::RSA
+ rsa = OpenSSL::PKey::RSA.new
+ rsa.set_key(key.n, key.e, nil)
+ rsa
+ when OpenSSL::PKey::DSA
+ dsa = OpenSSL::PKey::DSA.new
+ dsa.set_pqg(key.p, key.q, key.g)
+ dsa.set_key(key.pub_key, nil)
+ dsa
+ when OpenSSL::PKey::DH
+ dh = OpenSSL::PKey::DH.new
+ dh.set_pqg(key.p, nil, key.g)
+ dh
+ else
+ if defined?(OpenSSL::PKey::EC) && OpenSSL::PKey::EC === key
+ ec = OpenSSL::PKey::EC.new(key.group)
+ ec.public_key = key.public_key
+ ec
else
- if defined?(OpenSSL::PKey::EC) && OpenSSL::PKey::EC === key
- ec = OpenSSL::PKey::EC.new(key.group)
- ec.public_key = key.public_key
- ec
- else
- raise "unknown key type"
- end
+ raise "unknown key type"
end
end
end
end
+
+end