Skip to content

Commit ec7b8e7

Browse files
committed
[test] include start_server from 2.3 + setup tests as in MRI's repo
1 parent c1901f2 commit ec7b8e7

File tree

4 files changed

+172
-18
lines changed

4 files changed

+172
-18
lines changed

src/test/ruby/ssl/test_helper.rb

Lines changed: 117 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,40 @@ def setup; require 'openssl'
2929
@server = nil
3030
end
3131

32-
def start_server(port0, verify_mode, start_immediately, args = {}, &block)
33-
require 'socket'
32+
private
3433

34+
# threads should respond to shift method.
35+
# Array can be used.
36+
def assert_join_threads(threads, message = nil)
37+
errs = []; values = []
38+
while th = threads.shift
39+
begin
40+
values << th.value
41+
rescue Exception
42+
errs << [th, $!]
43+
end
44+
end
45+
unless errs.empty?
46+
msg = "exceptions on #{errs.length} threads:\n" +
47+
errs.map {|t, err|
48+
"#{t.inspect}:\n" +
49+
err.backtrace.map.with_index {|line, i|
50+
if i == 0
51+
"#{line}: #{err.message} (#{err.class})"
52+
else
53+
"\tfrom #{line}"
54+
end
55+
}.join("\n")
56+
}.join("\n---\n")
57+
msg = "#{message}\n#{msg}" if message
58+
fail msg # raise MiniTest::Assertion, msg
59+
end
60+
values
61+
end
62+
63+
protected
64+
65+
def start_server0(port0, verify_mode, start_immediately, args = {}, &block); require 'socket'
3566
ctx_proc = args[:ctx_proc]
3667
server_proc = args[:server_proc]
3768
server_proc ||= method(:readwrite_loop)
@@ -64,7 +95,7 @@ def start_server(port0, verify_mode, start_immediately, args = {}, &block)
6495
begin
6596
server = Thread.new do
6697
Thread.current.abort_on_exception = true
67-
server_loop(context, ssls, server_proc)
98+
server_loop0(context, ssls, server_proc)
6899
end
69100

70101
$stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, $$, port) #if $DEBUG
@@ -75,6 +106,63 @@ def start_server(port0, verify_mode, start_immediately, args = {}, &block)
75106
end
76107
end
77108

109+
def start_server(verify_mode, start_immediately, args = {}, &block); require 'socket'
110+
IO.pipe do |stop_pipe_r, stop_pipe_w|
111+
ctx_proc = args[:ctx_proc]
112+
server_proc = args[:server_proc]
113+
ignore_listener_error = args.fetch(:ignore_listener_error, false)
114+
use_anon_cipher = args.fetch(:use_anon_cipher, false)
115+
server_proc ||= method(:readwrite_loop)
116+
117+
store = OpenSSL::X509::Store.new
118+
store.add_cert(@ca_cert)
119+
store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
120+
ctx = OpenSSL::SSL::SSLContext.new
121+
ctx.ciphers = "ADH-AES256-GCM-SHA384" if use_anon_cipher
122+
ctx.cert_store = store
123+
#ctx.extra_chain_cert = [ ca_cert ]
124+
ctx.cert = @svr_cert
125+
ctx.key = @svr_key
126+
ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
127+
ctx.verify_mode = verify_mode
128+
ctx_proc.call(ctx) if ctx_proc
129+
130+
Socket.do_not_reverse_lookup = true
131+
132+
tcps = TCPServer.new("127.0.0.1", 0)
133+
port = tcps.connect_address.ip_port
134+
135+
ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
136+
ssls.start_immediately = start_immediately
137+
138+
threads = []
139+
begin
140+
server = Thread.new do
141+
# Thread.current.abort_on_exception = true
142+
begin
143+
server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads)
144+
ensure
145+
tcps.close
146+
end
147+
end
148+
threads.unshift server
149+
150+
$stderr.printf("SSL server started: pid=%d port=%d\n", $$, port) if $DEBUG
151+
152+
client = Thread.new do
153+
begin
154+
block.call(server, port.to_i)
155+
ensure
156+
stop_pipe_w.close
157+
end
158+
end
159+
threads.unshift client
160+
ensure
161+
assert_join_threads(threads)
162+
end
163+
end
164+
end
165+
78166
def tcp_server_close(thread, tcp_server)
79167
begin
80168
tcp_server.shutdown
@@ -110,7 +198,7 @@ def tcp_server_close(thread, tcp_server)
110198
( defined? JRUBY_VERSION && JRUBY_VERSION < '1.7.0' )
111199
private :tcp_server_close
112200

