metasploit-framework/lib/rex/parser/nokogiri_doc_mixin.rb

157 lines
4.0 KiB
Ruby
Raw Normal View History

module Rex
module Parser
# Determines if Nokogiri is available and if it's a minimum
# acceptable version.
def self.load_nokogiri
@nokogiri_loaded = false
begin
require 'nokogiri'
major,minor = Nokogiri::VERSION.split(".")[0,2]
if major.to_i >= 1
if minor.to_i >= 4
@nokogiri_loaded = true
end
end
rescue LoadError => e
@nokogiri_loaded = false
@nokogiri_error = e
end
@nokogiri_loaded
end
def self.nokogiri_loaded
!!@nokogiri_loaded
end
# Useful during development, shouldn't be used in normal operation.
def self.reload(fname)
$stdout.puts "Reloading #{fname}..."
load __FILE__
load File.join(File.expand_path(File.dirname(__FILE__)),fname)
end
end
end
module Rex
module Parser
load_nokogiri && module NokogiriDocMixin
# Set up the getters and instance variables for the document
eval("attr_reader :args, :db, :state, :block, :report_data")
def initialize(args,db,&block)
@args = args
@db = db
@state = {}
@state[:current_tag] = {}
@block = block if block
@report_data = {:wspace => args[:wspace]}
super()
end
# Turn XML attribute pairs in to more workable hashes (there
# are better Enumerable tricks in Ruby 1.9, but ignoring for now)
def attr_hash(attrs)
h = {}
attrs.each {|k,v| h[k] = v}
h
end
def valid_ip(addr)
valid = false
valid = ::Rex::Socket::RangeWalker.new(addr).valid? rescue false
!!valid
end
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"
"MSB-MS-#{ref_value}"
when "URL", "BID"
"#{ref_type}-#{ref_value}"
else # Handle others?
"#{ref_type}-#{ref_value}"
end
return ret
end
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
def in_tag(tagname)
@state[:current_tag].keys.include? tagname
end
# If there's an address, it's not on the blacklist,
# it has ports, and the port list isn't
# empty... it's okay.
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
# XXX: Document classes ought to define this
def determine_port_state(v)
return v
end
# Nokogiri 1.4.4 (and presumably beyond) generates attrs as pairs,
# like [["value1","foo"],["value2","bar"]] (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.
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
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
end
end
end