diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2cc86d2a1f..6d7f77a3e6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -426,6 +426,8 @@ option(CURL_DISABLE_KERBEROS_AUTH "Disable Kerberos authentication" OFF)
mark_as_advanced(CURL_DISABLE_KERBEROS_AUTH)
option(CURL_DISABLE_NEGOTIATE_AUTH "Disable negotiate authentication" OFF)
mark_as_advanced(CURL_DISABLE_NEGOTIATE_AUTH)
+option(CURL_DISABLE_NEGOTIATE_NTLM "Block NTLM within SPNEGO negotiation" OFF)
+mark_as_advanced(CURL_DISABLE_NEGOTIATE_NTLM)
option(CURL_DISABLE_AWS "Disable aws-sigv4" OFF)
mark_as_advanced(CURL_DISABLE_AWS)
option(CURL_DISABLE_DICT "Disable DICT" OFF)
diff --git a/configure.ac b/configure.ac
index 98535dada8..b9190f4166 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4507,6 +4507,26 @@ AS_HELP_STRING([--disable-negotiate-auth],[Disable negotiate authentication]),
AC_MSG_RESULT(yes)
)
+dnl ************************************************************
+dnl disable NTLM within SPNEGO negotiation
+dnl
+AC_MSG_CHECKING([whether to allow NTLM within SPNEGO])
+AC_ARG_ENABLE(negotiate-ntlm,
+AS_HELP_STRING([--enable-negotiate-ntlm],[Allow NTLM within SPNEGO (default)])
+AS_HELP_STRING([--disable-negotiate-ntlm],[Block NTLM within SPNEGO]),
+[ case "$enableval" in
+ no)
+ AC_MSG_RESULT(no)
+ AC_DEFINE(CURL_DISABLE_NEGOTIATE_NTLM, 1, [to block NTLM within SPNEGO])
+ CURL_DISABLE_NEGOTIATE_NTLM=1
+ ;;
+ *)
+ AC_MSG_RESULT(yes)
+ ;;
+ esac ],
+ AC_MSG_RESULT(yes)
+)
+
dnl ************************************************************
dnl disable aws
dnl
diff --git a/docs/CURL-DISABLE.md b/docs/CURL-DISABLE.md
index c266f0c0ad..f3664898af 100644
--- a/docs/CURL-DISABLE.md
+++ b/docs/CURL-DISABLE.md
@@ -38,6 +38,10 @@ Disable support for the Kerberos authentication methods.
Disable support for the negotiate authentication methods.
+## `CURL_DISABLE_NEGOTIATE_NTLM`
+
+Block NTLM authentication within SPNEGO negotiation.
+
## `CURL_DISABLE_AWS`
Disable **aws-sigv4** support.
diff --git a/docs/libcurl/curl_version_info.md b/docs/libcurl/curl_version_info.md
index 83c7cdb9fe..8a389fa0c6 100644
--- a/docs/libcurl/curl_version_info.md
+++ b/docs/libcurl/curl_version_info.md
@@ -320,6 +320,12 @@ libcurl ignore cookies with a domain that is on the list.
libcurl was built with support for SPNEGO authentication (Simple and Protected
GSS-API Negotiation Mechanism, defined in RFC 2478.)
+## `SPNEGO-no-NTLM`
+
+*features* mask bit: none
+
+NTLM authentication is blocked within SPNEGO negotiation.
+
## `SSL`
*features* mask bit: CURL_VERSION_SSL
diff --git a/lib/curl_config-cmake.h.in b/lib/curl_config-cmake.h.in
index 1dcab9d897..f5a16d2d2b 100644
--- a/lib/curl_config-cmake.h.in
+++ b/lib/curl_config-cmake.h.in
@@ -58,6 +58,9 @@
/* disables negotiate authentication */
#cmakedefine CURL_DISABLE_NEGOTIATE_AUTH 1
+/* blocks NTLM within SPNEGO negotiation */
+#cmakedefine CURL_DISABLE_NEGOTIATE_NTLM 1
+
/* disables aws-sigv4 */
#cmakedefine CURL_DISABLE_AWS 1
diff --git a/lib/vauth/spnego_gssapi.c b/lib/vauth/spnego_gssapi.c
index 5519ae4c85..1a1c7b212b 100644
--- a/lib/vauth/spnego_gssapi.c
+++ b/lib/vauth/spnego_gssapi.c
@@ -160,6 +160,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
#endif
#ifdef HAVE_GSS_SET_NEG_MECHS
+#ifdef CURL_DISABLE_NEGOTIATE_NTLM
/* Acquire explicit credentials and restrict SPNEGO sub-mechanisms to
* exclude NTLM. We enumerate all available mechanisms and filter out
* the NTLMSSP OID, matching SSPI's "!ntlm". */
@@ -203,6 +204,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
gss_release_oid_set(&minor_status, &available_mechs);
}
}
+#endif /* CURL_DISABLE_NEGOTIATE_NTLM */
#endif /* HAVE_GSS_SET_NEG_MECHS */
/* Generate our challenge-response message */
@@ -240,6 +242,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
}
/* Check if NTLM was selected and is disallowed */
+#ifdef CURL_DISABLE_NEGOTIATE_NTLM
if(nego->context != GSS_C_NO_CONTEXT) {
/* OID 1.3.6.1.4.1.311.2.2.10 (NTLMSSP) */
static const gss_OID_desc ntlmssp_oid = {
@@ -261,6 +264,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
return CURLE_AUTH_ERROR;
}
}
+#endif /* CURL_DISABLE_NEGOTIATE_NTLM */
/* Free previous token */
if(nego->output_token.length && nego->output_token.value)
diff --git a/lib/vauth/spnego_sspi.c b/lib/vauth/spnego_sspi.c
index e0029ba04a..e07978fb64 100644
--- a/lib/vauth/spnego_sspi.c
+++ b/lib/vauth/spnego_sspi.c
@@ -146,6 +146,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
/* Use the current Windows user */
nego->p_identity = NULL;
+#ifdef CURL_DISABLE_NEGOTIATE_NTLM
/* Exclude NTLM from SPNEGO negotiation via the PackageList field */
if(!nego->p_identity) {
memset(&nego->identity, 0, sizeof(nego->identity));
@@ -166,6 +167,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
nego->identity.PackageList =
(unsigned TCHAR *)CURL_UNCONST(TEXT("!ntlm"));
nego->identity.PackageListLength = 5;
+#endif /* CURL_DISABLE_NEGOTIATE_NTLM */
/* Allocate our credentials handle */
nego->credentials = curlx_calloc(1, sizeof(CredHandle));
diff --git a/lib/version.c b/lib/version.c
index 7ccd875dc8..3976490163 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -525,6 +525,9 @@ static const struct feat features_table[] = {
#endif /* USE_SSL */
#ifdef USE_SPNEGO
FEATURE("SPNEGO", NULL, CURL_VERSION_SPNEGO),
+#ifdef CURL_DISABLE_NEGOTIATE_NTLM
+ FEATURE("SPNEGO-no-NTLM", NULL, 0),
+#endif
#endif
#ifdef USE_SSL
FEATURE("SSL", NULL, CURL_VERSION_SSL),
diff --git a/tests/data/test2092 b/tests/data/test2092
index 3cfdd9cab4..5423e15055 100644
--- a/tests/data/test2092
+++ b/tests/data/test2092
@@ -30,6 +30,7 @@ SPNEGO skips auth when NTLM blocked by CURL_DISABLE_NEGOTIATE_NTLM
GSS-API
Debug
+negotiate-ntlm-disabled
CURL_STUB_GSS_CREDS="NTLM_Alice"
diff --git a/tests/data/test2093 b/tests/data/test2093
index b74979f384..95f84c2656 100644
--- a/tests/data/test2093
+++ b/tests/data/test2093
@@ -42,6 +42,7 @@ SPNEGO with Kerberos still works when built with CURL_DISABLE_NEGOTIATE_NTLM
GSS-API
Debug
+negotiate-ntlm-disabled
CURL_STUB_GSS_CREDS="KRB5_Alice"
diff --git a/tests/runtests.pl b/tests/runtests.pl
index 2a180bfeb4..e444a5e23a 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -690,6 +690,8 @@ sub checksystemfeatures {
$feature{"Kerberos"} = $feat =~ /Kerberos/i;
# SPNEGO enabled
$feature{"SPNEGO"} = $feat =~ /SPNEGO/i;
+ # SPNEGO NTLM disabled (compile-time)
+ $feature{"negotiate-ntlm-disabled"} = $feat =~ /SPNEGO-no-NTLM/i;
# TLS-SRP enabled
$feature{"TLS-SRP"} = $feat =~ /TLS-SRP/i;
# PSL enabled