urldata: remove conn->bits.user_passwd

The authentication status should be told by the transfer and not the
connection.

Reported-by: John H. Ayad
Fixes #8449
Closes #8451
This commit is contained in:
Daniel Stenberg 2022-02-14 17:33:50 +01:00
parent eb13cc2927
commit 7d600ad1c3
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
13 changed files with 53 additions and 58 deletions

View 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. * 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? */ /* Have credentials been provided? */
if(conn->bits.user_passwd) if(data->state.aptr.user)
return TRUE; return TRUE;
/* EXTERNAL can authenticate without a user name and/or password */ /* 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) if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_external_message(conn->user, &resp); 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 defined(USE_KERBEROS5)
if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() && if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() &&
Curl_auth_user_contains_domain(conn->user)) { Curl_auth_user_contains_domain(conn->user)) {

View 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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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); const struct SASLproto *params);
/* Check if we have enough auth data and capabilities to authenticate */ /* 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 */ /* Calculate the required login details for SASL authentication */
CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,

View File

@ -190,10 +190,6 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
*done = TRUE; /* unconditionally */ *done = TRUE; /* unconditionally */
if(conn->bits.user_passwd) {
/* AUTH is missing */
}
if(strncasecompare(path, DICT_MATCH, sizeof(DICT_MATCH)-1) || if(strncasecompare(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
strncasecompare(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) || strncasecompare(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
strncasecompare(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) { strncasecompare(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {

View File

@ -587,7 +587,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
if(data->state.authproblem) if(data->state.authproblem)
return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; 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) || ((data->req.httpcode == 401) ||
(conn->bits.authneg && data->req.httpcode < 300))) { (conn->bits.authneg && data->req.httpcode < 300))) {
pickhost = pickoneauth(&data->state.authhost, authmask); pickhost = pickoneauth(&data->state.authhost, authmask);
@ -726,7 +726,7 @@ output_auth_headers(struct Curl_easy *data,
(proxy && conn->bits.proxy_user_passwd && (proxy && conn->bits.proxy_user_passwd &&
!Curl_checkProxyheaders(data, conn, STRCONST("Proxy-authorization"))) || !Curl_checkProxyheaders(data, conn, STRCONST("Proxy-authorization"))) ||
#endif #endif
(!proxy && conn->bits.user_passwd && (!proxy && data->state.aptr.user &&
!Curl_checkheaders(data, STRCONST("Authorization")))) { !Curl_checkheaders(data, STRCONST("Authorization")))) {
auth = "Basic"; auth = "Basic";
result = http_output_basic(data, proxy); result = http_output_basic(data, proxy);
@ -810,7 +810,7 @@ Curl_http_output_auth(struct Curl_easy *data,
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
(conn->bits.httpproxy && conn->bits.proxy_user_passwd) || (conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
#endif #endif
conn->bits.user_passwd || data->set.str[STRING_BEARER]) data->state.aptr.user || data->set.str[STRING_BEARER])
/* continue please */; /* continue please */;
else { else {
authhost->done = TRUE; 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 ** Either we're not authenticating, or we're supposed to
** be authenticating something else. This is an error. ** 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; return TRUE;
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
if((httpcode == 407) && !data->conn->bits.proxy_user_passwd) if((httpcode == 407) && !data->conn->bits.proxy_user_passwd)

View 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 /* Check we have a username and password to authenticate with and end the
connect phase if we don't */ connect phase if we don't */
if(!conn->bits.user_passwd) { if(!data->state.aptr.user) {
state(data, IMAP_STOP); state(data, IMAP_STOP);
return result; 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 /* Check if already authenticated OR if there is enough data to authenticate
with and end the connect phase if we don't */ with and end the connect phase if we don't */
if(imapc->preauth || if(imapc->preauth ||
!Curl_sasl_can_authenticate(&imapc->sasl, conn)) { !Curl_sasl_can_authenticate(&imapc->sasl, data)) {
state(data, IMAP_STOP); state(data, IMAP_STOP);
return result; return result;
} }

View File

@ -328,7 +328,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
host = conn->host.name; host = conn->host.name;
#endif #endif
if(conn->bits.user_passwd) { if(data->state.aptr.user) {
user = conn->user; user = conn->user;
passwd = conn->passwd; passwd = conn->passwd;
} }

View File

@ -432,7 +432,7 @@ static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
passwd.bv_val = NULL; passwd.bv_val = NULL;
passwd.bv_len = 0; passwd.bv_len = 0;
if(conn->bits.user_passwd) { if(data->state.aptr.user) {
binddn = conn->user; binddn = conn->user;
passwd.bv_val = conn->passwd; passwd.bv_val = conn->passwd;
passwd.bv_len = strlen(passwd.bv_val); 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); state(data, newstate);
else else
result = oldap_map_error(rc, result = oldap_map_error(rc,
conn->bits.user_passwd? data->state.aptr.user?
CURLE_LOGIN_DENIED: CURLE_LDAP_CANNOT_BIND); CURLE_LOGIN_DENIED: CURLE_LDAP_CANNOT_BIND);
return result; return result;
} }
@ -645,7 +645,7 @@ static CURLcode oldap_state_mechs_resp(struct Curl_easy *data,
/* FALLTHROUGH */ /* FALLTHROUGH */
case LDAP_SUCCESS: case LDAP_SUCCESS:
case LDAP_NO_RESULTS_RETURNED: 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); result = oldap_perform_sasl(data);
else else
result = CURLE_LOGIN_DENIED; result = CURLE_LOGIN_DENIED;
@ -799,7 +799,7 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
conn->bits.tls_upgraded = TRUE; conn->bits.tls_upgraded = TRUE;
if(li->sasl.prefmech != SASL_AUTH_NONE) if(li->sasl.prefmech != SASL_AUTH_NONE)
result = oldap_perform_mechs(data); result = oldap_perform_mechs(data);
else if(conn->bits.user_passwd) else if(data->state.aptr.user)
result = oldap_perform_bind(data, OLDAP_BIND); result = oldap_perform_bind(data, OLDAP_BIND);
else { else {
state(data, OLDAP_STOP); /* Version 3 supported: no bind required */ state(data, OLDAP_STOP); /* Version 3 supported: no bind required */

View 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 /* Check we have a username and password to authenticate with and end the
connect phase if we don't */ connect phase if we don't */
if(!conn->bits.user_passwd) { if(!data->state.aptr.user) {
state(data, POP3_STOP); state(data, POP3_STOP);
return result; 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 /* Check we have a username and password to authenticate with and end the
connect phase if we don't */ connect phase if we don't */
if(!conn->bits.user_passwd) { if(!data->state.aptr.user) {
state(data, POP3_STOP); state(data, POP3_STOP);
return result; 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 /* Check we have enough data to authenticate with and end the
connect phase if we don't */ 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); state(data, POP3_STOP);
return result; return result;
} }

View File

@ -262,7 +262,7 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done)
(void) done; (void) done;
/* Check we have a username and password to authenticate with */ /* Check we have a username and password to authenticate with */
if(!conn->bits.user_passwd) if(!data->state.aptr.user)
return CURLE_LOGIN_DENIED; return CURLE_LOGIN_DENIED;
/* Initialize the connection state */ /* Initialize the connection state */

View File

@ -492,7 +492,7 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data)
/* Check we have enough data to authenticate with, and the /* Check we have enough data to authenticate with, and the
server supports authentication, and end the connect phase if not */ server supports authentication, and end the connect phase if not */
if(!smtpc->auth_supported || if(!smtpc->auth_supported ||
!Curl_sasl_can_authenticate(&smtpc->sasl, conn)) { !Curl_sasl_can_authenticate(&smtpc->sasl, data)) {
state(data, SMTP_STOP); state(data, SMTP_STOP);
return result; return result;
} }

View 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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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 /* Add the user name as an environment variable if it
was given on the command line */ 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); msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
beg = curl_slist_append(tn->telnet_vars, option_arg); beg = curl_slist_append(tn->telnet_vars, option_arg);
if(!beg) { if(!beg) {

View File

@ -1738,7 +1738,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy; conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
#endif /* CURL_DISABLE_PROXY */ #endif /* CURL_DISABLE_PROXY */
conn->bits.user_passwd = (data->state.aptr.user) ? TRUE : FALSE;
#ifndef CURL_DISABLE_FTP #ifndef CURL_DISABLE_FTP
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
@ -2019,6 +2018,24 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
* User name and password set with their own options override the * User name and password set with their own options override the
* credentials possibly set in the URL. * credentials possibly set in the URL.
*/ */
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.password, 0, &decoded, NULL,
conn->handler->flags&PROTOPT_USERPWDCTRL ?
REJECT_ZERO : REJECT_CTRL);
if(result)
return result;
conn->passwd = decoded;
result = Curl_setstropt(&data->state.aptr.passwd, decoded);
if(result)
return result;
}
else if(uc != CURLUE_NO_PASSWORD)
return Curl_uc_to_curlcode(uc);
}
if(!data->state.aptr.user) { if(!data->state.aptr.user) {
/* we don't use the URL API's URL decoder option here since it rejects /* 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 control codes and we want to allow them for some schemes in the user
@ -2032,32 +2049,16 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
if(result) if(result)
return result; return result;
conn->user = decoded; conn->user = decoded;
conn->bits.user_passwd = TRUE;
result = Curl_setstropt(&data->state.aptr.user, decoded); result = Curl_setstropt(&data->state.aptr.user, decoded);
if(result)
return result;
} }
else if(uc != CURLUE_NO_USER) else if(uc != CURLUE_NO_USER)
return Curl_uc_to_curlcode(uc); return Curl_uc_to_curlcode(uc);
} else if(data->state.aptr.passwd) {
/* no user was set but a password, set a blank user */
if(!data->state.aptr.passwd) { result = Curl_setstropt(&data->state.aptr.user, "");
uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
if(!uc) {
char *decoded;
result = Curl_urldecode(data->state.up.password, 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;
} }
else if(uc != CURLUE_NO_PASSWORD) if(result)
return Curl_uc_to_curlcode(uc); return result;
} }
uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options, 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; char **optionsp = &conn->options;
#ifndef CURL_DISABLE_NETRC #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(*userp);
Curl_safefree(*passwdp); Curl_safefree(*passwdp);
conn->bits.user_passwd = FALSE; /* disable user+password */ Curl_safefree(data->state.aptr.user); /* disable user+password */
} }
#endif #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 file, so that it is safe to use even if we followed a Location: to a
different host or similar. */ different host or similar. */
conn->bits.netrc = TRUE; conn->bits.netrc = TRUE;
conn->bits.user_passwd = TRUE; /* enable user+password */
} }
if(url_provided) { if(url_provided) {
Curl_safefree(conn->user); 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 * 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; CURLcode result = CURLE_OK;
const char *setuser = CURL_DEFAULT_USER; const char *setuser = CURL_DEFAULT_USER;
const char *setpasswd = CURL_DEFAULT_PASSWORD; const char *setpasswd = CURL_DEFAULT_PASSWORD;
/* If our protocol needs a password and we have none, use the defaults */ /* 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 { else {
setuser = ""; 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 /* 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 */ * be new for this request even when we re-use an existing connection */
conn->bits.user_passwd = old_conn->bits.user_passwd; if(old_conn->user) {
if(conn->bits.user_passwd) {
/* use the new user name and password though */ /* use the new user name and password though */
Curl_safefree(conn->user); Curl_safefree(conn->user);
Curl_safefree(conn->passwd); Curl_safefree(conn->passwd);
@ -3664,7 +3664,7 @@ static CURLcode create_conn(struct Curl_easy *data,
if(result) if(result)
goto out; goto out;
result = set_login(conn); /* default credentials */ result = set_login(data, conn); /* default credentials */
if(result) if(result)
goto out; goto out;

View File

@ -481,7 +481,6 @@ struct ConnectBits {
that overrides the host in the URL */ that overrides the host in the URL */
BIT(conn_to_port); /* if set, this connection has a "connect to port" BIT(conn_to_port); /* if set, this connection has a "connect to port"
that overrides the port in the URL (remote 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 BIT(ipv6_ip); /* we communicate with a remote site specified with pure IPv6
IP address */ IP address */
BIT(ipv6); /* we communicate with a site using an IPv6 address */ BIT(ipv6); /* we communicate with a site using an IPv6 address */