git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 2/2] http: use credential API to handle proxy authentication

From
KFKnut Franke <k.franke@science-computing.de>
Date
Oct 28, 2015, 09:40 UTC
Message-ID
<1446025245-10128-3-git-send-email-k.franke@science-computing.de>
In-Reply-To
<1446025245-10128-1-git-send-email-k.franke@science-computing.de>

Currently, the only way to pass proxy credentials to curl is by including them in the proxy URL. Usually, this means they will end up on disk unencrypted, one way or another (by inclusion in ~/.gitconfig, shell profile or history). Since proxy authentication often uses a domain user, credentials can be security sensitive; therefore, a safer way of passing credentials is desirable.

If the configured proxy contains a username but not a password, query the credential API for one. Also, make sure we approve/reject proxy credentials properly.

For consistency reasons, add parsing of http_proxy/https_proxy/all_proxy environment variables, which would otherwise be evaluated as a fallback by curl. Without this, we would have different semantics for git configuration and environment variables.

Signed-off-by: Knut Franke <k.franke@science-computing.de>
---
 http.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 http.h |  1 +
 2 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/http.c b/http.c
index 4756bab..11bebe1 100644
--- a/http.c
+++ b/http.c
@@ -79,6 +79,7 @@ static struct {
 	// curl(1) and is not included in CURLAUTH_ANY, so we leave it out
 	// here, too
 };
+struct credential http_proxy_auth = CREDENTIAL_INIT;
 static const char *curl_cookie_file;
 static int curl_save_cookies;
 struct credential http_auth = CREDENTIAL_INIT;
@@ -176,6 +177,9 @@ static void finish_active_slot(struct active_request_slot *slot)
 #else
 		slot->results->auth_avail = 0;
 #endif
+
+		curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CONNECTCODE,
+			&slot->results->http_connectcode);
 	}
 
 	/* Run callback if appropriate */
