Fixes #462. Handle proxy errors like regular socket errors. This can lead to missing results in tests, so we may need to add special proxy exception checks to the scanner mixin
git-svn-id: file:///home/svn/framework3/trunk@7352 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
56f18687c5
commit
34d76a72e0
|
@ -11,7 +11,7 @@ module Exception
|
||||||
end
|
end
|
||||||
|
|
||||||
###
|
###
|
||||||
#
|
#
|
||||||
# This exception is raised when a timeout occurs.
|
# This exception is raised when a timeout occurs.
|
||||||
#
|
#
|
||||||
###
|
###
|
||||||
|
@ -53,7 +53,7 @@ end
|
||||||
###
|
###
|
||||||
class ArgumentError < ::ArgumentError
|
class ArgumentError < ::ArgumentError
|
||||||
include Exception
|
include Exception
|
||||||
|
|
||||||
def initialize(message = nil)
|
def initialize(message = nil)
|
||||||
@message = message
|
@message = message
|
||||||
end
|
end
|
||||||
|
@ -139,7 +139,7 @@ module SocketError
|
||||||
end
|
end
|
||||||
|
|
||||||
###
|
###
|
||||||
#
|
#
|
||||||
# This exception is raised when there is some kind of error related to
|
# This exception is raised when there is some kind of error related to
|
||||||
# communication with a host.
|
# communication with a host.
|
||||||
#
|
#
|
||||||
|
@ -215,6 +215,7 @@ class ConnectionTimeout < ConnectionError
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
#
|
#
|
||||||
# This exception is raised when an attempt to use an address or port that is
|
# This exception is raised when an attempt to use an address or port that is
|
||||||
|
@ -244,10 +245,31 @@ class UnsupportedProtocol < ::ArgumentError
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
"The protocol #{proto} is not supported."
|
"The protocol #{proto} is not supported."
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_accessor :proto
|
attr_accessor :proto
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
#
|
||||||
|
# This exception is raised when a proxy fails to pass a connection
|
||||||
|
#
|
||||||
|
###
|
||||||
|
class ConnectionProxyError < ConnectionError
|
||||||
|
def initialize(host,port,ptype,reason)
|
||||||
|
super(host,port)
|
||||||
|
self.ptype = ptype
|
||||||
|
self.reason = reason
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
self.ptype + ": " + self.reason
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_accessor :ptype, :reason
|
||||||
end
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
|
@ -249,53 +249,53 @@ class Rex::Socket::Comm::Local
|
||||||
setup = "CONNECT #{host}:#{port} HTTP/1.0\r\n\r\n"
|
setup = "CONNECT #{host}:#{port} HTTP/1.0\r\n\r\n"
|
||||||
size = sock.put(setup)
|
size = sock.put(setup)
|
||||||
if (size != setup.length)
|
if (size != setup.length)
|
||||||
raise ArgumentError, "Wrote less data than expected to the http proxy"
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ret = sock.get_once(39,30)
|
ret = sock.get_once(39,30)
|
||||||
rescue IOError
|
rescue IOError
|
||||||
raise Rex::ConnectionRefused.new(host, port), caller
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
|
||||||
end
|
end
|
||||||
|
|
||||||
if ret.nil?
|
if ret.nil?
|
||||||
raise ArgumentError, "The http proxy did not respond"
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
|
||||||
end
|
end
|
||||||
|
|
||||||
resp = Rex::Proto::Http::Response.new
|
resp = Rex::Proto::Http::Response.new
|
||||||
resp.update_cmd_parts(ret.split(/\r?\n/)[0])
|
resp.update_cmd_parts(ret.split(/\r?\n/)[0])
|
||||||
|
|
||||||
if resp.code != 200
|
if resp.code != 200
|
||||||
raise ArgumentError, "Connection with http proxy failed"
|
raise Rex::ConnectionProxyError.new(host, port, type, "The proxy returned a non-OK response"), caller
|
||||||
end
|
end
|
||||||
when 'socks4'
|
when 'socks4'
|
||||||
setup = [4,1,port.to_i].pack('CCn') + Socket.gethostbyname(host)[3] + Rex::Text.rand_text_alpha(rand(8)+1) + "\x00"
|
setup = [4,1,port.to_i].pack('CCn') + Socket.gethostbyname(host)[3] + Rex::Text.rand_text_alpha(rand(8)+1) + "\x00"
|
||||||
size = sock.put(setup)
|
size = sock.put(setup)
|
||||||
if (size != setup.length)
|
if (size != setup.length)
|
||||||
raise ArgumentError, "Wrote less data than expected to the socks4 proxy"
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ret = sock.get_once(8, 30)
|
ret = sock.get_once(8, 30)
|
||||||
rescue IOError
|
rescue IOError
|
||||||
raise Rex::ConnectionRefused.new(host, port), caller
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
|
||||||
end
|
end
|
||||||
|
|
||||||
if (ret.nil? or ret.length < 8)
|
if (ret.nil? or ret.length < 8)
|
||||||
raise ArgumentError, 'SOCKS4 server did not respond with a proper response'
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a complete response from the proxy"), caller
|
||||||
end
|
end
|
||||||
if ret[1,1] != "\x5a"
|
if ret[1,1] != "\x5a"
|
||||||
raise "SOCKS4 server responded with error code #{ret[0,1].unpack("C")[0]}"
|
raise Rex::ConnectionProxyError.new(host, port, type, "Proxy responded with error code #{ret[0,1].unpack("C")[0]}"), caller
|
||||||
end
|
end
|
||||||
when 'socks5'
|
when 'socks5'
|
||||||
auth_methods = [5,1,0].pack('CCC')
|
auth_methods = [5,1,0].pack('CCC')
|
||||||
size = sock.put(auth_methods)
|
size = sock.put(auth_methods)
|
||||||
if (size != auth_methods.length)
|
if (size != auth_methods.length)
|
||||||
raise ArgumentError, "Wrote less data than expected to the socks5 proxy"
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
|
||||||
end
|
end
|
||||||
ret = sock.get_once(2,30)
|
ret = sock.get_once(2,30)
|
||||||
if (ret[1,1] == "\xff")
|
if (ret[1,1] == "\xff")
|
||||||
raise ArgumentError, "Proxy requires authentication"
|
raise Rex::ConnectionProxyError.new(host, port, type, "The proxy requires authentication"), caller
|
||||||
end
|
end
|
||||||
|
|
||||||
if (Rex::Socket.is_ipv4?(host))
|
if (Rex::Socket.is_ipv4?(host))
|
||||||
|
@ -314,23 +314,23 @@ class Rex::Socket::Comm::Local
|
||||||
|
|
||||||
size = sock.put(setup)
|
size = sock.put(setup)
|
||||||
if (size != setup.length)
|
if (size != setup.length)
|
||||||
raise ArgumentError, "Wrote less data than expected to the socks5 proxy"
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
response = sock.get_once(10, 30)
|
response = sock.get_once(10, 30)
|
||||||
rescue IOError
|
rescue IOError
|
||||||
raise Rex::ConnectionRefused.new(host, port), caller
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
|
||||||
end
|
end
|
||||||
|
|
||||||
if (response.nil? or response.length < 10)
|
if (response.nil? or response.length < 10)
|
||||||
raise ArgumentError, 'SOCKS5 server did not respond with a proper response'
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a complete response from the proxy"), caller
|
||||||
end
|
end
|
||||||
if response[1] != 0
|
if response[1,1] != "\x00"
|
||||||
raise "SOCKS5 server responded with error code #{response[1]}"
|
raise Rex::ConnectionProxyError.new(host, port, type, "Proxy responded with error code #{response[1,1].unpack("C")[0]}"), caller
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise ArgumentError, 'Unsupported proxy type and/or version', caller
|
raise RuntimeError, "The proxy type specified is not valid", caller
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue