git@vger.kernel.org list mirror (unofficial, one of many)
 help / color / mirror / code / Atom feed
From: Simon.Richter@hogyros.de
To: git@vger.kernel.org
Cc: Simon Richter <Simon.Richter@hogyros.de>
Subject: [PATCH 2/3] Add config option/env var to limit HTTP auth methods
Date: Fri, 13 May 2022 09:04:15 +0200	[thread overview]
Message-ID: <20220513070416.37235-3-Simon.Richter@hogyros.de> (raw)
In-Reply-To: <20220513070416.37235-1-Simon.Richter@hogyros.de>

From: Simon Richter <Simon.Richter@hogyros.de>

This allows forcing an authentication mechanism when the available
credentials do not match the automatically selected "best" mechanism.

For example, MS DevOps server supports both NTLM and Basic authentication,
but the NTLM backend is connected to the user database only and does not
accept Personal Access Tokens; curl however selects NTLM over Basic if both
are available.

Signed-off-by: Simon Richter <Simon.Richter@hogyros.de>
---
 Documentation/config/http.txt   | 19 +++++++++++++++++++
 Documentation/config/remote.txt |  4 ++++
 http.c                          | 33 ++++++++++++++++++++++++++++++++-
 remote.c                        |  4 ++++
 remote.h                        |  3 +++
 5 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/Documentation/config/http.txt b/Documentation/config/http.txt
index 7003661c0d..d9875afa4d 100644
--- a/Documentation/config/http.txt
+++ b/Documentation/config/http.txt
@@ -1,3 +1,22 @@
+http.authMethod::
+	Set the method with which to authenticate to the HTTP server, if
+	required. This can be overridden on a per-remote basis; see
+	`remote.<name>.authMethod`. Both can be overridden by the
+	`GIT_HTTP_AUTHMETHOD` environment variable.  Possible values are:
++
+--
+* `anyauth` - Automatically pick a suitable authentication method. It is
+  assumed that the server answers an unauthenticated request with a 401
+  status code and one or more WWW-Authenticate headers with supported
+  authentication methods. This is the default.
+* `basic` - HTTP Basic authentication
+* `digest` - HTTP Digest authentication; this prevents the password from being
+  transmitted to the server in clear text
+* `negotiate` - GSS-Negotiate authentication (compare the --negotiate option
+  of `curl(1)`)
+* `ntlm` - NTLM authentication (compare the --ntlm option of `curl(1)`)
+--
+
 http.proxy::
 	Override the HTTP proxy, normally configured using the 'http_proxy',
 	'https_proxy', and 'all_proxy' environment variables (see `curl(1)`). In
diff --git a/Documentation/config/remote.txt b/Documentation/config/remote.txt
index 0678b4bcfe..0f87234427 100644
--- a/Documentation/config/remote.txt
+++ b/Documentation/config/remote.txt
@@ -10,6 +10,10 @@ remote.<name>.url::
 remote.<name>.pushurl::
 	The push URL of a remote repository.  See linkgit:git-push[1].
 
+remote.<name>.authMethod::
+	For http and https remotes, the method to use for
+	authenticating against the server. See `http.authMethod`.
+
 remote.<name>.proxy::
 	For remotes that require curl (http, https and ftp), the URL to
 	the proxy to use for that remote.  Set to the empty string to
diff --git a/http.c b/http.c
index 318dc5daea..c5af90b1b8 100644
--- a/http.c
+++ b/http.c
@@ -108,6 +108,7 @@ static const char *curl_proxyuserpwd;
 static const char *curl_cookie_file;
 static int curl_save_cookies;
 struct credential http_auth = CREDENTIAL_INIT;
+static const char *http_authmethod;
 static int http_proactive_auth;
 static const char *user_agent;
 static int curl_empty_auth = -1;
@@ -356,6 +357,9 @@ static int http_options(const char *var, const char *value, void *cb)
 	if (!strcmp("http.useragent", var))
 		return git_config_string(&user_agent, var, value);
 
+	if (!strcmp("http.authmethod", var))
+		return git_config_string(&http_authmethod, var, value);
+
 	if (!strcmp("http.emptyauth", var)) {
 		if (value && !strcmp("auto", value))
 			curl_empty_auth = -1;
@@ -450,6 +454,27 @@ static void var_override(const char **var, char *value)
 	}
 }
 