@@ -333,6 +337,25 @@ static void copy_from_env(const char **var, const char *envname)
 
 static void init_curl_proxy_auth(CURL *result)
 {
+	if (http_proxy_auth.username) {
+		if (!http_proxy_auth.password) {
+			credential_fill(&http_proxy_auth);
+		}
+#if LIBCURL_VERSION_NUM >= 0x071301
+		curl_easy_setopt(result, CURLOPT_PROXYUSERNAME,
+			http_proxy_auth.username);
+		curl_easy_setopt(result, CURLOPT_PROXYPASSWORD,
+			http_proxy_auth.password);
+#else
+		struct strbuf up = STRBUF_INIT;
+		strbuf_reset(&up);
+		strbuf_addstr_urlencode(&up, http_proxy_auth.username, 1);
+		strbuf_addch(&up, ':');
+		strbuf_addstr_urlencode(&up, http_proxy_auth.password, 1);
+		curl_easy_setopt(result, CURLOPT_PROXYUSERPWD, up.buf);
+#endif
+	}
+
 	copy_from_env(&http_proxy_authmethod, "GIT_HTTP_PROXY_AUTHMETHOD");
 
 	if (http_proxy_authmethod) {
@@ -513,8 +536,36 @@ static CURL *get_curl_handle(void)
 		curl_easy_setopt(result, CURLOPT_USE_SSL, CURLUSESSL_TRY);
 #endif
 
+	/*
+	 * curl also examines these variables as a fallback; but we need to query
+	 * them here in order to decide whether to prompt for missing password (cf.
+	 * init_curl_proxy_auth()).
+	 */
+	if (!curl_http_proxy) {
+		if (!strcmp(http_auth.protocol, "https")) {
+			copy_from_env(&curl_http_proxy, "HTTPS_PROXY");
+			copy_from_env(&curl_http_proxy, "https_proxy");
+		} else {
+			copy_from_env(&curl_http_proxy, "http_proxy");
+		}
+		if (!curl_http_proxy) {
+			copy_from_env(&curl_http_proxy, "ALL_PROXY");
+			copy_from_env(&curl_http_proxy, "all_proxy");
+		}
+	}
+
 	if (curl_http_proxy) {
-		curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
+		if (strstr(curl_http_proxy, "://"))
+			credential_from_url(&http_proxy_auth, curl_http_proxy);
+		else {
+			struct strbuf url = STRBUF_INIT;
+			strbuf_reset(&url);
+			strbuf_addstr(&url, "http://");
+			strbuf_addstr(&url, curl_http_proxy);
+			credential_from_url(&http_proxy_auth, url.buf);
+		}
+
+		curl_easy_setopt(result, CURLOPT_PROXY, http_proxy_auth.host);
 	}
 	init_curl_proxy_auth(result);
 
@@ -658,6 +709,12 @@ void http_cleanup(void)
 		curl_http_proxy = NULL;
 	}
 
+	if (http_proxy_auth.password) {
+		memset(http_proxy_auth.password, 0, strlen(http_proxy_auth.password));
+		free(http_proxy_auth.password);
+		http_proxy_auth.password = NULL;
+	}
+
 	if (http_proxy_authmethod) {
 		free((void *)http_proxy_authmethod);
 		http_proxy_authmethod = NULL;
@@ -991,6 +1048,8 @@ static int handle_curl_result(struct slot_results *results)
 
 	if (results->curl_result == CURLE_OK) {
 		credential_approve(&http_auth);
+		if (http_proxy_auth.password)
+			credential_approve(&http_proxy_auth);
 		return HTTP_OK;
 	} else if (missing_target(results))
 		return HTTP_MISSING_TARGET;
@@ -1005,6 +1064,8 @@ static int handle_curl_result(struct slot_results *results)
 			return HTTP_REAUTH;
 		}
 	} else {
+		if (results->http_connectcode == 407)
+			credential_reject(&http_proxy_auth);
 #if LIBCURL_VERSION_NUM >= 0x070c00
 		if (!curl_errorstr[0])
 			strlcpy(curl_errorstr,
diff --git a/http.h b/http.h
index 49afe39..7352a9e 100644
--- a/http.h
+++ b/http.h
@@ -54,6 +54,7 @@ struct slot_results {
 	CURLcode curl_result;
 	long http_code;
 	long auth_avail;
+	long http_connectcode;
 };
 
 struct active_request_slot {
-- 
2.3.7

-- 
Vorstandsvorsitzender/Chairman of the board of management:
Gerd-Lothar Leonhart
Vorstand/Board of Management:
Dr. Bernd Finkbeiner, Dr. Arno Steitz
Vorsitzender des Aufsichtsrats/
Chairman of the Supervisory Board:
Philippe Miltin
Sitz/Registered Office: Tuebingen
Registergericht/Registration Court: Stuttgart
Registernummer/Commercial Register No.: HRB 382196
Previous: Eric SunshineNext: Eric Sunshine
Message 12 of 34 in “http: allow selection of proxy authentication method”
  1. 1/2 http: allow selection of proxy authentication methodKnut Franke, Oct 26, 2015
  2. 2/2 http: use credential API to handle proxy authenticationKnut Franke, Oct 26, 2015
  3. Junio C HamanoOct 26, 2015
  4. Knut FrankeOct 27, 2015
  5. http proxy authentication improvementsKnut Franke, Oct 28, 2015
  6. 1/2 http: allow selection of proxy authentication methodKnut Franke, Oct 28, 2015
  7. Junio C HamanoOct 28, 2015
  8. Junio C HamanoOct 28, 2015
  9. Knut FrankeOct 30, 2015
  10. Junio C HamanoOct 30, 2015
  11. Eric SunshineOct 28, 2015
  12. 2/2 http: use credential API to handle proxy authenticationKnut Franke, Oct 28, 2015
  13. Eric SunshineOct 28, 2015
  14. Knut FrankeOct 30, 2015
  15. Junio C HamanoOct 30, 2015
  16. Eric SunshineOct 30, 2015
  17. 0/2 Knut Franke, Nov 2, 2015
  18. 1/2 http: allow selection of proxy authentication methodKnut Franke, Nov 2, 2015
  19. Junio C HamanoNov 2, 2015
  20. Knut FrankeNov 3, 2015
  21. Junio C HamanoNov 3, 2015
  22. 2/2 http: use credential API to handle proxy authenticationKnut Franke, Nov 2, 2015
  23. Junio C HamanoNov 2, 2015
  24. Knut FrankeNov 3, 2015
  25. Eric SunshineNov 3, 2015
  26. 0/2 Knut Franke, Nov 4, 2015
  27. 1/2 http: allow selection of proxy authentication methodKnut Franke, Nov 4, 2015
  28. Junio C HamanoNov 4, 2015
  29. 2/2 http: use credential API to handle proxy authenticationKnut Franke, Nov 4, 2015
  30. Eric SunshineNov 4, 2015
  31. Junio C HamanoNov 4, 2015
  32. Jeff KingNov 5, 2015
  33. Knut FrankeNov 5, 2015
  34. Jeff KingNov 5, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.