Initial revision

git-svn-id: file:///home/svn/incoming/trunk@3400 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
vlad902 2006-01-17 01:12:38 +00:00
parent ba0b13292b
commit dc83e49db2
2 changed files with 284 additions and 0 deletions

View File

@ -0,0 +1,174 @@
require 'rex/socket'
require 'rex/proto/sunrpc/xdr'
module Rex
module Proto
module SunRPC
# XXX: CPORT!
class Client
AUTH_NULL = 0
AUTH_UNIX = 1
PMAP_PROG = 100000
PMAP_VERS = 2
PMAP_GETPORT = 3
CALL = 0
MSG_ACCEPTED = 0
SUCCESS = 0
attr_reader :rhost, :proto_call, :program, :version
attr_accessor :pport
def initialize()
@pport = nil
@auth_type = AUTH_NULL
@auth_data = ''
@call_sock = nil
end
def create(rhost, rpcport, program, version, proto_create, proto_call)
if proto_create !~ /^(tcp|udp)$/ || proto_call !~ /^(tcp|udp)$/
raise ArgumentError, 'Protocol is not "tcp" or "udp"'
end
@rhost, @program, @version, @proto_call = rhost, program, version, proto_call.downcase
proto_num = 0
if @proto_create.eql?('tcp')
proto_num = 6
elsif @proto_create.eql?('udp')
proto_num = 17
end
buf =
XDR.encode(CALL, 2, PMAP_PROG, PMAP_VERS, PMAP_GETPORT,
@auth_type, [@auth_data, 400], AUTH_NULL, '',
@program, @version, proto_num, 0)
sock = SunRPC.make_rpc(@proto_create, @rhost, rpcport)
SunRPC.send_rpc(sock, buf)
ret = SunRPC.recv_rpc(sock)
SunRPC.close_rpc(sock)
arr = XDR.decode!(ret, Integer, Integer, Integer, String, Integer,
Integer)
if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS || arr[5] == 0
raise 'SunRPC.create() failed'
end
@pport = arr[5]
end
def call(procedure, buffer)
buf =
XDR.encode(CALL, 2, @program, @version, procedure,
@auth_type, [@auth_data, 400], AUTH_NULL, '')+
buffer
if !@call_sock
@call_sock = SunRPC.make_rpc(@proto_call, @rhost, @pport)
end
SunRPC.send_rpc(@call_sock, buf)
ret = SunRPC.recv_rpc(@call_sock)
arr = XDR.decode!(ret, Integer, Integer, Integer, String, Integer)
if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS
raise 'SunRPC.call() failed'
end
return ret
end
def destroy()
SunRPC.close_rpc(@call_sock) if @call_sock
end
def authnull_create()
@auth_type = AUTH_NULL
@auth_data = ''
end
def authunix_create(host, uid, gid, groupz)
raise ArgumentError, 'Hostname length is too long' if host.length > 255
raise ArgumentError, 'Too many groups' if groupz.length > 10
@auth_type = AUTH_UNIX
@auth_data =
XDR.encode(0, host, uid, gid, groupz) # XXX: TIME! GROUPZ?!
end
# XXX: Dirty, integrate some sort of request system into create/call?
def SunRPC.portmap_req(host, port, rpc_vers, procedure, buffer)
buf = XDR.encode(CALL, 2, PMAP_PROG, rpc_vers, procedure,
AUTH_NULL, '', AUTH_NULL, '') + buffer
sock = SunRPC.make_rpc('tcp', host, port)
SunRPC.send_rpc(sock, buf)
ret = SunRPC.recv_rpc(sock)
SunRPC.close_rpc(sock)
arr = XDR.decode!(ret, Integer, Integer, Integer, String, Integer)
if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS || arr[5] == 0
raise 'SunRPC: portmap_req failed'
end
return ret
end
# Msf::Config.data_directory
# def SunRPC.program2name(number)
# File.foreach('data/rpc_names') { |line|
# next if line.empty? || line =~ /^\s*#/
#
# if line =~ /^(\S+?)\s+(\d+)/ && number == $2.to_i
# return $1
# end
# }
#
# return "UNKNOWN-#{number}"
# end
private
def SunRPC.make_rpc(proto, host, port)
Rex::Socket.create_tcp(
'PeerHost' => host,
'PeerPort' => port,
'Proto' => proto)
end
def SunRPC.send_rpc(sock, buf)
buf = gen_xid() + buf
if sock.tcp?
buf = XDR.encode(0x80000000 | buf.length) + buf
end
sock.write(buf)
end
def SunRPC.recv_rpc(sock)
buf = sock.get_once(-1, 5)
buf.slice!(0..3)
if sock.tcp?
buf.slice!(0..3)
end
return buf
end
def SunRPC.close_rpc(sock)
sock.close
end
def SunRPC.gen_xid()
return XDR.encode(rand(0xffffffff) + 1)
end
end
end
end
end

