<feed xmlns='http://www.w3.org/2005/Atom'>
<title>git/send-pack.c, branch v2.2.1</title>
<subtitle>Mirror of https://git.kernel.org/pub/scm/git/git.git/
</subtitle>
<id>https://git.shady.money/git/atom?h=v2.2.1</id>
<link rel='self' href='https://git.shady.money/git/atom?h=v2.2.1'/>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/'/>
<updated>2014-10-08T20:05:25Z</updated>
<entry>
<title>Merge branch 'jc/push-cert'</title>
<updated>2014-10-08T20:05:25Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2014-10-08T20:05:15Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=fb06b5280ea05d75515fa780cf08d4ec9d6fe101'/>
<id>urn:sha1:fb06b5280ea05d75515fa780cf08d4ec9d6fe101</id>
<content type='text'>
Allow "git push" request to be signed, so that it can be verified and
audited, using the GPG signature of the person who pushed, that the
tips of branches at a public repository really point the commits
the pusher wanted to, without having to "trust" the server.

* jc/push-cert: (24 commits)
  receive-pack::hmac_sha1(): copy the entire SHA-1 hash out
  signed push: allow stale nonce in stateless mode
  signed push: teach smart-HTTP to pass "git push --signed" around
  signed push: fortify against replay attacks
  signed push: add "pushee" header to push certificate
  signed push: remove duplicated protocol info
  send-pack: send feature request on push-cert packet
  receive-pack: GPG-validate push certificates
  push: the beginning of "git push --signed"
  pack-protocol doc: typofix for PKT-LINE
  gpg-interface: move parse_signature() to where it should be
  gpg-interface: move parse_gpg_output() to where it should be
  send-pack: clarify that cmds_sent is a boolean
  send-pack: refactor inspecting and resetting status and sending commands
  send-pack: rename "new_refs" to "need_pack_data"
  receive-pack: factor out capability string generation
  send-pack: factor out capability string generation
  send-pack: always send capabilities
  send-pack: refactor decision to send update per ref
  send-pack: move REF_STATUS_REJECT_NODELETE logic a bit higher
  ...
</content>
</entry>
<entry>
<title>signed push: fortify against replay attacks</title>
<updated>2014-09-17T21:27:40Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2014-08-21T23:45:30Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=b89363e4a5277038629491f8765c0598f366326c'/>
<id>urn:sha1:b89363e4a5277038629491f8765c0598f366326c</id>
<content type='text'>
In order to prevent a valid push certificate for pushing into an
repository from getting replayed in a different push operation, send
a nonce string from the receive-pack process and have the signer
include it in the push certificate.  The receiving end uses an HMAC
hash of the path to the repository it serves and the current time
stamp, hashed with a secret seed (the secret seed does not have to
be per-repository but can be defined in /etc/gitconfig) to generate
the nonce, in order to ensure that a random third party cannot forge
a nonce that looks like it originated from it.

The original nonce is exported as GIT_PUSH_CERT_NONCE for the hooks
to examine and match against the value on the "nonce" header in the
certificate to notice a replay, but returned "nonce" header in the
push certificate is examined by receive-pack and the result is
exported as GIT_PUSH_CERT_NONCE_STATUS, whose value would be "OK"
if the nonce recorded in the certificate matches what we expect, so
that the hooks can more easily check.

Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>signed push: add "pushee" header to push certificate</title>
<updated>2014-09-15T20:23:28Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2014-08-23T01:15:24Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=9be89160e7382a88e56a02bcf38f4694dd6542d6'/>
<id>urn:sha1:9be89160e7382a88e56a02bcf38f4694dd6542d6</id>
<content type='text'>
Record the URL of the intended recipient for a push (after
anonymizing it if it has authentication material) on a new "pushee
URL" header.  Because the networking configuration (SSH-tunnels,
proxies, etc.) on the pushing user's side varies, the receiving
repository may not know the single canonical URL all the pushing
users would refer it as (besides, many sites allow pushing over
ssh://host/path and https://host/path protocols to the same
repository but with different local part of the path).  So this
value may not be reliably used for replay-attack prevention
purposes, but this will still serve as a human readable hint to
identify the repository the certificate refers to.

Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>signed push: remove duplicated protocol info</title>
<updated>2014-09-15T20:23:28Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2014-08-18T21:38:45Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=4adf569dea052dac88121d822e11c249986b3398'/>
<id>urn:sha1:4adf569dea052dac88121d822e11c249986b3398</id>
<content type='text'>
With the interim protocol, we used to send the update commands even
though we already send a signed copy of the same information when
push certificate is in use.  Update the send-pack/receive-pack pair
not to do so.

