Skip to content

Commit fa68e64

Browse files
committed
Do not set SNI hostname if connecting to IP address
RFC 6066, section 3, explicitly disallows the use of an IP address as an SNI server name. So check if the connection is being made to an IP address using the resolv regexps, and do not set an SNI hostname in that case. Recent changes to LibreSSL make it more strictly follow RFC 6066, resulting an s.hostname= raising an error if passed an IP address. When such verions of LibreSSL are used, this change not only fixes the net/http tests, it also fixes tests for webrick and open-uri, which both make SSL connections to 127.0.0.1 using net/http in their tests. Avoid warning in the openssl extension by unsetting @ssl_context.verify_hostname if connecting to an IP address. Make changes so that the post_connection_check still happens when connecting to an IP address, which is necessary to keep checking that the certificate returned includes the IP address, which one of the tests depends on. Revert the previous change that modified the regexp used for checking the error message.
1 parent d2aed67 commit fa68e64

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

lib/net/http.rb

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
require 'net/protocol'
2424
require 'uri'
25+
require 'resolv'
2526
autoload :OpenSSL, 'openssl'
2627

2728
module Net #:nodoc:
@@ -1036,17 +1037,34 @@ def connect
10361037
OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
10371038
OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
10381039
@ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
1040+
1041+
# Still do the post_connection_check below even if connecting
1042+
# to IP address
1043+
verify_hostname = @ssl_context.verify_hostname
1044+
1045+
# Server Name Indication (SNI) RFC 3546/6066
1046+
case @address
1047+
when Resolv::IPv4::Regex, Resolv::IPv6::Regex
1048+
# don't set SNI, as IP addresses in SNI is not valid
1049+
# per RFC 6066, section 3.
1050+
1051+
# Avoid openssl warning
1052+
@ssl_context.verify_hostname = false
1053+
else
1054+
ssl_host_address = @address
1055+
end
1056+
10391057
debug "starting SSL for #{conn_addr}:#{conn_port}..."
10401058
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
10411059
s.sync_close = true
1042-
# Server Name Indication (SNI) RFC 3546
1043-
s.hostname = @address if s.respond_to? :hostname=
1060+
s.hostname = ssl_host_address if s.respond_to?(:hostname=) && ssl_host_address
1061+
10441062
if @ssl_session and
10451063
Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
10461064
s.session = @ssl_session
10471065
end
10481066
ssl_socket_connect(s, @open_timeout)
1049-
if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && @ssl_context.verify_hostname
1067+
if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && verify_hostname
10501068
s.post_connection_check(@address)
10511069
end
10521070
debug "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"

test/net/http/test_https.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ def test_identity_verify_failure
255255
ex = assert_raise(OpenSSL::SSL::SSLError){
256256
http.request_get("/") {|res| }
257257
}
258-
re_msg = /certificate verify failed|hostname \"#{HOST_IP}\" does not match|ssl3 ext invalid servername/
258+
re_msg = /certificate verify failed|hostname \"#{HOST_IP}\" does not match/
259259
assert_match(re_msg, ex.message)
260260
end
261261

0 commit comments

Comments
 (0)