Package: nagios-plugins-contrib
Version: 9.20140106
Tags: patch
check_packages incorrectly determines whether a security update is available
in the following cases:
1)
libxml2:
Installed: 2.8.0+dfsg1-7+nmu2
Candidate: 2.8.0+dfsg1-7+nmu3
Version table:
2.8.0+dfsg1-7+nmu3 0
500 http://ftp.fr.debian.org/debian/ wheezy-proposed-updates/main amd64
Packages
*** 2.8.0+dfsg1-7+nmu2 0
500 http://ftp.fr.debian.org/debian/ wheezy/main amd64 Packages
500 http://security.debian.org/ wheezy/updates/main amd64 Packages
100 /var/lib/dpkg/status
check_packages thinks there is a security update because it sees the security
line
without checking if that is actually part of the update.
$candidate_found is set to 1 after the "2.8.0+dfsg1-7+nmu3 0" line and never
reset to 0.
2)
[this apt-cache policy output is faked]
libxml2:
Installed: 2.8.0+dfsg1-7+nmu2
Candidate: 2.8.0+dfsg1-7+nmu4
Version table:
2.8.0+dfsg1-7+nmu4 0
500 http://ftp.fr.debian.org/debian/ wheezy-updates/main amd64 Packages
2.8.0+dfsg1-7+nmu3 0
500 http://security.debian.org/ wheezy/updates/main amd64 Packages
*** 2.8.0+dfsg1-7+nmu2 0
500 http://ftp.fr.debian.org/debian/ wheezy/main amd64 Packages
100 /var/lib/dpkg/status
Here it fails to notice the security update. $candidate_found is set to 0 after
the "2.8.0+dfsg1-7+nmu3 0" line so it fails to notice that a previous unapplied
update
fixed a security issue.
The attached updated security_updates_critical patch fixes this by resetting
$candidate_found only when parsing a different package from the apt-cache
output or
when parsing the installed version.
Cheers,
Felix
--- a/dsa/checks/dsa-check-packages
+++ b/dsa/checks/dsa-check-packages
@@ -94,6 +94,7 @@ sub get_packages {
chomp(@lines);
my $pkgname = undef;
+ my $candidate_found = 0;
while (defined($line = shift @lines)) {
if ($line =~ /^([^ ]*):$/) {
# when we have multi-arch capable fu, we require that
@@ -115,6 +116,7 @@ sub get_packages {
# For squeeze systems (no m-a), apt-cache policy output
# is all different.
$pkgname = $1;
+ $candidate_found = 0;
if ($has_arch) {
my $from_list = shift @installed_packages;
next if ($pkgname eq $from_list); # no :$arch in pkgname we asked for
@@ -132,12 +133,22 @@ sub get_packages {
} elsif ($line =~ /^ +Installed: (.*)$/) {
# etch dpkg -l does not print epochs, so use this info, it's better
$installed->{$pkgname}{'installed'} = $1;
+ # initialize security-update
+ $installed->{$pkgname}{'security-update'} = 0;
} elsif ($line =~ /^ +Candidate: (.*)$/) {
$installed->{$pkgname}{'candidate'} = $1;
+ } elsif ($line =~ / ([^ ]+) [0-9]+/) {
+ # check if the next lines show the sources of our candidate
+ if ($1 eq $installed->{$pkgname}{'candidate'}) {
+ $candidate_found = 1;
+ }
+ } elsif (($line =~ / +[0-9]+ [^ ]+\/(security\.([^ ]+\.)?debian\.org|debian-security).*\/updates\//) && $candidate_found ) {
+ $installed->{$pkgname}{'security-update'} = 1;
} elsif ($line =~ /^ +\*\*\*/) {
$line = shift @lines;
my @l = split(/ +/, $line);
$installed->{$pkgname}{'origin'} = $l[2];
+ $candidate_found = 0;
}
}
@@ -141,7 +153,7 @@ sub get_packages {
}
}
- my (%current, %obsolete, %outofdate);
+ my (%current, %obsolete, %outofdate, %security_outofdate);
for my $pkgname (keys %$installed) {
my $pkg = $installed->{$pkgname};
@@ -151,7 +163,11 @@ sub get_packages {
}
if ($pkg->{'candidate'} ne $pkg->{'installed'}) {
- $outofdate{$pkgname} = $pkg;
+ if ($pkg->{'security-update'}) {
+ $security_outofdate{$pkgname} = $pkg;
+ } else {
+ $outofdate{$pkgname} = $pkg;
+ }
next;
};
if ($pkg->{'origin'} eq '/var/lib/dpkg/status') {
@@ -163,6 +179,7 @@ sub get_packages {
$pkgs{'current'} = \%current;
$pkgs{'outofdate'} = \%outofdate;
+ $pkgs{'security_outofdate'} = \%security_outofdate;
$pkgs{'obsolete'} = \%obsolete;
return \%pkgs;
}
@@ -298,6 +315,12 @@ my @reportform = (
'short' => "%d pc",
'perf' => "prg_conf=%d;1;;0",
'status' => 'WARNING' },
+ { 'key' => 'security_outofdate',
+ 'listpackages' => 1,
+ 'long' => "%d packages with outstanding security updates: %s",
+ 'short' => "%d security-updates",
+ 'perf' => "security_outdated=%d;;1;0",
+ 'status' => 'CRITICAL' },
);
my @longout;