The notable thing on the receive-pack side is that it makes sure
that there is no command sent over the traditional protocol packet
outside the push certificate.  Otherwise a pusher can claim to be
pushing one set of ref updates in the signed certificate while
issuing commands to update unrelated refs, and such an update will
evade later audits.

Finally, start documenting the protocol.

Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>send-pack: send feature request on push-cert packet</title>
<updated>2014-09-15T20:23:28Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2014-08-18T20:46:58Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=20a7558f31e44e26ddbb8aa55bfd9316a6b67f82'/>
<id>urn:sha1:20a7558f31e44e26ddbb8aa55bfd9316a6b67f82</id>
<content type='text'>
We would want to update the interim protocol so that we do not send
the usual update commands when the push certificate feature is in
use, as the same information is in the certificate.  Once that
happens, the push-cert packet may become the only protocol command,
but then there is no packet to put the feature request behind, like
we always did.

As we have prepared the receiving end that understands the push-cert
feature to accept the feature request on the first protocol packet
(other than "shallow ", which was an unfortunate historical mistake
that has to come before everything else), we can give the feature
request on the push-cert packet instead of the first update protocol
packet, in preparation for the next step to actually update to the
final protocol.

Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>push: the beginning of "git push --signed"</title>
<updated>2014-09-15T20:23:20Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2014-09-12T18:17:07Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=a85b377d0419a9dfaca8af2320cc33b051cbed04'/>
<id>urn:sha1:a85b377d0419a9dfaca8af2320cc33b051cbed04</id>
<content type='text'>
While signed tags and commits assert that the objects thusly signed
came from you, who signed these objects, there is not a good way to
assert that you wanted to have a particular object at the tip of a
particular branch.  My signing v2.0.1 tag only means I want to call
the version v2.0.1, and it does not mean I want to push it out to my
'master' branch---it is likely that I only want it in 'maint', so
the signature on the object alone is insufficient.

The only assurance to you that 'maint' points at what I wanted to
place there comes from your trust on the hosting site and my
authentication with it, which cannot easily audited later.

Introduce a mechanism that allows you to sign a "push certificate"
(for the lack of better name) every time you push, asserting that
what object you are pushing to update which ref that used to point
at what other object.  Think of it as a cryptographic protection for
ref updates, similar to signed tags/commits but working on an
orthogonal axis.

