2005-06-02 07:52:17 +00:00
|
|
|
require 'socket'
|
|
|
|
require 'resolv'
|
2005-09-30 05:59:44 +00:00
|
|
|
require 'rex/exceptions'
|
2005-06-02 07:52:17 +00:00
|
|
|
|
|
|
|
module Rex
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# Base class for all sockets.
|
|
|
|
#
|
|
|
|
###
|
2005-09-27 05:31:48 +00:00
|
|
|
module Socket
|
2005-06-02 07:52:17 +00:00
|
|
|
|
2005-06-03 04:51:51 +00:00
|
|
|
module Comm
|
|
|
|
end
|
|
|
|
|
2005-07-09 21:18:49 +00:00
|
|
|
require 'rex/socket/parameters'
|
2005-07-24 20:53:54 +00:00
|
|
|
require 'rex/socket/tcp'
|
|
|
|
require 'rex/socket/tcp_server'
|
2005-09-30 05:59:44 +00:00
|
|
|
|
|
|
|
require 'rex/socket/comm'
|
2005-07-24 20:53:54 +00:00
|
|
|
require 'rex/socket/comm/local'
|
2005-09-30 05:59:44 +00:00
|
|
|
|
2005-09-30 05:48:45 +00:00
|
|
|
require 'rex/socket/switch_board'
|
2005-10-27 04:14:02 +00:00
|
|
|
require 'rex/socket/subnet_walker'
|
2005-06-03 04:51:51 +00:00
|
|
|
|
2005-06-02 07:52:17 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Factory methods
|
|
|
|
#
|
|
|
|
##
|
2005-11-15 05:22:13 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Create a socket instance using the supplied parameter hash.
|
|
|
|
#
|
2005-06-04 06:19:42 +00:00
|
|
|
def self.create(opts = {})
|
2005-06-02 07:52:17 +00:00
|
|
|
return create_param(Rex::Socket::Parameters.from_hash(opts))
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Create a socket using the supplied Rex::Socket::Parameter instance.
|
|
|
|
#
|
2005-06-02 07:52:17 +00:00
|
|
|
def self.create_param(param)
|
|
|
|
return param.comm.create(param)
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Create a TCP socket using the supplied parameter hash.
|
|
|
|
#
|
2005-06-04 06:19:42 +00:00
|
|
|
def self.create_tcp(opts = {})
|
2005-06-03 04:51:51 +00:00
|
|
|
return create_param(Rex::Socket::Parameters.from_hash(opts.merge('Proto' => 'tcp')))
|
2005-06-02 07:52:17 +00:00
|
|
|
end
|
2005-11-15 05:22:13 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Create a TCP server socket using the supplied parameter hash.
|
|
|
|
#
|
|
|
|
def self.create_tcp_server(opts = {})
|
2005-06-03 07:13:15 +00:00
|
|
|
return create_tcp(opts.merge('Server' => true))
|
|
|
|
end
|
2005-06-02 07:52:17 +00:00
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Create a UDP socket using the supplied parameter hash.
|
|
|
|
#
|
2005-06-04 06:19:42 +00:00
|
|
|
def self.create_udp(opts = {})
|
|
|
|
return create_param(Rex::Socket::Parameters.from_hash(opts.merge('Proto' => 'udp')))
|
|
|
|
end
|
|
|
|
|
2005-06-02 07:52:17 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Serialization
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
|
|
|
#
|
|
|
|
# Create a sockaddr structure using the supplied IP address, port, and
|
|
|
|
# address family
|
|
|
|
#
|
|
|
|
def self.to_sockaddr(ip, port, af = ::Socket::AF_INET)
|
|
|
|
ip = "0.0.0.0" unless ip
|
|
|
|
ip = Resolv.getaddress(ip)
|
|
|
|
data = [ af, port.to_i ] + ip.split('.').collect { |o| o.to_i } + [ "" ]
|
|
|
|
|
|
|
|
return data.pack('snCCCCa8')
|
|
|
|
end
|
|
|
|
|
2005-06-04 06:19:42 +00:00
|
|
|
#
|
|
|
|
# Returns the address family, host, and port of the supplied sockaddr as
|
|
|
|
# [ af, host, port ]
|
|
|
|
#
|
|
|
|
def self.from_sockaddr(saddr)
|
|
|
|
up = saddr.unpack('snCCCC')
|
|
|
|
|
|
|
|
af = up.shift
|
|
|
|
port = up.shift
|
|
|
|
|
|
|
|
return [ af, up.join('.'), port ]
|
|
|
|
end
|
|
|
|
|
2005-07-08 14:53:12 +00:00
|
|
|
#
|
2005-11-15 05:22:13 +00:00
|
|
|
# Resolves a host to raw network-byte order.
|
2005-07-08 14:53:12 +00:00
|
|
|
#
|
|
|
|
def self.resolv_nbo(host)
|
|
|
|
return to_sockaddr(host, 0)[4,4]
|
|
|
|
end
|
|
|
|
|
2005-10-27 04:14:02 +00:00
|
|
|
#
|
|
|
|
# Resolves a host to a network-byte order ruby integer.
|
|
|
|
#
|
2005-09-30 05:43:06 +00:00
|
|
|
def self.resolv_nbo_i(host)
|
|
|
|
return resolv_nbo(host).unpack('N')[0]
|
|
|
|
end
|
|
|
|
|
2005-10-27 04:14:02 +00:00
|
|
|
#
|
|
|
|
# Resolves a host to a dotted address.
|
|
|
|
#
|
|
|
|
def self.resolv_to_dotted(host)
|
|
|
|
Resolv.getaddress(host)
|
|
|
|
end
|
|
|
|
|
2005-09-30 05:43:06 +00:00
|
|
|
#
|
|
|
|
# Converts a netmask (255.255.255.240) into a bitmask (28). This is the
|
|
|
|
# lame kid way of doing it.
|
|
|
|
#
|
|
|
|
def self.net2bitmask(netmask)
|
|
|
|
raw = resolv_nbo(netmask).unpack('N')[0]
|
|
|
|
|
|
|
|
0.upto(31) { |bit|
|
|
|
|
p = 2 ** bit
|
|
|
|
return (32 - bit) if ((raw & p) == p)
|
|
|
|
}
|
|
|
|
|
|
|
|
0
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Converts a bitmask (28) into a netmask (255.255.255.240)
|
|
|
|
#
|
|
|
|
def self.bit2netmask(bitmask)
|
|
|
|
[ (~((2 ** (32 - bitmask)) - 1)) & 0xffffffff ].pack('N').unpack('CCCC').join('.')
|
|
|
|
end
|
|
|
|
|
2005-11-24 00:08:09 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Utility class methods
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
|
|
|
def self.source_address(dest='1.2.3.4')
|
|
|
|
self.create_udp(
|
|
|
|
'PeerHost' => dest,
|
|
|
|
'PeerPort' => 31337
|
|
|
|
).getsockname[1]
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2005-06-02 07:52:17 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Class initialization
|
|
|
|
#
|
|
|
|
##
|
2005-06-03 07:37:15 +00:00
|
|
|
|
2005-09-27 05:31:48 +00:00
|
|
|
#
|
|
|
|
# Initialize general socket parameters.
|
|
|
|
#
|
|
|
|
def initsock(params = nil)
|
2005-06-03 07:37:15 +00:00
|
|
|
if (params)
|
|
|
|
self.peerhost = params.peerhost
|
|
|
|
self.peerport = params.peerport
|
|
|
|
self.localhost = params.localhost
|
|
|
|
self.localport = params.localport
|
2005-11-24 18:50:33 +00:00
|
|
|
self.context = params.context || {}
|
2005-06-03 07:37:15 +00:00
|
|
|
end
|
2005-06-02 07:52:17 +00:00
|
|
|
end
|
|
|
|
|
2005-06-03 07:13:15 +00:00
|
|
|
#
|
2005-09-27 05:31:48 +00:00
|
|
|
# By default, all sockets are themselves selectable file descriptors.
|
2005-06-03 07:13:15 +00:00
|
|
|
#
|
2005-09-27 05:31:48 +00:00
|
|
|
def fd
|
|
|
|
self
|
2005-06-03 07:13:15 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2005-09-27 05:31:48 +00:00
|
|
|
# Returns local connection information.
|
2005-06-03 07:13:15 +00:00
|
|
|
#
|
2005-09-27 05:31:48 +00:00
|
|
|
def getsockname
|
|
|
|
return Socket.from_sockaddr(super)
|
2005-06-03 07:13:15 +00:00
|
|
|
end
|
|
|
|
|
2005-07-16 08:12:58 +00:00
|
|
|
#
|
2005-09-27 05:31:48 +00:00
|
|
|
# Wrapper around getsockname
|
2005-07-16 08:12:58 +00:00
|
|
|
#
|
|
|
|
def getlocalname
|
2005-09-27 05:31:48 +00:00
|
|
|
getsockname
|
2005-07-16 08:12:58 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Return peer connection information.
|
|
|
|
#
|
|
|
|
def getpeername
|
2005-09-27 05:31:48 +00:00
|
|
|
return Socket.from_sockaddr(super)
|
2005-07-16 08:12:58 +00:00
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# The peer host of the connected socket.
|
|
|
|
#
|
|
|
|
attr_reader :peerhost
|
|
|
|
#
|
|
|
|
# The peer port of the connected socket.
|
|
|
|
#
|
|
|
|
attr_reader :peerport
|
|
|
|
#
|
|
|
|
# The local host of the connected socket.
|
|
|
|
#
|
|
|
|
attr_reader :localhost
|
|
|
|
#
|
|
|
|
# The local port of the connected socket.
|
|
|
|
#
|
|
|
|
attr_reader :localport
|
2005-11-24 18:50:33 +00:00
|
|
|
#
|
|
|
|
# Contextual information that describes the source and other
|
|
|
|
# instance-specific attributes. This comes from the param.context
|
|
|
|
# attribute.
|
|
|
|
#
|
|
|
|
attr_reader :context
|
2005-06-02 07:52:17 +00:00
|
|
|
|
|
|
|
protected
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
attr_writer :peerhost, :peerport, :localhost, :localport # :nodoc:
|
2005-11-24 18:50:33 +00:00
|
|
|
attr_writer :context # :nodoc:
|
2005-06-02 07:52:17 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
2005-09-29 20:18:24 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Globalized socket constants
|
|
|
|
#
|
|
|
|
SHUT_RDWR = ::Socket::SHUT_RDWR
|
|
|
|
SHUT_RD = ::Socket::SHUT_RD
|
|
|
|
SHUT_WR = ::Socket::SHUT_WR
|