netrc: don't ignore the login name specified with "--user"

- for "--netrc", don't ignore the login/password specified with "--user",
  only ignore the login/password in the URL.
  This restores the netrc behaviour of curl 7.61.1 and earlier.
- fix the documentation of CURL_NETRC_REQUIRED
- improve the detection of login/password changes when reading .netrc
- don't read .netrc if both login and password are already set

Fixes #3213
Closes #3224
This commit is contained in:
Michael Kaufmann 2018-11-03 16:58:18 +01:00
parent a77b640cc0
commit 53db15ba55
6 changed files with 83 additions and 55 deletions

View file

@ -53,6 +53,8 @@ enum host_lookup_state {
int Curl_parsenetrc(const char *host,
char **loginp,
char **passwordp,
bool *login_changed,
bool *password_changed,
char *netrcfile)
{
FILE *file;
@ -164,7 +166,7 @@ int Curl_parsenetrc(const char *host,
if(specific_login) {
state_our_login = strcasecompare(login, tok);
}
else {
else if(!login || strcmp(login, tok)) {
if(login_alloc) {
free(login);
login_alloc = FALSE;
@ -179,7 +181,8 @@ int Curl_parsenetrc(const char *host,
state_login = 0;
}
else if(state_password) {
if(state_our_login || !specific_login) {
if((state_our_login || !specific_login)
&& (!password || strcmp(password, tok))) {
if(password_alloc) {
free(password);
password_alloc = FALSE;
@ -211,15 +214,19 @@ int Curl_parsenetrc(const char *host,
out:
if(!retcode) {
*login_changed = FALSE;
*password_changed = FALSE;
if(login_alloc) {
if(*loginp)
free(*loginp);
*loginp = login;
*login_changed = TRUE;
}
if(password_alloc) {
if(*passwordp)
free(*passwordp);
*passwordp = password;
*password_changed = TRUE;
}
}
else {

View file

@ -26,6 +26,8 @@
int Curl_parsenetrc(const char *host,
char **loginp,
char **passwordp,
bool *login_changed,
bool *password_changed,
char *filename);
/* Assume: (*passwordp)[0]=0, host[0] != 0.
* If (*loginp)[0] = 0, search for login and password within a machine

View file

@ -2999,6 +2999,20 @@ static CURLcode override_login(struct Curl_easy *data,
bool user_changed = FALSE;
bool passwd_changed = FALSE;
CURLUcode uc;
if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
/* ignore user+password in the URL */
if(*userp) {
Curl_safefree(*userp);
user_changed = TRUE;
}
if(*passwdp) {
Curl_safefree(*passwdp);
passwd_changed = TRUE;
}
conn->bits.user_passwd = FALSE; /* disable user+password */
}
if(data->set.str[STRING_USERNAME]) {
free(*userp);
*userp = strdup(data->set.str[STRING_USERNAME]);
@ -3025,16 +3039,15 @@ static CURLcode override_login(struct Curl_easy *data,
}
conn->bits.netrc = FALSE;
if(data->set.use_netrc != CURL_NETRC_IGNORED) {
char *nuser = NULL;
char *npasswd = NULL;
if(data->set.use_netrc != CURL_NETRC_IGNORED &&
(!*userp || !**userp || !*passwdp || !**passwdp)) {
bool netrc_user_changed = FALSE;
bool netrc_passwd_changed = FALSE;
int ret;
if(data->set.use_netrc == CURL_NETRC_OPTIONAL)
nuser = *userp; /* to separate otherwise identical machines */
ret = Curl_parsenetrc(conn->host.name,
&nuser, &npasswd,
userp, passwdp,
&netrc_user_changed, &netrc_passwd_changed,
data->set.str[STRING_NETRC_FILE]);
if(ret > 0) {
infof(data, "Couldn't find host %s in the "
@ -3051,31 +3064,11 @@ static CURLcode override_login(struct Curl_easy *data,
conn->bits.netrc = TRUE;
conn->bits.user_passwd = TRUE; /* enable user+password */
if(data->set.use_netrc == CURL_NETRC_OPTIONAL) {
/* prefer credentials outside netrc */
if(nuser && !*userp) {
free(*userp);
*userp = nuser;
user_changed = TRUE;
}
if(npasswd && !*passwdp) {
free(*passwdp);
*passwdp = npasswd;
passwd_changed = TRUE;
}
if(netrc_user_changed) {
user_changed = TRUE;
}
else {
/* prefer netrc credentials */
if(nuser) {
free(*userp);
*userp = nuser;
user_changed = TRUE;
}
if(npasswd) {
free(*passwdp);
*passwdp = npasswd;
passwd_changed = TRUE;
}
if(netrc_passwd_changed) {
passwd_changed = TRUE;
}
}
}