class Rex::Proto::SunRPC::Client

XXX: CPORT!

Constants

AUTH_NULL
AUTH_UNIX
CALL
PMAP_GETPORT
PMAP_PROG
PMAP_VERS

Attributes

call_sock[RW]
context[RW]
pport[RW]
program[RW]
proto[RW]
rhost[RW]
rport[RW]
should_fragment[RW]
timeout[RW]
version[RW]

Public Class Methods

new(opts) click to toggle source
# File lib/rex/proto/sunrpc/client.rb, line 45
def initialize(opts)
  self.rhost   = opts[:rhost]
  self.rport   = opts[:rport]
  self.program = opts[:program]
  self.version = opts[:version]
  self.timeout = opts[:timeout] || 20
  self.context = opts[:context] || {}
  self.proto   = opts[:proto]

  if self.proto.downcase !~ /^(tcp|udp)$/
    raise ::Rex::ArgumentError, 'Protocol is not "tcp" or "udp"'
  end

  @pport = nil

  @auth_type = AUTH_NULL
  @auth_data = ''

  @call_sock = nil
end

Public Instance Methods

authnull_create() click to toggle source
# File lib/rex/proto/sunrpc/client.rb, line 107
def authnull_create
  @auth_type = AUTH_NULL
  @auth_data = ''
end
authunix_create(host, uid, gid, groupz) click to toggle source
# File lib/rex/proto/sunrpc/client.rb, line 112
  def authunix_create(host, uid, gid, groupz)
    raise ::Rex::ArgumentError, 'Hostname length is too long' if host.length > 255
# 10?
    raise ::Rex::ArgumentError, 'Too many groups' if groupz.length > 10

    @auth_type = AUTH_UNIX
    @auth_data =
      Rex::Encoder::XDR.encode(0, host, uid, gid, groupz) # XXX: TIME! GROUPZ?!
  end
call(procedure, buffer, maxwait = self.timeout) click to toggle source
# File lib/rex/proto/sunrpc/client.rb, line 88
def call(procedure, buffer, maxwait = self.timeout)
  buf =
    Rex::Encoder::XDR.encode(CALL, 2, @program, @version, procedure,
      @auth_type, [@auth_data, 400], AUTH_NULL, '')+
    buffer

  if ! @call_sock
    @call_sock = make_rpc(@proto, @rhost, @pport)
  end

  send_rpc(@call_sock, buf)
  recv_rpc(@call_sock, maxwait)
end
create() click to toggle source

XXX: Add optional parameter to have proto be something else

# File lib/rex/proto/sunrpc/client.rb, line 67
def create()
  proto_num = 0
  if @proto.eql?('tcp')
    proto_num = 6
  elsif @proto.eql?('udp')
    proto_num = 17
  end

  buf =
    Rex::Encoder::XDR.encode(CALL, 2, PMAP_PROG, PMAP_VERS, PMAP_GETPORT,
      @auth_type, [@auth_data, 400], AUTH_NULL, '',
      @program, @version, proto_num, 0)

  sock = make_rpc(@proto, @rhost, @rport)
  send_rpc(sock, buf)
  ret = recv_rpc(sock)
  close_rpc(sock)

  return ret
end
destroy() click to toggle source
# File lib/rex/proto/sunrpc/client.rb, line 102
def destroy
  close_rpc(@call_sock) if @call_sock
  @call_sock = nil
end
portmap_req(host, port, rpc_vers, procedure, buffer) click to toggle source

XXX: Dirty, integrate some sort of request system into create/call?

# File lib/rex/proto/sunrpc/client.rb, line 123
def portmap_req(host, port, rpc_vers, procedure, buffer)
  buf = Rex::Encoder::XDR.encode(CALL, 2, PMAP_PROG, rpc_vers, procedure,
    AUTH_NULL, '', AUTH_NULL, '') + buffer

  sock = make_rpc('tcp', host, port)
  send_rpc(sock, buf)
  ret = recv_rpc(sock)
  close_rpc(sock)

  return ret
end

Private Instance Methods

build_tcp(buf) click to toggle source
# File lib/rex/proto/sunrpc/client.rb, line 146
def build_tcp(buf)
  if !self.should_fragment
    return Rex::Encoder::XDR.encode(0x80000000 | buf.length) + buf
  end

  str = buf.dup

  fragmented = ''

  while (str.size > 0)
    frag = str.slice!(0, rand(3) + 1)
    len = frag.size
    if str.size == 0
      len |= 0x80000000
    end

    fragmented += Rex::Encoder::XDR.encode(len) + frag
  end

  return fragmented
end
close_rpc(sock) click to toggle source
# File lib/rex/proto/sunrpc/client.rb, line 194
def close_rpc(sock)
  sock.close
end
gen_xid() click to toggle source
# File lib/rex/proto/sunrpc/client.rb, line 198
def gen_xid
  return Rex::Encoder::XDR.encode(rand(0xffffffff) + 1)
end
make_rpc(proto, host, port) click to toggle source
# File lib/rex/proto/sunrpc/client.rb, line 136
def make_rpc(proto, host, port)
  Rex::Socket.create(
    'PeerHost'        => host,
    'PeerPort'        => port,
    'Proto'           => proto,
    'Timeout'   => self.timeout,
    'Context'   => self.context
  )
end
recv_rpc(sock, maxwait=self.timeout) click to toggle source
# File lib/rex/proto/sunrpc/client.rb, line 176
def recv_rpc(sock, maxwait=self.timeout)

  buf = nil
  begin
    Timeout.timeout(maxwait) { buf = sock.get }
  rescue ::Timeout
  end

  return nil if not buf

  buf.slice!(0..3)
  if sock.type?.eql?('tcp')
    buf.slice!(0..3)
  end
  return buf if buf.length > 1
  return nil
end
send_rpc(sock, buf) click to toggle source
# File lib/rex/proto/sunrpc/client.rb, line 168
def send_rpc(sock, buf)
  buf = gen_xid() + buf
  if sock.type?.eql?('tcp')
    buf = build_tcp(buf)
  end
  sock.put(buf)
end