#!/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;