summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2017-03-10 21:24:23 (GMT)
committerJunio C Hamano <gitster@pobox.com>2017-03-10 21:24:23 (GMT)
commit92718f57c2e18e69bc7ae3ed18c7157c475e17a9 (patch)
treee36c53ecc0f9a00b1b73a389f8d5e2f314a095f4
parentea1e784c4739ff35b05a4ddc959482eb00ef48d6 (diff)
parent40a18fc77ca3ba1b018f0fbdcbdf4a6d237aadf3 (diff)
downloadgit-92718f57c2e18e69bc7ae3ed18c7157c475e17a9.zip
git-92718f57c2e18e69bc7ae3ed18c7157c475e17a9.tar.gz
git-92718f57c2e18e69bc7ae3ed18c7157c475e17a9.tar.bz2
Merge branch 'jk/http-auth'
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
-rw-r--r--http.c50
1 files changed, 46 insertions, 4 deletions
diff --git a/http.c b/http.c
index 90a1c0f..d2d6899 100644
--- a/http.c
+++ b/http.c
@@ -109,7 +109,7 @@ static int curl_save_cookies;
struct credential http_auth = CREDENTIAL_INIT;
static int http_proactive_auth;
static const char *user_agent;
-static int curl_empty_auth;
+static int curl_empty_auth = -1;
enum http_follow_config http_follow_config = HTTP_FOLLOW_INITIAL;
@@ -125,6 +125,14 @@ static struct credential cert_auth = CREDENTIAL_INIT;
static int ssl_cert_password_required;
#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
static unsigned long http_auth_methods = CURLAUTH_ANY;
+static int http_auth_methods_restricted;
+/* Modes for which empty_auth cannot actually help us. */
+static unsigned long empty_auth_useless =
+ CURLAUTH_BASIC
+#ifdef CURLAUTH_DIGEST_IE
+ | CURLAUTH_DIGEST_IE
+#endif
+ | CURLAUTH_DIGEST;
#endif
static struct curl_slist *pragma_header;
@@ -333,7 +341,10 @@ static int http_options(const char *var, const char *value, void *cb)
return git_config_string(&user_agent, var, value);
if (!strcmp("http.emptyauth", var)) {
- curl_empty_auth = git_config_bool(var, value);
+ if (value && !strcmp("auto", value))
+ curl_empty_auth = -1;
+ else
+ curl_empty_auth = git_config_bool(var, value);
return 0;
}
@@ -382,10 +393,37 @@ static int http_options(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}
+static int curl_empty_auth_enabled(void)
+{
+ if (curl_empty_auth >= 0)
+ return curl_empty_auth;
+
+#ifndef LIBCURL_CAN_HANDLE_AUTH_ANY
+ /*
+ * Our libcurl is too old to do AUTH_ANY in the first place;
+ * just default to turning the feature off.
+ */
+#else
+ /*
+ * In the automatic case, kick in the empty-auth
+ * hack as long as we would potentially try some
+ * method more exotic than "Basic" or "Digest".
+ *
+ * But only do this when this is our second or
+ * subsequent request, as by then we know what
+ * methods are available.
+ */
+ if (http_auth_methods_restricted &&
+ (http_auth_methods & ~empty_auth_useless))
+ return 1;
+#endif
+ return 0;
+}
+
static void init_curl_http_auth(CURL *result)
{
if (!http_auth.username || !*http_auth.username) {
- if (curl_empty_auth)
+ if (curl_empty_auth_enabled())
curl_easy_setopt(result, CURLOPT_USERPWD, ":");
return;
}
@@ -1079,7 +1117,7 @@ struct active_request_slot *get_active_slot(void)
#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods);
#endif
- if (http_auth.password || curl_empty_auth)
+ if (http_auth.password || curl_empty_auth_enabled())
init_curl_http_auth(slot->curl);
return slot;
@@ -1347,6 +1385,10 @@ static int handle_curl_result(struct slot_results *results)
} else {
#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
http_auth_methods &= ~CURLAUTH_GSSNEGOTIATE;
+ if (results->auth_avail) {
+ http_auth_methods &= results->auth_avail;
+ http_auth_methods_restricted = 1;
+ }
#endif
return HTTP_REAUTH;
}