Subject: dpkg-sig --verify does not fail unless the .deb is signed
Package: dpkg-sig
Version: 0.13.1+nmu2
Severity: grave
Tags: security, patch
Dear Maintainer,
Perhaps I've misunderstood the purpose of this tool, but one may have
hoped for something that would check that a .deb was signed with a
trusted key.
dpkg-sig does:
* report an error with non-zero exit status if a .deb has bad signature
* report no error with zero exit status if a .deb has good signature
dpkg-sig does NOT:
* report an error with non-zero exit status if a .deb is unsigned
Steps to reproduce:
* mkdir /tmp/build && cd /tmp/build
* apt-get source liblzo2-2
* apt-get build-dep liblzo2-2
* dpkg-source -x lzo2_2.08-1.2.dsc
* cd lzo2-2.08/
* dpkg-buildpackage -rfakeroot -b -uc -us # builds unsigned .deb
* dpkg-sig --verify ../liblzo2-2_2.08-1.2_amd64.deb
* echo $?
Expected behaviour:
* echo $? should print non-zero exit status
Actual behaviour:
* echo $? prints 0
Impact:
Any user of dpkg-sig --verify cares about having valid signatures on
their .debs.
It seems this could be a security issue to then trivially allow
bypassing this check simply by presenting an unsigned .deb, hence the
grave severity.
This hurts anyone who depends on this tool in their work-flow AND had
the misguided expectation that it would error out on unsigned debs as
I did.
Therefore I've attached a patch which I suspect changes the tool to
conform to this expectation. It was only briefly tested, please review
before applying.
-- System Information:
Debian Release: 8.0
APT prefers testing-updates
APT policy: (500, 'testing-updates'), (500, 'unstable'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 3.16.0-4-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_AU.UTF-8, LC_CTYPE=en_AU.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
Versions of packages dpkg-sig depends on:
ii gnupg 1.4.18-7
ii libconfig-file-perl 1.50-2
ii perl [libdigest-md5-perl] 5.20.2-3
dpkg-sig recommends no packages.
Versions of packages dpkg-sig suggests:
pn libterm-readkey-perl <none>
pn ssh <none>
-- no debconf information
--- dpkg-sig.orig 2015-04-28 20:08:01.276000000 +1000
+++ dpkg-sig 2015-04-28 20:02:33.372000000 +1000
@@ -140,6 +140,7 @@
print @verify_output;
exit 2 if grep { /^BADSIG/ } @verify_output;
exit 3 if grep { /^UNKNOWNSIG/ } @verify_output;
+ exit 4 if grep { /^NOSIG/ } @verify_output;
} elsif ($list) {
for (get_deb_parts($file)) {
print "$1\n" if ($_->[0] =~ /_gpg(.+)/);
@@ -181,6 +182,7 @@
print @verify_output;
exit 2 if grep { /^BADSIG/ }
@verify_output;
exit 3 if grep { /^UNKNOWNSIG/ }
@verify_output;
+ exit 4 if grep { /^NOSIG/ }
@verify_output;
} elsif ($list) {
for (get_deb_parts($deb)) {
print "$1\n" if ($_->[0] =~
/_gpg(.+)/);
@@ -502,6 +504,7 @@
#Get MD5 sums:
my $digests = get_deb_digests($deb);
+ my $found_sigs;
for (my $n=0;$n<@$digests;$n++) {
my ($part_name, $size, $sha1sum, $md5sum) = @{@$digests[$n]};
@@ -517,12 +520,15 @@
if ($sig =~ /BEGIN PGP SIGNED MESSAGE/) {
$status = verify_deb_sig_v4($part_name, $n, $digests,
\@info, \@return);
+ $found_sigs = 1;
}
if ($check_v3_sig && (!$status || $status eq "BAD")) {
$status = verify_deb_sig_v3($part_name, $n, $digests,
\@info, \@return);
+ $found_sigs = 1;
}
if ($check_v2_sig && (!$status || $status eq "BAD")) {
$status = verify_deb_sig_v2($part_name, $n, $digests,
\@info, \@return);
+ $found_sigs = 1;
}
if ($status && $status eq "GOOD") {
@@ -533,6 +539,9 @@
push @return, "BADSIG $part_name\n"
}
}
+ if (!$found_sigs) {
+ push @return, "NOSIG\n"
+ }
return @return;
}