2012-06-29 05:18:28 +00:00
|
|
|
# -*- coding: binary -*-
|
2011-05-06 18:47:10 +00:00
|
|
|
require 'singleton'
|
2011-05-12 20:03:55 +00:00
|
|
|
require 'rex/socket'
|
|
|
|
require 'rex/socket/tcp'
|
|
|
|
require 'rex/socket/ssl_tcp'
|
|
|
|
require 'rex/socket/ssl_tcp_server'
|
|
|
|
require 'rex/socket/udp'
|
|
|
|
require 'rex/socket/ip'
|
2007-04-24 06:27:39 +00:00
|
|
|
require 'timeout'
|
2005-06-02 07:52:17 +00:00
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# Local communication class factory.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class Rex::Socket::Comm::Local
|
|
|
|
|
2005-11-15 20:33:55 +00:00
|
|
|
include Singleton
|
2005-09-30 05:59:44 +00:00
|
|
|
include Rex::Socket::Comm
|
|
|
|
|
2005-06-02 07:52:17 +00:00
|
|
|
#
|
|
|
|
# Creates an instance of a socket using the supplied parameters.
|
|
|
|
#
|
|
|
|
def self.create(param)
|
2009-12-17 08:02:11 +00:00
|
|
|
|
|
|
|
# Work around jRuby socket implementation issues
|
|
|
|
if(RUBY_PLATFORM == 'java')
|
|
|
|
return self.create_jruby(param)
|
|
|
|
end
|
|
|
|
|
2005-06-02 07:52:17 +00:00
|
|
|
case param.proto
|
|
|
|
when 'tcp'
|
2005-06-03 04:51:51 +00:00
|
|
|
return create_by_type(param, ::Socket::SOCK_STREAM, ::Socket::IPPROTO_TCP)
|
|
|
|
when 'udp'
|
|
|
|
return create_by_type(param, ::Socket::SOCK_DGRAM, ::Socket::IPPROTO_UDP)
|
2008-07-22 19:03:59 +00:00
|
|
|
when 'ip'
|
|
|
|
return create_ip(param)
|
2005-06-02 07:52:17 +00:00
|
|
|
else
|
2005-06-04 20:38:49 +00:00
|
|
|
raise Rex::UnsupportedProtocol.new(param.proto), caller
|
2005-06-02 07:52:17 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-12-17 08:02:11 +00:00
|
|
|
#
|
|
|
|
# Creates an instance of a socket using the supplied parameters.
|
|
|
|
# Use various hacks to make this work with jRuby
|
|
|
|
#
|
|
|
|
def self.create_jruby(param)
|
|
|
|
sock = nil
|
|
|
|
|
|
|
|
# Notify handlers of the before socket create event.
|
|
|
|
self.instance.notify_before_socket_create(self, param)
|
|
|
|
|
|
|
|
case param.proto
|
|
|
|
when 'tcp'
|
|
|
|
if (param.server?)
|
|
|
|
sock = TCPServer.new(param.localport, param.localhost)
|
|
|
|
klass = Rex::Socket::TcpServer
|
|
|
|
if (param.ssl)
|
|
|
|
klass = Rex::Socket::SslTcpServer
|
|
|
|
end
|
|
|
|
sock.extend(klass)
|
|
|
|
|
|
|
|
else
|
|
|
|
sock = TCPSocket.new(param.peerhost, param.peerport)
|
|
|
|
klass = Rex::Socket::Tcp
|
|
|
|
if (param.ssl)
|
|
|
|
klass = Rex::Socket::SslTcp
|
|
|
|
end
|
|
|
|
sock.extend(klass)
|
|
|
|
end
|
|
|
|
when 'udp'
|
|
|
|
if (param.server?)
|
|
|
|
sock = UDPServer.new(param.localport, param.localhost)
|
|
|
|
klass = Rex::Socket::UdpServer
|
|
|
|
sock.extend(klass)
|
|
|
|
else
|
|
|
|
sock = UDPSocket.new(param.peerhost, param.peerport)
|
|
|
|
klass = Rex::Socket::Udp
|
|
|
|
sock.extend(klass)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
raise Rex::UnsupportedProtocol.new(param.proto), caller
|
|
|
|
end
|
|
|
|
|
|
|
|
sock.initsock(param)
|
|
|
|
self.instance.notify_socket_created(self, sock, param)
|
|
|
|
return sock
|
|
|
|
end
|
|
|
|
|
2008-07-22 19:03:59 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Creates a raw IP socket using the supplied Parameter instance.
|
|
|
|
# Special-cased because of how different it is from UDP/TCP
|
|
|
|
#
|
|
|
|
def self.create_ip(param)
|
2009-01-14 00:15:33 +00:00
|
|
|
self.instance.notify_before_socket_create(self, param)
|
|
|
|
|
2008-07-25 06:04:51 +00:00
|
|
|
sock = ::Socket.open(::Socket::PF_INET, ::Socket::SOCK_RAW, ::Socket::IPPROTO_RAW)
|
|
|
|
sock.setsockopt(::Socket::IPPROTO_IP, ::Socket::IP_HDRINCL, 1)
|
2008-07-22 19:03:59 +00:00
|
|
|
|
2009-07-13 15:24:46 +00:00
|
|
|
# Configure broadcast support
|
|
|
|
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_BROADCAST, true)
|
2009-07-13 13:19:31 +00:00
|
|
|
|
2009-01-14 00:27:37 +00:00
|
|
|
if (param.bare? == false)
|
|
|
|
sock.extend(::Rex::Socket::Ip)
|
|
|
|
sock.initsock(param)
|
|
|
|
end
|
2009-01-14 00:15:33 +00:00
|
|
|
|
|
|
|
self.instance.notify_socket_created(self, sock, param)
|
|
|
|
|
2008-07-22 19:03:59 +00:00
|
|
|
sock
|
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
|
|
|
|
2005-06-02 07:52:17 +00:00
|
|
|
#
|
2005-11-15 05:22:13 +00:00
|
|
|
# Creates a socket using the supplied Parameter instance.
|
2005-06-02 07:52:17 +00:00
|
|
|
#
|
2005-06-03 04:51:51 +00:00
|
|
|
def self.create_by_type(param, type, proto = 0)
|
2007-04-29 23:43:39 +00:00
|
|
|
|
|
|
|
# Whether to use IPv6 addressing
|
|
|
|
usev6 = false
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2007-04-29 23:43:39 +00:00
|
|
|
# Detect IPv6 addresses and enable IPv6 accordingly
|
|
|
|
if ( Rex::Socket.support_ipv6?())
|
|
|
|
|
|
|
|
# Allow the caller to force IPv6
|
|
|
|
if (param.v6)
|
|
|
|
usev6 = true
|
|
|
|
end
|
|
|
|
|
|
|
|
# Force IPv6 mode for non-connected UDP sockets
|
|
|
|
if (type == ::Socket::SOCK_DGRAM and not param.peerhost)
|
2008-01-06 21:51:07 +00:00
|
|
|
# FreeBSD allows IPv6 socket creation, but throws an error on sendto()
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2008-01-06 21:51:07 +00:00
|
|
|
if (not Rex::Compat.is_freebsd())
|
|
|
|
usev6 = true
|
|
|
|
end
|
2007-04-29 23:43:39 +00:00
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2007-04-29 23:43:39 +00:00
|
|
|
local = Rex::Socket.resolv_nbo(param.localhost) if param.localhost
|
|
|
|
peer = Rex::Socket.resolv_nbo(param.peerhost) if param.peerhost
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2007-04-29 23:43:39 +00:00
|
|
|
if (local and local.length == 16)
|
2009-11-02 18:14:57 +00:00
|
|
|
usev6 = true
|
2007-04-29 23:43:39 +00:00
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2007-04-29 23:43:39 +00:00
|
|
|
if (peer and peer.length == 16)
|
2009-11-02 18:14:57 +00:00
|
|
|
usev6 = true
|
2007-04-29 23:43:39 +00:00
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2007-04-29 23:43:39 +00:00
|
|
|
if (usev6)
|
|
|
|
if (local and local.length == 4)
|
2007-05-01 04:50:16 +00:00
|
|
|
if (local == "\x00\x00\x00\x00")
|
|
|
|
param.localhost = '::'
|
2009-01-04 18:42:55 +00:00
|
|
|
elsif (local == "\x7f\x00\x00\x01")
|
|
|
|
param.localhost = '::1'
|
2007-05-01 04:50:16 +00:00
|
|
|
else
|
2011-12-10 14:16:01 +00:00
|
|
|
param.localhost = '::ffff:' + Rex::Socket.getaddress(param.localhost, true)
|
2007-05-01 04:50:16 +00:00
|
|
|
end
|
2007-04-29 23:43:39 +00:00
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2007-04-29 23:43:39 +00:00
|
|
|
if (peer and peer.length == 4)
|
2007-05-01 04:50:16 +00:00
|
|
|
if (peer == "\x00\x00\x00\x00")
|
|
|
|
param.peerhost = '::'
|
2009-01-04 18:42:55 +00:00
|
|
|
elsif (peer == "\x7f\x00\x00\x01")
|
|
|
|
param.peerhost = '::1'
|
2007-05-01 04:50:16 +00:00
|
|
|
else
|
2011-12-10 14:16:01 +00:00
|
|
|
param.peerhost = '::ffff:' + Rex::Socket.getaddress(param.peerhost, true)
|
2007-05-01 04:50:16 +00:00
|
|
|
end
|
2007-04-29 23:43:39 +00:00
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2007-04-29 23:43:39 +00:00
|
|
|
param.v6 = true
|
2009-11-02 18:14:57 +00:00
|
|
|
end
|
2007-04-29 23:43:39 +00:00
|
|
|
else
|
|
|
|
# No IPv6 support
|
|
|
|
param.v6 = false
|
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2005-11-15 20:33:55 +00:00
|
|
|
# Notify handlers of the before socket create event.
|
|
|
|
self.instance.notify_before_socket_create(self, param)
|
|
|
|
|
2005-06-03 07:32:17 +00:00
|
|
|
# Create the socket
|
2007-04-29 23:43:39 +00:00
|
|
|
sock = nil
|
|
|
|
if (param.v6)
|
2009-11-02 18:14:57 +00:00
|
|
|
sock = ::Socket.new(::Socket::AF_INET6, type, proto)
|
2007-04-29 23:43:39 +00:00
|
|
|
else
|
|
|
|
sock = ::Socket.new(::Socket::AF_INET, type, proto)
|
|
|
|
end
|
2005-06-02 07:52:17 +00:00
|
|
|
|
|
|
|
# Bind to a given local address and/or port if they are supplied
|
2011-12-10 21:24:10 +00:00
|
|
|
if param.localport or param.localhost
|
2009-11-02 18:14:57 +00:00
|
|
|
begin
|
2008-12-19 08:02:53 +00:00
|
|
|
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, true)
|
2005-06-04 20:38:49 +00:00
|
|
|
sock.bind(Rex::Socket.to_sockaddr(param.localhost, param.localport))
|
2005-11-27 18:42:44 +00:00
|
|
|
|
2010-11-19 22:28:35 +00:00
|
|
|
rescue ::Errno::EADDRNOTAVAIL,::Errno::EADDRINUSE
|
2005-11-27 18:42:44 +00:00
|
|
|
sock.close
|
2005-06-04 20:38:49 +00:00
|
|
|
raise Rex::AddressInUse.new(param.localhost, param.localport), caller
|
|
|
|
end
|
2005-06-02 07:52:17 +00:00
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2009-07-13 15:24:46 +00:00
|
|
|
# Configure broadcast support for all datagram sockets
|
|
|
|
if (type == ::Socket::SOCK_DGRAM)
|
2009-07-13 13:19:31 +00:00
|
|
|
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_BROADCAST, true)
|
|
|
|
end
|
2005-06-02 07:52:17 +00:00
|
|
|
|
|
|
|
# If a server TCP instance is being created...
|
|
|
|
if (param.server?)
|
2011-04-30 18:08:52 +00:00
|
|
|
sock.listen(256)
|
2005-06-02 07:52:17 +00:00
|
|
|
|
2009-01-14 00:27:37 +00:00
|
|
|
if (param.bare? == false)
|
|
|
|
klass = Rex::Socket::TcpServer
|
|
|
|
if (param.ssl)
|
|
|
|
klass = Rex::Socket::SslTcpServer
|
|
|
|
end
|
|
|
|
sock.extend(klass)
|
2005-06-02 07:52:17 +00:00
|
|
|
|
2009-01-14 00:27:37 +00:00
|
|
|
sock.initsock(param)
|
2006-04-24 18:49:00 +00:00
|
|
|
end
|
2005-06-02 07:52:17 +00:00
|
|
|
# Otherwise, if we're creating a client...
|
|
|
|
else
|
2006-01-27 05:33:08 +00:00
|
|
|
chain = []
|
2005-12-18 02:19:21 +00:00
|
|
|
|
2005-06-03 04:51:51 +00:00
|
|
|
# If we were supplied with host information
|
|
|
|
if (param.peerhost)
|
2012-05-24 23:10:26 +00:00
|
|
|
|
2011-12-10 21:24:10 +00:00
|
|
|
# A flag that indicates whether we need to try multiple scopes
|
|
|
|
retry_scopes = false
|
2012-05-24 23:10:26 +00:00
|
|
|
|
2011-12-10 21:24:10 +00:00
|
|
|
# Always retry with link-local IPv6 addresses
|
|
|
|
if Rex::Socket.is_ipv6?( param.peerhost ) and param.peerhost =~ /^fe80::/
|
|
|
|
retry_scopes = true
|
|
|
|
end
|
2012-05-24 23:10:26 +00:00
|
|
|
|
2011-12-10 21:24:10 +00:00
|
|
|
# Prepare a list of scope IDs to try when connecting to
|
|
|
|
# link-level addresses. Read from /proc if it is available,
|
|
|
|
# otherwise increment through the first 255 IDs.
|
|
|
|
@@ip6_lla_scopes ||= []
|
2012-05-24 23:10:26 +00:00
|
|
|
|
2011-12-10 21:24:10 +00:00
|
|
|
if @@ip6_lla_scopes.length == 0 and retry_scopes
|
2012-05-24 23:10:26 +00:00
|
|
|
|
2011-12-10 21:24:10 +00:00
|
|
|
# Linux specific interface lookup code
|
|
|
|
if ::File.exists?( "/proc/self/net/igmp6" )
|
|
|
|
::File.open("/proc/self/net/igmp6") do |fd|
|
|
|
|
fd.each_line do |line|
|
|
|
|
line = line.strip
|
|
|
|
tscope, tint, junk = line.split(/\s+/, 3)
|
|
|
|
next if not tint
|
2012-05-24 23:10:26 +00:00
|
|
|
|
2011-12-10 21:24:10 +00:00
|
|
|
# Specifying lo in any connect call results in the socket
|
|
|
|
# being unusable, even if the correct interface is set.
|
|
|
|
next if tint == "lo"
|
2012-05-24 23:10:26 +00:00
|
|
|
|
2011-12-10 21:24:10 +00:00
|
|
|
@@ip6_lla_scopes << tscope
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
# Other Unix-like platforms should support a raw scope ID
|
|
|
|
[*(1 .. 255)].map{ |x| @@ip6_lla_scopes << x.to_s }
|
2006-01-27 05:33:08 +00:00
|
|
|
end
|
2011-12-10 21:24:10 +00:00
|
|
|
end
|
2012-05-24 23:10:26 +00:00
|
|
|
|
2011-12-10 21:24:10 +00:00
|
|
|
ip6_scope_idx = 0
|
|
|
|
ip = param.peerhost
|
|
|
|
port = param.peerport
|
|
|
|
|
|
|
|
if param.proxies
|
|
|
|
chain = param.proxies.dup
|
|
|
|
chain.push(['host',param.peerhost,param.peerport])
|
|
|
|
ip = chain[0][1]
|
|
|
|
port = chain[0][2].to_i
|
|
|
|
end
|
2012-05-24 23:10:26 +00:00
|
|
|
|
2011-12-10 21:24:10 +00:00
|
|
|
begin
|
2008-11-11 05:11:40 +00:00
|
|
|
|
2009-07-09 21:45:52 +00:00
|
|
|
begin
|
2009-11-02 18:14:57 +00:00
|
|
|
Timeout.timeout(param.timeout) do
|
2009-10-20 17:24:33 +00:00
|
|
|
sock.connect(Rex::Socket.to_sockaddr(ip, port))
|
2009-07-09 21:45:52 +00:00
|
|
|
end
|
|
|
|
rescue ::Timeout::Error
|
|
|
|
raise ::Errno::ETIMEDOUT
|
2009-11-02 18:14:57 +00:00
|
|
|
end
|
2009-07-09 21:45:52 +00:00
|
|
|
|
2010-11-19 22:28:35 +00:00
|
|
|
rescue ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL
|
2011-12-10 21:24:10 +00:00
|
|
|
|
|
|
|
# Rescue errors caused by a bad Scope ID for a link-local address
|
|
|
|
if retry_scopes and @@ip6_lla_scopes[ ip6_scope_idx ]
|
2012-05-24 23:10:26 +00:00
|
|
|
ip = param.peerhost + "%" + @@ip6_lla_scopes[ ip6_scope_idx ]
|
2011-12-10 21:24:10 +00:00
|
|
|
ip6_scope_idx += 1
|
|
|
|
retry
|
|
|
|
end
|
2012-05-24 23:10:26 +00:00
|
|
|
|
2007-04-24 06:27:39 +00:00
|
|
|
sock.close
|
|
|
|
raise Rex::HostUnreachable.new(param.peerhost, param.peerport), caller
|
2010-11-19 22:32:29 +00:00
|
|
|
|
2010-11-19 22:28:35 +00:00
|
|
|
rescue ::Errno::EADDRNOTAVAIL,::Errno::EADDRINUSE
|
|
|
|
sock.close
|
|
|
|
raise Rex::AddressInUse.new(param.peerhost, param.peerport), caller
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2007-04-24 06:27:39 +00:00
|
|
|
rescue Errno::ETIMEDOUT
|
|
|
|
sock.close
|
|
|
|
raise Rex::ConnectionTimeout.new(param.peerhost, param.peerport), caller
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2008-11-11 05:11:40 +00:00
|
|
|
rescue ::Errno::ECONNRESET,::Errno::ECONNREFUSED,::Errno::ENOTCONN,::Errno::ECONNABORTED
|
2005-11-27 18:42:44 +00:00
|
|
|
sock.close
|
2005-06-04 20:38:49 +00:00
|
|
|
raise Rex::ConnectionRefused.new(param.peerhost, param.peerport), caller
|
|
|
|
end
|
2005-06-03 04:51:51 +00:00
|
|
|
end
|
2005-06-02 07:52:17 +00:00
|
|
|
|
2005-11-15 20:33:55 +00:00
|
|
|
if (param.bare? == false)
|
|
|
|
case param.proto
|
|
|
|
when 'tcp'
|
|
|
|
klass = Rex::Socket::Tcp
|
|
|
|
sock.extend(klass)
|
|
|
|
sock.initsock(param)
|
|
|
|
when 'udp'
|
|
|
|
sock.extend(Rex::Socket::Udp)
|
|
|
|
sock.initsock(param)
|
|
|
|
end
|
|
|
|
end
|
2005-12-18 02:19:21 +00:00
|
|
|
|
2006-01-27 05:33:08 +00:00
|
|
|
if chain.size > 1
|
|
|
|
chain.each_with_index {
|
|
|
|
|proxy, i|
|
|
|
|
next_hop = chain[i + 1]
|
|
|
|
if next_hop
|
|
|
|
proxy(sock, proxy[0], next_hop[1], next_hop[2])
|
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2009-09-27 15:36:30 +00:00
|
|
|
# Now extend the socket with SSL and perform the handshake
|
|
|
|
if(param.bare? == false and param.ssl)
|
|
|
|
klass = Rex::Socket::SslTcp
|
|
|
|
sock.extend(klass)
|
2009-11-02 18:14:57 +00:00
|
|
|
sock.initsock(param)
|
2009-09-27 15:36:30 +00:00
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
|
|
|
|
2005-11-15 20:33:55 +00:00
|
|
|
end
|
2005-06-03 22:51:09 +00:00
|
|
|
|
2005-11-15 20:33:55 +00:00
|
|
|
# Notify handlers that a socket has been created.
|
|
|
|
self.instance.notify_socket_created(self, sock, param)
|
2005-09-27 05:31:48 +00:00
|
|
|
|
2005-11-15 20:33:55 +00:00
|
|
|
sock
|
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2009-06-03 01:24:35 +00:00
|
|
|
def self.proxy(sock, type, host, port)
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2008-07-01 01:44:56 +00:00
|
|
|
#$stdout.print("PROXY\n")
|
2007-09-24 04:44:44 +00:00
|
|
|
case type.downcase
|
2009-01-24 06:32:06 +00:00
|
|
|
when 'http'
|
2009-02-05 21:29:15 +00:00
|
|
|
setup = "CONNECT #{host}:#{port} HTTP/1.0\r\n\r\n"
|
2009-01-24 06:32:06 +00:00
|
|
|
size = sock.put(setup)
|
|
|
|
if (size != setup.length)
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
|
2009-01-24 06:32:06 +00:00
|
|
|
end
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2009-01-24 06:32:06 +00:00
|
|
|
begin
|
|
|
|
ret = sock.get_once(39,30)
|
|
|
|
rescue IOError
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
|
2009-01-24 06:32:06 +00:00
|
|
|
end
|
2009-01-24 14:48:18 +00:00
|
|
|
|
|
|
|
if ret.nil?
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
|
2009-01-24 14:48:18 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
resp = Rex::Proto::Http::Response.new
|
|
|
|
resp.update_cmd_parts(ret.split(/\r?\n/)[0])
|
|
|
|
|
|
|
|
if resp.code != 200
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "The proxy returned a non-OK response"), caller
|
2009-01-24 06:32:06 +00:00
|
|
|
end
|
2007-09-24 04:44:44 +00:00
|
|
|
when 'socks4'
|
|
|
|
setup = [4,1,port.to_i].pack('CCn') + Socket.gethostbyname(host)[3] + Rex::Text.rand_text_alpha(rand(8)+1) + "\x00"
|
2006-01-27 05:33:08 +00:00
|
|
|
size = sock.put(setup)
|
2007-09-24 04:44:44 +00:00
|
|
|
if (size != setup.length)
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
|
2006-01-27 05:33:08 +00:00
|
|
|
end
|
2008-07-01 01:44:56 +00:00
|
|
|
|
2006-01-27 05:33:08 +00:00
|
|
|
begin
|
|
|
|
ret = sock.get_once(8, 30)
|
|
|
|
rescue IOError
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
|
2006-01-27 05:33:08 +00:00
|
|
|
end
|
2008-07-01 01:44:56 +00:00
|
|
|
|
2006-01-27 05:33:08 +00:00
|
|
|
if (ret.nil? or ret.length < 8)
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a complete response from the proxy"), caller
|
2006-01-27 05:33:08 +00:00
|
|
|
end
|
2009-09-27 15:36:30 +00:00
|
|
|
if ret[1,1] != "\x5a"
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Proxy responded with error code #{ret[0,1].unpack("C")[0]}"), caller
|
2006-01-27 05:33:08 +00:00
|
|
|
end
|
2008-06-22 22:55:38 +00:00
|
|
|
when 'socks5'
|
|
|
|
auth_methods = [5,1,0].pack('CCC')
|
|
|
|
size = sock.put(auth_methods)
|
|
|
|
if (size != auth_methods.length)
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
|
2008-06-22 22:55:38 +00:00
|
|
|
end
|
2009-09-27 15:36:30 +00:00
|
|
|
ret = sock.get_once(2,30)
|
|
|
|
if (ret[1,1] == "\xff")
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "The proxy requires authentication"), caller
|
2008-06-22 22:55:38 +00:00
|
|
|
end
|
|
|
|
|
2008-07-01 01:44:56 +00:00
|
|
|
if (Rex::Socket.is_ipv4?(host))
|
2009-11-02 18:14:57 +00:00
|
|
|
addr = Rex::Socket.gethostbyname(host)[3]
|
2008-07-01 01:44:56 +00:00
|
|
|
setup = [5,1,0,1].pack('C4') + addr + [port.to_i].pack('n')
|
|
|
|
elsif (Rex::Socket.support_ipv6? and Rex::Socket.is_ipv6?(host))
|
|
|
|
# IPv6 stuff all untested
|
2009-11-02 18:14:57 +00:00
|
|
|
addr = Rex::Socket.gethostbyname(host)[3]
|
2008-07-01 01:44:56 +00:00
|
|
|
setup = [5,1,0,4].pack('C4') + addr + [port.to_i].pack('n')
|
|
|
|
else
|
|
|
|
# Then it must be a domain name.
|
|
|
|
# Unfortunately, it looks like the host has always been
|
|
|
|
# resolved by the time it gets here, so this code never runs.
|
|
|
|
setup = [5,1,0,3].pack('C4') + [host.length].pack('C') + host + [port.to_i].pack('n')
|
|
|
|
end
|
|
|
|
|
2008-06-22 22:55:38 +00:00
|
|
|
size = sock.put(setup)
|
|
|
|
if (size != setup.length)
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
|
2008-06-22 22:55:38 +00:00
|
|
|
end
|
2008-07-01 01:44:56 +00:00
|
|
|
|
2008-06-22 22:55:38 +00:00
|
|
|
begin
|
|
|
|
response = sock.get_once(10, 30)
|
|
|
|
rescue IOError
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
|
2008-06-22 22:55:38 +00:00
|
|
|
end
|
2008-07-01 01:44:56 +00:00
|
|
|
|
|
|
|
if (response.nil? or response.length < 10)
|
2009-11-04 16:36:06 +00:00
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a complete response from the proxy"), caller
|
2008-06-22 22:55:38 +00:00
|
|
|
end
|
2009-11-04 16:36:06 +00:00
|
|
|
if response[1,1] != "\x00"
|
|
|
|
raise Rex::ConnectionProxyError.new(host, port, type, "Proxy responded with error code #{response[1,1].unpack("C")[0]}"), caller
|
2008-06-22 22:55:38 +00:00
|
|
|
end
|
2006-01-27 05:33:08 +00:00
|
|
|
else
|
2009-11-04 16:36:06 +00:00
|
|
|
raise RuntimeError, "The proxy type specified is not valid", caller
|
2006-01-27 05:33:08 +00:00
|
|
|
end
|
|
|
|
end
|
2005-09-27 05:31:48 +00:00
|
|
|
|
2005-11-15 20:33:55 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Registration
|
|
|
|
#
|
|
|
|
##
|
2009-11-02 18:14:57 +00:00
|
|
|
|
2005-11-15 20:33:55 +00:00
|
|
|
def self.register_event_handler(handler) # :nodoc:
|
|
|
|
self.instance.register_event_handler(handler)
|
|
|
|
end
|
2005-09-27 05:31:48 +00:00
|
|
|
|
2005-11-15 20:33:55 +00:00
|
|
|
def self.deregister_event_handler(handler) # :nodoc:
|
|
|
|
self.instance.deregister_event_handler(handler)
|
|
|
|
end
|
2005-09-27 05:31:48 +00:00
|
|
|
|
2005-11-15 20:33:55 +00:00
|
|
|
def self.each_event_handler(handler) # :nodoc:
|
|
|
|
self.instance.each_event_handler(handler)
|
2005-06-02 07:52:17 +00:00
|
|
|
end
|
|
|
|
|
2008-11-11 05:11:40 +00:00
|
|
|
end
|