spnego: add --disable-negotiate-ntlm compile-time option

Add configure and CMake options to define CURL_DISABLE_NEGOTIATE_NTLM,
which gates the NTLM blocking logic in the SSPI and GSS-API SPNEGO
code paths behind a compile-time flag.

Add a 'SPNEGO-no-NTLM' feature string to curl --version output and
gate the SPNEGO NTLM blocking tests on the negotiate-ntlm-disabled
feature.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
This commit is contained in:
Matthew John Cheetham 2026-04-14 14:11:00 +01:00
parent 3ea51e7a1f
commit 0267a63dc0
11 changed files with 48 additions and 0 deletions

View file

@ -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)

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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));

View file

@ -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),

View file

@ -30,6 +30,7 @@ SPNEGO skips auth when NTLM blocked by CURL_DISABLE_NEGOTIATE_NTLM
<features>
GSS-API
Debug
negotiate-ntlm-disabled
</features>
<setenv>
CURL_STUB_GSS_CREDS="NTLM_Alice"

View file

@ -42,6 +42,7 @@ SPNEGO with Kerberos still works when built with CURL_DISABLE_NEGOTIATE_NTLM
<features>
GSS-API
Debug
negotiate-ntlm-disabled
</features>
<setenv>
CURL_STUB_GSS_CREDS="KRB5_Alice"

View file

@ -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