Skip to content

Commit 429934f

Browse files
dschoGit for Windows Build Agent
authored andcommitted
credential: advertise NTLM suppression and allow helpers to re-enable
The previous commits disabled NTLM authentication by default due to its cryptographic weaknesses. Users can re-enable it via the config setting http.<url>.allowNTLMAuth, but this requires manual intervention. Credential helpers may have knowledge about which servers are trusted for NTLM authentication (e.g., known on-prem Azure DevOps instances). To allow them to signal this trust, introduce a simple negotiation: when NTLM is suppressed and the server offered it, Git advertises ntlm=suppressed to the credential helper. The helper can respond with ntlm=allow to re-enable NTLM for this request. This happens precisely at the point where we would otherwise warn the user about NTLM being suppressed, ensuring the capability is only advertised when relevant. Helped-by: Matthew John Cheetham <mjcheetham@outlook.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 6328cd0 commit 429934f

File tree

4 files changed

+35
-3
lines changed

4 files changed

+35
-3
lines changed

credential.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,9 @@ int credential_read(struct credential *c, FILE *fp,
360360
credential_set_capability(&c->capa_authtype, op_type);
361361
else if (!strcmp(value, "state"))
362362
credential_set_capability(&c->capa_state, op_type);
363+
} else if (!strcmp(key, "ntlm")) {
364+
if (!strcmp(value, "allow"))
365+
c->ntlm_allow = 1;
363366
} else if (!strcmp(key, "continue")) {
364367
c->multistage = !!git_config_bool("continue", value);
365368
} else if (!strcmp(key, "password_expiry_utc")) {
@@ -420,6 +423,8 @@ void credential_write(const struct credential *c, FILE *fp,
420423
if (c->ephemeral)
421424
credential_write_item(c, fp, "ephemeral", "1", 0);
422425
}
426+
if (c->ntlm_suppressed)
427+
credential_write_item(c, fp, "ntlm", "suppressed", 0);
423428
credential_write_item(c, fp, "protocol", c->protocol, 1);
424429
credential_write_item(c, fp, "host", c->host, 1);
425430
credential_write_item(c, fp, "path", c->path, 0);

credential.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ struct credential {
177177
struct credential_capability capa_authtype;
178178
struct credential_capability capa_state;
179179

180+
unsigned ntlm_suppressed:1,
181+
ntlm_allow:1;
182+
180183
char *username;
181184
char *password;
182185
char *credential;

http.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,11 @@ static void init_curl_http_auth(CURL *result)
660660

661661
credential_fill(the_repository, &http_auth, 1);
662662

663+
if (http_auth.ntlm_allow && !(http_auth_methods & CURLAUTH_NTLM)) {
664+
http_auth_methods |= CURLAUTH_NTLM;
665+
curl_easy_setopt(result, CURLOPT_HTTPAUTH, http_auth_methods);
666+
}
667+
663668
if (http_auth.password) {
664669
if (always_auth_proactively()) {
665670
/*
@@ -1891,6 +1896,8 @@ static int handle_curl_result(struct slot_results *results)
18911896
} else if (missing_target(results))
18921897
return HTTP_MISSING_TARGET;
18931898
else if (results->http_code == 401) {
1899+
http_auth.ntlm_suppressed = (results->auth_avail & CURLAUTH_NTLM) &&
1900+
!(http_auth_any & CURLAUTH_NTLM);
18941901
if ((http_auth.username && http_auth.password) ||\
18951902
(http_auth.authtype && http_auth.credential)) {
18961903
if (http_auth.multistage) {
@@ -1900,8 +1907,7 @@ static int handle_curl_result(struct slot_results *results)
19001907
credential_reject(the_repository, &http_auth);
19011908
if (always_auth_proactively())
19021909
http_proactive_auth = PROACTIVE_AUTH_NONE;
1903-
if ((results->auth_avail & CURLAUTH_NTLM) &&
1904-
!(http_auth_any & CURLAUTH_NTLM)) {
1910+
if (http_auth.ntlm_suppressed) {
19051911
warning(_("Due to its cryptographic weaknesses, "
19061912
"NTLM authentication has been\n"
19071913
"disabled in Git by default. You can "
@@ -2424,6 +2430,13 @@ static int http_request_recoverable(const char *url,
24242430
credential_fill(the_repository, &http_auth, 1);
24252431
}
24262432

2433+
/*
2434+
* Re-enable NTLM auth if the helper allows it and we would
2435+
* otherwise suppress authentication via NTLM.
2436+
*/
2437+
if (http_auth.ntlm_suppressed && http_auth.ntlm_allow)
2438+
http_auth_methods |= CURLAUTH_NTLM;
2439+
24272440
ret = http_request(url, result, target, options);
24282441
}
24292442
if (ret == HTTP_RATE_LIMITED) {

t/t5563-simple-http-auth.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,8 +733,19 @@ test_expect_success NTLM 'access using NTLM auth' '
733733
test_must_fail env GIT_TRACE_CURL=1 git \
734734
ls-remote "$HTTPD_URL/ntlm_auth/repo.git" 2>err &&
735735
test_grep "allowNTLMAuth" err &&
736+
737+
# Can be enabled via config
736738
GIT_TRACE_CURL=1 git -c http.$HTTPD_URL.allowNTLMAuth=true \
737-
ls-remote "$HTTPD_URL/ntlm_auth/repo.git"
739+
ls-remote "$HTTPD_URL/ntlm_auth/repo.git" &&
740+
741+
# Or via credential helper responding with ntlm=allow
742+
set_credential_reply get <<-EOF &&
743+
username=user
744+
password=pwd
745+
ntlm=allow
746+
EOF
747+
748+
git ls-remote "$HTTPD_URL/ntlm_auth/repo.git"
738749
'
739750

740751
test_done

0 commit comments

Comments
 (0)