# -*- coding: binary -*-
module Rex
module Parser

# XXX - Retina XML does not include ANY service/port information export
class RetinaXMLStreamParser

  attr_accessor :on_found_host

  def initialize(on_found_host = nil)
    reset_state
    self.on_found_host = on_found_host if on_found_host
  end

  def reset_state
    @state = :generic_state
    @host  = { 'vulns' => [] }
    reset_audit_state
  end

  def reset_audit_state
    @audit = { 'refs' => [] }
  end

  def tag_start(name, attributes)
    @state = "in_#{name.downcase}".intern
  end

  def text(str)
    case @state
    when :in_ip
      @host["address"] = str
    when :in_dnsname
      @host["hostname"] = str.split(/\s+/).first
    when :in_netbiosname
      @host["netbios"] = str
    when :in_mac
      @host["mac"] = str
    when :in_os
      @host["os"] = str
    when :in_rthid
      @audit['refs'].push(['RETINA', str])
    when :in_cve
      str.split(",").each do |cve|
        cve = cve.to_s.strip
        next if cve.empty?
        pre,val = cve.split('-', 2)
        next if not val
        next if pre != "CVE"
        @audit['refs'].push( ['CVE', val] )
      end
    when :in_name
      @audit['name'] = str
    when :in_description
      @audit['description'] = str
    when :in_risk
      @audit['risk'] = str
    when :in_cce
      @audit['cce'] = str
    when :in_date
      @audit['data'] = str
    end
  end

  def tag_end(name)
    case name
    when "host"
      on_found_host.call(@host) if on_found_host
      reset_state
    when "audit"
      @host['vulns'].push @audit
      reset_audit_state
    end
  end

  # We don't need these methods, but they're necessary to keep REXML happy
  def xmldecl(version, encoding, standalone); end
  def cdata; end
  def comment(str); end
  def instruction(name, instruction); end
  def attlist; end
end
end
end

__END__
<scanJob>
  <hosts>
    <host>
      <ip>10.2.79.98</ip>
      <netBIOSName>bsmith-10156B07C</netBIOSName>
      <dnsName>bsmith-10156b07c.core.testcorp.com  random.testcorp.com</dnsName>
      <mac>00:02:29:0E:38:2B</mac>
      <os>Windows Server 2003 (X64), Service Pack 2</os>
      <audit>
        <rthID>7851</rthID>
        <cve>CVE-2009-0089,CVE-2009-0550,CVE-2009-0086</cve>
        <cce>N/A</cce>
        <name>Microsoft Windows HTTP Services Multiple Vulnerabilities (960803)</name>
        <description>Microsoft Windows HTTP Services contains multiple vulnerabilities when handling ..</description>
        <date>09/15/2010</date>
        <risk>Low</risk>
        <pciLevel>5 (Urgent)</pciLevel>
        <cvssScore>10 [AV:N/AC:L/Au:N/C:C/I:C/A:C]</cvssScore>
        <fixInformation>....</fixInformation>
      </audit>
    </host>
  </hosts>
</scanJob>

