]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
urldata: remove conn->bits.user_passwd
authorDaniel Stenberg <daniel@haxx.se>
Mon, 14 Feb 2022 16:33:50 +0000 (17:33 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 16 Feb 2022 09:28:31 +0000 (10:28 +0100)
The authentication status should be told by the transfer and not the
connection.

Reported-by: John H. Ayad
Fixes #8449
Closes #8451

13 files changed:
lib/curl_sasl.c
lib/curl_sasl.h
lib/dict.c
lib/http.c
lib/imap.c
lib/ldap.c
lib/openldap.c
lib/pop3.c
lib/smb.c
lib/smtp.c
lib/telnet.c
lib/url.c
lib/urldata.h

index bf2484ef0530d702cd2949205249db0290180089..7e28c92fd392088ef2dec63f57ecb55703fd51c9 100644 (file)
@@ -310,10 +310,10 @@ static CURLcode build_message(struct SASL *sasl, struct bufref *msg)
  *
  * Check if we have enough auth data and capabilities to authenticate.
  */
-bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn)
+bool Curl_sasl_can_authenticate(struct SASL *sasl, struct Curl_easy *data)
 {
   /* Have credentials been provided? */
-  if(conn->bits.user_passwd)
+  if(data->state.aptr.user)
     return TRUE;
 
   /* EXTERNAL can authenticate without a user name and/or password */
@@ -365,7 +365,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
     if(force_ir || data->set.sasl_ir)
       result = Curl_auth_create_external_message(conn->user, &resp);
   }
-  else if(conn->bits.user_passwd) {
+  else if(data->state.aptr.user) {
 #if defined(USE_KERBEROS5)
     if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() &&
        Curl_auth_user_contains_domain(conn->user)) {
index 91458c74a063d4f6b8326e4ae2f6ceeb7f50b549..d377ae7bc8f32b9edc060e175ff8c8f05498dff2 100644 (file)
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -150,7 +150,7 @@ void Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data,
                     const struct SASLproto *params);
 
 /* Check if we have enough auth data and capabilities to authenticate */
-bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn);
+bool Curl_sasl_can_authenticate(struct SASL *sasl, struct Curl_easy *data);
 
 /* Calculate the required login details for SASL authentication  */
 CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
index 73b0e3176184d509fd28473c611b7ef93f894442..e23e661912a7469e3fc5c90dab2b3261251b9dad 100644 (file)
@@ -190,10 +190,6 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
 
   *done = TRUE; /* unconditionally */
 
