The following commit has been merged in the master branch:
commit 9945c52208fa7520bb307868d6c152ced8238969
Author: Guillem Jover <[email protected]>
Date:   Sun Dec 16 00:33:25 2012 +0100

    Dpkg: Fix OpenPGP armored signature parsing
    
    Change parsing code to honour RFC4880. Handle whitespaces at EOL, and
    correctly expect five trailing dashes on the Armor Header Lines.
    
    Closes: #695919
    
    Reported-by: Ansgar Burchardt <[email protected]>

diff --git a/debian/changelog b/debian/changelog
index 0a2c7d5..c881d8b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -6,6 +6,8 @@ dpkg (1.16.10) UNRELEASED; urgency=low
   * Add missing @LIBLZMA_LIBS@ to Libs.Private in libdpkg.pc.in.
   * Do not use an undefined va_list variable in dpkg_put_errno().
   * Abort installation if we cannot set the security context for a file.
+  * Fix OpenPGP armored signature parsing, to be resilient against doctored
+    input, including source package control files. Closes: #695919
 
   [ Updated programs translations ]
   * Esperanto (Felipe Castro).
diff --git a/scripts/Dpkg/Control/Hash.pm b/scripts/Dpkg/Control/Hash.pm
index fabcf68..623ca73 100644
--- a/scripts/Dpkg/Control/Hash.pm
+++ b/scripts/Dpkg/Control/Hash.pm
@@ -193,31 +193,32 @@ sub parse {
                $line = substr $line, 1;
            }
            $self->{$cf} .= "\n$line";
