ruby-changes:20147
From: nahi <ko1@a...>
Date: Wed, 22 Jun 2011 12:40:25 +0900 (JST)
Subject: [ruby-changes:20147] nahi:r32195 (trunk): * test/openssl/test_ssl_session.rb: Split out SSL::Session related
nahi 2011-06-22 12:40:08 +0900 (Wed, 22 Jun 2011) New Revision: 32195 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=32195 Log: * test/openssl/test_ssl_session.rb: Split out SSL::Session related tests from test_ssl.rb Added files: trunk/test/openssl/test_ssl_session.rb Modified files: trunk/ChangeLog trunk/test/openssl/test_ssl.rb trunk/test/openssl/utils.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 32194) +++ ChangeLog (revision 32195) @@ -1,3 +1,8 @@ +Wed Jun 22 12:38:52 2011 Hiroshi Nakamura <nahi@r...> + + * test/openssl/test_ssl_session.rb: Split out SSL::Session related + tests from test_ssl.rb + Wed Jun 22 03:20:52 2011 Aaron Patterson <aaron@t...> * ext/psych/lib/psych/visitors/to_ruby.rb: Fix cyclic references of Index: test/openssl/utils.rb =================================================================== --- test/openssl/utils.rb (revision 32194) +++ test/openssl/utils.rb (revision 32195) @@ -168,4 +168,146 @@ $VERBOSE = back end end + + class OpenSSL::SSLTestCase < Test::Unit::TestCase + RUBY = EnvUtil.rubybin + SSL_SERVER = File.join(File.dirname(__FILE__), "ssl_server.rb") + PORT = 20443 + ITERATIONS = ($0 == __FILE__) ? 100 : 10 + + def setup + @ca_key = OpenSSL::TestUtils::TEST_KEY_RSA2048 + @svr_key = OpenSSL::TestUtils::TEST_KEY_RSA1024 + @cli_key = OpenSSL::TestUtils::TEST_KEY_DSA256 + @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") + now = Time.at(Time.now.to_i) + ca_exts = [ + ["basicConstraints","CA:TRUE",true], + ["keyUsage","cRLSign,keyCertSign",true], + ] + ee_exts = [ + ["keyUsage","keyEncipherment,digitalSignature",true], + ] + @ca_cert = issue_cert(@ca, @ca_key, 1, now, now+3600, ca_exts, nil, nil, OpenSSL::Digest::SHA1.new) + @svr_cert = issue_cert(@svr, @svr_key, 2, now, now+1800, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new) + @cli_cert = issue_cert(@cli, @cli_key, 3, now, now+1800, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new) + @server = nil + end + + def teardown + end + + def issue_cert(*arg) + OpenSSL::TestUtils.issue_cert(*arg) + end + + def issue_crl(*arg) + OpenSSL::TestUtils.issue_crl(*arg) + end + + def readwrite_loop(ctx, ssl) + while line = ssl.gets + if line =~ /^STARTTLS$/ + ssl.accept + next + end + ssl.write(line) + end + rescue OpenSSL::SSL::SSLError + rescue IOError + ensure + ssl.close rescue nil + end + + def server_loop(ctx, ssls, server_proc) + loop do + ssl = nil + begin + ssl = ssls.accept + rescue OpenSSL::SSL::SSLError + retry + end + + Thread.start do + Thread.current.abort_on_exception = true + server_proc.call(ctx, ssl) + end + end + rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK + end + + DHParam = OpenSSL::PKey::DH.new(128) + def start_server(port0, verify_mode, start_immediately, args = {}, &block) + ctx_proc = args[:ctx_proc] + server_proc = args[:server_proc] + server_proc ||= method(:readwrite_loop) + + 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.extra_chain_cert = [ ca_cert ] + ctx.cert = @svr_cert + ctx.key = @svr_key + ctx.tmp_dh_callback = proc { DHParam } + ctx.verify_mode = verify_mode + ctx_proc.call(ctx) if ctx_proc + + Socket.do_not_reverse_lookup = true + tcps = nil + port = port0 + begin + tcps = TCPServer.new("127.0.0.1", port) + rescue Errno::EADDRINUSE + port += 1 + retry + end + + ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx) + ssls.start_immediately = start_immediately + + begin + server = Thread.new do + Thread.current.abort_on_exception = true + server_loop(ctx, ssls, server_proc) + end + + $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, pid, port) if $DEBUG + + block.call(server, port.to_i) + ensure + begin + begin + tcps.shutdown + rescue Errno::ENOTCONN + # when `Errno::ENOTCONN: Socket is not connected' on some platforms, + # call #close instead of #shutdown. + tcps.close + tcps = nil + end if (tcps) + if (server) + server.join(5) + if server.alive? + server.kill + server.join + flunk("TCPServer was closed and SSLServer is still alive") unless $! + end + end + ensure + tcps.close if (tcps) + end + end + end + + def starttls(ssl) + ssl.puts("STARTTLS") + sleep 1 # When this line is eliminated, process on Cygwin blocks + # forever at ssl.connect. But I don't know why it does. + ssl.connect + end + end + end if defined?(OpenSSL) Index: test/openssl/test_ssl.rb =================================================================== --- test/openssl/test_ssl.rb (revision 32194) +++ test/openssl/test_ssl.rb (revision 32195) @@ -2,152 +2,7 @@ if defined?(OpenSSL) -class OpenSSL::TestSSL < Test::Unit::TestCase - RUBY = EnvUtil.rubybin - SSL_SERVER = File.join(File.dirname(__FILE__), "ssl_server.rb") - PORT = 20443 - ITERATIONS = ($0 == __FILE__) ? 100 : 10 - - def setup - @ca_key = OpenSSL::TestUtils::TEST_KEY_RSA2048 - @svr_key = OpenSSL::TestUtils::TEST_KEY_RSA1024 - @cli_key = OpenSSL::TestUtils::TEST_KEY_DSA256 - @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") - - now = Time.at(Time.now.to_i) - ca_exts = [ - ["basicConstraints","CA:TRUE",true], - ["keyUsage","cRLSign,keyCertSign",true], - ] - ee_exts = [ - ["keyUsage","keyEncipherment,digitalSignature",true], - ] - @ca_cert = issue_cert(@ca, @ca_key, 1, now, now+3600, ca_exts, - nil, nil, OpenSSL::Digest::SHA1.new) - @svr_cert = issue_cert(@svr, @svr_key, 2, now, now+1800, ee_exts, - @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new) - @cli_cert = issue_cert(@cli, @cli_key, 3, now, now+1800, ee_exts, - @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new) - @server = nil - end - - def teardown - end - - def issue_cert(*arg) - OpenSSL::TestUtils.issue_cert(*arg) - end - - def issue_crl(*arg) - OpenSSL::TestUtils.issue_crl(*arg) - end - - def readwrite_loop(ctx, ssl) - while line = ssl.gets - if line =~ /^STARTTLS$/ - ssl.accept - next - end - ssl.write(line) - end - rescue OpenSSL::SSL::SSLError - rescue IOError - ensure - ssl.close rescue nil - end - - def server_loop(ctx, ssls, server_proc) - loop do - ssl = nil - begin - ssl = ssls.accept - rescue OpenSSL::SSL::SSLError - retry - end - - Thread.start do - Thread.current.abort_on_exception = true - server_proc.call(ctx, ssl) - end - end - rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK - end - - DHParam = OpenSSL::PKey::DH.new(128) - def start_server(port0, verify_mode, start_immediately, args = {}, &block) - ctx_proc = args[:ctx_proc] - server_proc = args[:server_proc] - server_proc ||= method(:readwrite_loop) - - 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.extra_chain_cert = [ ca_cert ] - ctx.cert = @svr_cert - ctx.key = @svr_key - ctx.tmp_dh_callback = proc { DHParam } - ctx.verify_mode = verify_mode - ctx_proc.call(ctx) if ctx_proc - - Socket.do_not_reverse_lookup = true - tcps = nil - port = port0 - begin - tcps = TCPServer.new("127.0.0.1", port) - rescue Errno::EADDRINUSE - port += 1 - retry - end - - ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx) - ssls.start_immediately = start_immediately - - begin - server = Thread.new do - Thread.current.abort_on_exception = true - server_loop(ctx, ssls, server_proc) - end - - $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, pid, port) if $DEBUG - - block.call(server, port.to_i) - ensure - begin - begin - tcps.shutdown - rescue Errno::ENOTCONN - # when `Errno::ENOTCONN: Socket is not connected' on some platforms, - # call #close instead of #shutdown. - tcps.close - tcps = nil - end if (tcps) - if (server) - server.join(5) - if server.alive? - server.kill - server.join - flunk("TCPServer was closed and SSLServer is still alive") unless $! - end - end - ensure - tcps.close if (tcps) - end - end - end - - def starttls(ssl) - ssl.puts("STARTTLS") - - sleep 1 # When this line is eliminated, process on Cygwin blocks - # forever at ssl.connect. But I don't know why it does. - - ssl.connect - end - +class OpenSSL::TestSSL < OpenSSL::SSLTestCase def test_ctx_setup ctx = OpenSSL::SSL::SSLContext.new assert_equal(ctx.setup, true) @@ -445,128 +300,6 @@ } end - def test_client_session - last_session = nil - start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port| - 2.times do - sock = TCPSocket.new("127.0.0.1", port) - # Debian's openssl 0.9.8g-13 failed at assert(ssl.session_reused?), - # when use default SSLContext. [ruby-dev:36167] - ctx = OpenSSL::SSL::SSLContext.new("TLSv1") - ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) - ssl.sync_close = true - ssl.session = last_session if last_session - ssl.connect - - session = ssl.session - if last_session - assert(ssl.session_reused?) - - if session.respond_to?(:id) - assert_equal(session.id, last_session.id) - end - 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 - - str = "x" * 100 + "\n" - ssl.puts(str) - assert_equal(str, ssl.gets) - - ssl.close - end - end - end - - def test_server_session - connections = 0 - saved_session = nil - - ctx_proc = Proc.new do |ctx, ssl| -# add test for session callbacks here - end - - 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?) - 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 - 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(saved_session) - when 3 - assert_equal(stats[:cache_num], 2) - assert_equal(stats[:cache_hits], 2) - assert_equal(stats[:cache_misses], 1) - assert(ssl.session_reused?) - ctx.flush_sessions(Time.now + 5000) - 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(saved_session) - end - connections += 1 - - readwrite_loop(ctx, ssl) - end - - first_session = nil - start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port| - 10.times do |i| - sock = TCPSocket.new("127.0.0.1", port) - ctx = OpenSSL::SSL::SSLContext.new - if defined?(OpenSSL::SSL::OP_NO_TICKET) - # disable RFC4507 support - ctx.options = OpenSSL::SSL::OP_NO_TICKET - end - 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?) - end - end - first_session ||= session - - str = "x" * 100 + "\n" - ssl.puts(str) - assert_equal(str, ssl.gets) - - ssl.close - end - end - end - def test_tlsext_hostname return unless OpenSSL::SSL::SSLSocket.instance_methods.include?(:hostname) Index: test/openssl/test_ssl_session.rb =================================================================== --- test/openssl/test_ssl_session.rb (revision 0) +++ test/openssl/test_ssl_session.rb (revision 32195) @@ -0,0 +1,129 @@ +require_relative "utils" + +if defined?(OpenSSL) + +class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase + def test_client_session + last_session = nil + start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port| + 2.times do + sock = TCPSocket.new("127.0.0.1", port) + # Debian's openssl 0.9.8g-13 failed at assert(ssl.session_reused?), + # when use default SSLContext. [ruby-dev:36167] + ctx = OpenSSL::SSL::SSLContext.new("TLSv1") + ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) + ssl.sync_close = true + ssl.session = last_session if last_session + ssl.connect + + session = ssl.session + if last_session + assert(ssl.session_reused?) + + if session.respond_to?(:id) + assert_equal(session.id, last_session.id) + end + 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 + + str = "x" * 100 + "\n" + ssl.puts(str) + assert_equal(str, ssl.gets) + + ssl.close + end + end + end + + def test_server_session + connections = 0 + saved_session = nil + + ctx_proc = Proc.new do |ctx, ssl| +# add test for session callbacks here + end + + 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?) + 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 + 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(saved_session) + when 3 + assert_equal(stats[:cache_num], 2) + assert_equal(stats[:cache_hits], 2) + assert_equal(stats[:cache_misses], 1) + assert(ssl.session_reused?) + ctx.flush_sessions(Time.now + 5000) + 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(saved_session) + end + connections += 1 + + readwrite_loop(ctx, ssl) + end + + first_session = nil + start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port| + 10.times do |i| + sock = TCPSocket.new("127.0.0.1", port) + ctx = OpenSSL::SSL::SSLContext.new + if defined?(OpenSSL::SSL::OP_NO_TICKET) + # disable RFC4507 support + ctx.options = OpenSSL::SSL::OP_NO_TICKET + end + 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?) + end + end + first_session ||= session + + str = "x" * 100 + "\n" + ssl.puts(str) + assert_equal(str, ssl.gets) + + ssl.close + end + end + end +end + +end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/