sasl: give help when unable to select AUTH

When SASL is unable to select an AUTH mechanism, give user help
in info message why no AUTH could be selected.

Fixes #17420
Closes #17427
Reported-by: Aditya Garg
This commit is contained in:
Stefan Eissing 2025-05-23 12:21:18 +02:00 committed by Daniel Stenberg
parent b445031e94
commit 37b25f7bb0
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
7 changed files with 110 additions and 16 deletions

View file

@ -756,4 +756,101 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
return result;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void sasl_unchosen(struct Curl_easy *data, unsigned short mech,
unsigned short enabledmechs,
bool built_in, bool platform,
const char *param_missing)
{
const char *mname = NULL;
size_t i;
if(!(enabledmechs & mech))
return;
for(i = 0; mechtable[i].name; ++i) {
if(mechtable[i].bit == mech) {
mname = mechtable[i].name;
break;
}
}
if(!mname) /* should not happen */
return;
if(!built_in)
infof(data, "SASL: %s not builtin", mname);
else if(!platform)
infof(data, "SASL: %s not supported by the platform/libraries", mname);
else {
if(param_missing)
infof(data, "SASL: %s is missing %s", mname, param_missing);
if(!data->state.aptr.user)
infof(data, "SASL: %s is missing username", mname);
}
}
#endif /* CURL_DISABLE_VERBOSE_STRINGS */
CURLcode Curl_sasl_is_blocked(struct SASL *sasl, struct Curl_easy *data)
{
#ifndef CURL_DISABLE_VERBOSE_STRINGS
#ifdef USE_KERBEROS5
#define CURL_SASL_KERBEROS5 TRUE
#else
#define CURL_SASL_KERBEROS5 FALSE
#endif
#ifdef USE_GSASL
#define CURL_SASL_GASL TRUE
#else
#define CURL_SASL_GASL FALSE
#endif
#ifdef CURL_DISABLE_DIGEST_AUTH
#define CURL_SASL_DIGEST TRUE
#else
#define CURL_SASL_DIGEST FALSE
#endif
#ifndef USE_NTLM
#define CURL_SASL_NTLM TRUE
#else
#define CURL_SASL_NTLM FALSE
#endif
/* Failing SASL authentication is a pain. Give a helping hand if
* we were unable to select an AUTH mechanism.
* `sasl->authmechs` are mechanisms offered by the peer
* `sasl->prefmech` are mechanisms preferred by us */
unsigned short enabledmechs = sasl->authmechs & sasl->prefmech;
if(!sasl->authmechs)
infof(data, "SASL: no auth mechanism was offered or recognized");
else if(!enabledmechs)
infof(data, "SASL: no overlap between offered and configured "
"auth mechanisms");
else {
infof(data, "SASL: no auth mechanism offered could be selected");
if((enabledmechs & SASL_MECH_EXTERNAL) && data->conn->passwd[0])
infof(data, "SASL: auth EXTERNAL not chosen with password");
sasl_unchosen(data, SASL_MECH_GSSAPI, enabledmechs,
CURL_SASL_KERBEROS5, Curl_auth_is_gssapi_supported(), NULL);
sasl_unchosen(data, SASL_MECH_SCRAM_SHA_256, enabledmechs,
CURL_SASL_GASL, FALSE, NULL);
sasl_unchosen(data, SASL_MECH_SCRAM_SHA_1, enabledmechs,
CURL_SASL_GASL, FALSE, NULL);
sasl_unchosen(data, SASL_MECH_DIGEST_MD5, enabledmechs,
CURL_SASL_DIGEST, Curl_auth_is_digest_supported(), NULL);
sasl_unchosen(data, SASL_MECH_CRAM_MD5, enabledmechs,
CURL_SASL_DIGEST, TRUE, NULL);
sasl_unchosen(data, SASL_MECH_NTLM, enabledmechs,
CURL_SASL_NTLM, Curl_auth_is_ntlm_supported(), NULL);
sasl_unchosen(data, SASL_MECH_OAUTHBEARER, enabledmechs, TRUE, TRUE,
data->set.str[STRING_BEARER] ?
NULL : "CURLOPT_XOAUTH2_BEARER");
sasl_unchosen(data, SASL_MECH_XOAUTH2, enabledmechs, TRUE, TRUE,
data->set.str[STRING_BEARER] ?
NULL : "CURLOPT_XOAUTH2_BEARER");
}
#endif /* CURL_DISABLE_VERBOSE_STRINGS */
(void)sasl;
(void)data;
return CURLE_LOGIN_DENIED;
}
#endif /* protocols are enabled that use SASL */

View file

@ -162,4 +162,6 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
int code, saslprogress *progress);
CURLcode Curl_sasl_is_blocked(struct SASL *sasl, struct Curl_easy *data);
#endif /* HEADER_CURL_SASL_H */

View file

@ -723,11 +723,8 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data,
else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
/* Perform clear text authentication */
result = imap_perform_login(data, imapc, data->conn);
else {
/* Other mechanisms not supported */
infof(data, "No known authentication mechanisms supported");
result = CURLE_LOGIN_DENIED;
}
else
result = Curl_sasl_is_blocked(&imapc->sasl, data);
}
return result;

View file

@ -491,7 +491,7 @@ static CURLcode oldap_perform_sasl(struct Curl_easy *data)
oldap_state(data, li, OLDAP_SASL);
if(!result && progress != SASL_INPROGRESS)
result = CURLE_LOGIN_DENIED;
result = Curl_sasl_is_blocked(&li->sasl, data);
return result;
}

View file

@ -726,11 +726,8 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data,
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
/* Perform clear text authentication */
result = pop3_perform_user(data, conn);
else {
/* Other mechanisms not supported */
infof(data, "No known authentication mechanisms supported");
result = CURLE_LOGIN_DENIED;
}
else
result = Curl_sasl_is_blocked(&pop3c->sasl, data);
}
return result;

View file

@ -590,11 +590,8 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data,
if(!result) {
if(progress == SASL_INPROGRESS)
smtp_state(data, smtpc, SMTP_AUTH);
else {
/* Other mechanisms not supported */
infof(data, "No known authentication mechanisms supported");
result = CURLE_LOGIN_DENIED;
}
else
result = Curl_sasl_is_blocked(&smtpc->sasl, data);
}
return result;

View file

@ -167,6 +167,8 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
/* This is used to clean up the NTLM specific data */
void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm);
#else
#define Curl_auth_is_ntlm_supported() FALSE
#endif /* USE_NTLM */
/* This is used to generate a base64 encoded OAuth 2.0 message */
@ -207,6 +209,8 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
/* This is used to clean up the GSSAPI specific data */
void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5);
#else
#define Curl_auth_is_gssapi_supported() FALSE
#endif /* USE_KERBEROS5 */
#if defined(USE_SPNEGO)