Skip to content

Commit d880bfd

Browse files
committed
Merge branch 'jk/http-auth' into maint
Reduce authentication round-trip over HTTP when the server supports just a single authentication method. * jk/http-auth: http: add an "auto" mode for http.emptyauth http: restrict auth methods to what the server advertises
2 parents e7e07d5 + 40a18fc commit d880bfd

File tree

1 file changed

+46
-4
lines changed

1 file changed

+46
-4
lines changed

http.c

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ static int curl_save_cookies;
109109
struct credential http_auth = CREDENTIAL_INIT;
110110
static int http_proactive_auth;
111111
static const char *user_agent;
112-
static int curl_empty_auth;
112+
static int curl_empty_auth = -1;
113113

114114
enum http_follow_config http_follow_config = HTTP_FOLLOW_INITIAL;
115115

@@ -125,6 +125,14 @@ static struct credential cert_auth = CREDENTIAL_INIT;
125125
static int ssl_cert_password_required;
126126
#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
127127
static unsigned long http_auth_methods = CURLAUTH_ANY;
128+
static int http_auth_methods_restricted;
129+
/* Modes for which empty_auth cannot actually help us. */
130+
static unsigned long empty_auth_useless =
131+
CURLAUTH_BASIC
132+
#ifdef CURLAUTH_DIGEST_IE
133+
| CURLAUTH_DIGEST_IE
134+
#endif
135+
| CURLAUTH_DIGEST;
128136
#endif
129137

130138
static struct curl_slist *pragma_header;
@@ -333,7 +341,10 @@ static int http_options(const char *var, const char *value, void *cb)
333341
return git_config_string(&user_agent, var, value);
334342

335343
if (!strcmp("http.emptyauth", var)) {
336-
curl_empty_auth = git_config_bool(var, value);
344+
if (value && !strcmp("auto", value))
345+
curl_empty_auth = -1;
346+
else
347+
curl_empty_auth = git_config_bool(var, value);
337348
return 0;
338349
}
339350

@@ -382,10 +393,37 @@ static int http_options(const char *var, const char *value, void *cb)
382393
return git_default_config(var, value, cb);
383394
}
384395

396+
static int curl_empty_auth_enabled(void)
397+
{
398+
if (curl_empty_auth >= 0)
399+
return curl_empty_auth;
400+
401+
#ifndef LIBCURL_CAN_HANDLE_AUTH_ANY
402+
/*
403+
* Our libcurl is too old to do AUTH_ANY in the first place;
404+
* just default to turning the feature off.
405+
*/
406+
#else
407+
/*
408+
* In the automatic case, kick in the empty-auth
409+
* hack as long as we would potentially try some
410+
* method more exotic than "Basic" or "Digest".
411+
*
412+
* But only do this when this is our second or
413+
* subsequent request, as by then we know what
414+
* methods are available.
415+
*/
416+
if (http_auth_methods_restricted &&
417+
(http_auth_methods & ~empty_auth_useless))
418+
return 1;
419+
#endif
420+
return 0;
421+
}
422+
385423
static void init_curl_http_auth(CURL *result)
386424
{
387425
if (!http_auth.username || !*http_auth.username) {
388-
if (curl_empty_auth)
426+
if (curl_empty_auth_enabled())
389427
curl_easy_setopt(result, CURLOPT_USERPWD, ":");
390428
return;
391429
}
@@ -1079,7 +1117,7 @@ struct active_request_slot *get_active_slot(void)
10791117
#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
10801118
curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods);
10811119
#endif
1082-
if (http_auth.password || curl_empty_auth)
1120+
if (http_auth.password || curl_empty_auth_enabled())
10831121
init_curl_http_auth(slot->curl);
10841122

10851123
return slot;
@@ -1347,6 +1385,10 @@ static int handle_curl_result(struct slot_results *results)
13471385
} else {
13481386
#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
13491387
http_auth_methods &= ~CURLAUTH_GSSNEGOTIATE;
1388+
if (results->auth_avail) {
1389+
http_auth_methods &= results->auth_avail;
1390+
http_auth_methods_restricted = 1;
1391+
}
13501392
#endif
13511393
return HTTP_REAUTH;
13521394
}

0 commit comments

Comments
 (0)