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;
 }

Reply via email to