The basic flow based on this mechanism goes like this:

 1. You push out your work with "git push --signed".

 2. The sending side learns where the remote refs are as usual,
    together with what protocol extension the receiving end
    supports.  If the receiving end does not advertise the protocol
    extension "push-cert", an attempt to "git push --signed" fails.

    Otherwise, a text file, that looks like the following, is
    prepared in core:

	certificate version 0.1
	pusher Junio C Hamano &lt;gitster@pobox.com&gt; 1315427886 -0700

	7339ca65... 21580ecb... refs/heads/master
	3793ac56... 12850bec... refs/heads/next

    The file begins with a few header lines, which may grow as we
    gain more experience.  The 'pusher' header records the name of
    the signer (the value of user.signingkey configuration variable,
    falling back to GIT_COMMITTER_{NAME|EMAIL}) and the time of the
    certificate generation.  After the header, a blank line follows,
    followed by a copy of the protocol message lines.

    Each line shows the old and the new object name at the tip of
    the ref this push tries to update, in the way identical to how
    the underlying "git push" protocol exchange tells the ref
    updates to the receiving end (by recording the "old" object
    name, the push certificate also protects against replaying).  It
    is expected that new command packet types other than the
    old-new-refname kind will be included in push certificate in the
    same way as would appear in the plain vanilla command packets in
    unsigned pushes.

    The user then is asked to sign this push certificate using GPG,
    formatted in a way similar to how signed tag objects are signed,
    and the result is sent to the other side (i.e. receive-pack).

    In the protocol exchange, this step comes immediately before the
    sender tells what the result of the push should be, which in
    turn comes before it sends the pack data.

 3. When the receiving end sees a push certificate, the certificate
    is written out as a blob.  The pre-receive hook can learn about
    the certificate by checking GIT_PUSH_CERT environment variable,
    which, if present, tells the object name of this blob, and make
    the decision to allow or reject this push.  Additionally, the
    post-receive hook can also look at the certificate, which may be
    a good place to log all the received certificates for later
    audits.

Because a push certificate carry the same information as the usual
command packets in the protocol exchange, we can omit the latter
when a push certificate is in use and reduce the protocol overhead.
This however is not included in this patch to make it easier to
review (in other words, the series at this step should never be
released without the remainder of the series, as it implements an
interim protocol that will be incompatible with the final one).
As such, the documentation update for the protocol is left out of
this step.

Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>send-pack: clarify that cmds_sent is a boolean</title>
<updated>2014-09-15T20:23:20Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2014-08-19T20:02:19Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=c67072b90bdc56501483e0ba96d0d833e86362c3'/>
<id>urn:sha1:c67072b90bdc56501483e0ba96d0d833e86362c3</id>
<content type='text'>
We use it to make sure that the feature request is sent only once on
the very first request packet (ignoring the "shallow " line, which
was an unfortunate mistake we cannot retroactively fix with existing
receive-pack already deployed in the field) and we set it to "true"
with cmds_sent++, not because we care about the actual number of
updates sent but because it is merely an idiomatic way.

Set it explicitly to one to clarify that the code that uses this
variable only cares about its zero-ness.

Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>send-pack: refactor inspecting and resetting status and sending commands</title>
<updated>2014-09-15T20:23:19Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2014-08-15T19:29:42Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=b783aa71c096032c02a20f9a41c5f42ce7b914c4'/>
<id>urn:sha1:b783aa71c096032c02a20f9a41c5f42ce7b914c4</id>
<content type='text'>
The main loop over remote_refs list inspects the ref status
to see if we need to generate pack data (i.e. a delete-only push
does not need to send any additional data), resets it to "expecting
the status report" state, and formats the actual update commands
to be sent.

Split the former two out of the main loop, as it will become
conditional in later steps.

Besides, we should have code that does real thing here, before the
"Finally, tell the other end!" part ;-)

Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>send-pack: rename "new_refs" to "need_pack_data"</title>
<updated>2014-09-15T20:23:19Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2014-08-15T19:23:51Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=ab2b0c908aa1d1643fb15ffca4b943c3add9b945'/>
<id>urn:sha1:ab2b0c908aa1d1643fb15ffca4b943c3add9b945</id>
<content type='text'>
The variable counts how many non-deleting command is being sent, but
is only checked with 0-ness to decide if we need to send the pack
data.

Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>send-pack: factor out capability string generation</title>
<updated>2014-09-15T20:23:19Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2014-08-15T18:37:01Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=887f3533fd764722ffb6e4ea34c01ad9256f0186'/>
<id>urn:sha1:887f3533fd764722ffb6e4ea34c01ad9256f0186</id>
<content type='text'>
A run of 'var ? " var" : ""' fed to a long printf string in a deeply
nested block was hard to read.  Move it outside the loop and format
it into a strbuf.

As an added bonus, the trick to add "agent=&lt;agent-name&gt;" by using
two conditionals is replaced by a more readable version.

Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
</feed>
