[ruby/net-http] implement talking SSL to the proxy too
https://bugs.ruby-lang.org/issues/16482 https://github.com/ruby/net-http/commit/ae2d83f88b
This commit is contained in:
parent
70bdc0f777
commit
bc1b4235fb
@ -1103,7 +1103,7 @@ module Net #:nodoc:
|
|||||||
# For proxy-defining arguments +p_addr+ through +p_no_proxy+,
|
# For proxy-defining arguments +p_addr+ through +p_no_proxy+,
|
||||||
# see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
|
# see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
|
||||||
#
|
#
|
||||||
def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil)
|
def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil, p_use_ssl = nil)
|
||||||
http = super address, port
|
http = super address, port
|
||||||
|
|
||||||
if proxy_class? then # from Net::HTTP::Proxy()
|
if proxy_class? then # from Net::HTTP::Proxy()
|
||||||
@ -1112,6 +1112,7 @@ module Net #:nodoc:
|
|||||||
http.proxy_port = @proxy_port
|
http.proxy_port = @proxy_port
|
||||||
http.proxy_user = @proxy_user
|
http.proxy_user = @proxy_user
|
||||||
http.proxy_pass = @proxy_pass
|
http.proxy_pass = @proxy_pass
|
||||||
|
http.proxy_use_ssl = @proxy_use_ssl
|
||||||
elsif p_addr == :ENV then
|
elsif p_addr == :ENV then
|
||||||
http.proxy_from_env = true
|
http.proxy_from_env = true
|
||||||
else
|
else
|
||||||
@ -1123,6 +1124,7 @@ module Net #:nodoc:
|
|||||||
http.proxy_port = p_port || default_port
|
http.proxy_port = p_port || default_port
|
||||||
http.proxy_user = p_user
|
http.proxy_user = p_user
|
||||||
http.proxy_pass = p_pass
|
http.proxy_pass = p_pass
|
||||||
|
http.proxy_use_ssl = p_use_ssl
|
||||||
end
|
end
|
||||||
|
|
||||||
http
|
http
|
||||||
@ -1190,6 +1192,7 @@ module Net #:nodoc:
|
|||||||
@proxy_port = nil
|
@proxy_port = nil
|
||||||
@proxy_user = nil
|
@proxy_user = nil
|
||||||
@proxy_pass = nil
|
@proxy_pass = nil
|
||||||
|
@proxy_use_ssl = nil
|
||||||
|
|
||||||
@use_ssl = false
|
@use_ssl = false
|
||||||
@ssl_context = nil
|
@ssl_context = nil
|
||||||
@ -1324,6 +1327,7 @@ module Net #:nodoc:
|
|||||||
# Sets the proxy password;
|
# Sets the proxy password;
|
||||||
# see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
|
# see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
|
||||||
attr_writer :proxy_pass
|
attr_writer :proxy_pass
|
||||||
|
attr_writer :proxy_use_ssl
|
||||||
|
|
||||||
# Returns the IP address for the connection.
|
# Returns the IP address for the connection.
|
||||||
#
|
#
|
||||||
@ -1668,7 +1672,13 @@ module Net #:nodoc:
|
|||||||
debug "opened"
|
debug "opened"
|
||||||
if use_ssl?
|
if use_ssl?
|
||||||
if proxy?
|
if proxy?
|
||||||
plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
|
if @proxy_use_ssl
|
||||||
|
proxy_sock = OpenSSL::SSL::SSLSocket.new(s)
|
||||||
|
ssl_socket_connect(proxy_sock, @open_timeout)
|
||||||
|
else
|
||||||
|
proxy_sock = s
|
||||||
|
end
|
||||||
|
proxy_sock = BufferedIO.new(proxy_sock, read_timeout: @read_timeout,
|
||||||
write_timeout: @write_timeout,
|
write_timeout: @write_timeout,
|
||||||
continue_timeout: @continue_timeout,
|
continue_timeout: @continue_timeout,
|
||||||
debug_output: @debug_output)
|
debug_output: @debug_output)
|
||||||
@ -1679,8 +1689,8 @@ module Net #:nodoc:
|
|||||||
buf << "Proxy-Authorization: Basic #{credential}\r\n"
|
buf << "Proxy-Authorization: Basic #{credential}\r\n"
|
||||||
end
|
end
|
||||||
buf << "\r\n"
|
buf << "\r\n"
|
||||||
plain_sock.write(buf)
|
proxy_sock.write(buf)
|
||||||
HTTPResponse.read_new(plain_sock).value
|
HTTPResponse.read_new(proxy_sock).value
|
||||||
# assuming nothing left in buffers after successful CONNECT response
|
# assuming nothing left in buffers after successful CONNECT response
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1788,13 +1798,14 @@ module Net #:nodoc:
|
|||||||
@proxy_port = nil
|
@proxy_port = nil
|
||||||
@proxy_user = nil
|
@proxy_user = nil
|
||||||
@proxy_pass = nil
|
@proxy_pass = nil
|
||||||
|
@proxy_use_ssl = nil
|
||||||
|
|
||||||
# Creates an \HTTP proxy class which behaves like \Net::HTTP, but
|
# Creates an \HTTP proxy class which behaves like \Net::HTTP, but
|
||||||
# performs all access via the specified proxy.
|
# performs all access via the specified proxy.
|
||||||
#
|
#
|
||||||
# This class is obsolete. You may pass these same parameters directly to
|
# This class is obsolete. You may pass these same parameters directly to
|
||||||
# \Net::HTTP.new. See Net::HTTP.new for details of the arguments.
|
# \Net::HTTP.new. See Net::HTTP.new for details of the arguments.
|
||||||
def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil) #:nodoc:
|
def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_use_ssl = nil) #:nodoc:
|
||||||
return self unless p_addr
|
return self unless p_addr
|
||||||
|
|
||||||
Class.new(self) {
|
Class.new(self) {
|
||||||
@ -1812,6 +1823,7 @@ module Net #:nodoc:
|
|||||||
|
|
||||||
@proxy_user = p_user
|
@proxy_user = p_user
|
||||||
@proxy_pass = p_pass
|
@proxy_pass = p_pass
|
||||||
|
@proxy_use_ssl = p_use_ssl
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1836,6 +1848,9 @@ module Net #:nodoc:
|
|||||||
# Returns the password for accessing the proxy, or +nil+ if none;
|
# Returns the password for accessing the proxy, or +nil+ if none;
|
||||||
# see Net::HTTP@Proxy+Server.
|
# see Net::HTTP@Proxy+Server.
|
||||||
attr_reader :proxy_pass
|
attr_reader :proxy_pass
|
||||||
|
|
||||||
|
# Use SSL when talking to the proxy. If Net::HTTP does not use a proxy, nil.
|
||||||
|
attr_reader :proxy_use_ssl
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns +true+ if a proxy server is defined, +false+ otherwise;
|
# Returns +true+ if a proxy server is defined, +false+ otherwise;
|
||||||
|
@ -43,5 +43,53 @@ class HTTPSProxyTest < Test::Unit::TestCase
|
|||||||
assert_join_threads([client_thread, server_thread])
|
assert_join_threads([client_thread, server_thread])
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_https_proxy_ssl_connection
|
||||||
|
begin
|
||||||
|
OpenSSL
|
||||||
|
rescue LoadError
|
||||||
|
omit 'autoload problem. see [ruby-dev:45021][Bug #5786]'
|
||||||
|
end
|
||||||
|
|
||||||
|
tcpserver = TCPServer.new("127.0.0.1", 0)
|
||||||
|
ctx = OpenSSL::SSL::SSLContext.new
|
||||||
|
ctx.key = OpenSSL::PKey::RSA.new 2048
|
||||||
|
ctx.cert = OpenSSL::X509::Certificate.new
|
||||||
|
ctx.cert.subject = OpenSSL::X509::Name.new [['CN', 'localhost']]
|
||||||
|
ctx.cert.issuer = ctx.cert.subject
|
||||||
|
ctx.cert.public_key = ctx.key
|
||||||
|
ctx.cert.not_before = Time.now
|
||||||
|
ctx.cert.not_after = Time.now + 60 * 60 * 24
|
||||||
|
ctx.cert.sign ctx.key, OpenSSL::Digest::SHA1.new
|
||||||
|
serv = OpenSSL::SSL::SSLServer.new(tcpserver, ctx)
|
||||||
|
|
||||||
|
_, port, _, _ = serv.addr
|
||||||
|
client_thread = Thread.new {
|
||||||
|
proxy = Net::HTTP.Proxy("127.0.0.1", port, 'user', 'password', true)
|
||||||
|
http = proxy.new("foo.example.org", 8000)
|
||||||
|
http.use_ssl = true
|
||||||
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||||
|
begin
|
||||||
|
http.start
|
||||||
|
rescue EOFError
|
||||||
|
end
|
||||||
|
}
|
||||||
|
server_thread = Thread.new {
|
||||||
|
sock = serv.accept
|
||||||
|
begin
|
||||||
|
proxy_request = sock.gets("\r\n\r\n")
|
||||||
|
assert_equal(
|
||||||
|
"CONNECT foo.example.org:8000 HTTP/1.1\r\n" +
|
||||||
|
"Host: foo.example.org:8000\r\n" +
|
||||||
|
"Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==\r\n" +
|
||||||
|
"\r\n",
|
||||||
|
proxy_request,
|
||||||
|
"[ruby-core:96672]")
|
||||||
|
ensure
|
||||||
|
sock.close
|
||||||
|
end
|
||||||
|
}
|
||||||
|
assert_join_threads([client_thread, server_thread])
|
||||||
|
end
|
||||||
end if defined?(OpenSSL)
|
end if defined?(OpenSSL)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user