class Metasploit::Aggregator::Tlv::Tlv

Base TLV (Type-Length-Value) class

Constants

HEADER_SIZE

Attributes

compress[RW]
type[RW]
value[RW]

Public Class Methods

new(type, value = nil, compress=false) click to toggle source

Returns an instance of a TLV.

# File lib/metasploit/aggregator/tlv/packet.rb, line 170
def initialize(type, value = nil, compress=false)
  @type     = type
  @compress = compress

  if (value != nil)
    if (type & TLV_META_TYPE_STRING == TLV_META_TYPE_STRING)
      if (value.kind_of?(Integer))
        @value = value.to_s
      else
        @value = value.dup
      end
    else
      @value = value
    end
  end
end

Public Instance Methods

from_r(raw) click to toggle source

Translates the raw format of the TLV into a sanitize version.

# File lib/metasploit/aggregator/tlv/packet.rb, line 300
def from_r(raw)
  self.value  = nil

  length, self.type = raw.unpack("NN");

  # check if the tlv value has been compressed...
  if( self.type & TLV_META_TYPE_COMPRESSED == TLV_META_TYPE_COMPRESSED )
    # set this TLV as using compression
    @compress = true
    # remove the TLV_META_TYPE_COMPRESSED flag from the tlv type to restore the
    # tlv type to its original, allowing for transparent data compression.
    self.type = self.type ^ TLV_META_TYPE_COMPRESSED
    # decompress the compressed data (skipping the length and type DWORD's)

    # disable raw_decompression for now - not needed by aggregator at this time
    # raw_decompressed = Rex::Text.zlib_inflate( raw[HEADER_SIZE..length-1] )
    #
    # # update the length to reflect the decompressed data length (+HEADER_SIZE for the length and type DWORD's)
    # length = raw_decompressed.length + HEADER_SIZE
    # # update the raw buffer with the new length, decompressed data and updated type.
    # raw = [length, self.type].pack("NN") + raw_decompressed
  end

  if (self.type & TLV_META_TYPE_STRING == TLV_META_TYPE_STRING)
    if (raw.length > 0)
      self.value = raw[HEADER_SIZE..length-2]
    else
      self.value = nil
    end
  elsif (self.type & TLV_META_TYPE_UINT == TLV_META_TYPE_UINT)
    self.value = raw.unpack("NNN")[2]
  elsif (self.type & TLV_META_TYPE_QWORD == TLV_META_TYPE_QWORD)
    self.value = raw.unpack("NNQ<")[2]
    self.value = self.ntohq( self.value )
  elsif (self.type & TLV_META_TYPE_BOOL == TLV_META_TYPE_BOOL)
    self.value = raw.unpack("NNc")[2]

    if (self.value == 1)
      self.value = true
    else
      self.value = false
    end
  else
    self.value = raw[HEADER_SIZE..length-1]
  end

  length
end
inspect() click to toggle source
# File lib/metasploit/aggregator/tlv/packet.rb, line 187
def inspect
  utype = type ^ TLV_META_TYPE_COMPRESSED
  group = false
  meta = case (utype & TLV_META_MASK)
           when TLV_META_TYPE_STRING; "STRING"
           when TLV_META_TYPE_UINT; "INT"
           when TLV_META_TYPE_RAW; "RAW"
           when TLV_META_TYPE_BOOL; "BOOL"
           when TLV_META_TYPE_QWORD; "QWORD"
           when TLV_META_TYPE_GROUP; group=true; "GROUP"
           when TLV_META_TYPE_COMPLEX; "COMPLEX"
           else; 'unknown-meta-type'
         end
  stype = "unknown-#{type}"
  Metasploit::Aggregator::Tlv.constants.each do |value|
    next unless Metasploit::Aggregator::Tlv.const_get(value) == type
    stype = value.to_s
    break
  end
  val = value.inspect
  if val.length > 50
    val = val[0,50] + ' ..."'
  end
  group ||= (self.class.to_s =~ /Packet/)
  if group
    tlvs_inspect = "tlvs=[\n"
    @tlvs.each { |t|
      tlvs_inspect << "  #{t.inspect}\n"
    }
    tlvs_inspect << "]"
  else
    tlvs_inspect = "meta=#{meta.ljust 10} value=#{val}"
  end
  "#<#{self.class} type=#{stype.ljust 15} #{tlvs_inspect}>"
end
meta_type?(meta) click to toggle source

Checks to see if a TLVs meta type is equivalent to the meta type passed.

# File lib/metasploit/aggregator/tlv/packet.rb, line 232
def meta_type?(meta)
  return (self.type & meta == meta)
end
to_r() click to toggle source

Converts the TLV to raw.

# File lib/metasploit/aggregator/tlv/packet.rb, line 259
def to_r
  # Forcibly convert to ASCII-8BIT encoding
  raw = value.to_s.unpack("C*").pack("C*")

  if (self.type & TLV_META_TYPE_STRING == TLV_META_TYPE_STRING)
    raw += "\x00"
  elsif (self.type & TLV_META_TYPE_UINT == TLV_META_TYPE_UINT)
    raw = [value].pack("N")
  elsif (self.type & TLV_META_TYPE_QWORD == TLV_META_TYPE_QWORD)
    raw = [ self.htonq( value.to_i ) ].pack("Q<")
  elsif (self.type & TLV_META_TYPE_BOOL == TLV_META_TYPE_BOOL)
    if (value == true)
      raw = [1].pack("c")
    else
      raw = [0].pack("c")
    end
  end

  # check if the tlv is to be compressed...
  if @compress
    raw_uncompressed = raw
    # compress the raw data
    raw_compressed = Rex::Text.zlib_deflate( raw_uncompressed )
    # check we have actually made the raw data smaller...
    # (small blobs often compress slightly larger then the origional)
    # if the compressed data is not smaller, we dont use the compressed data
    if( raw_compressed.length < raw_uncompressed.length )
      # if so, set the TLV's type to indicate compression is used
      self.type = self.type | TLV_META_TYPE_COMPRESSED
      # update the raw data with the uncompressed data length + compressed data
      # (we include the uncompressed data length as the C side will need to know this for decompression)
      raw = [ raw_uncompressed.length ].pack("N") + raw_compressed
    end
  end

  [raw.length + HEADER_SIZE, self.type].pack("NN") + raw
end
type?(type) click to toggle source

Checks to see if the TLVs type is equivalent to the type passed.

# File lib/metasploit/aggregator/tlv/packet.rb, line 239
def type?(type)
  return self.type == type
end
value?(value) click to toggle source

Checks to see if the TLVs value is equivalent to the value passed.

# File lib/metasploit/aggregator/tlv/packet.rb, line 246
def value?(value)
  return self.value == value
end

Protected Instance Methods

htonq(value) click to toggle source
# File lib/metasploit/aggregator/tlv/packet.rb, line 351
def htonq(value)
  if [1].pack( 's' ) == [1].pack('n')
    return value
  else
    [value].pack('Q<').reverse.unpack('Q<').first
  end
end
ntohq(value) click to toggle source
# File lib/metasploit/aggregator/tlv/packet.rb, line 359
def ntohq(value)
  htonq(value)
end