git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "brian m. carlson" <sandals@crustytoothpaste.net>
To: git@vger.kernel.org
Cc: "Dan Langille (dalangil)" <dalangil@cisco.com>,
	Jeff King <peff@peff.net>, Jonathan Nieder <jrnieder@gmail.com>
Subject: [PATCH] remote-curl: fall back to Basic auth if Negotiate fails.
Date: Sat, 27 Dec 2014 04:01:33 +0000	[thread overview]
Message-ID: <1419652893-477694-1-git-send-email-sandals@crustytoothpaste.net> (raw)
In-Reply-To: <FBFEB910-4CB8-4049-901C-AADBFAB3AE9E@cisco.com>

Apache servers using mod_auth_kerb can be configured to allow the user
to authenticate either using Negotiate (using the Kerberos ticket) or
Basic authentication (using the Kerberos password).  Often, one will
want to use Negotiate authentication if it is available, but fall back
to Basic authentication if the ticket is missing or expired.

Teach the HTTP client code to stop trying authentication mechanisms that
don't use a password (currently Negotiate) after the first failure,
since if they failed the first time, they will never succeed.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
I was able to reproduce the problem on my server.  This fixes the
problem for me both when info/refs requires authentication and when it
does not.  Dan, please try and see if this fixes the problem for you.

I'm not clear on whether NTLM is a passwordless authentication method.
Since I don't use Windows or NTLM, I can't test it, but if it is, just
adding it to HTTP_AUTH_PASSWORDLESS should be sufficient.

 http.c        | 14 ++++++++++++++
 http.h        |  5 ++++-
 remote-curl.c | 13 ++++++++++++-
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/http.c b/http.c
index 040f362..e3e4c65 100644
--- a/http.c
+++ b/http.c
@@ -986,6 +986,16 @@ static void extract_content_type(struct strbuf *raw, struct strbuf *type,
 		strbuf_addstr(charset, "ISO-8859-1");
 }
 
+void disable_passwordless_auth(struct active_request_slot *slot)
+{
+#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
+#define HTTP_AUTH_PASSWORDLESS (CURLAUTH_GSSNEGOTIATE)
+	curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH,
+			 CURLAUTH_ANY & ~HTTP_AUTH_PASSWORDLESS);
+#endif
+}
+
+
 /* http_request() targets */
 #define HTTP_REQUEST_STRBUF	0
 #define HTTP_REQUEST_FILE	1