110
lib/rex/proto/sunrpc/xdr.rb Normal file
View File

@ -0,0 +1,110 @@
module Rex
module Proto
module SunRPC
###
#
# This class implements basic XDR encoding.
#
###
module XDR
MAX_ARG = 0xffffffff
# Also: unsigned int, bool, enum
def XDR.encode_int(int)
return [int].pack('N')
end
def XDR.decode_int!(data)
return data.slice!(0..3).unpack('N')[0]
end
def XDR.encode_lchar(char)
char |= 0xffffff00 if char & 0x80 != 0
return encode_int(char)
end
def XDR.decode_lchar!(data)
return (decode_int!(data) & 0xff).chr
end
# Also: Variable length opaque
def XDR.encode_string(str, max=MAX_ARG)
raise ArgumentError, 'XDR: String too long' if str.length > max
len = str.length
str += "\x00" * ((4 - (len & 3)) & 3)
return encode_int(len) + str
end
def XDR.decode_string!(data)
real_len = decode_int!(data)
return "" if real_len == 0
align_len = (real_len + 3) & ~3
return data.slice!(0..align_len-1).slice(0..real_len-1)
end
def XDR.encode_varray(arr, max=MAX_ARG, &block)
raise ArgumentError, 'XDR: Too many array elements' if arr.length > max
return encode_int(arr.length) + arr.collect(&block).join(nil)
end
def XDR.decode_varray!(data)
buf = []
1.upto(decode_int!(data)) { buf.push(yield(data)) }
return buf
end
# encode(0, [0, 1], "foo", ["bar", 4]) does:
# encode_int(0) + encode_varray([0, 1]) { |i| XDR.encode_int(i) } +
# encode_string("foo") + encode_string("bar, 4)
def XDR.encode(*data)
data.collect do |var|
if var.kind_of?(String)
encode_string(var)
elsif var.kind_of?(Integer)
encode_int(var)
elsif var.kind_of?(Array) && var[0].kind_of?(String)
raise ArgumentError, 'XDR: Incorrect string array arguments' if var.length != 2
encode_string(var[0], var[1])
elsif var.kind_of?(Array) && var[0].kind_of?(Integer)
encode_varray(var) { |i| XDR.encode_int(i) }
# 0 means an empty array index in the case of Integer and an empty string in
# the case of String so we get the best of both worlds
elsif var.kind_of?(Array) && var[0].nil?
encode_int(0)
else
type = var.class
type = var[0].class if var.kind_of?(Array)
raise TypeError, "XDR: encode does not support #{type}"
end
end.join(nil)
end
# decode(buf, Integer, String, [Integer], [String]) does:
# [decode_int!(buf), decode_string!(buf),
# decode_varray!(buf) { |i| XDR.decode_int!(i) },
# decode_varray!(buf) { |s| XDR.decode_string(s) }]
def XDR.decode!(buf, *data)
return *data.collect do |var|
if data.length == 0
elsif var.kind_of?(Array) && var[0] == String
decode_varray!(buf) { |s| XDR.decode_string!(s) }
elsif var.kind_of?(Array) && var[0] == Integer
decode_varray!(buf) { |i| XDR.decode_int!(i) }
elsif var == String
decode_string!(buf)
elsif var == Integer
decode_int!(buf)
end
end
end
end
end
end
end