On Thu, Nov 13, 2008 at 12:55:36PM -0500, Ted Unangst wrote: > On Thu, Nov 13, 2008 at 12:35 PM, Aaron W. Hsu <[EMAIL PROTECTED]> wrote: > > Is security-announce an open list? If not, give me access and I'll > > keep it reasonably up to date, give or take a day or so of release of > > the Security Errata on the website, unless there is an even faster way > > of checking it out, such as CVS. > > It is moderated, and really, outsiders should not be posting to it > because then it appears that they have some position of authority. > The only person who should be posting to the list is the person who > made the fix, because they are the security contact. When people > reply, it is important they are talking to the right person.
I just wrote something quick in perl that scrapes the errata pages of the two most recent releases and sends a nicely formatted email for any that are have change since the last check. It does require a couple of packages be installed (p5-libwww and p5-HTML-Tree) but if there were enough interest from someone who could do something with it, I could probably make it work with just what is available in the base system. There are lots of ways to break something that scrapes html, but it is at least automated. l8rZ, -- andrew - ICQ# 253198 - Jabber: [EMAIL PROTECTED] #!/usr/bin/perl -T use strict; use warnings; %ENV = (); #Additional modules needed use LWP::Simple; # pkg_add p5-libwww use HTML::TreeBuilder; # pkg_add p5-HTML-Tree # Core modules use Text::Wrap; use Fcntl ':flock'; # import LOCK_* constants # should end with a / my $base_url = 'http://www.OpenBSD.org/'; my $start_page = 'errata.html'; my $sender = '[EMAIL PROTECTED]'; my $recipient = '[EMAIL PROTECTED]'; # should end with a / my $base_dir = '/home/andrew/.openbsd_errata_notifier/'; my $max_versions_to_process = 2; #*#*# Nothing to change beyond this point #*#*# my $tree = HTML::TreeBuilder->new(); my $content = get( $base_url . $start_page ) or die "Could't get [$start_page]: $!"; $tree->parse($content)->eof; my @errata_urls; foreach my $link ( @{ $tree->extract_links('a') } ) { my ( $url, $element, $attr, $tag ) = @{$link}; if ( $url =~ /^errata\d+\.html\Z/xms ) { push @errata_urls, $base_url . $url; } } $tree->delete; my $processed = 0; URL: foreach my $url ( reverse @errata_urls ) { $processed++; last URL if $processed > $max_versions_to_process; my $tree = HTML::TreeBuilder->new(); my $content = get($url) or die "Couldn't get [$url]: $!"; $tree->parse($content)->eof; my $title = $tree->find('title')->as_trimmed_text; my ($version) = $title =~ /\b ( \d+ \. \d ) \b/xms; foreach my $entry ( reverse $tree->find('ul')->find('li') ) { my $errata = process_errata_entry($entry); $errata->{version} = $version; $errata->{url} = $url; my $message = format_errata_message($errata); my $file = make_errata_dir($errata); if ( should_send( $message, $file ) ) { mail($message); } } $tree->delete; } sub process_errata_entry { my ($errata) = @_; my $id = $errata->find('a')->attr('name'); my ( $num, $type, $date ) = split /:\s*/xms, $errata->find('strong')->as_trimmed_text; my $arch = $errata->find('i')->as_trimmed_text; my %errata = ( id => $id, number => $num, type => $type, date => $date, arch => $arch, ); foreach my $content ( $errata->content_list ) { if ( ref $content eq 'HTML::Element' ) { if ( my $href = $content->attr('href') ) { if ( $href =~ m{ftp\.openbsd\.org.*patch\Z}ixms ) { $errata{patch} = { href => $href, text => $content->as_trimmed_text, }; $content->delete; } elsif ( $href =~ m{CVE-} ) { push @{ $errata{cve} }, { href => $href, text => $content->as_trimmed_text, }; $content->delete; } } } } foreach my $br ( $errata->find('br') ) { $br->replace_with("\n"); } my @descr = split /\n/, $errata->as_text; shift @descr; pop @descr; foreach my $m (@descr) { $m =~ s/^\s+//xms; $m =~ s/\.\W+\Z/\./xms; } $errata{description} = [EMAIL PROTECTED]; return \%errata; } sub mail { my ($message) = @_; open( my $sendmail, "|/usr/sbin/sendmail -oi -t -odq" ) or die "Can't fork for sendmail: $!\n"; print $sendmail $message; close $sendmail or warn "sendmail didn't close nicely"; } sub format_errata_message { my ($errata) = @_; my $message = <<"EOL"; From: $sender To: $recipient EOL $message .= 'Subject: OpenBSD ' . $errata->{version} . ' Errata ' . $errata->{number} . q{: } . $errata->{type} . q{: } . $errata->{date} . q{ } . '(' . $errata->{arch} . ')' . "\n\n"; my $body .= join "\n\n", @{ $errata->{description} }; $body .= "\n\n"; if ( $errata->{patch} ) { $body .= $errata->{patch}->{text} . "\n"; $body .= $errata->{patch}->{href} . "\n\n"; } if ( $errata->{cve} ) { $body .= "The following CVE are addressed with this errata.\n"; foreach my $cve ( @{ $errata->{cve} } ) { $body .= $cve->{text} . "\n " . $cve->{href} . "\n"; } $body .= "\n"; } $body .= "For more information, see \n" . $errata->{url} . '#' . $errata->{id} . "\n"; $message .= wrap( '', '', $body ); return $message; } sub make_errata_dir { my ($errata) = @_; if ( !-d $base_dir ) { mkdir $base_dir or die "Couldn't mkdir [$base_dir]: $!"; } my $dir = $base_dir . $errata->{version}; if ( !-d $dir ) { mkdir $dir or die "Couldn't mkdir [$dir]: $!"; } return $dir . '/' . $errata->{id}; } sub should_send { my ( $message, $file ) = @_; if ( -e $file ) { open my $fh, '<', $file or die "Couldn't open [$file]: $!"; flock( $fh, LOCK_SH ); my $old_message = do { local $/; <$fh> }; flock( $fh, LOCK_UN ); close $fh; if ( $old_message eq $message ) { return; } } open my $fh, '>', $file or die "Couldn't open [$file]: $!"; flock( $fh, LOCK_EX ); print $fh $message; flock( $fh, LOCK_UN ); close $fh; return 1; }