Skip to content

Commit fc60c97

Browse files
committed
ssl: delay closing TCP sockets in start_server
Some tests expect server-side SSLSocket#accept to fail for various reasons. On some systems, closing the underlying socket immediately with IO#close causes the TCP connection to be terminated with RST. Do not close it immediately so that the client can reliably receive the TLS alert. This allows writing more meaningful assertions. Also add a dedicated test case for the rb_sys_fail() path in SSLSocket#connect.
1 parent b67520f commit fc60c97

2 files changed

Lines changed: 29 additions & 15 deletions

File tree

test/openssl/test_ssl.rb

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,8 @@ def test_verify_mode_client_cert_required
491491
sctx.verify_mode =
492492
OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
493493
start_server(sctx, ignore_listener_error: true) { |port|
494-
assert_handshake_error {
494+
# TLS 1.3 alert: certificate_required(116)
495+
assert_raise_with_message(OpenSSL::SSL::SSLError, /alert number 116/) {
495496
server_connect(port) { |ssl| ssl.puts("abc"); ssl.gets }
496497
}
497498
}
@@ -547,7 +548,7 @@ def test_client_cert_cb_ignore_error
547548
# 1. Exception in client_cert_cb is suppressed
548549
# 2. No client certificate will be sent to the server
549550
# 3. SSL_VERIFY_FAIL_IF_NO_PEER_CERT causes the handshake to fail
550-
assert_handshake_error {
551+
assert_raise(OpenSSL::SSL::SSLError) {
551552
server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets }
552553
}
553554
end
@@ -1286,6 +1287,27 @@ def test_verify_hostname_failure_error_code
12861287
end
12871288
end
12881289

1290+
def test_connect_systemcallerror
1291+
# SSL_connect() should fail with SSL_ERROR_SYSCALL and errno should be
1292+
# kept intact from the underlying recv(2)/send(2).
1293+
pend "AWS-LC does not preserve errno on SSL_ERROR_SYSCALL" if aws_lc?
1294+
1295+
server_proc = proc do |sock|
1296+
sock.setsockopt(:SOCKET, :LINGER, [1, 0].pack("ii"))
1297+
sock.read(1)
1298+
sock.close
1299+
end
1300+
start_server_proc(server_proc) do |port|
1301+
sock = TCPSocket.new("127.0.0.1", port)
1302+
ssl = OpenSSL::SSL::SSLSocket.new(sock)
1303+
assert_raise(Errno::ECONNRESET, Errno::EPIPE) {
1304+
ssl.connect
1305+
}
1306+
ensure
1307+
sock&.close
1308+
end
1309+
end
1310+
12891311
def test_connect_certificate_verify_failed_exception_message
12901312
start_server(ignore_listener_error: true) { |port|
12911313
ctx = OpenSSL::SSL::SSLContext.new
@@ -1338,7 +1360,7 @@ def check_supported_protocol_versions
13381360
ssl.puts "abc"; assert_equal "abc\n", ssl.gets
13391361
}
13401362
supported << ver
1341-
rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET
1363+
rescue OpenSSL::SSL::SSLError
13421364
end
13431365
end
13441366

@@ -2106,7 +2128,7 @@ def test_client_sigalgs
21062128
start_server(sctx, ignore_listener_error: true) do |port|
21072129
ctx1 = OpenSSL::SSL::SSLContext.new
21082130
ctx1.add_certificate(@cli_cert, @cli_key) # RSA
2109-
assert_handshake_error {
2131+
assert_raise(OpenSSL::SSL::SSLError) {
21102132
server_connect(port, ctx1) { |ssl|
21112133
ssl.puts("abc"); ssl.gets
21122134
}
@@ -2458,14 +2480,6 @@ def server_connect(port, ctx = nil)
24582480
sock.close
24592481
end
24602482
end
2461-
2462-
def assert_handshake_error
2463-
# different OpenSSL versions react differently when facing a SSL/TLS version
2464-
# that has been marked as forbidden, therefore any of these may be raised
2465-
assert_raise(OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::EPIPE) {
2466-
yield
2467-
}
2468-
end
24692483
end
24702484

24712485
end

test/openssl/utils.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,20 +210,19 @@ def start_server_proc(server_proc, &block)
210210
port = tcps.connect_address.ip_port
211211

212212
threads = []
213+
sockets = []
213214
server_thread = Thread.new do
214215
Thread.current.report_on_exception = false
215216

216217
loop do
217218
readable, = IO.select([tcps, stop_pipe_r])
218219
break if readable.include? stop_pipe_r
219-
sock = tcps.accept
220+
sockets << sock = tcps.accept
220221

221222
th = Thread.new do
222223
Thread.current.report_on_exception = false
223224

224225
server_proc.call(sock)
225-
ensure
226-
sock.close
227226
end
228227
threads << th
229228
end
@@ -254,6 +253,7 @@ def start_server_proc(server_proc, &block)
254253
rescue Exception
255254
end
256255
}
256+
sockets.each(&:close)
257257
raise pend if pend
258258
assert_join_threads(threads)
259259
end

0 commit comments

Comments
 (0)