Merge branch 'jk/http-walker-limit-redirect' into maint
Update the error messages from the dumb-http client when it fails to obtain loose objects; we used to give sensible error message only upon 404 but we now forbid unexpected redirects that needs to be reported with something sensible. * jk/http-walker-limit-redirect: http-walker: complain about non-404 loose object errors http: treat http-alternates like redirects http: make redirects more obvious remote-curl: rename shadowed options variable http: always update the base URL for redirects http: simplify update_url_from_redirect
This commit is contained in:
56
http.c
56
http.c
@ -111,6 +111,8 @@ static int http_proactive_auth;
|
||||
static const char *user_agent;
|
||||
static int curl_empty_auth;
|
||||
|
||||
enum http_follow_config http_follow_config = HTTP_FOLLOW_INITIAL;
|
||||
|
||||
#if LIBCURL_VERSION_NUM >= 0x071700
|
||||
/* Use CURLOPT_KEYPASSWD as is */
|
||||
#elif LIBCURL_VERSION_NUM >= 0x070903
|
||||
@ -366,6 +368,16 @@ static int http_options(const char *var, const char *value, void *cb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp("http.followredirects", var)) {
|
||||
if (value && !strcmp(value, "initial"))
|
||||
http_follow_config = HTTP_FOLLOW_INITIAL;
|
||||
else if (git_config_bool(var, value))
|
||||
http_follow_config = HTTP_FOLLOW_ALWAYS;
|
||||
else
|
||||
http_follow_config = HTTP_FOLLOW_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fall back on the default ones */
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
@ -717,7 +729,6 @@ static CURL *get_curl_handle(void)
|
||||
curl_low_speed_time);
|
||||
}
|
||||
|
||||
curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20);
|
||||
#if LIBCURL_VERSION_NUM >= 0x071301
|
||||
curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
|
||||
@ -734,6 +745,7 @@ static CURL *get_curl_handle(void)
|
||||
if (is_transport_allowed("ftps"))
|
||||
allowed_protocols |= CURLPROTO_FTPS;
|
||||
curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS, allowed_protocols);
|
||||
curl_easy_setopt(result, CURLOPT_PROTOCOLS, allowed_protocols);
|
||||
#else
|
||||
if (transport_restrict_protocols())
|
||||
warning("protocol restrictions not applied to curl redirects because\n"
|
||||
@ -1044,6 +1056,16 @@ struct active_request_slot *get_active_slot(void)
|
||||
curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL);
|
||||
|
||||
/*
|
||||
* Default following to off unless "ALWAYS" is configured; this gives
|
||||
* callers a sane starting point, and they can tweak for individual
|
||||
* HTTP_FOLLOW_* cases themselves.
|
||||
*/
|
||||
if (http_follow_config == HTTP_FOLLOW_ALWAYS)
|
||||
curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
else
|
||||
curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 0);
|
||||
|
||||
#if LIBCURL_VERSION_NUM >= 0x070a08
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IPRESOLVE, git_curl_ipresolve);
|
||||
#endif
|
||||
@ -1286,9 +1308,12 @@ static int handle_curl_result(struct slot_results *results)
|
||||
* If we see a failing http code with CURLE_OK, we have turned off
|
||||
* FAILONERROR (to keep the server's custom error response), and should
|
||||
* translate the code into failure here.
|
||||
*
|
||||
* Likewise, if we see a redirect (30x code), that means we turned off
|
||||
* redirect-following, and we should treat the result as an error.
|
||||
*/
|
||||
if (results->curl_result == CURLE_OK &&
|
||||
results->http_code >= 400) {
|
||||
results->http_code >= 300) {
|
||||
results->curl_result = CURLE_HTTP_RETURNED_ERROR;
|
||||
/*
|
||||
* Normally curl will already have put the "reason phrase"
|
||||
@ -1607,6 +1632,9 @@ static int http_request(const char *url,
|
||||
strbuf_addstr(&buf, " no-cache");
|
||||
if (options && options->keep_error)
|
||||
curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
|
||||
if (options && options->initial_request &&
|
||||
http_follow_config == HTTP_FOLLOW_INITIAL)
|
||||
curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
|
||||
headers = curl_slist_append(headers, buf.buf);
|
||||
|
||||
@ -1655,16 +1683,16 @@ static int http_request(const char *url,
|
||||
*
|
||||
* Note that this assumes a sane redirect scheme. It's entirely possible
|
||||
* in the example above to end up at a URL that does not even end in
|
||||
* "info/refs". In such a case we simply punt, as there is not much we can
|
||||
* do (and such a scheme is unlikely to represent a real git repository,
|
||||
* which means we are likely about to abort anyway).
|
||||
* "info/refs". In such a case we die. There's not much we can do, such a
|
||||
* scheme is unlikely to represent a real git repository, and failing to
|
||||
* rewrite the base opens options for malicious redirects to do funny things.
|
||||
*/
|
||||
static int update_url_from_redirect(struct strbuf *base,
|
||||
const char *asked,
|
||||
const struct strbuf *got)
|
||||
{
|
||||
const char *tail;
|
||||
size_t tail_len;
|
||||
size_t new_len;
|
||||
|
||||
if (!strcmp(asked, got->buf))
|
||||
return 0;
|
||||
@ -1673,14 +1701,16 @@ static int update_url_from_redirect(struct strbuf *base,
|
||||
die("BUG: update_url_from_redirect: %s is not a superset of %s",
|
||||
asked, base->buf);
|
||||
|
||||
tail_len = strlen(tail);
|
||||
|
||||
if (got->len < tail_len ||
|
||||
strcmp(tail, got->buf + got->len - tail_len))
|
||||
return 0; /* insane redirect scheme */
|
||||
new_len = got->len;
|
||||
if (!strip_suffix_mem(got->buf, &new_len, tail))
|
||||
die(_("unable to update url base from redirection:\n"
|
||||
" asked for: %s\n"
|
||||
" redirect: %s"),
|
||||
asked, got->buf);
|
||||
|
||||
strbuf_reset(base);
|
||||
strbuf_add(base, got->buf, got->len - tail_len);
|
||||
strbuf_add(base, got->buf, new_len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2028,7 +2058,7 @@ static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb,
|
||||
if (c != CURLE_OK)
|
||||
die("BUG: curl_easy_getinfo for HTTP code failed: %s",
|
||||
curl_easy_strerror(c));
|
||||
if (slot->http_code >= 400)
|
||||
if (slot->http_code >= 300)
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user