<feed xmlns='http://www.w3.org/2005/Atom'>
<title>git/http.c, branch v2.33.6</title>
<subtitle>Mirror of https://git.kernel.org/pub/scm/git/git.git/
</subtitle>
<id>https://git.shady.money/git/atom?h=v2.33.6</id>
<link rel='self' href='https://git.shady.money/git/atom?h=v2.33.6'/>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/'/>
<updated>2021-09-23T04:24:58Z</updated>
<entry>
<title>http: match headers case-insensitively when redacting</title>
<updated>2021-09-23T04:24:58Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2021-09-22T22:11:53Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=b66c77a64e696eb5e5994a58c0d50073f8e93bf1'/>
<id>urn:sha1:b66c77a64e696eb5e5994a58c0d50073f8e93bf1</id>
<content type='text'>
When HTTP/2 is in use, we fail to correctly redact "Authorization" (and
other) headers in our GIT_TRACE_CURL output.

We get the headers in our CURLOPT_DEBUGFUNCTION callback, curl_trace().
It passes them along to curl_dump_header(), which in turn checks
redact_sensitive_header(). We see the headers as a text buffer like:

  Host: ...
  Authorization: Basic ...

After breaking it into lines, we match each header using skip_prefix().
This is case-sensitive, even though HTTP headers are case-insensitive.
This has worked reliably in the past because these headers are generated
by curl itself, which is predictable in what it sends.

But when HTTP/2 is in use, instead we get a lower-case "authorization:"
header, and we fail to match it. The fix is simple: we should match with
skip_iprefix().

Testing is more complicated, though. We do have a test for the redacting
feature, but we don't hit the problem case because our test Apache setup
does not understand HTTP/2. You can reproduce the issue by applying this
on top of the test change in this patch:

	diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
	index afa91e38b0..19267c7107 100644
	--- a/t/lib-httpd/apache.conf
	+++ b/t/lib-httpd/apache.conf
	@@ -29,6 +29,9 @@ ErrorLog error.log
	 	LoadModule setenvif_module modules/mod_setenvif.so
	 &lt;/IfModule&gt;

	+LoadModule http2_module modules/mod_http2.so
	+Protocols h2c
	+
	 &lt;IfVersion &lt; 2.4&gt;
	 LockFile accept.lock
	 &lt;/IfVersion&gt;
	@@ -64,8 +67,8 @@ LockFile accept.lock
	 &lt;IfModule !mod_access_compat.c&gt;
	 	LoadModule access_compat_module modules/mod_access_compat.so
	 &lt;/IfModule&gt;
	-&lt;IfModule !mod_mpm_prefork.c&gt;
	-	LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
	+&lt;IfModule !mod_mpm_event.c&gt;
	+	LoadModule mpm_event_module modules/mod_mpm_event.so
	 &lt;/IfModule&gt;
	 &lt;IfModule !mod_unixd.c&gt;
	 	LoadModule unixd_module modules/mod_unixd.so
	diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
	index 1c2a444ae7..ff74f0ae8a 100755
	--- a/t/t5551-http-fetch-smart.sh
	+++ b/t/t5551-http-fetch-smart.sh
	@@ -24,6 +24,10 @@ test_expect_success 'create http-accessible bare repository' '
	 	git push public main:main
	 '

	+test_expect_success 'prefer http/2' '
	+	git config --global http.version HTTP/2
	+'
	+
	 setup_askpass_helper

	 test_expect_success 'clone http repository' '

but this has a few issues:

  - it's not necessarily portable. The http2 apache module might not be
    available on all systems. Further, the http2 module isn't compatible
    with the prefork mpm, so we have to switch to something else. But we
    don't necessarily know what's available. It would be nice if we
    could have conditional config, but IfModule only tells us if a
    module is already loaded, not whether it is available at all.

    This might be a non-issue. The http tests are already optional, and
    modern-enough systems may just have both of these. But...

  - if we do this, then we'd no longer be testing HTTP/1.1 at all. I'm
    not sure how much that matters since it's all handled by curl under
    the hood, but I'd worry that some detail leaks through. We'd
    probably want two scripts running similar tests, one with HTTP/2 and
    one with HTTP/1.1.

  - speaking of which, a later test fails with the patch above! The
    problem is that it is making sure we used a chunked
    transfer-encoding by looking for that header in the trace. But
    HTTP/2 doesn't support that, as it has its own streaming mechanisms
    (the overall operation works fine; we just don't see the header in
    the trace).

Furthermore, even with the changes above, this test still does not
detect the current failure, because we see _both_ HTTP/1.1 and HTTP/2
requests, which confuse it. Quoting only the interesting bits from the
resulting trace file, we first see:

  =&gt; Send header: GET /auth/smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1
  =&gt; Send header: Connection: Upgrade, HTTP2-Settings
  =&gt; Send header: Upgrade: h2c
  =&gt; Send header: HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA

  &lt;= Recv header: HTTP/1.1 401 Unauthorized
  &lt;= Recv header: Date: Wed, 22 Sep 2021 20:03:32 GMT
  &lt;= Recv header: Server: Apache/2.4.49 (Debian)
  &lt;= Recv header: WWW-Authenticate: Basic realm="git-auth"