113-
def server_loop(context, server, server_proc)
201+
def server_loop0(context, server, server_proc)
114202
loop do
115203
ssl = nil
116204
begin
@@ -127,6 +215,31 @@ def server_loop(context, server, server_proc)
127215
rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET
128216
end
129217

218+
def server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads)
219+
loop do
220+
ssl = nil
221+
begin
222+
readable, = IO.select([ssls, stop_pipe_r])
223+
return if readable.include? stop_pipe_r
224+
ssl = ssls.accept
225+
rescue OpenSSL::SSL::SSLError
226+
if ignore_listener_error
227+
retry
228+
else
229+
raise
230+
end
231+
end
232+
233+
threads << Thread.start do
234+
# Thread.current.abort_on_exception = true
235+
server_proc.call(ctx, ssl)
236+
end
237+
end
238+
rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET => ex
239+
raise(ex) unless ignore_listener_error
240+
puts ex.inspect if $VERBOSE
241+
end
242+
130243
def server_connect(port, ctx = nil)
131244
sock = TCPSocket.new('127.0.0.1', port)
132245
ssl = ctx ? OpenSSL::SSL::SSLSocket.new(sock, ctx) : OpenSSL::SSL::SSLSocket.new(sock)

src/test/ruby/ssl/test_session.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class TestSSLSession < TestCase
55
include SSLTestHelper
66

77
def test_session
8-
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
8+
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
99
sock = TCPSocket.new("127.0.0.1", port)
1010
ctx = OpenSSL::SSL::SSLContext.new("TLSv1")
1111
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)

src/test/ruby/ssl/test_socket.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def test_sync_close_without_connect
7272
include SSLTestHelper
7373

7474
def test_ssl_sysread_blocking_error
75-
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
75+
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
7676
server_connect(port) do |ssl|
7777
ssl.write("abc\n")
7878
# assert_raise(TypeError) { eval 'ssl.sysread(4, exception: false)' }

src/test/ruby/ssl/test_ssl.rb

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class TestSSL < TestCase
88
def test_context_default_constants
99
assert OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
1010
assert_equal 'SSLv23', OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ssl_version]
11-
assert_equal "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW", OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers]
11+
# assert_equal "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW", OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers]
1212
assert_equal OpenSSL::SSL::VERIFY_PEER, OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:verify_mode]
1313

1414
assert OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE
@@ -18,7 +18,7 @@ def test_context_default_constants
1818
def test_post_connection_check
1919
sslerr = OpenSSL::SSL::SSLError
2020

21-
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
21+
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
2222
sock = TCPSocket.new("127.0.0.1", port)
2323
ssl = OpenSSL::SSL::SSLSocket.new(sock)
2424
ssl.connect
@@ -42,7 +42,7 @@ def test_post_connection_check
4242
]
4343
@svr_cert = issue_cert(@svr, @svr_key, 4, now, now + 1800, exts,
4444
@ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
45-
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
45+
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
4646
sock = TCPSocket.new("127.0.0.1", port)
4747
ssl = OpenSSL::SSL::SSLSocket.new(sock)
4848
ssl.connect
@@ -66,7 +66,7 @@ def test_post_connection_check
6666
]
6767
@svr_cert = issue_cert(@svr, @svr_key, 5, now, now + 1800, exts,
6868
@ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
69-
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
69+
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
7070
sock = TCPSocket.new("127.0.0.1", port)
7171
ssl = OpenSSL::SSL::SSLSocket.new(sock)
7272
ssl.connect
@@ -83,6 +83,10 @@ def test_post_connection_check
8383
end
8484

8585
def test_post_connect_check_with_anon_ciphers
86+
unless OpenSSL::ExtConfig::TLS_DH_anon_WITH_AES_256_GCM_SHA384
87+
return skip('OpenSSL::ExtConfig::TLS_DH_anon_WITH_AES_256_GCM_SHA384 not enabled')
88+
end
89+
8690
start_server(OpenSSL::SSL::VERIFY_NONE, true, { use_anon_cipher: true }) { |server, port|
8791
ctx = OpenSSL::SSL::SSLContext.new
8892
ctx.ciphers = "aNULL"
@@ -92,13 +96,13 @@ def test_post_connect_check_with_anon_ciphers
9296
assert_raise_with_message(OpenSSL::SSL::SSLError, msg){ssl.post_connection_check("localhost.localdomain")}
9397
}
9498
}
95-
end if OpenSSL::ExtConfig::TLS_DH_anon_WITH_AES_256_GCM_SHA384
99+
end
96100

