]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
sasl: give help when unable to select AUTH
authorStefan Eissing <stefan@eissing.org>
Fri, 23 May 2025 10:21:18 +0000 (12:21 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 23 May 2025 20:56:05 +0000 (22:56 +0200)
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
lib/curl_sasl.c
lib/curl_sasl.h
lib/imap.c
lib/openldap.c
lib/pop3.c
lib/smtp.c
lib/vauth/vauth.h

index 7943925bed09d33ac5c6fd986d01c515e03845d9..4fcbaac263bd9547ae47497af4a5e15a6139e989 100644 (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 */
index e94e6431a2425b4bba0e536703cda5eca099979c..59983f7c669dad2d557a3b5314fcf8cdfebe2720 100644 (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 */
index 56e34e1593b20e2e3f95ce5d215a7a125de6afc9..4b2e6087f214cdcae8df6fa821bef4e09c77858c 100644 (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;
index c5e7229f3c6826ef54e6963c476022e2d1bd1cfa..6343c40c094af6e1c40e79575c4793a391ac38ad 100644 (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;
 }
 
index 62d2e26addc370bddd8dd5962c619f008dc29a26..852834ececcff1653a02f9e0d089d9a199bc6605 100644 (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;
index f9711a3a17e66e16e0962d1bdd909bfc45b98754..cccb9f381ab0eab5b51852259eef8301cc269616 100644 (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;
index 7ff0b05595a1d8e7ec225d85e42c057f472a4119..d8459880677e43646314ddb5ccec2405bace2f2b 100644 (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)