+static void init_curl_http_auth_method(CURL *result)
+{
+	var_override(&http_authmethod, getenv("GIT_HTTP_AUTHMETHOD"));
+
+	if (http_authmethod) {
+		int i;
+		for (i = 0; i < ARRAY_SIZE(authmethods); i++) {
+			if (!strcmp(http_authmethod, authmethods[i].name)) {
+				http_auth_methods = authmethods[i].curlauth_param;
+				break;
+			}
+		}
+		if (i == ARRAY_SIZE(authmethods)) {
+			warning("unsupported authentication method %s: using anyauth",
+					http_authmethod);
+			http_auth_methods = CURLAUTH_ANY;
+		}
+	}
+	curl_easy_setopt(result, CURLOPT_HTTPAUTH, http_auth_methods);
+}
+
 static void set_proxyauth_name_password(CURL *result)
 {
 		curl_easy_setopt(result, CURLOPT_PROXYUSERNAME,
@@ -786,7 +811,7 @@ static CURL *get_curl_handle(void)
 #endif
 
 	curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
-	curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+	init_curl_http_auth_method(result);
 
 #ifdef CURLGSSAPI_DELEGATION_FLAG
 	if (curl_deleg) {
@@ -1040,6 +1065,9 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
 	if (remote && remote->http_proxy)
 		curl_http_proxy = xstrdup(remote->http_proxy);
 
+	if (remote)
+		var_override(&http_authmethod, remote->http_authmethod);
+
 	if (remote)
 		var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);
 
@@ -1504,6 +1532,9 @@ static int handle_curl_result(struct slot_results *results)
 			if (results->auth_avail) {
 				http_auth_methods &= results->auth_avail;
 				http_auth_methods_restricted = 1;
+				/* fail if no methods left */
+				if(http_auth_methods == 0)
+					return HTTP_NOAUTH;
 			}
 			return HTTP_REAUTH;
 		}
diff --git a/remote.c b/remote.c
index 42a4e7106e..dca7b82c9f 100644
--- a/remote.c
+++ b/remote.c
@@ -155,6 +155,7 @@ static void remote_clear(struct remote *remote)
 	FREE_AND_NULL(remote->pushurl);
 	free((char *)remote->receivepack);
 	free((char *)remote->uploadpack);
+	FREE_AND_NULL(remote->http_authmethod);
 	FREE_AND_NULL(remote->http_proxy);
 	FREE_AND_NULL(remote->http_proxy_authmethod);
 }
@@ -461,6 +462,9 @@ static int handle_config(const char *key, const char *value, void *cb)
 			remote->fetch_tags = -1;
 		else if (!strcmp(value, "--tags"))
 			remote->fetch_tags = 2;
+	} else if (!strcmp(subkey, "authmethod")) {
+		return git_config_string((const char **)&remote->http_authmethod,
+					 key, value);
 	} else if (!strcmp(subkey, "proxy")) {
 		return git_config_string((const char **)&remote->http_proxy,
 					 key, value);
diff --git a/remote.h b/remote.h
index 4a1209ae2c..c063d30356 100644
--- a/remote.h
+++ b/remote.h
@@ -105,6 +105,9 @@ struct remote {
 	const char *receivepack;
 	const char *uploadpack;
 
+	/* The method for authenticating against the (HTTP) server */
+	char *http_authmethod;
+
 	/* The proxy to use for curl (http, https, ftp, etc.) URLs. */
 	char *http_proxy;
 
-- 
2.30.2


  parent reply	other threads:[~2022-05-13  7:13 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-13  7:04 [PATCH 0/3] Allow configuration of HTTP authentication method Simon.Richter
2022-05-13  7:04 ` [PATCH 1/3] Rename proxy_authmethods -> authmethods Simon.Richter
2022-05-13 19:50   ` Junio C Hamano
2022-05-13  7:04 ` Simon.Richter [this message]
2022-05-13 20:26   ` [PATCH 2/3] Add config option/env var to limit HTTP auth methods Junio C Hamano
2022-05-13  7:04 ` [RFC PATCH 3/3] Allow empty user name in HTTP authentication Simon.Richter
2022-05-13 23:51   ` brian m. carlson

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

  List information: http://vger.kernel.org/majordomo-info.html

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

  git send-email \
    --in-reply-to=20220513070416.37235-3-Simon.Richter@hogyros.de \
    --to=simon.richter@hogyros.de \
    --cc=git@vger.kernel.org \
    --subject='Re: [PATCH 2/3] Add config option/env var to limit HTTP auth methods' \
    /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

Code repositories for project(s) associated with this inbox:

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).