So the client asks for HTTP/2, but Apache does not do the upgrade for
the 401 response. Then the client repeats with credentials:

  =&gt; Send header: GET /auth/smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1
  =&gt; Send header: Authorization: Basic &lt;redacted&gt;
  =&gt; Send header: Connection: Upgrade, HTTP2-Settings
  =&gt; Send header: Upgrade: h2c
  =&gt; Send header: HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA

  &lt;= Recv header: HTTP/1.1 101 Switching Protocols
  &lt;= Recv header: Upgrade: h2c
  &lt;= Recv header: Connection: Upgrade
  &lt;= Recv header: HTTP/2 200
  &lt;= Recv header: content-type: application/x-git-upload-pack-advertisement

So the client does properly redact there, because we're speaking
HTTP/1.1, and the server indicates it can do the upgrade. And then the
client will make further requests using HTTP/2:

  =&gt; Send header: POST /auth/smart/repo.git/git-upload-pack HTTP/2
  =&gt; Send header: authorization: Basic dXNlckBob3N0OnBhc3NAaG9zdA==
  =&gt; Send header: content-type: application/x-git-upload-pack-request

And there we can see that the credential is _not_ redacted. This part of
the test is what gets confused:

	# Ensure that there is no "Basic" followed by a base64 string, but that
	# the auth details are redacted
	! grep "Authorization: Basic [0-9a-zA-Z+/]" trace &amp;&amp;
	grep "Authorization: Basic &lt;redacted&gt;" trace

The first grep does not match the un-redacted HTTP/2 header, because
it insists on an uppercase "A". And the second one does find the
HTTP/1.1 header. So as far as the test is concerned, everything is OK,
but it failed to notice the un-redacted lines.

We can make this test (and the other related ones) more robust by adding
"-i" to grep case-insensitively. This isn't really doing anything for
now, since we're not actually speaking HTTP/2, but it future-proofs the
tests for a day when we do (either we add explicit HTTP/2 test support,
or it's eventually enabled by default by our Apache+curl test setup).
And it doesn't hurt in the meantime for the tests to be more careful.

The change to use "grep -i", coupled with the changes to use HTTP/2
shown above, causes the test to fail with the current code, and pass
after this patch is applied.

And finally, there's one other way to demonstrate the issue (and how I
actually found it originally). Looking at GIT_TRACE_CURL output against
github.com, you'll see the unredacted output, even if you didn't set
http.version. That's because setting it is only necessary for curl to
send the extra headers in its HTTP/1.1 request that say "Hey, I speak
HTTP/2; upgrade if you do, too". But for a production site speaking
https, the server advertises via ALPN, a TLS extension, that it supports
HTTP/2, and the client can immediately start using it.

Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Merge branch 'cs/http-use-basic-after-failed-negotiate'</title>
<updated>2021-05-20T20:49:41Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2021-05-20T20:48:25Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=c69f2f8c869361e9e2bdb9fb3ceb2fe058013744'/>
<id>urn:sha1:c69f2f8c869361e9e2bdb9fb3ceb2fe058013744</id>
<content type='text'>
Regression fix for a change made during this cycle.

* cs/http-use-basic-after-failed-negotiate:
  Revert "remote-curl: fall back to basic auth if Negotiate fails"
  t5551: test http interaction with credential helpers
</content>
</entry>
<entry>
<title>Revert "remote-curl: fall back to basic auth if Negotiate fails"</title>
<updated>2021-05-19T01:09:58Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2021-05-18T06:27:42Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=ecf7b129fa8619bfe16c5f7e470717ad79186e07'/>
<id>urn:sha1:ecf7b129fa8619bfe16c5f7e470717ad79186e07</id>
<content type='text'>
This reverts commit 1b0d9545bb85912a16b367229d414f55d140d3be.

That commit does fix the situation it intended to (avoiding Negotiate
even when the credentials were provided in the URL), but it creates a
more serious regression: we now never hit the conditional for "we had a
username and password, tried them, but the server still gave us a 401".
That has two bad effects:

 1. we never call credential_reject(), and thus a bogus credential
    stored by a helper will live on forever

 2. we never return HTTP_NOAUTH, so the error message the user gets is
    "The requested URL returned error: 401", instead of "Authentication
    failed".

