Subject: Re: [PATCH 18/18] signed push: final protocol update

From: Junio C Hamano <[email-masked]>
Date: Thu, 21 Aug 2014 16:40:11 -0700

Shawn Pearce <[email-masked]> writes:

> On Tue, Aug 19, 2014 at 3:06 PM, Junio C Hamano <[email-masked]> wrote:
>>
>> +  push-cert         = PKT-LINE("push-cert" NUL capability-list LF)
>
> Haha. NUL.  I love our wire protocol.
>
>> +                     PKT-LINE("certificate version 0.1" LF)
>> +                     PKT-LINE("pusher" ident LF)
>> +                     PKT-LINE(LF)
>> +                     *PKT-LINE(command LF)
>> +                     *PKT-LINE(GPG signature lines LF)
>
> Should we include the URL as part of this certificate?
>
> Perhaps the pusher means to sign the master branch of experimental
> tree, but not their trunk tree?

Yes, in $gmane/255582 I cover this and also mention that we would
need some "nonce" from the receiving end to make it harder to
replay.

Currently I am leaning toward to add both "pushed-to <URL>" and also
"nonce <nonce>", the latter of which the receiver can ask with
"push-cert=<nonce>" in its initial capability advertisement.

There are a few gotchas I can certainly use help on, especially from
a smart-http expert ;-).

 * "pushed-to <URL>" will identify the site and the repository, so
   you cannot MITM my push to an experimental server and replay it
   against the authoritative server.

   However, the receiving end may not even know what name its users
   call the repository being pushed into.  Obviously gethostname()
   may not be what the pusher called us, and getcwd() may not match
   the repository name without leading "/var/repos/shard3/" path
   components stripped, for example.

   I am not sure if we even have the necessary information at
   send-pack.c::send_pack() level, where it already has an
   established connection to the server (hence it does not need to
   know to whom it is talking to).

 * The receiving end will issue "push-cert=<nonce>" in its initial
   capability advertisement, and this <nonce> will be given on the
   PUSH_CERT_NONCE environment to the pre/post-receive hooks, to
   allow the "nonce <nonce>" header in the signed certificate to be
   checked against it.  You cannot capture my an earlier push to the
   authoritative server and replay it later.

   That would all work well within a single receive-pack process,
   but with "stateless" RPC, it is unclear to me how we should
   arrange the <nonce> the initial instance of receive-pack placed
   on its capability advertisement to be securely passed to the
   instance of receive-pack that actually receives the push
   certificate.