Skip to content

Commit

Permalink
http authentication via prompts
Browse files Browse the repository at this point in the history
Curl is designed not to ask for password when only username is given in
the URL, but has a way for application to feed a (username, password) pair
to it.  With this patch, you do not have to keep your password in
plaintext in your $HOME/.netrc file when talking with a password protected
URL with http://<username>@<host>/path/to/repository.git/ syntax.

The code handles only the http-walker side, not the push side.  At least,
not yet.  But interested parties can add support for it.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Junio C Hamano committed Mar 11, 2009
1 parent 7059cd9 commit c33976c
Showing 1 changed file with 60 additions and 0 deletions.
60 changes: 60 additions & 0 deletions http.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ static long curl_low_speed_limit = -1;
static long curl_low_speed_time = -1;
static int curl_ftp_no_epsv;
static const char *curl_http_proxy;
static char *user_name, *user_pass;

static struct curl_slist *pragma_header;

Expand Down Expand Up @@ -135,6 +136,20 @@ static int http_options(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}

static void init_curl_http_auth(CURL *result)
{
if (!user_name)
curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
else {
struct strbuf up = STRBUF_INIT;
if (!user_pass)
user_pass = xstrdup(getpass("Password: "));
strbuf_addf(&up, "%s:%s", user_name, user_pass);
curl_easy_setopt(result, CURLOPT_USERPWD,
strbuf_detach(&up, NULL));
}
}

static CURL *get_curl_handle(void)
{
CURL *result = curl_easy_init();
Expand All @@ -153,6 +168,8 @@ static CURL *get_curl_handle(void)
curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
#endif

init_curl_http_auth(result);

if (ssl_cert != NULL)
curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
#if LIBCURL_VERSION_NUM >= 0x070902
Expand Down Expand Up @@ -190,6 +207,46 @@ static CURL *get_curl_handle(void)
return result;
}

static void http_auth_init(const char *url)
{
char *at, *colon, *cp, *slash;
int len;

cp = strstr(url, "://");
if (!cp)
return;

/*
* Ok, the URL looks like "proto://something". Which one?
* "proto://<user>:<pass>@<host>/...",
* "proto://<user>@<host>/...", or just
* "proto://<host>/..."?
*/
cp += 3;
at = strchr(cp, '@');
colon = strchr(cp, ':');
slash = strchrnul(cp, '/');
if (!at || slash <= at)
return; /* No credentials */
if (!colon || at <= colon) {
/* Only username */
len = at - cp;
user_name = xmalloc(len + 1);
memcpy(user_name, cp, len);
user_name[len] = '\0';
user_pass = NULL;
} else {
len = colon - cp;
user_name = xmalloc(len + 1);
memcpy(user_name, cp, len);
user_name[len] = '\0';
len = at - (colon + 1);
user_pass = xmalloc(len + 1);
memcpy(user_pass, colon + 1, len);
user_pass[len] = '\0';
}
}

static void set_from_env(const char **var, const char *envname)
{
const char *val = getenv(envname);
Expand Down Expand Up @@ -255,6 +312,9 @@ void http_init(struct remote *remote)
if (getenv("GIT_CURL_FTP_NO_EPSV"))
curl_ftp_no_epsv = 1;

if (remote && remote->url && remote->url[0])
http_auth_init(remote->url[0]);

#ifndef NO_CURL_EASY_DUPHANDLE
curl_default = get_curl_handle();
#endif
Expand Down

0 comments on commit c33976c

Please sign in to comment.