-       } elsif (m/^-----BEGIN PGP SIGNED MESSAGE/) {
+       } elsif (m/^-----BEGIN PGP SIGNED MESSAGE-----$/) {
            $expect_pgp_sig = 1;
            if ($$self->{'allow_pgp'}) {
                # Skip PGP headers
                while (<$fh>) {
-                   last if m/^$/;
+                   last if m/^\s*$/;
                }
            } else {
                syntaxerr($desc, _g("PGP signature not allowed here"));
            }
-       } elsif (m/^$/ || ($expect_pgp_sig && m/^-----BEGIN PGP SIGNATURE/)) {
+       } elsif (m/^$/ || ($expect_pgp_sig && m/^-----BEGIN PGP 
SIGNATURE-----$/)) {
            if ($expect_pgp_sig) {
                # Skip empty lines
                $_ = <$fh> while defined($_) && $_ =~ /^\s*$/;
                length($_) ||
                     syntaxerr($desc, _g("expected PGP signature, found EOF " .
                                         "after blank line"));
-               s/\n$//;
-               unless (m/^-----BEGIN PGP SIGNATURE/) {
+               s/\s*\n$//;
+               unless (m/^-----BEGIN PGP SIGNATURE-----$/) {
                    syntaxerr($desc, sprintf(_g("expected PGP signature, " .
                                                 "found something else \`%s'"), 
$_));
                 }
                # Skip PGP signature
                while (<$fh>) {
-                   last if m/^-----END PGP SIGNATURE/;
+                   s/\s*\n$//;
+                   last if m/^-----END PGP SIGNATURE-----$/;
                }
                unless (defined($_)) {
                     syntaxerr($desc, _g("unfinished PGP signature"));
diff --git a/scripts/Dpkg/Source/Package.pm b/scripts/Dpkg/Source/Package.pm
index 47ea319..cbc35aa 100644
--- a/scripts/Dpkg/Source/Package.pm
+++ b/scripts/Dpkg/Source/Package.pm
@@ -194,7 +194,7 @@ sub initialize {
     $self->{'is_signed'} = 0;
     while (<DSC>) {
         next if /^\s*$/o;
-        $self->{'is_signed'} = 1 if /^-----BEGIN PGP SIGNED MESSAGE-----$/o;
+        $self->{'is_signed'} = 1 if /^-----BEGIN PGP SIGNED MESSAGE-----\s*$/o;
         last;
     }
     close(DSC);
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 3172097..13c9123 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -229,6 +229,11 @@ test_data = \
        t/600_Dpkg_Changelog/regressions \
        t/600_Dpkg_Changelog/shadow \
        t/700_Dpkg_Control/control-1 \
+       t/700_Dpkg_Control/bogus-unsigned.dsc \
+       t/700_Dpkg_Control/bogus-armor-double.dsc \
+       t/700_Dpkg_Control/bogus-armor-trail.dsc \
+       t/700_Dpkg_Control/bogus-armor-nested.dsc \
+       t/700_Dpkg_Control/bogus-armor-spaces.dsc \
        t/750_Dpkg_Substvars/substvars1 \
        t/910_merge_changelogs/ch-old \
        t/910_merge_changelogs/ch-a \
diff --git a/scripts/t/700_Dpkg_Control.t b/scripts/t/700_Dpkg_Control.t
index fbdc997..dab90d5 100644
--- a/scripts/t/700_Dpkg_Control.t
+++ b/scripts/t/700_Dpkg_Control.t
@@ -13,17 +13,32 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-use Test::More tests => 11;
+use Test::More tests => 20;
 
 use strict;
 use warnings;
 use IO::String;
 
-use_ok('Dpkg::Control::Info');
+BEGIN {
+    use_ok('Dpkg::Control');
+    use_ok('Dpkg::Control::Info');
+}
 
 my $srcdir = $ENV{srcdir} || '.';
 my $datadir = $srcdir . '/t/700_Dpkg_Control';
 
+sub parse_dsc {
+    my ($path) = @_;
+
+    my $dsc = Dpkg::Control->new(type => CTRL_PKG_SRC);
+    eval {
+        $dsc->load($path);
+        1;
+    } or return;
+
+    return $dsc;
+}
+
 my $c = Dpkg::Control::Info->new("$datadir/control-1");
 
 my $io = IO::String->new();
@@ -86,3 +101,25 @@ is(${$io->string_ref()},
 Architecture: all
 Depends: hello
 ', "Dump of second binary package of $datadir/control-1");
+
+# Check OpenPGP armored signatures in source control files
+
+my $dsc;
+
+$dsc = parse_dsc("$datadir/bogus-unsigned.dsc");
+is($dsc, undef, 'Unsigned .dsc w/ OpenPGP armor');
+
+$dsc = parse_dsc("$datadir/bogus-armor-trail.dsc");
+is($dsc, undef, 'Signed .dsc w/ bogus OpenPGP armor trailer');
+
+$dsc = parse_dsc("$datadir/bogus-armor-double.dsc");
+ok(defined $dsc, 'Signed .dsc w/ two OpenPGP armor signatures');
+is($dsc->{Source}, 'pass', 'Signed spaced .dsc package name');
+
+$dsc = parse_dsc("$datadir/bogus-armor-spaces.dsc");
+ok(defined $dsc, 'Signed .dsc w/ spaced OpenPGP armor');
+is($dsc->{Source}, 'pass', 'Signed spaced .dsc package name');
+
+$dsc = parse_dsc("$datadir/bogus-armor-nested.dsc");
+ok(defined $dsc, 'Signed .dsc w/ nested OpenPGP armor');
+is($dsc->{Source}, 'pass', 'Signed nested .dsc package name');
diff --git a/scripts/t/700_Dpkg_Control/bogus-armor-double.dsc 
b/scripts/t/700_Dpkg_Control/bogus-armor-double.dsc
new file mode 100644
index 0000000..1888a00
--- /dev/null
+++ b/scripts/t/700_Dpkg_Control/bogus-armor-double.dsc
@@ -0,0 +1,13 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Source: pass
+
+-----BEGIN PGP SIGNATURE-----
+
+Valid signature here.
+-----END PGP SIGNATURE-----
+-----BEGIN PGP SIGNATURE-----
+
+Fake signature here.
+-----END PGP SIGNATURE-----
diff --git a/scripts/t/700_Dpkg_Control/bogus-armor-nested.dsc 
b/scripts/t/700_Dpkg_Control/bogus-armor-nested.dsc
new file mode 100644
index 0000000..ca99c35
--- /dev/null
+++ b/scripts/t/700_Dpkg_Control/bogus-armor-nested.dsc
@@ -0,0 +1,15 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+        
+Source: pass
+  
+-----BEGIN PGP SIGNATURE-----
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Source: fail
+
+-----BEGIN PGP SIGNATURE-----
+
+Valid signature here.
+-----END PGP SIGNATURE-----
diff --git a/scripts/t/700_Dpkg_Control/bogus-armor-spaces.dsc 
b/scripts/t/700_Dpkg_Control/bogus-armor-spaces.dsc
new file mode 100644
index 0000000..ab71ab5
--- /dev/null
+++ b/scripts/t/700_Dpkg_Control/bogus-armor-spaces.dsc
@@ -0,0 +1,18 @@
+-----BEGIN PGP SIGNED MESSAGE-----     
+Hash: SHA1
+        
+Source: pass
+  
+-----BEGIN PGP SIGNATURE-----            
+Version: GnuPG v1.4.12 (GNU/Linux)
+  
+Valid signature here.
+-----END PGP SIGNATURE-----
+
+Source: fail
+
+-----BEGIN PGP SIGNATURE
+Version: vim v7.3.547 (GNU/Linux)
+
+Fake signature here.
+-----END PGP SIGNATURE
diff --git a/scripts/t/700_Dpkg_Control/bogus-armor-trail.dsc 
b/scripts/t/700_Dpkg_Control/bogus-armor-trail.dsc
new file mode 100644
index 0000000..90b00f1
--- /dev/null
+++ b/scripts/t/700_Dpkg_Control/bogus-armor-trail.dsc
@@ -0,0 +1,14 @@
+-----BEGIN PGP SIGNED MESSAGE
+
+Source: fail
+
+-----BEGIN PGP SIGNATURE
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+Source: pass
+
+-----BEGIN PGP SIGNATURE-----   
+
+Valid signature here.
+-----END PGP SIGNATURE-----
diff --git a/scripts/t/700_Dpkg_Control/bogus-unsigned.dsc 
b/scripts/t/700_Dpkg_Control/bogus-unsigned.dsc
new file mode 100644
index 0000000..7573eb3
--- /dev/null
+++ b/scripts/t/700_Dpkg_Control/bogus-unsigned.dsc
@@ -0,0 +1,5 @@
+-----BEGIN PGP MESSAGE-----
+
+Source: fail
+
+-----END PGP MESSAGE-----

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to