@@ -1035,6 +1045,9 @@ static int http_request(const char *url,
 	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
 	curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip");
 
+	if (options->no_passwordless_auth)
+		disable_passwordless_auth(slot);
+
 	ret = run_one_slot(slot, &results);
 
 	if (options && options->content_type) {
@@ -1139,6 +1152,7 @@ static int http_request_reauth(const char *url,
 	}
 
 	credential_fill(&http_auth);
+	options->no_passwordless_auth = 1;
 
 	return http_request(url, result, target, options);
 }
diff --git a/http.h b/http.h
index 473179b..fc42bf5 100644
--- a/http.h
+++ b/http.h
@@ -98,6 +98,8 @@ extern int handle_curl_result(struct slot_results *results);
 int run_one_slot(struct active_request_slot *slot,
 		 struct slot_results *results);
 
+void disable_passwordless_auth(struct active_request_slot *slot);
+
 #ifdef USE_CURL_MULTI
 extern void fill_active_slots(void);
 extern void add_fill_function(void *data, int (*fill)(void *));
@@ -138,7 +140,8 @@ extern char *get_remote_object_url(const char *url, const char *hex,
 /* Options for http_get_*() */
 struct http_get_options {
 	unsigned no_cache:1,
-		 keep_error:1;
+		 keep_error:1,
+		 no_passwordless_auth:1;
 
 	/* If non-NULL, returns the content-type of the response. */
 	struct strbuf *content_type;
diff --git a/remote-curl.c b/remote-curl.c
index dd63bc2..89bf4ea 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -369,6 +369,8 @@ struct rpc_state {
 	struct strbuf result;
 	unsigned gzip_request : 1;
 	unsigned initial_buffer : 1;
+	/* Automatic authentication didn't work, so don't try it again. */
+	unsigned no_passwordless_auth : 1;
 };
 
 static size_t rpc_out(void *ptr, size_t eltsize,
@@ -467,6 +469,9 @@ static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
 	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
 	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buf);
 
+	if (rpc->no_passwordless_auth)
+		disable_passwordless_auth(slot);
+
 	err = run_slot(slot, results);
 
 	curl_slist_free_all(headers);
@@ -510,8 +515,10 @@ static int post_rpc(struct rpc_state *rpc)
 
 		do {
 			err = probe_rpc(rpc, &results);
-			if (err == HTTP_REAUTH)
+			if (err == HTTP_REAUTH) {
 				credential_fill(&http_auth);
+				rpc->no_passwordless_auth = 1;
+			}
 		} while (err == HTTP_REAUTH);
 		if (err != HTTP_OK)
 			return -1;
@@ -533,6 +540,9 @@ retry:
 	curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
 	curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip");
 
+	if (rpc->no_passwordless_auth)
+		disable_passwordless_auth(slot);
+
 	if (large_request) {
 		/* The request body is large and the size cannot be predicted.
 		 * We must use chunked encoding to send it.
@@ -617,6 +627,7 @@ retry:
 	err = run_slot(slot, NULL);
 	if (err == HTTP_REAUTH && !large_request) {
 		credential_fill(&http_auth);
+		rpc->no_passwordless_auth = 1;
 		goto retry;
 	}
 	if (err != HTTP_OK)
-- 
2.2.1.209.g41e5f3a

  reply	other threads:[~2014-12-27  4:02 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-18 22:19 git-http-backend auth via Kerberos Dan Langille (dalangil)
2014-12-18 22:54 ` brian m. carlson
2014-12-19 15:07   ` Dan Langille (dalangil)
2014-12-19 15:50     ` Dan Langille (dalangil)
2014-12-19 16:07     ` Dan Langille (dalangil)
2014-12-19 20:16     ` brian m. carlson
2014-12-19 20:57       ` Dan Langille (dalangil)
2014-12-27  4:01         ` brian m. carlson [this message]
2014-12-27 17:56           ` [PATCH] remote-curl: fall back to Basic auth if Negotiate fails Jeff King
2014-12-27 21:09             ` brian m. carlson
2014-12-27 21:29               ` Jeff King
2014-12-28  0:05                 ` brian m. carlson
2015-01-01 19:56           ` [PATCH v2] " brian m. carlson
2015-01-03 11:19             ` Jeff King
2015-01-03 17:45               ` brian m. carlson
2015-01-03 20:14                 ` Jeff King
2015-01-05 16:02             ` Dan Langille (dalangil)
2015-01-05 21:23             ` Dan Langille (dalangil)
2015-01-05 23:53               ` brian m. carlson
2015-01-06 15:31                 ` Dan Langille (dalangil)
2015-01-06 15:41                   ` Dan Langille (dalangil)
2015-01-06 16:07                   ` Dan Langille (dalangil)
2015-01-08  0:02                     ` brian m. carlson
2015-01-08  0:29             ` [PATCH v3] " brian m. carlson
2015-01-20 16:40               ` Dan Langille (dalangil)
2015-01-21  0:22                 ` Junio C Hamano
2015-01-22 14:47                   ` Dan Langille (dalangil)
2015-02-17 23:05                   ` Dan Langille (dalangil)
2015-02-17 23:36                     ` Junio C Hamano
2015-02-18 16:17                       ` Dan Langille (dalangil)
2015-02-19 20:35                         ` brian m. carlson
2015-02-24 21:03                           ` Dan Langille (dalangil)
2015-02-25 20:59                             ` Dan Langille (dalangil)
2015-03-10 18:05                               ` Dan Langille (dalangil)
2015-03-10 22:29                                 ` brian m. carlson
2015-03-11 19:33                                   ` Dan Langille (dalangil)
2015-03-11 21:59                                     ` brian m. carlson
2015-03-12 13:09                                       ` Dan Langille (dalangil)
2015-01-05 13:12           ` [PATCH] " Dan Langille (dalangil)

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=1419652893-477694-1-git-send-email-sandals@crustytoothpaste.net \
    --to=sandals@crustytoothpaste.net \
    --cc=dalangil@cisco.com \
    --cc=git@vger.kernel.org \
    --cc=jrnieder@gmail.com \
    --cc=peff@peff.net \
    /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).