Skip to content

Commit 2e736fd

Browse files
committed
remote-curl: retry failed requests for auth even with gzip
Commit b81401c taught the post_rpc function to retry the http request after prompting for credentials. However, it did not handle two cases: 1. If we have a large request, we do not retry. That's OK, since we would have sent a probe (with retry) already. 2. If we are gzipping the request, we do not retry. That was considered OK, because the intended use was for push (e.g., listing refs is OK, but actually pushing objects is not), and we never gzip on push. This patch teaches post_rpc to retry even a gzipped request. This has two advantages: 1. It is possible to configure a "half-auth" state for fetching, where the set of refs and their sha1s are advertised, but one cannot actually fetch objects. This is not a recommended configuration, as it leaks some information about what is in the repository (e.g., an attacker can try brute-forcing possible content in your repository and checking whether it matches your branch sha1). However, it can be slightly more convenient, since a no-op fetch will not require a password at all. 2. It future-proofs us should we decide to ever gzip more requests. Signed-off-by: Jeff King <[email protected]>
1 parent df126e1 commit 2e736fd

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

remote-curl.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,15 @@ static int post_rpc(struct rpc_state *rpc)
474474
fflush(stderr);
475475
}
476476

477+
} else if (gzip_body) {
478+
/*
479+
* If we are looping to retry authentication, then the previous
480+
* run will have set up the headers and gzip buffer already,
481+
* and we just need to send it.
482+
*/
483+
curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body);
484+
curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size);
485+
477486
} else if (use_gzip && 1024 < rpc->len) {
478487
/* The client backend isn't giving us compressed data so
479488
* we can try to deflate it ourselves, this may save on.
@@ -530,7 +539,7 @@ static int post_rpc(struct rpc_state *rpc)
530539
curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc);
531540

532541
err = run_slot(slot);
533-
if (err == HTTP_REAUTH && !large_request && !use_gzip)
542+
if (err == HTTP_REAUTH && !large_request)
534543
goto retry;
535544
if (err != HTTP_OK)
536545
err = -1;

t/lib-httpd/apache.conf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ SSLEngine On
9696
Require valid-user
9797
</LocationMatch>
9898

99+
<LocationMatch "^/auth-fetch/.*/git-upload-pack$">
100+
AuthType Basic
101+
AuthName "git-auth"
102+
AuthUserFile passwd
103+
Require valid-user
104+
</LocationMatch>
105+
99106
<IfDefine DAV>
100107
LoadModule dav_module modules/mod_dav.so
101108
LoadModule dav_fs_module modules/mod_dav_fs.so

t/t5551-http-fetch.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,21 @@ test_expect_success 'clone from auth-only-for-push repository' '
129129
test_cmp expect actual
130130
'
131131

132+
test_expect_success 'clone from auth-only-for-objects repository' '
133+
echo two >expect &&
134+
set_askpass user@host &&
135+
git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth &&
136+
expect_askpass both user@host &&
137+
git --git-dir=half-auth log -1 --format=%s >actual &&
138+
test_cmp expect actual
139+
'
140+
141+
test_expect_success 'no-op half-auth fetch does not require a password' '
142+
set_askpass wrong &&
143+
git --git-dir=half-auth fetch &&
144+
expect_askpass none
145+
'
146+
132147
test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
133148

134149
test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '

0 commit comments

Comments
 (0)