git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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

From
Shawn Pearce <spearce@spearce.org>
Date
Aug 22, 2014, 23:54 UTC
Message-ID
<CAJo=hJu_T7irRk=fBsJ+GQxbVQ9GgO2ytihxKm+bXSLsL+wQbg@mail.gmail.com>
In-Reply-To
<xmqqa96wpfqb.fsf@gitster.dls.corp.google.com>
On Fri, Aug 22, 2014 at 10:59 AM, Junio C Hamano <gitster@pobox.com> wrote:
Show 43 quoted lines
> Junio C Hamano <gitster@pobox.com> writes:
>
>> 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.
>
> A good <nonce> may be something like taking the SHA-1 hash of the
> concatenation of the sitename, repo-path and the timestamp when the
> receive-pack generated the <nonce>.  Replaying a push certificate
> for a push to a repository at a site that gives such a <nonce> can
> succeed at the same chance of finding a SHA-1 collision [*1*].  As
> long as you exercise good hygiene and only push to repositories that
> give such <nonce>, we can do without checking "pushed-to" that says
> where the push went.
Yes, this is an interesting solution.

As you know, the stateless HTTP thing doesn't allow the nonce on the server to be carried from the initial ref advertisement into the final receive-pack. We would either need to write the nonce to disk and load it back up later (ick), or use some sort of stateless nonce.

A stateless nonce could look like:
  nonce = HMAC_SHA1( SHA1(site+path) + '.' + now, site_key )

where site_key is a private key known to the server. It doesn't have to be per-repo.

receive-pack would then be willing to accept any nonce whose timestamp is within a window, e.g. 10 minutes of the current time, and whose signature verifies in the HMAC. The 10 minute window is important to allow clients time to generate the object list, perform delta compression, and begin transmitting to the server.

> So "nonce <nonce>" is the only thing that is necessary to make them
> impossible to replay.  For auditing purposes, "pushed-to <URL>" that
> records the repository the pusher intended to push to may help but
> probably not necessary [*2*].

So pushed-to is still useful as a documentation/historical artifact, but isn't important for verifying the certificate. That fixes a lot of problems with repositories having different paths under e.g. git:// vs. ssh:// vs. https:// on the same host.

Previous: Junio C HamanoNext: Junio C Hamano
Message 35 of 59 in “Signed push”
  1. 00/18 Signed pushJunio C Hamano, Aug 19, 2014
  2. 01/18 receive-pack: do not overallocate command structureJunio C Hamano, Aug 19, 2014
  3. 02/18 receive-pack: parse feature request a bit earlierJunio C Hamano, Aug 19, 2014
  4. Junio C HamanoAug 19, 2014
  5. 03/18 receive-pack: do not reuse old_sha1[] to other thingsJunio C Hamano, Aug 19, 2014
  6. Junio C HamanoAug 19, 2014
  7. 04/18 receive-pack: factor out queueing of commandJunio C Hamano, Aug 19, 2014
  8. 05/18 send-pack: move REF_STATUS_REJECT_NODELETE logic a bit higherJunio C Hamano, Aug 19, 2014
  9. 06/18 send-pack: refactor decision to send update per refJunio C Hamano, Aug 19, 2014
  10. 07/18 send-pack: always send capabilitiesJunio C Hamano, Aug 19, 2014
  11. 08/18 send-pack: factor out capability string generationJunio C Hamano, Aug 19, 2014
  12. 09/18 send-pack: rename "new_refs" to "need_pack_data"Junio C Hamano, Aug 19, 2014
  13. 10/18 send-pack: refactor inspecting and resetting status and sending commandsJunio C Hamano, Aug 19, 2014
  14. 11/18 send-pack: clarify that cmds_sent is a booleanJunio C Hamano, Aug 19, 2014
  15. 12/18 gpg-interface: move parse_gpg_output() to where it should beJunio C Hamano, Aug 19, 2014
  16. 13/18 gpg-interface: move parse_signature() to where it should beJunio C Hamano, Aug 19, 2014
  17. 14/18 pack-protocol doc: typofix for PKT-LINEJunio C Hamano, Aug 19, 2014
  18. 15/18 the beginning of the signed pushJunio C Hamano, Aug 19, 2014
  19. brian m. carlsonAug 20, 2014
  20. Bert WesargAug 20, 2014
  21. Junio C HamanoAug 20, 2014
  22. 16/18 receive-pack: GPG-validate push certificatesJunio C Hamano, Aug 19, 2014
  23. David TurnerAug 20, 2014
  24. Junio C HamanoAug 20, 2014
  25. David TurnerAug 20, 2014
  26. Junio C HamanoAug 20, 2014
  27. David TurnerAug 21, 2014
  28. Junio C HamanoAug 22, 2014
  29. 17/18 send-pack: send feature request on push-cert packetJunio C Hamano, Aug 19, 2014
  30. 18/18 signed push: final protocol updateJunio C Hamano, Aug 19, 2014
  31. Shawn PearceAug 21, 2014
  32. Junio C HamanoAug 21, 2014
  33. Kyle J. McKayAug 22, 2014
  34. Junio C HamanoAug 22, 2014
  35. Shawn PearceAug 22, 2014
  36. Junio C HamanoAug 25, 2014
  37. Shawn PearceAug 26, 2014
  38. Junio C HamanoAug 26, 2014
  39. Junio C HamanoAug 26, 2014
  40. Junio C HamanoSep 4, 2014
  41. Shawn PearceSep 5, 2014
  42. Junio C HamanoAug 22, 2014
  43. David TurnerAug 22, 2014
  44. Duy NguyenAug 19, 2014
  45. Junio C HamanoAug 19, 2014
  46. Nico WilliamsAug 20, 2014
  47. Junio C HamanoAug 20, 2014
  48. Junio C HamanoAug 20, 2014
  49. Junio C HamanoAug 20, 2014
  50. Nico WilliamsAug 20, 2014
  51. Stefan BellerAug 22, 2014
  52. Junio C HamanoAug 22, 2014
  53. Stefan BellerAug 22, 2014
  54. Junio C HamanoAug 22, 2014
  55. Stefan BellerAug 22, 2014
  56. Junio C HamanoAug 22, 2014
  57. Stefan BellerAug 22, 2014
  58. Junio C HamanoAug 25, 2014
  59. Jason PyeronAug 25, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.