-  if(conn->bits.user_passwd) {
-    /* AUTH is missing */
-  }
-
   if(strncasecompare(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
      strncasecompare(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
      strncasecompare(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
index 9f37dedafde61aadc92ecca56a85865272186ac7..e9e5bded5ff99ed30c19357160c39342c137d239 100644 (file)
@@ -587,7 +587,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
   if(data->state.authproblem)
     return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
 
-  if((conn->bits.user_passwd || data->set.str[STRING_BEARER]) &&
+  if((data->state.aptr.user || data->set.str[STRING_BEARER]) &&
      ((data->req.httpcode == 401) ||
       (conn->bits.authneg && data->req.httpcode < 300))) {
     pickhost = pickoneauth(&data->state.authhost, authmask);
@@ -726,7 +726,7 @@ output_auth_headers(struct Curl_easy *data,
       (proxy && conn->bits.proxy_user_passwd &&
        !Curl_checkProxyheaders(data, conn, STRCONST("Proxy-authorization"))) ||
 #endif
-      (!proxy && conn->bits.user_passwd &&
+      (!proxy && data->state.aptr.user &&
        !Curl_checkheaders(data, STRCONST("Authorization")))) {
       auth = "Basic";
       result = http_output_basic(data, proxy);
@@ -810,7 +810,7 @@ Curl_http_output_auth(struct Curl_easy *data,
 #ifndef CURL_DISABLE_PROXY
     (conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
 #endif
-     conn->bits.user_passwd || data->set.str[STRING_BEARER])
+     data->state.aptr.user || data->set.str[STRING_BEARER])
     /* continue please */;
   else {
     authhost->done = TRUE;
@@ -1142,7 +1142,7 @@ static bool http_should_fail(struct Curl_easy *data)
   ** Either we're not authenticating, or we're supposed to
   ** be authenticating something else.  This is an error.
   */
-  if((httpcode == 401) && !data->conn->bits.user_passwd)
+  if((httpcode == 401) && !data->state.aptr.user)
     return TRUE;
 #ifndef CURL_DISABLE_PROXY
   if((httpcode == 407) && !data->conn->bits.proxy_user_passwd)
index c043bfa3b55597108fc516b37415728aa39ec59e..fb5a114d1d6f6bf8fe0e1ab8dedf3f37bdd29a80 100644 (file)
@@ -507,7 +507,7 @@ static CURLcode imap_perform_login(struct Curl_easy *data,
 
   /* Check we have a username and password to authenticate with and end the
      connect phase if we don't */
-  if(!conn->bits.user_passwd) {
+  if(!data->state.aptr.user) {
     state(data, IMAP_STOP);
 
     return result;
@@ -608,7 +608,7 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data,
   /* Check if already authenticated OR if there is enough data to authenticate
      with and end the connect phase if we don't */
   if(imapc->preauth ||
-     !Curl_sasl_can_authenticate(&imapc->sasl, conn)) {
+     !Curl_sasl_can_authenticate(&imapc->sasl, data)) {
     state(data, IMAP_STOP);
     return result;
   }
index 0b3ee373b43699a843bc63bdf6d5c4592a85ff53..52eac0d55845c996b0ed2aa3176d671c15fd39ce 100644 (file)
@@ -328,7 +328,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
   host = conn->host.name;
 #endif
 
-  if(conn->bits.user_passwd) {
+  if(data->state.aptr.user) {
     user = conn->user;
     passwd = conn->passwd;
   }
index 97150bdb65b761a6ffbaa86bc1f2abe96b5c6d78..4e92567706582a95da50ecc4e6367c570e18b477 100644 (file)
@@ -432,7 +432,7 @@ static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
   passwd.bv_val = NULL;
   passwd.bv_len = 0;
 
-  if(conn->bits.user_passwd) {
+  if(data->state.aptr.user) {
     binddn = conn->user;
     passwd.bv_val = conn->passwd;
     passwd.bv_len = strlen(passwd.bv_val);
@@ -444,7 +444,7 @@ static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
     state(data, newstate);
   else
     result = oldap_map_error(rc,
-                             conn->bits.user_passwd?
+                             data->state.aptr.user?
                              CURLE_LOGIN_DENIED: CURLE_LDAP_CANNOT_BIND);
   return result;
 }
@@ -645,7 +645,7 @@ static CURLcode oldap_state_mechs_resp(struct Curl_easy *data,
       /* FALLTHROUGH */
     case LDAP_SUCCESS:
     case LDAP_NO_RESULTS_RETURNED:
-      if(Curl_sasl_can_authenticate(&li->sasl, conn))
+      if(Curl_sasl_can_authenticate(&li->sasl, data))
         result = oldap_perform_sasl(data);
       else
         result = CURLE_LOGIN_DENIED;
@@ -799,7 +799,7 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
       conn->bits.tls_upgraded = TRUE;
       if(li->sasl.prefmech != SASL_AUTH_NONE)
         result = oldap_perform_mechs(data);
-      else if(conn->bits.user_passwd)
+      else if(data->state.aptr.user)
         result = oldap_perform_bind(data, OLDAP_BIND);
       else {
         state(data, OLDAP_STOP); /* Version 3 supported: no bind required */
index d2fd92a4bcb24289be7cdcda70e7bff35437f3bb..065bdbaf51ca6be716fbf6ce7c65c149bc867f9a 100644 (file)
@@ -401,7 +401,7 @@ static CURLcode pop3_perform_user(struct Curl_easy *data,
 
   /* Check we have a username and password to authenticate with and end the
      connect phase if we don't */
-  if(!conn->bits.user_passwd) {
+  if(!data->state.aptr.user) {
     state(data, POP3_STOP);
 
     return result;
@@ -435,7 +435,7 @@ static CURLcode pop3_perform_apop(struct Curl_easy *data,
 
   /* Check we have a username and password to authenticate with and end the
      connect phase if we don't */
-  if(!conn->bits.user_passwd) {
+  if(!data->state.aptr.user) {
     state(data, POP3_STOP);
 
     return result;
@@ -545,7 +545,7 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data,
 
   /* Check we have enough data to authenticate with and end the
      connect phase if we don't */
-  if(!Curl_sasl_can_authenticate(&pop3c->sasl, conn)) {
+  if(!Curl_sasl_can_authenticate(&pop3c->sasl, data)) {
     state(data, POP3_STOP);
     return result;
   }
index e756ce372acd61c37063f7380ff1b8f18b879fe3..8f44704a2c5b1736b5156a713aef431de470ee3f 100644 (file)
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -262,7 +262,7 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done)
   (void) done;
 
   /* Check we have a username and password to authenticate with */
-  if(!conn->bits.user_passwd)
+  if(!data->state.aptr.user)
     return CURLE_LOGIN_DENIED;
 
   /* Initialize the connection state */
index d589153240652c7b5cabc212894a00a4b7e79ecc..28aa44a49a0449cf41f7da6631d09b8866144981 100644 (file)
@@ -492,7 +492,7 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data)
   /* Check we have enough data to authenticate with, and the
      server supports authentication, and end the connect phase if not */
   if(!smtpc->auth_supported ||
-     !Curl_sasl_can_authenticate(&smtpc->sasl, conn)) {
+     !Curl_sasl_can_authenticate(&smtpc->sasl, data)) {
     state(data, SMTP_STOP);
     return result;
   }
index a81bb81c3675ac47fa5b94c1e16bd49ca27d2db5..e70997324471090f9733f95bdf7aea11304e712b 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -781,7 +781,7 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
 
   /* Add the user name as an environment variable if it
      was given on the command line */
-  if(conn->bits.user_passwd) {
+  if(data->state.aptr.user) {
     msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
     beg = curl_slist_append(tn->telnet_vars, option_arg);
     if(!beg) {
index c386e6f1b348190157504862506e0511a03151dc..de43df4f7b13bd8c2ca4ddd2439e0184d4b822ee 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -1738,7 +1738,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
 #endif /* CURL_DISABLE_PROXY */
 
-  conn->bits.user_passwd = (data->state.aptr.user) ? TRUE : FALSE;
 #ifndef CURL_DISABLE_FTP
   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
@@ -2019,45 +2018,47 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
    * User name and password set with their own options override the
    * credentials possibly set in the URL.
    */
-  if(!data->state.aptr.user) {
-    /* we don't use the URL API's URL decoder option here since it rejects
-       control codes and we want to allow them for some schemes in the user
-       and password fields */
-    uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
+  if(!data->state.aptr.passwd) {
+    uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
     if(!uc) {
       char *decoded;
-      result = Curl_urldecode(data->state.up.user, 0, &decoded, NULL,
+      result = Curl_urldecode(data->state.up.password, 0, &decoded, NULL,
                               conn->handler->flags&PROTOPT_USERPWDCTRL ?
                               REJECT_ZERO : REJECT_CTRL);
       if(result)
         return result;
-      conn->user = decoded;
-      conn->bits.user_passwd = TRUE;
-      result = Curl_setstropt(&data->state.aptr.user, decoded);
+      conn->passwd = decoded;
+      result = Curl_setstropt(&data->state.aptr.passwd, decoded);
       if(result)
         return result;
     }
-    else if(uc != CURLUE_NO_USER)
+    else if(uc != CURLUE_NO_PASSWORD)
       return Curl_uc_to_curlcode(uc);
   }
 
-  if(!data->state.aptr.passwd) {
-    uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
+  if(!data->state.aptr.user) {
+    /* we don't use the URL API's URL decoder option here since it rejects
+       control codes and we want to allow them for some schemes in the user
+       and password fields */
+    uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
     if(!uc) {
       char *decoded;
-      result = Curl_urldecode(data->state.up.password, 0, &decoded, NULL,
+      result = Curl_urldecode(data->state.up.user, 0, &decoded, NULL,
                               conn->handler->flags&PROTOPT_USERPWDCTRL ?
                               REJECT_ZERO : REJECT_CTRL);
       if(result)
         return result;
-      conn->passwd = decoded;
-      conn->bits.user_passwd = TRUE;
-      result = Curl_setstropt(&data->state.aptr.passwd, decoded);
-      if(result)
-        return result;
+      conn->user = decoded;
+      result = Curl_setstropt(&data->state.aptr.user, decoded);
     }
-    else if(uc != CURLUE_NO_PASSWORD)
+    else if(uc != CURLUE_NO_USER)
       return Curl_uc_to_curlcode(uc);
+    else if(data->state.aptr.passwd) {
+      /* no user was set but a password, set a blank user */
+      result = Curl_setstropt(&data->state.aptr.user, "");
+    }
+    if(result)
+      return result;
   }
 
   uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
@@ -2905,10 +2906,10 @@ static CURLcode override_login(struct Curl_easy *data,
   char **optionsp = &conn->options;
 
 #ifndef CURL_DISABLE_NETRC
-  if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
+  if(data->set.use_netrc == CURL_NETRC_REQUIRED && data->state.aptr.user) {
     Curl_safefree(*userp);
     Curl_safefree(*passwdp);
-    conn->bits.user_passwd = FALSE; /* disable user+password */
+    Curl_safefree(data->state.aptr.user); /* disable user+password */
   }
 #endif
 
@@ -2949,7 +2950,6 @@ static CURLcode override_login(struct Curl_easy *data,
          file, so that it is safe to use even if we followed a Location: to a
          different host or similar. */
       conn->bits.netrc = TRUE;
-      conn->bits.user_passwd = TRUE; /* enable user+password */
     }
     if(url_provided) {
       Curl_safefree(conn->user);
@@ -3004,14 +3004,15 @@ static CURLcode override_login(struct Curl_easy *data,
 /*
  * Set the login details so they're available in the connection
  */
-static CURLcode set_login(struct connectdata *conn)
+static CURLcode set_login(struct Curl_easy *data,
+                          struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
   const char *setuser = CURL_DEFAULT_USER;
   const char *setpasswd = CURL_DEFAULT_PASSWORD;
 
   /* If our protocol needs a password and we have none, use the defaults */
-  if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd)
+  if((conn->handler->flags & PROTOPT_NEEDSPWD) && !data->state.aptr.user)
     ;
   else {
     setuser = "";
@@ -3485,8 +3486,7 @@ static void reuse_conn(struct Curl_easy *data,
 
   /* get the user+password information from the old_conn struct since it may
    * be new for this request even when we re-use an existing connection */
-  conn->bits.user_passwd = old_conn->bits.user_passwd;
-  if(conn->bits.user_passwd) {
+  if(old_conn->user) {
     /* use the new user name and password though */
     Curl_safefree(conn->user);
     Curl_safefree(conn->passwd);
@@ -3664,7 +3664,7 @@ static CURLcode create_conn(struct Curl_easy *data,
   if(result)
     goto out;
 
-  result = set_login(conn); /* default credentials */
+  result = set_login(data, conn); /* default credentials */
   if(result)
     goto out;
 
index 663ae2ff007cbe0e83e489868562ddb34cff286d..cc8a600db43a6c07284e04d441a571da624cd74c 100644 (file)
@@ -481,7 +481,6 @@ struct ConnectBits {
                         that overrides the host in the URL */
   BIT(conn_to_port); /* if set, this connection has a "connect to port"
                         that overrides the port in the URL (remote port) */
-  BIT(user_passwd); /* do we use user+password for this connection? */
   BIT(ipv6_ip); /* we communicate with a remote site specified with pure IPv6
                    IP address */
   BIT(ipv6);    /* we communicate with a site using an IPv6 address */