git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Knut Franke <k.franke@science-computing.de>
To: git@vger.kernel.org
Cc: Knut Franke <k.franke@science-computing.de>
Subject: [PATCH 2/2] http: use credential API to handle proxy authentication
Date: Wed, 28 Oct 2015 10:40:45 +0100	[thread overview]
Message-ID: <1446025245-10128-3-git-send-email-k.franke@science-computing.de> (raw)
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

  parent reply	other threads:[~2015-10-28  9:51 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-26 17:55 [PATCH 1/2] http: allow selection of proxy authentication method Knut Franke
2015-10-26 17:55 ` [PATCH 2/2] http: use credential API to handle proxy authentication Knut Franke
2015-10-26 20:33 ` [PATCH 1/2] http: allow selection of proxy authentication method Junio C Hamano
2015-10-27  8:47   ` Knut Franke
2015-10-28  9:40 ` [PATCH v2] http proxy authentication improvements Knut Franke
2015-10-28  9:40   ` [PATCH 1/2] http: allow selection of proxy authentication method Knut Franke
2015-10-28 16:51     ` Junio C Hamano
2015-10-28 16:59       ` Junio C Hamano
2015-10-30 18:01       ` Knut Franke
2015-10-30 19:19         ` Junio C Hamano
2015-10-28 18:54     ` Eric Sunshine
2015-10-28  9:40   ` Knut Franke [this message]
2015-10-28 18:58     ` [PATCH 2/2] http: use credential API to handle proxy authentication Eric Sunshine
2015-10-30 18:24       ` Knut Franke
2015-10-30 19:31         ` Junio C Hamano
2015-10-30 19:35           ` Eric Sunshine
2015-11-02 16:54 ` [PATCH v3 0/2] Knut Franke
2015-11-02 16:54   ` [PATCH 1/2] http: allow selection of proxy authentication method Knut Franke
2015-11-02 22:46     ` Junio C Hamano
2015-11-03  9:07       ` Knut Franke
2015-11-03 19:46         ` Junio C Hamano
2015-11-02 16:54   ` [PATCH 2/2] http: use credential API to handle proxy authentication Knut Franke
2015-11-02 22:54     ` Junio C Hamano
2015-11-03  9:31       ` Knut Franke
2015-11-03 18:12         ` Eric Sunshine
2015-11-04  9:13 ` [PATCH v4 0/2] Knut Franke
2015-11-04  9:13   ` [PATCH 1/2] http: allow selection of proxy authentication method Knut Franke
2015-11-04 19:42     ` Junio C Hamano
2015-11-04  9:13   ` [PATCH 2/2] http: use credential API to handle proxy authentication Knut Franke
2015-11-04 19:41     ` Eric Sunshine
2015-11-04 19:53     ` Junio C Hamano
2015-11-05  8:24     ` Jeff King
2015-11-05 11:56       ` Knut Franke
2015-11-05 17:30         ` Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1446025245-10128-3-git-send-email-k.franke@science-computing.de \
    --to=k.franke@science-computing.de \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).