#!/usr/bin/perl
my $html=shift;
my $dsa_list=shift;
my $dtsa_list=shift;
my $dla_list=shift;
my $our_list=shift;
my %cves;
sub read_dsa {
my $list=shift;
open (DSA, "<$list") || die "$list: $!\n";
my $dsa;
while () {
if (/^\[/) {
($dsa)=m/(DT?SA-.*?|DLA-.*?) /;
}
if (/\{\s*(CVE)/) {
my ($cvelist)=m/\{(.*)\}/;
foreach my $cve (split ' ', $cvelist) {
next unless $cve=~/^CVE-\d+/;
$cves{$cve}{cve}=$cve;
push @{$cves{$cve}{xref}}, $dsa;
}
}
}
close DSA;
}
read_dsa($dsa_list);
read_dsa($dtsa_list);
read_dsa($dla_list);
my %listedcves;
open (HTML, "<$html") || die "$html: $!\n";
my $cve;
while () {
if (m!Name:\s+(CVE-\d+-\d+)!) {
$cve=$1;
$cves{$cve}{cve}=$cve;
$listedcves{$cve}=1;
}
if (m!\*\*\s+RESERVED\s+\*\*!) {
$cves{$cve}{reserved}=1;
}
if (m!\*\*\s+REJECT\s+\*\*!) {
$cves{$cve}{rejected}=1;
}
if (m!Description:\s*\s*(.*)
! &&
! m!\*\*\s+RESERVED\s+\*\*! && ! m!\*\*\s+REJECT\s+\*\*!) {
my $desc;
$desc=$1;
if (! length $desc) {
$desc=;
chomp $desc;
}
# truncate length of description text added to lists
$desc = substr( $desc, 0, 70 );
$cves{$cve}{description}="($desc ...)";
}
}
close HTML;
my $stopped=0;
my @out;
sub docve {
my $cve=shift;
push @out, "$cve".(length $cves{$cve}{description} ? " ".$cves{$cve}{description} : "")."\n";
if ($cves{$cve}{reserved}) {
push @out, "\tRESERVED\n";
}
if ($cves{$cve}{rejected}) {
push @out, "\tREJECTED\n";
}
if (scalar @{$cves{$cve}{xref}} > 0) {
push @out, "\t{".join(" ", @{$cves{$cve}{xref}})."}\n";
}
if ($cves{$cve}{notes}) {
foreach (@{$cves{$cve}{notes}}) {
if (length(@{$cves{$cve}{notes}}) == 1 &&
$cves{$cve}{rejected} && m/(?:TODO: check$|to be rejected)/) {
next;
}
push @out, "\t$_\n";
}
}
if (! $cves{$cve}{reserved} && ! $cves{$cve}{rejected} &&
! $cves{$cve}{notes} &&
! $stopped) {
if ($cve =~ /^CVE-199|^CVE-200[012]/) {
push @out, "\tNOT-FOR-US: Data pre-dating the Security Tracker\n";
}
else {
push @out, "\tTODO: check\n";
}
}
delete $cves{$cve};
}
open (IN, "<$our_list") || die "$our_list: $!\n";
my $cve;
while () {
chomp;
if (/^(CVE-(?:[0-9]+|[A-Z]+)-(?:[0-9]+|[A-Z]+))\s*(.*)/) {
my $desc=$2;
docve($cve) if $cve;
$cve=$1;
if (length $desc && $desc !~ /^\(.*\)$/ &&
(! exists $cves{$cve}{description} ||
! length $cves{$cve}{description})) {
$cves{$cve}{description}=$desc;
}
}
elsif (/^\s+(RESERVED|REJECTED)\s*$/) {
# skip it
}
elsif (/^\s+NOTE: covered by DT?SA.*/) {
# skip it (old form)
}
elsif (/^\s+{\s*(.+?)\s*}/) {
my @xrefs=split('\s+', $1);
push @{$cves{$cve}{xref}}, grep(!/^(?:DT?SA|DLA)/, @xrefs);
}
elsif (/^\s+(.*)/ && $cve) {
push @{$cves{$cve}{notes}}, $1;
}
elsif (/^STOP/) {
docve($cve) if $cve;
push @out, "$_\n";
$stopped=1;
$cve='';
}
else {
docve($cve) if $cve;
push @out, "$_\n" if length $_;
$cve='';
}
}
close IN;
docve($cve) if $cve;
foreach my $cve (reverse sort { $cves{$a}{cve} cmp $cves{$b}{cve} } keys %cves) {
next unless $listedcves{$cve};
print $cve.(length $cves{$cve}{description} ? " ".$cves{$cve}{description} : "")."\n";
if ($cves{$cve}{reserved}) {
print "\tRESERVED\n";
}
if ($cves{$cve}{rejected}) {
print "\tREJECTED\n";
}
if (scalar @{$cves{$cve}{xref}} > 0) {
print "\t{".join(" ", @{$cves{$cve}{xref}})."}\n";
}
if (!$cves{$cve}{reserved} || $cves{$cve}{rejected} ) {
print "\tTODO: check\n";
}
}
print @out;