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-b9f4589650da
unstable
HD Moore 2009-11-04 16:36:06 +00:00
parent 56f18687c5
commit 34d76a72e0
2 changed files with 42 additions and 20 deletions

View File

@ -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

View File

@ -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