[PATCH] Prompt for a username when an HTTP request 401s
From: Scott Chacon <hidden>
Date: 2016-06-15 22:48:27
Subsystem:
the rest · Maintainer:
Linus Torvalds
When an HTTP request returns a 401, Git will currently fail with a confusing message saying that it got a 401. This changes http_request to prompt for the username and password, then return HTTP_REAUTH so http_get_strbuf can try again. If it gets a 401 even when a user/pass is supplied, http_request will now return HTTP_NOAUTH which remote_curl can then use to display a more intelligent error message that is less confusing. Signed-off-by: Scott Chacon <redacted> --- Third version of this with Shawn's comments on why getpass() is needed. http.c | 20 ++++++++++++++++++-- http.h | 2 ++ remote-curl.c | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/http.c b/http.c
index deab595..62db1f0 100644
--- a/http.c
+++ b/http.c@@ -815,7 +815,19 @@ static int http_request(const char *url, void*result, int target, int options)
ret = HTTP_OK;
else if (missing_target(&results))
ret = HTTP_MISSING_TARGET;
- else
+ else if (results.http_code == 401) {
+ if (user_name) {
+ ret = HTTP_NOAUTH;
+ } else {
+ // getpass is needed here because its very likely stdin/stdout are
+ // pipes to our parent process. So we instead need to use /dev/tty,
+ // but that is non-portable. Using getpass() can at least be stubbed
+ // on other platforms with a different implementation if/when necessary.
+ user_name = xstrdup(getpass("Username: "));
+ init_curl_http_auth(slot->curl);
+ ret = HTTP_REAUTH;
+ }
+ } else
ret = HTTP_ERROR;
} else {
error("Unable to start HTTP request for %s", url);@@ -831,7 +843,11 @@ static int http_request(const char *url, void*result, int target, int options)
int http_get_strbuf(const char *url, struct strbuf *result, int options)
{
- return http_request(url, result, HTTP_REQUEST_STRBUF, options);
+ int http_ret = http_request(url, result, HTTP_REQUEST_STRBUF, options);
+ if (http_ret == HTTP_REAUTH) {
+ http_ret = http_request(url, result, HTTP_REQUEST_STRBUF, options);
+ }
+ return http_ret;
}
/*diff --git a/http.h b/http.h
index 5c9441c..2dd03e8 100644
--- a/http.h
+++ b/http.h@@ -126,6 +126,8 @@ extern char *get_remote_object_url(const char*url, const char *hex, #define HTTP_MISSING_TARGET 1 #define HTTP_ERROR 2 #define HTTP_START_FAILED 3 +#define HTTP_REAUTH 4 +#define HTTP_NOAUTH 5 /* * Requests an url and stores the result in a strbuf.
diff --git a/remote-curl.c b/remote-curl.c
index b76bfcb..0782756 100644
--- a/remote-curl.c
+++ b/remote-curl.c@@ -132,6 +132,8 @@ static struct discovery* discover_refs(const char *service) case HTTP_MISSING_TARGET: die("%s not found: did you run git update-server-info on the" " server?", refs_url); + case HTTP_NOAUTH: + die("Authentication failed"); default: http_error(refs_url, http_ret); die("HTTP request failed");
--
1.7.0.1