| 1 |
#!/usr/bin/perl
|
| 2 |
use warnings;
|
| 3 |
use strict;
|
| 4 |
|
| 5 |
my $user="debian-security\@lists.debian.org";
|
| 6 |
my $list=shift;
|
| 7 |
my $oldlist="$list.old";
|
| 8 |
|
| 9 |
if (! -e $list) {
|
| 10 |
die "$list does not exist\n";
|
| 11 |
}
|
| 12 |
if (! -e $oldlist) {
|
| 13 |
die "$oldlist does not exist (touch it if running for first time)\n";
|
| 14 |
}
|
| 15 |
|
| 16 |
my %old = processlist($oldlist);
|
| 17 |
my %new = processlist($list);
|
| 18 |
|
| 19 |
# Build up a list of changes between the two lists.
|
| 20 |
my @changes;
|
| 21 |
|
| 22 |
# Remove anything that is on both lists from both,
|
| 23 |
# so the lists only contain changes.
|
| 24 |
foreach my $bug (keys %old) {
|
| 25 |
foreach my $cve (keys %{$old{$bug}}) {
|
| 26 |
if (exists $new{$bug} && exists $new{$bug}{$cve}) {
|
| 27 |
delete $new{$bug}{$cve};
|
| 28 |
delete $old{$bug}{$cve};
|
| 29 |
}
|
| 30 |
}
|
| 31 |
}
|
| 32 |
|
| 33 |
# Remove tags for all old stuff. Hs to come before adding tags for new
|
| 34 |
# stuff, to deal with edge cases where bugs move between CVE ids.
|
| 35 |
foreach my $bug (keys %old) {
|
| 36 |
foreach my $cve (keys %{$old{$bug}}) {
|
| 37 |
push @changes, "usertag $bug - $cve"
|
| 38 |
unless $cve =~ /CVE-\d+-XXXX/;
|
| 39 |
push @changes, "usertag $bug - tracked";
|
| 40 |
}
|
| 41 |
}
|
| 42 |
|
| 43 |
# Add tags for all new stuff.
|
| 44 |
foreach my $bug (keys %new) {
|
| 45 |
foreach my $cve (keys %{$new{$bug}}) {
|
| 46 |
push @changes, "usertag $bug + $cve"
|
| 47 |
unless $cve =~ /CVE-\d+-XXXX/;
|
| 48 |
push @changes, "usertag $bug + tracked";
|
| 49 |
}
|
| 50 |
}
|
| 51 |
|
| 52 |
if (system("cp", $list, $oldlist) != 0) {
|
| 53 |
die "failed to copy $list to $oldlist, didn't send any mail";
|
| 54 |
}
|
| 55 |
|
| 56 |
if (@changes) {
|
| 57 |
open(MAIL, "| mail -s \"CVE usertag update\" control\@bugs.debian.org");
|
| 58 |
#open(MAIL, ">&STDOUT");
|
| 59 |
print MAIL "user $user\n";
|
| 60 |
print MAIL "$_\n" foreach @changes;
|
| 61 |
close MAIL;
|
| 62 |
}
|
| 63 |
print int(@changes)." tags changed\n";
|
| 64 |
|
| 65 |
sub processlist {
|
| 66 |
my $list=shift;
|
| 67 |
my %ret;
|
| 68 |
|
| 69 |
open (IN, $list) || die "read $list: $!\n";
|
| 70 |
my $cve;
|
| 71 |
while (<IN>) {
|
| 72 |
chomp;
|
| 73 |
if (/^(CVE-(?:[0-9]+|[A-Z]+)-(?:[0-9]+|[A-Z]+))\s*(.*)/) {
|
| 74 |
$cve=$1;
|
| 75 |
}
|
| 76 |
elsif (/\s+-\s+.*\((.*)\)/) {
|
| 77 |
my @notes=split(/\s*;\s+/, $1);
|
| 78 |
foreach my $note (@notes) {
|
| 79 |
if ($note =~ /bug #(\d+)/) {
|
| 80 |
if (! defined $cve) {
|
| 81 |
print STDERR "no cve for bug at line $.!\n";
|
| 82 |
next;
|
| 83 |
}
|
| 84 |
$ret{$1}{$cve}=1;
|
| 85 |
}
|
| 86 |
}
|
| 87 |
}
|
| 88 |
}
|
| 89 |
close IN;
|
| 90 |
|
| 91 |
return %ret;
|
| 92 |
}
|