]> git.ipfire.org Git - thirdparty/git.git/blobdiff - http.c
The seventh batch
[thirdparty/git.git] / http.c
diff --git a/http.c b/http.c
index 22639b09742a336ef72e8c9f6405294e95f90bb2..752c879c1f159495e7a4c3647bd0a078f1aa29f8 100644 (file)
--- a/http.c
+++ b/http.c
@@ -561,18 +561,34 @@ static int curl_empty_auth_enabled(void)
        return 0;
 }
 
+struct curl_slist *http_append_auth_header(const struct credential *c,
+                                          struct curl_slist *headers)
+{
+       if (c->authtype && c->credential) {
+               struct strbuf auth = STRBUF_INIT;
+               strbuf_addf(&auth, "Authorization: %s %s",
+                           c->authtype, c->credential);
+               headers = curl_slist_append(headers, auth.buf);
+               strbuf_release(&auth);
+       }
+       return headers;
+}
+
 static void init_curl_http_auth(CURL *result)
 {
-       if (!http_auth.username || !*http_auth.username) {
+       if ((!http_auth.username || !*http_auth.username) &&
+           (!http_auth.credential || !*http_auth.credential)) {
                if (curl_empty_auth_enabled())
                        curl_easy_setopt(result, CURLOPT_USERPWD, ":");
                return;
        }
 
-       credential_fill(&http_auth);
+       credential_fill(&http_auth, 1);
 
-       curl_easy_setopt(result, CURLOPT_USERNAME, http_auth.username);
-       curl_easy_setopt(result, CURLOPT_PASSWORD, http_auth.password);
+       if (http_auth.password) {
+               curl_easy_setopt(result, CURLOPT_USERNAME, http_auth.username);
+               curl_easy_setopt(result, CURLOPT_PASSWORD, http_auth.password);
+       }
 }
 
 /* *var must be free-able */
@@ -586,17 +602,22 @@ static void var_override(const char **var, char *value)
 
 static void set_proxyauth_name_password(CURL *result)
 {
+       if (proxy_auth.password) {
                curl_easy_setopt(result, CURLOPT_PROXYUSERNAME,
                        proxy_auth.username);
                curl_easy_setopt(result, CURLOPT_PROXYPASSWORD,
                        proxy_auth.password);
+       } else if (proxy_auth.authtype && proxy_auth.credential) {
+               curl_easy_setopt(result, CURLOPT_PROXYHEADER,
+                                http_append_auth_header(&proxy_auth, NULL));
+       }
 }
 
 static void init_curl_proxy_auth(CURL *result)
 {
        if (proxy_auth.username) {
-               if (!proxy_auth.password)
-                       credential_fill(&proxy_auth);
+               if (!proxy_auth.password && !proxy_auth.credential)
+                       credential_fill(&proxy_auth, 1);
                set_proxyauth_name_password(result);
        }
 
@@ -630,7 +651,7 @@ static int has_cert_password(void)
                cert_auth.host = xstrdup("");
                cert_auth.username = xstrdup("");
                cert_auth.path = xstrdup(ssl_cert);
-               credential_fill(&cert_auth);
+               credential_fill(&cert_auth, 0);
        }
        return 1;
 }
@@ -645,7 +666,7 @@ static int has_proxy_cert_password(void)
                proxy_cert_auth.host = xstrdup("");
                proxy_cert_auth.username = xstrdup("");
                proxy_cert_auth.path = xstrdup(http_proxy_ssl_cert);
-               credential_fill(&proxy_cert_auth);
+               credential_fill(&proxy_cert_auth, 0);
        }
        return 1;
 }
@@ -1451,6 +1472,7 @@ struct active_request_slot *get_active_slot(void)
        curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, NULL);
        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, NULL);
        curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, NULL);
+       curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, -1L);
        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0);
        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
        curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1);
@@ -1468,7 +1490,7 @@ struct active_request_slot *get_active_slot(void)
 
        curl_easy_setopt(slot->curl, CURLOPT_IPRESOLVE, git_curl_ipresolve);
        curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods);
-       if (http_auth.password || curl_empty_auth_enabled())
+       if (http_auth.password || http_auth.credential || curl_empty_auth_enabled())
                init_curl_http_auth(slot->curl);
 
        return slot;
@@ -1757,7 +1779,12 @@ static int handle_curl_result(struct slot_results *results)
        } else if (missing_target(results))
                return HTTP_MISSING_TARGET;
        else if (results->http_code == 401) {
-               if (http_auth.username && http_auth.password) {
+               if ((http_auth.username && http_auth.password) ||\
+                   (http_auth.authtype && http_auth.credential)) {
+                       if (http_auth.multistage) {
+                               credential_clear_secrets(&http_auth);
+                               return HTTP_REAUTH;
+                       }
                        credential_reject(&http_auth);
                        return HTTP_NOAUTH;
                } else {
@@ -2065,11 +2092,15 @@ static int http_request(const char *url,
        /* Add additional headers here */
        if (options && options->extra_headers) {
                const struct string_list_item *item;
-               for_each_string_list_item(item, options->extra_headers) {
-                       headers = curl_slist_append(headers, item->string);
+               if (options && options->extra_headers) {
+                       for_each_string_list_item(item, options->extra_headers) {
+                               headers = curl_slist_append(headers, item->string);
+                       }
                }
        }
 
+       headers = http_append_auth_header(&http_auth, headers);
+
        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");
@@ -2151,6 +2182,7 @@ static int http_request_reauth(const char *url,
                               void *result, int target,
                               struct http_get_options *options)
 {
+       int i = 3;
        int ret = http_request(url, result, target, options);
 
        if (ret != HTTP_OK && ret != HTTP_REAUTH)
@@ -2164,35 +2196,35 @@ static int http_request_reauth(const char *url,
                }
        }
 
-       if (ret != HTTP_REAUTH)
-               return ret;
-
-       /*
-        * The previous request may have put cruft into our output stream; we
-        * should clear it out before making our next request.
-        */
-       switch (target) {
-       case HTTP_REQUEST_STRBUF:
-               strbuf_reset(result);
-               break;
-       case HTTP_REQUEST_FILE:
-               if (fflush(result)) {
-                       error_errno("unable to flush a file");
-                       return HTTP_START_FAILED;
-               }
-               rewind(result);
-               if (ftruncate(fileno(result), 0) < 0) {
-                       error_errno("unable to truncate a file");
-                       return HTTP_START_FAILED;
+       while (ret == HTTP_REAUTH && --i) {
+               /*
+                * The previous request may have put cruft into our output stream; we
+                * should clear it out before making our next request.
+                */
+               switch (target) {
+               case HTTP_REQUEST_STRBUF:
+                       strbuf_reset(result);
+                       break;
+               case HTTP_REQUEST_FILE:
+                       if (fflush(result)) {
+                               error_errno("unable to flush a file");
+                               return HTTP_START_FAILED;
+                       }
+                       rewind(result);
+                       if (ftruncate(fileno(result), 0) < 0) {
+                               error_errno("unable to truncate a file");
+                               return HTTP_START_FAILED;
+                       }
+                       break;
+               default:
+                       BUG("Unknown http_request target");
                }
-               break;
-       default:
-               BUG("Unknown http_request target");
-       }
 
-       credential_fill(&http_auth);
+               credential_fill(&http_auth, 1);
 
-       return http_request(url, result, target, options);
+               ret = http_request(url, result, target, options);
+       }
+       return ret;
 }
 
 int http_get_strbuf(const char *url,