97101
def test_ssl_version_tlsv1
98102
ctx_proc = Proc.new do |ctx|
99103
ctx.ssl_version = "TLSv1"
100104
end
101-
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
105+
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
102106
sock = TCPSocket.new("127.0.0.1", port)
103107
ssl = OpenSSL::SSL::SSLSocket.new(sock)
104108
ssl.connect
@@ -111,7 +115,7 @@ def test_ssl_version_tlsv1_1
111115
ctx_proc = Proc.new do |ctx|
112116
ctx.ssl_version = "TLSv1_1"
113117
end
114-
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
118+
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
115119
sock = TCPSocket.new("127.0.0.1", port)
116120
ssl = OpenSSL::SSL::SSLSocket.new(sock)
117121
ssl.connect
@@ -124,7 +128,7 @@ def test_ssl_version_tlsv1_2
124128
ctx_proc = Proc.new do |ctx|
125129
ctx.ssl_version = "TLSv1_2"
126130
end
127-
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
131+
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
128132
sock = TCPSocket.new("127.0.0.1", port)
129133
ssl = OpenSSL::SSL::SSLSocket.new(sock)
130134
ssl.connect
@@ -134,7 +138,7 @@ def test_ssl_version_tlsv1_2
134138
end unless java6? # TLS1_2 is not supported by JDK 6
135139

136140
def test_read_nonblock_would_block
137-
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
141+
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
138142
sock = TCPSocket.new("127.0.0.1", port)
139143
ssl = OpenSSL::SSL::SSLSocket.new(sock)
140144
ssl.connect
@@ -158,15 +162,15 @@ def test_read_nonblock_would_block
158162
result = eval "ssl.read_nonblock(5, 'buff', exception: false)"
159163
assert_equal :wait_readable, result
160164
end
161-
result = ssl.sysread_nonblock(5, :exception => false)
165+
result = ssl.send :sysread_nonblock, 5, :exception => false
162166
assert_equal :wait_readable, result
163167

164168
ssl.close
165169
end
166170
end if RUBY_VERSION > '1.9'
167171

168172
def test_connect_nonblock_would_block
169-
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
173+
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
170174
sock = TCPSocket.new("127.0.0.1", port)
171175
ssl = OpenSSL::SSL::SSLSocket.new(sock)
172176

@@ -201,7 +205,7 @@ def test_renegotiation_cb
201205
num_handshakes = 0
202206
renegotiation_cb = Proc.new { |ssl| num_handshakes += 1 }
203207
ctx_proc = Proc.new { |ctx| ctx.renegotiation_cb = renegotiation_cb }
204-
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, {:ctx_proc => ctx_proc}) do |server, port|
208+
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true, {:ctx_proc => ctx_proc}) do |server, port|
205209
sock = TCPSocket.new("127.0.0.1", port)
206210
ssl = OpenSSL::SSL::SSLSocket.new(sock)
207211
ssl.connect
@@ -210,4 +214,41 @@ def test_renegotiation_cb
210214
end
211215
end
212216

217+
def test_tlsext_hostname
218+
return unless OpenSSL::SSL::SSLSocket.instance_methods.include?(:hostname)
219+
220+
ctx_proc = Proc.new do |ctx, ssl|
221+
foo_ctx = ctx.dup
222+
223+
ctx.servername_cb = Proc.new do |ssl2, hostname|
224+
case hostname
225+
when 'foo.example.com'
226+
foo_ctx
227+
when 'bar.example.com'
228+
nil
229+
else
230+
raise "unknown hostname #{hostname.inspect}"
231+
end
232+
end
233+
end
234+
235+
server_proc = Proc.new { |ctx, ssl| readwrite_loop(ctx, ssl) }
236+
237+
start_server(OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port|
238+
2.times do |i|
239+
ctx = OpenSSL::SSL::SSLContext.new
240+
if defined?(OpenSSL::SSL::OP_NO_TICKET)
241+
# disable RFC4507 support
242+
ctx.options = OpenSSL::SSL::OP_NO_TICKET
243+
end
244+
server_connect(port, ctx) { |ssl|
245+
ssl.hostname = (i & 1 == 0) ? 'foo.example.com' : 'bar.example.com'
246+
str = "x" * 100 + "\n"
247+
ssl.puts(str)
248+
assert_equal(str, ssl.gets)
249+
}
250+
end
251+
end
252+
end
253+
213254
end

0 commit comments

Comments
 (0)