Doing this correctly seems non-trivial, as we don't know whether the
Negotiate auth was a problem. Since this is a regression in the upcoming
v2.23.0 release (for which we're in -rc0), let's revert for now and work
on a fix separately.

(Note that this isn't a pure revert; the previous commit added a test
showing the regression, so we can now flip it to expect_success).

Reported-by: Ben Humphreys &lt;behumphreys@atlassian.com&gt;
Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Use the final_oid_fn to finalize hashing of object IDs</title>
<updated>2021-04-27T07:31:38Z</updated>
<author>
<name>brian m. carlson</name>
<email>sandals@crustytoothpaste.net</email>
</author>
<published>2021-04-26T01:02:53Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=5951bf467ea92458c3bea3051c8413041f3b27d5'/>
<id>urn:sha1:5951bf467ea92458c3bea3051c8413041f3b27d5</id>
<content type='text'>
When we're hashing a value which is going to be an object ID, we want to
zero-pad that value if necessary.  To do so, use the final_oid_fn
instead of the final_fn anytime we're going to create an object ID to
ensure we perform this operation.

Signed-off-by: brian m. carlson &lt;sandals@crustytoothpaste.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Merge branch 'cs/http-use-basic-after-failed-negotiate'</title>
<updated>2021-03-30T21:35:37Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2021-03-30T21:35:37Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=501380286295cac300dae86c3f0f6c10ff34b767'/>
<id>urn:sha1:501380286295cac300dae86c3f0f6c10ff34b767</id>
<content type='text'>
When accessing a server with a URL like https://user:pass@site/, we
did not to fall back to the basic authentication with the
credential material embedded in the URL after the "Negotiate"
authentication failed.  Now we do.

* cs/http-use-basic-after-failed-negotiate:
  remote-curl: fall back to basic auth if Negotiate fails
</content>
</entry>
<entry>
<title>Merge branch 'js/http-pki-credential-store'</title>
<updated>2021-03-26T21:59:02Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2021-03-26T21:59:02Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=8c81fce4b07c7e0f76960f35b6ffdc817c09b7ad'/>
<id>urn:sha1:8c81fce4b07c7e0f76960f35b6ffdc817c09b7ad</id>
<content type='text'>
The http codepath learned to let the credential layer to cache the
password used to unlock a certificate that has successfully been
used.

* js/http-pki-credential-store:
  http: drop the check for an empty proxy password before approving
  http: store credential when PKI auth is used
</content>
</entry>
<entry>
<title>remote-curl: fall back to basic auth if Negotiate fails</title>
<updated>2021-03-22T18:55:41Z</updated>
<author>
<name>Christopher Schenk</name>
<email>christopher@cschenk.net</email>
</author>
<published>2021-03-22T11:51:16Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=1b0d9545bb85912a16b367229d414f55d140d3be'/>
<id>urn:sha1:1b0d9545bb85912a16b367229d414f55d140d3be</id>
<content type='text'>
When the username and password are supplied in a url like this
https://myuser:secret@git.exampe/myrepo.git and the server supports the
negotiate authenticaten method, git does not fall back to basic auth and
libcurl hardly tries to authenticate with the negotiate method.

Stop using the Negotiate authentication method after the first failure
because if it fails on the first try it will never succeed.

Signed-off-by: Christopher Schenk &lt;christopher@cschenk.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>use CALLOC_ARRAY</title>
<updated>2021-03-14T00:00:09Z</updated>
<author>
<name>René Scharfe</name>
<email>l.s.r@web.de</email>
</author>
<published>2021-03-13T16:17:22Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=ca56dadb4b65ccaeab809d80db80a312dc00941a'/>
<id>urn:sha1:ca56dadb4b65ccaeab809d80db80a312dc00941a</id>
<content type='text'>
Add and apply a semantic patch for converting code that open-codes
CALLOC_ARRAY to use it instead.  It shortens the code and infers the
element size automatically.

Signed-off-by: René Scharfe &lt;l.s.r@web.de&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>http: drop the check for an empty proxy password before approving</title>
<updated>2021-03-12T06:17:10Z</updated>
<author>
<name>John Szakmeister</name>
<email>john@szakmeister.net</email>
</author>
<published>2021-03-12T02:40:27Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=a4a4439fdf2fa5867b3f30040be535cff65b8a42'/>
<id>urn:sha1:a4a4439fdf2fa5867b3f30040be535cff65b8a42</id>
<content type='text'>
credential_approve() already checks for a non-empty password before
saving, so there's no need to do the extra check here.

Signed-off-by: John Szakmeister &lt;john@szakmeister.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>http: store credential when PKI auth is used</title>
<updated>2021-03-12T06:17:07Z</updated>
<author>
<name>John Szakmeister</name>
<email>john@szakmeister.net</email>
</author>
<published>2021-03-12T02:40:26Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=cd27f604e41475633d068d3f4852ab6b597c5e75'/>
<id>urn:sha1:cd27f604e41475633d068d3f4852ab6b597c5e75</id>
<content type='text'>
We already looked for the PKI credentials in the credential store, but
failed to approve it on success.  Meaning, the PKI certificate password
was never stored and git would request it on every connection to the
remote.  Let's complete the chain by storing the certificate password on
success.

Likewise, we also need to reject the credential when there is a failure.
Curl appears to report client-related certificate issues are reported
with the CURLE_SSL_CERTPROBLEM error.  This includes not only a bad
password, but potentially other client certificate related problems.
Since we cannot get more information from curl, we'll go ahead and
reject the credential upon receiving that error, just to be safe and
avoid caching or saving a bad password.

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