mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-11-22 00:05:57 -05:00
fix: ssl handshake correct handling of ip addresses
besides not setting session sni hostname, which it was already doing,
the verify_hostname is set to false to avoid warnings, and the
post_connection_check is still allowed to proceed, to check that the
certificate returned includes the IP address.
port of the similar net-http change found
[here](fa68e64bee)
also ommitting certain steps in the initializer if the ssl socket is
initiated outside of the httpx context and passed as an option.
This commit is contained in:
parent
0f234c2d7b
commit
f03d9bb648
@ -17,13 +17,26 @@ module HTTPX
|
||||
|
||||
def initialize(_, _, options)
|
||||
super
|
||||
@ctx = OpenSSL::SSL::SSLContext.new
|
||||
|
||||
ctx_options = TLS_OPTIONS.merge(options.ssl)
|
||||
@sni_hostname = ctx_options.delete(:hostname) || @hostname
|
||||
@ctx.set_params(ctx_options) unless ctx_options.empty?
|
||||
|
||||
if @io.is_a?(OpenSSL::SSL::SSLSocket)
|
||||
# externally initiated ssl socket
|
||||
@ctx = @io.context
|
||||
else
|
||||
@ctx = OpenSSL::SSL::SSLContext.new
|
||||
@ctx.set_params(ctx_options) unless ctx_options.empty?
|
||||
unless @ctx.session_cache_mode.nil? # a dummy method on JRuby
|
||||
@ctx.session_cache_mode =
|
||||
OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT | OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
|
||||
end
|
||||
end
|
||||
|
||||
@state = :negotiated if @keep_open
|
||||
|
||||
@hostname_is_ip = IPRegex.match?(@sni_hostname)
|
||||
@verify_hostname = @ctx.verify_hostname
|
||||
end
|
||||
|
||||
def protocol
|
||||
@ -61,7 +74,13 @@ module HTTPX
|
||||
|
||||
unless @io.is_a?(OpenSSL::SSL::SSLSocket)
|
||||
@io = OpenSSL::SSL::SSLSocket.new(@io, @ctx)
|
||||
@io.hostname = @sni_hostname unless @hostname_is_ip
|
||||
|
||||
if @hostname_is_ip
|
||||
# IP addresses in SNI is not valid per RFC 6066, section 3.
|
||||
@ctx.verify_hostname = false
|
||||
else
|
||||
@io.hostname = @sni_hostname
|
||||
end
|
||||
@io.sync_close = true
|
||||
end
|
||||
try_ssl_connect
|
||||
@ -71,7 +90,7 @@ module HTTPX
|
||||
# :nocov:
|
||||
def try_ssl_connect
|
||||
@io.connect_nonblock
|
||||
@io.post_connection_check(@sni_hostname) if @ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE && !@hostname_is_ip
|
||||
@io.post_connection_check(@sni_hostname) if @ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE && @verify_hostname
|
||||
transition(:negotiated)
|
||||
@interests = :w
|
||||
rescue ::IO::WaitReadable
|
||||
@ -103,7 +122,7 @@ module HTTPX
|
||||
@interests = :w
|
||||
return
|
||||
end
|
||||
@io.post_connection_check(@sni_hostname) if @ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE && !@hostname_is_ip
|
||||
@io.post_connection_check(@sni_hostname) if @ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE && @verify_hostname
|
||||
transition(:negotiated)
|
||||
@interests = :w
|
||||
end
|
||||
@ -130,6 +149,7 @@ module HTTPX
|
||||
case nextstate
|
||||
when :negotiated
|
||||
return unless @state == :connected
|
||||
|
||||
when :closed
|
||||
return unless @state == :negotiated ||
|
||||
@state == :connected
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
module HTTPX
|
||||
IPRegex: Regexp
|
||||
|
||||
@ctx: OpenSSL::SSL::SSLContext
|
||||
@verify_hostname: bool
|
||||
|
||||
class TLSError < OpenSSL::SSL::SSLError
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user