@matheusbsbs / matheus-bagliano / commits / c33976cbc6
Fork 0

http authentication via prompts

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>

Junio C Hamano committed Mar 9, 2009 at 23:34 UTC c33976cbc6d1895fca5c1683fba678e786ee3e58
1 file changed +60
http.c
+60
@@ -25,6 +25,7 @@ static long curl_low_speed_limit = -1;
25 static long curl_low_speed_time = -1;
26 static int curl_ftp_no_epsv;
27 static const char *curl_http_proxy;
28 +static char *user_name, *user_pass;
29
30 static struct curl_slist *pragma_header;
31
@@ -135,6 +136,20 @@ static int http_options(const char *var, const char *value, void *cb)
136 return git_default_config(var, value, cb);
137 }
138
139 +static void init_curl_http_auth(CURL *result)
140 +{
141 + if (!user_name)
142 + curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
143 + else {
144 + struct strbuf up = STRBUF_INIT;
145 + if (!user_pass)
146 + user_pass = xstrdup(getpass("Password: "));
147 + strbuf_addf(&up, "%s:%s", user_name, user_pass);
148 + curl_easy_setopt(result, CURLOPT_USERPWD,
149 + strbuf_detach(&up, NULL));
150 + }
151 +}
152 +
153 static CURL *get_curl_handle(void)
154 {
155 CURL *result = curl_easy_init();
@@ -153,6 +168,8 @@ static CURL *get_curl_handle(void)
168 curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
169 #endif
170
171 + init_curl_http_auth(result);
172 +
173 if (ssl_cert != NULL)
174 curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
175 #if LIBCURL_VERSION_NUM >= 0x070902
@@ -190,6 +207,46 @@ static CURL *get_curl_handle(void)
207 return result;
208 }
209
210 +static void http_auth_init(const char *url)
211 +{
212 + char *at, *colon, *cp, *slash;
213 + int len;
214 +
215 + cp = strstr(url, "://");
216 + if (!cp)
217 + return;
218 +
219 + /*
220 + * Ok, the URL looks like "proto://something". Which one?
221 + * "proto://<user>:<pass>@<host>/...",
222 + * "proto://<user>@<host>/...", or just
223 + * "proto://<host>/..."?
224 + */
225 + cp += 3;
226 + at = strchr(cp, '@');
227 + colon = strchr(cp, ':');
228 + slash = strchrnul(cp, '/');
229 + if (!at || slash <= at)
230 + return; /* No credentials */
231 + if (!colon || at <= colon) {
232 + /* Only username */
233 + len = at - cp;
234 + user_name = xmalloc(len + 1);
235 + memcpy(user_name, cp, len);
236 + user_name[len] = '\0';
237 + user_pass = NULL;
238 + } else {
239 + len = colon - cp;
240 + user_name = xmalloc(len + 1);
241 + memcpy(user_name, cp, len);
242 + user_name[len] = '\0';
243 + len = at - (colon + 1);
244 + user_pass = xmalloc(len + 1);
245 + memcpy(user_pass, colon + 1, len);
246 + user_pass[len] = '\0';
247 + }
248 +}
249 +
250 static void set_from_env(const char **var, const char *envname)
251 {
252 const char *val = getenv(envname);
@@ -255,6 +312,9 @@ void http_init(struct remote *remote)
312 if (getenv("GIT_CURL_FTP_NO_EPSV"))
313 curl_ftp_no_epsv = 1;
314
315 + if (remote && remote->url && remote->url[0])
316 + http_auth_init(remote->url[0]);
317 +
318 #ifndef NO_CURL_EASY_DUPHANDLE
319 curl_default = get_curl_handle();
320 #endif