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 */
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);
}
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;
}
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;
}
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);
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;
} 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 {
/* 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, "");
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)
}
}
- 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,