module Rex::Parser::NokogiriDocMixin

Public Class Methods

new(args,db,&block) click to toggle source
Calls superclass method
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 45
def initialize(args,db,&block)
  @args = args
  @db = db
  @state = {}
  @state[:current_tag] = {}
  @block = block if block
  @report_data = {:wspace => args[:wspace]}
  @nx_console_id = args[:nx_console_id]
  super()
end

Public Instance Methods

attr_hash(attrs) click to toggle source

Turn XML attribute pairs in to more workable hashes (there are better Enumerable tricks in Ruby 1.9, but ignoring for now)

# File lib/rex/parser/nokogiri_doc_mixin.rb, line 58
def attr_hash(attrs)
  h = {}
  attrs.each {|k,v| h[k] = v}
  h
end
cdata_block(text) click to toggle source

Effectively the same as characters()

# File lib/rex/parser/nokogiri_doc_mixin.rb, line 212
def cdata_block(text)
  return unless @state[:has_text]
  @text ||= ""
  @text << text
end
characters(text) click to toggle source

This breaks xml-encoded characters, so need to append. It’s on the end_element tag name to turn the appending off and clear out the data.

# File lib/rex/parser/nokogiri_doc_mixin.rb, line 205
def characters(text)
  return unless @state[:has_text]
  @text ||= ""
  @text << text
end
db_report(table, data) click to toggle source

Circumvent the unknown attribute logging by the various reporters. They seem to be there just for debugging anyway.

# File lib/rex/parser/nokogiri_doc_mixin.rb, line 139
def db_report(table, data)
  raise "Data should be a hash" unless data.kind_of? Hash
  nonempty_data = data.reject {|k,v| v.nil?}
  valid_attrs = db_valid_attributes(table)
  raise "Unknown table `#{table}'" if valid_attrs.empty?
  case table
  when :note, :web_site, :web_page, :web_form, :web_vuln
    just_the_facts = nonempty_data
  else
    just_the_facts = nonempty_data.select {|k,v| valid_attrs.include? k.to_s.to_sym}
  end
  return nil if just_the_facts.empty?
  just_the_facts[:task] = @args[:task]
  db.send("report_#{table}", just_the_facts)
end
db_valid_attributes(table) click to toggle source

XXX: It would be better to either have a single registry of acceptable keys if we’re going to alert on bad ones, or to be more forgiving if the caller is this thing. There is basically no way to tell if report_host()‘s tastes are going to change with this scheme.

# File lib/rex/parser/nokogiri_doc_mixin.rb, line 159
def db_valid_attributes(table)
  case table.to_s.to_sym
  when :host
    ::Mdm::Host.new.attribute_names.map {|x| x.to_sym} |
      [:host, :workspace]
  when :service
    ::Mdm::Service.new.attribute_names.map {|x| x.to_sym} |
      [:host, :host_name, :mac, :workspace]
  when :vuln
    ::Mdm::Vuln.new.attribute_names.map {|x| x.to_sym} |
      [:host, :refs, :workspace, :port, :proto, :details, :exploited_at]
  when :vuln_details
    ::Mdm::VulnDetails.new.attribute_names.map {|x| x.to_sym} | [ :key ]
  when :host_details
    ::Mdm::HostDetails.new.attribute_names.map {|x| x.to_sym} | [ :key ]
  when :note, :web_site, :web_page, :web_form, :web_vuln
    # These guys don't complain
    [:anything]
  else
    []
  end
end
determine_port_state(v) click to toggle source

XXX: Document classes ought to define this

# File lib/rex/parser/nokogiri_doc_mixin.rb, line 133
def determine_port_state(v)
  return v
end
end_document() click to toggle source
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 218
def end_document
  block = @block
  return unless @report_type_ok
  unless @state[:current_tag].empty?
    missing_ends = @state[:current_tag].keys.map {|x| "'#{x}'"}.join(", ")
    msg = "Warning, the provided file is incomplete, and there may be missing\n"
    msg << "data. The following tags were not closed: #{missing_ends}."
    db.emit(:warning,msg,&block) if block
  end
end
host_is_okay() click to toggle source

If there’s an address, it’s not on the blacklist, it has ports, and the port list isn’t empty… it’s okay.

# File lib/rex/parser/nokogiri_doc_mixin.rb, line 120
def host_is_okay
  return false unless @report_data[:host]
  return false unless valid_ip(@report_data[:host])
  return false unless @report_data[:state] == Msf::HostState::Alive
  if @args[:blacklist]
    return false if @args[:blacklist].include?(@report_data[:host])
  end
  return false unless @report_data[:ports]
  return false if @report_data[:ports].empty?
  return true
end
in_tag(tagname) click to toggle source
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 113
def in_tag(tagname)
  @state[:current_tag].keys.include? tagname
end
normalize_attrs(attrs) click to toggle source

Nokogiri 1.4.4 (and presumably beyond) generates attrs as pairs, like [[“value1”,“foo”],] (but not hashes for some reason). 1.4.3.1 (and presumably 1.4.3.x and prior) generates attrs as a flat array of strings. We want array_pairs.

# File lib/rex/parser/nokogiri_doc_mixin.rb, line 186
def normalize_attrs(attrs)
  attr_pairs = []
  case attrs.first
  when Array, NilClass
    attr_pairs = attrs
  when String
    attrs.each_index {|i|
      next if i % 2 == 0
      attr_pairs << [attrs[i-1],attrs[i]]
    }
  else # Wow, yet another format! It's either from the distant past or distant future.
    raise ::Msf::DBImportError.new("Unknown format for XML attributes. Please check your Nokogiri version.")
  end
  return attr_pairs
end
normalize_ref(ref_type, ref_value) click to toggle source
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 70
def normalize_ref(ref_type, ref_value)
  return if ref_type.nil? || ref_type.empty? || ref_value.nil? || ref_value.empty?
  ref_value = ref_value.strip
  ref_type = ref_type.strip.upcase

  ret = case ref_type
    when "CVE"
      ref_value.gsub("CAN", "CVE")
    when "MS"
      if ref_value =~ /^MS[0-9]/
        "MSB-#{ref_value}"
      else
        "MSB-MS#{ref_value}"
      end
    when "URL", "BID"
      "#{ref_type}-#{ref_value}"
    when "APPLE"
      ref_value
    when "XF"
      if ref_value =~ /\((\d+)\)$/
        "#{ref_type}-#{$1}"
      else
        "#{ref_type}-#{ref_value}"
      end
    else # Handle others?
      "#{ref_type}-#{ref_value}"
    end
  return ret
end
normalize_references(orig_refs) click to toggle source
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 100
def normalize_references(orig_refs)
  return [] unless orig_refs
  refs = []
  orig_refs.each do |ref_hash|

    ref_hash_sym = Hash[ref_hash.map {|k, v| [k.to_sym, v] }]
    ref_type = ref_hash_sym[:source].to_s.strip.upcase
    ref_value = ref_hash_sym[:value].to_s.strip
    refs << normalize_ref(ref_type, ref_value)
  end
  return refs.compact.uniq
end
valid_ip(addr) click to toggle source
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 64
def valid_ip(addr)
  valid = false
  valid = ::Rex::Socket::RangeWalker.new(addr).valid? rescue false
  !!valid
end