aboutsummaryrefslogtreecommitdiffstats
path: root/http.c
diff options
context:
space:
mode:
Diffstat (limited to 'http.c')
-rw-r--r--http.c78
1 files changed, 69 insertions, 9 deletions
diff --git a/http.c b/http.c
index 67cc47d28f..623ed23489 100644
--- a/http.c
+++ b/http.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "git-curl-compat.h"
#include "hex.h"
@@ -106,12 +108,19 @@ static struct {
};
#endif
+enum proactive_auth {
+ PROACTIVE_AUTH_NONE = 0,
+ PROACTIVE_AUTH_IF_CREDENTIALS,
+ PROACTIVE_AUTH_AUTO,
+ PROACTIVE_AUTH_BASIC,
+};
+
static struct credential proxy_auth = CREDENTIAL_INIT;
static const char *curl_proxyuserpwd;
static char *curl_cookie_file;
static int curl_save_cookies;
struct credential http_auth = CREDENTIAL_INIT;
-static int http_proactive_auth;
+static enum proactive_auth http_proactive_auth;
static char *user_agent;
static int curl_empty_auth = -1;
@@ -146,6 +155,12 @@ static int http_schannel_check_revoke = 1;
*/
static int http_schannel_use_ssl_cainfo;
+static int always_auth_proactively(void)
+{
+ return http_proactive_auth != PROACTIVE_AUTH_NONE &&
+ http_proactive_auth != PROACTIVE_AUTH_IF_CREDENTIALS;
+}
+
size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
{
size_t size = eltsize * nmemb;
@@ -537,6 +552,20 @@ static int http_options(const char *var, const char *value,
return 0;
}
+ if (!strcmp("http.proactiveauth", var)) {
+ if (!value)
+ return config_error_nonbool(var);
+ if (!strcmp(value, "auto"))
+ http_proactive_auth = PROACTIVE_AUTH_AUTO;
+ else if (!strcmp(value, "basic"))
+ http_proactive_auth = PROACTIVE_AUTH_BASIC;
+ else if (!strcmp(value, "none"))
+ http_proactive_auth = PROACTIVE_AUTH_NONE;
+ else
+ warning(_("Unknown value for http.proactiveauth"));
+ return 0;
+ }
+
/* Fall back on the default ones */
return git_default_config(var, value, ctx, data);
}
@@ -578,14 +607,29 @@ static void init_curl_http_auth(CURL *result)
{
if ((!http_auth.username || !*http_auth.username) &&
(!http_auth.credential || !*http_auth.credential)) {
- if (curl_empty_auth_enabled())
+ int empty_auth = curl_empty_auth_enabled();
+ if ((empty_auth != -1 && !always_auth_proactively()) || empty_auth == 1) {
curl_easy_setopt(result, CURLOPT_USERPWD, ":");
- return;
+ return;
+ } else if (!always_auth_proactively()) {
+ return;
+ } else if (http_proactive_auth == PROACTIVE_AUTH_BASIC) {
+ strvec_push(&http_auth.wwwauth_headers, "Basic");
+ }
}
credential_fill(&http_auth, 1);
if (http_auth.password) {
+ if (always_auth_proactively()) {
+ /*
+ * We got a credential without an authtype and we don't
+ * know what's available. Since our only two options at
+ * the moment are auto (which defaults to basic) and
+ * basic, use basic for now.
+ */
+ curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+ }
curl_easy_setopt(result, CURLOPT_USERNAME, http_auth.username);
curl_easy_setopt(result, CURLOPT_PASSWORD, http_auth.password);
}
@@ -1048,7 +1092,7 @@ static CURL *get_curl_handle(void)
#endif
}
- if (http_proactive_auth)
+ if (http_proactive_auth != PROACTIVE_AUTH_NONE)
init_curl_http_auth(result);
if (getenv("GIT_SSL_VERSION"))
@@ -1292,7 +1336,8 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
die("curl_global_init failed");
- http_proactive_auth = proactive_auth;
+ if (proactive_auth && http_proactive_auth == PROACTIVE_AUTH_NONE)
+ http_proactive_auth = PROACTIVE_AUTH_IF_CREDENTIALS;
if (remote && remote->http_proxy)
curl_http_proxy = xstrdup(remote->http_proxy);
@@ -1464,7 +1509,16 @@ struct active_request_slot *get_active_slot(void)
slot->finished = NULL;
slot->callback_data = NULL;
slot->callback_func = NULL;
+
+ if (curl_cookie_file && !strcmp(curl_cookie_file, "-")) {
+ warning(_("refusing to read cookies from http.cookiefile '-'"));
+ FREE_AND_NULL(curl_cookie_file);
+ }
curl_easy_setopt(slot->curl, CURLOPT_COOKIEFILE, curl_cookie_file);
+ if (curl_save_cookies && (!curl_cookie_file || !curl_cookie_file[0])) {
+ curl_save_cookies = 0;
+ warning(_("ignoring http.savecookies for empty http.cookiefile"));
+ }
if (curl_save_cookies)
curl_easy_setopt(slot->curl, CURLOPT_COOKIEJAR, curl_cookie_file);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
@@ -1788,6 +1842,8 @@ static int handle_curl_result(struct slot_results *results)
return HTTP_REAUTH;
}
credential_reject(&http_auth);
+ if (always_auth_proactively())
+ http_proactive_auth = PROACTIVE_AUTH_NONE;
return HTTP_NOAUTH;
} else {
http_auth_methods &= ~CURLAUTH_GSSNEGOTIATE;
@@ -1974,7 +2030,7 @@ static void write_accept_language(struct strbuf *buf)
/* add '*' */
REALLOC_ARRAY(language_tags, num_langs + 1);
- language_tags[num_langs++] = "*"; /* it's OK; this won't be freed */
+ language_tags[num_langs++] = xstrdup("*");
/* compute decimal_places */
for (max_q = 1, decimal_places = 0;
@@ -2004,8 +2060,7 @@ static void write_accept_language(struct strbuf *buf)
}
}
- /* free language tags -- last one is a static '*' */
- for (i = 0; i < num_langs - 1; i++)
+ for (i = 0; i < num_langs; i++)
free(language_tags[i]);
free(language_tags);
}
@@ -2185,7 +2240,12 @@ static int http_request_reauth(const char *url,
struct http_get_options *options)
{
int i = 3;
- int ret = http_request(url, result, target, options);
+ int ret;
+
+ if (always_auth_proactively())
+ credential_fill(&http_auth, 1);
+
+ ret = http_request(url, result, target, options);
if (ret != HTTP_OK && ret != HTTP_REAUTH)
return ret;