From: Ian Jackson Date: Sun, 12 Jan 2014 20:06:54 +0000 (+0000) Subject: dgit-repos-server: wip X-Git-Tag: debian/0.22~108 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=commitdiff_plain;h=3d27642f17e325c02209fff73d343f22ab4a0c0c dgit-repos-server: wip --- diff --git a/dgit-repos-server b/dgit-repos-server index 677e3d71..0cbcf357 100644 --- a/dgit-repos-server +++ b/dgit-repos-server @@ -20,24 +20,48 @@ use strict; # What we do is this: -# - extract the destination repo name somehow +# - extract the destination repo name # - make a hardlink clone of the destination repo # - provide the destination with a stunt pre-receive hook # - run actual git-receive-pack with that new destination # as a result of this the stunt pre-receive hook runs; it does this -# find the keyring(s) to use for verification -# verify the signed tag -# check that the signed tag has a suitable name -# parse the signed tag body to extract the intended -# distro and suite -# check that the distro is right -# check that the suite is the same as the branch we are -# supposed to update -# check that the signed tag refers to the same commit -# as the new suite -# check that the signer was correct -# push the signed tag to the actual repo -# push the new dgit branch head to the actual repo +# + understand what refs we are allegedly updating and +# check some correspondences: +# * we are updating only refs/tags/debian/* and refs/dgit/* +# * and only one of each +# * and the tag does not already exist +# and +# * recovering the suite name from the destination refs/dgit/ ref +# + disassemble the signed tag into its various fields and signature +# including: +# * parsing the first line of the tag message to recover +# the package name, version and suite +# * checking that the package name corresponds to the dest repo name +# * checking that the suite name is as recovered above +# + verify the signature on the signed tag +# and if necessary check that the keyid and package are listed in dm.txt +# + check various correspondences: +# * the suite is one of those permitted +# * the signed tag must refer to a commit +# * the signed tag commit must be the refs/dgit value +# * the name in the signed tag must correspond to its ref name +# * the tag name must be debian/ (massaged as needed) +# * the signed tag has a suitable name +# * the commit is a fast forward +# + push the signed tag and new dgit branch to the actual repo +# +# If the destination repo does not already exist, we need to make +# sure that we create it reasonably atomically, and also that +# we don't every have a destination repo containing no refs at all +# (because such a thing causes git-fetch-pack to barf). So then we +# do as above, except: +# - before starting, we take out our own lock for the destination repo +# - we don't make a hardline clone of the destination repo; instead +# we make a copy (not a hardlink clone) of _template +# - we set up a post-receive hook as well, which does the following: +# + check that exactly two refs were updated +# + delete the two stunt hooks +# + rename the working repo into place as the destination repo use POSIX; use Fcntl qw(:flock); @@ -132,7 +156,6 @@ sub parsetag () { open PT, ">dgit-tmp/plaintext" or die $!; open DS, ">dgit-tmp/plaintext.asc" or die $!; open T, "-|", qw(git cat-file tag), $tagval or die $!; - my %tagh; for (;;) { $!=0; $_=; defined or die $!; print PT or die $!; @@ -241,9 +264,10 @@ sub verifytag () { reject "key not found in keyrings"; } -sub checktag () { - tagh1('object') eq $commit or die; +sub checks () { +fixme check the suite against the approved list tagh1('type') eq 'commit' or die; + tagh1('object') eq $commit or die; tagh1('tag') eq $tagname or die; my $v = $version; @@ -273,7 +297,7 @@ sub stunthook () { readupdates(); parsetag(); verifytag(); - checktag(); + checks(); onwardpush(); }