chiark / gitweb /
dgit: fix rpush+buildinfo: Transfer buildinfos for signing.
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 8 Jul 2017 16:22:53 +0000 (17:22 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 8 Jul 2017 16:23:02 +0000 (17:23 +0100)
buildinfos are supposed to be signed.  And, indeed, if they are
present, debsign wants to sign them.  That means they need to be
transferred to the signing end, and back again.

We check that the filename is not totally unreasonable, but do not
attempt to verify it completely.  If there are situations where
unwanted or confusing buildinfos are generated, this is the fault of
the build process.  dgit rpush should, in this respect, do the same as
debsign+dput - ie faithfully sign and upload what the build has
provided.

We do check that the buildinfo doesn't look too much like a .changes,
and mentions the same files as the .changes (insofar as they mention
files in common).  This is a rather nugatory defence against some
kinds of bait and switch attacks.

This is in some sense an incompatible protocol change: if the build
host has a new dgit, and sends buildinfos, an old dgit on the
initiator will declare a protocol violation.  However, the new
protocol elements occur only when needed.  in this situation, the only
way to get things to work at all with the old dgit at either end would
be to strip out the buildinfos, which is obviously undesirable.

Closes:#867693.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
debian/changelog
dgit

index 73a0035d305e8aca32a5c52ab6fdb0bffabcac9e..942c77b49e64cc32e9c082d359eba5607bf7e71d 100644 (file)
@@ -1,6 +1,7 @@
 dgit (3.11~) unstable; urgency=medium
 
-  * 
+  * dgit: fix rpush+buildinfo: Transfer buildinfos for signing.
+    Closes:#867693.
 
  --
 
diff --git a/dgit b/dgit
index c2622ef7eb4ff7a949b77fcea66d1ad194a90213..6134f5c7162b159a9f8aa52bda97b5b340cec145 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -316,6 +316,9 @@ sub gbp_pq {
 #  > param tagformat old|new
 #  > param maint-view MAINT-VIEW-HEAD
 #
+#  > param buildinfo-filename P_V_X.buildinfo   # zero or more times
+#  > file buildinfo                             # for buildinfos to sign
+#
 #  > previously REFNAME=OBJNAME       # if --deliberately-not-fast-forward
 #                                     # goes into tag, for replay prevention
 #
@@ -332,6 +335,9 @@ sub gbp_pq {
 #  [etc]
 #  < data-block NBYTES    [transfer of signed changes]
 #  [etc]
+#  < data-block NBYTES    [transfer of each signed buildinfo
+#  [etc]                   same number and order as "file buildinfo"]
+#  ...
 #  < files-end
 #
 #  > complete
@@ -4296,6 +4302,14 @@ END
        responder_send_command("param maint-view $maintviewhead");
     }
 
+    # Perhaps send buildinfo(s) for signing
+    my $changes_files = getfield $changes, 'Files';
+    my @buildinfos = ($changes_files =~ m/ .* (\S+\.buildinfo)$/mg);
+    foreach my $bi (@buildinfos) {
+       responder_send_command("param buildinfo-filename $bi");
+       responder_send_file('buildinfo', "$buildproductsdir/$bi");
+    }
+
     if (deliberately_not_fast_forward) {
        git_for_each_ref(lrfetchrefs, sub {
            my ($objid,$objtype,$lrfetchrefname,$reftail) = @_;
@@ -4367,6 +4381,7 @@ END
     if ($we_are_responder) {
        my $dryrunsuffix = act_local() ? "" : ".tmp";
        my @rfiles = ($dscpath, $changesfile);
+       push @rfiles, map { "$buildproductsdir/$_" } @buildinfos;
        responder_receive_files('signed-dsc-changes',
                                map { "$_$dryrunsuffix" } @rfiles);
     } else {
@@ -4719,7 +4734,7 @@ sub i_resp_want ($) {
     print RI "files-end\n" or die $!;
 }
 
-our ($i_clogp, $i_version, $i_dscfn, $i_changesfn);
+our ($i_clogp, $i_version, $i_dscfn, $i_changesfn, @i_buildinfos);
 
 sub i_localname_parsed_changelog {
     return "remote-changelog.822";
@@ -4736,6 +4751,31 @@ sub i_localname_dsc {
 }
 sub i_file_dsc { }
 
+sub i_localname_buildinfo ($) {
+    my $bi = $i_param{'buildinfo-filename'};
+    defined $bi or badproto \*RO, "buildinfo before filename";
+    defined $i_changesfn or badproto \*RO, "buildinfo before changes";
+    $bi =~ m{^\Q$package\E_[!-.0-~]*\.buildinfo$}s
+       or badproto \*RO, "improper buildinfo filename";
+    return $&;
+}
+sub i_file_buildinfo {
+    my $bi = $i_param{'buildinfo-filename'};
+    my $bd = parsecontrol "$i_tmp/$bi", $bi;
+    my $ch = parsecontrol "$i_tmp/$i_changesfn", 'changes';
+    if (!forceing [qw(buildinfo-changes-mismatch)]) {
+       files_compare_inputs($bd, $ch);
+       (getfield $bd, $_) eq (getfield $ch, $_) or
+           fail "buildinfo mismatch $_"
+           foreach qw(Source Version);
+       !defined $bd->{$_} or
+           fail "buildinfo contains $_"
+           foreach qw(Changes Changed-by Distribution);
+    }
+    push @i_buildinfos, $bi;
+    delete $i_param{'buildinfo-filename'};
+}
+
 sub i_localname_changes {
     defined $i_dscfn or badproto \*RO, "dsc (before parsed-changelog)";
     $i_changesfn = $i_dscfn;
@@ -4777,7 +4817,7 @@ sub i_want_signed_tag {
 sub i_want_signed_dsc_changes {
     rename "$i_dscfn.tmp","$i_dscfn" or die "$i_dscfn $!";
     sign_changes $i_changesfn;
-    return ($i_dscfn, $i_changesfn);
+    return ($i_dscfn, $i_changesfn, @i_buildinfos);
 }
 
 #---------- building etc. ----------