mirror of
https://github.com/curl/curl.git
synced 2024-12-09 06:30:06 +08:00
netrc: support quoted strings
The .netrc parser now accepts strings within double-quotes in order to deal with for example passwords containing white space - which previously was not possible. A password that starts with a double-quote also ends with one, and double-quotes themselves are escaped with backslashes, like \". It also supports \n, \r and \t for newline, carriage return and tabs respectively. If the password does not start with a double quote, it will end at first white space and no escaping is performed. WARNING: this change is not entirely backwards compatible. If anyone previously used a double-quote as the first letter of their password, the parser will now get it differently compared to before. This is highly unfortunate but hard to avoid. Reported-by: ImpatientHippo on GitHub Fixes #8908 Closes #8937
This commit is contained in:
parent
b1f8d50a92
commit
eeaae10c0f
73
lib/netrc.c
73
lib/netrc.c
@ -78,24 +78,80 @@ static int parsenetrc(const char *host,
|
||||
|
||||
file = fopen(netrcfile, FOPEN_READTEXT);
|
||||
if(file) {
|
||||
char *tok;
|
||||
char *tok_buf;
|
||||
bool done = FALSE;
|
||||
char netrcbuffer[4096];
|
||||
int netrcbuffsize = (int)sizeof(netrcbuffer);
|
||||
|
||||
while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
|
||||
char *tok;
|
||||
char *tok_end;
|
||||
bool quoted;
|
||||
if(state == MACDEF) {
|
||||
if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
|
||||
state = NOTHING;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
tok = strtok_r(netrcbuffer, " \t\n", &tok_buf);
|
||||
if(tok && *tok == '#')
|
||||
/* treat an initial hash as a comment line */
|
||||
continue;
|
||||
tok = netrcbuffer;
|
||||
while(tok) {
|
||||
while(ISSPACE(*tok))
|
||||
tok++;
|
||||
/* tok is first non-space letter */
|
||||
if(!*tok || (*tok == '#'))
|
||||
/* end of line or the rest is a comment */
|
||||
break;
|
||||
|
||||
/* leading double-quote means quoted string */
|
||||
quoted = (*tok == '\"');
|
||||
|
||||
tok_end = tok;
|
||||
if(!quoted) {
|
||||
while(!ISSPACE(*tok_end))
|
||||
tok_end++;
|
||||
*tok_end = 0;
|
||||
}
|
||||
else {
|
||||
bool escape = FALSE;
|
||||
bool endquote = FALSE;
|
||||
char *store = tok;
|
||||
tok_end++; /* pass the leading quote */
|
||||
while(*tok_end) {
|
||||
char s = *tok_end;
|
||||
if(escape) {
|
||||
escape = FALSE;
|
||||
switch(s) {
|
||||
case 'n':
|
||||
s = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
s = '\r';
|
||||
break;
|
||||
case 't':
|
||||
s = '\t';
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(s == '\\') {
|
||||
escape = TRUE;
|
||||
tok_end++;
|
||||
continue;
|
||||
}
|
||||
else if(s == '\"') {
|
||||
tok_end++; /* pass the ending quote */
|
||||
endquote = TRUE;
|
||||
break;
|
||||
}
|
||||
*store++ = s;
|
||||
tok_end++;
|
||||
}
|
||||
*store = 0;
|
||||
if(escape || !endquote) {
|
||||
/* bad syntax, get out */
|
||||
retcode = NETRC_FAILED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if((login && *login) && (password && *password)) {
|
||||
done = TRUE;
|
||||
break;
|
||||
@ -183,9 +239,8 @@ static int parsenetrc(const char *host,
|
||||
}
|
||||
break;
|
||||
} /* switch (state) */
|
||||
|
||||
tok = strtok_r(NULL, " \t\n", &tok_buf);
|
||||
} /* while(tok) */
|
||||
tok = ++tok_end;
|
||||
}
|
||||
} /* while fgets() */
|
||||
|
||||
out:
|
||||
|
@ -3011,7 +3011,8 @@ static CURLcode override_login(struct Curl_easy *data,
|
||||
conn->host.name, data->set.str[STRING_NETRC_FILE]);
|
||||
}
|
||||
else if(ret < 0) {
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
failf(data, ".netrc parser error");
|
||||
return CURLE_READ_ERROR;
|
||||
}
|
||||
else {
|
||||
/* set bits.netrc TRUE to remember that we got the name from a .netrc
|
||||
|
Loading…
Reference in New Issue
Block a user