netrc: handle longer username and password
libcurl truncates usernames and passwords it reads from .netrc to LOGINSIZE and PASSWORDSIZE (64) characters without any indication to the user, to ensure the values returned from Curl_parsenetrc fit in a caller-provided buffer. Fix the interface by passing back dynamically allocated buffers allocated to fit the user's input. The parser still relies on a 256-character buffer to read each line, though. So now you can include an ~246-character password in your .netrc, instead of the previous limit of 63 characters. Reported-by: Colby Ranger
This commit is contained in:
committed by
Daniel Stenberg
parent
11baffbff6
commit
36585b5395
20
lib/netrc.c
20
lib/netrc.c
@@ -52,13 +52,13 @@ enum host_lookup_state {
|
|||||||
* @unittest: 1304
|
* @unittest: 1304
|
||||||
*/
|
*/
|
||||||
int Curl_parsenetrc(const char *host,
|
int Curl_parsenetrc(const char *host,
|
||||||
char *login,
|
char **loginp,
|
||||||
char *password,
|
char **passwordp,
|
||||||
char *netrcfile)
|
char *netrcfile)
|
||||||
{
|
{
|
||||||
FILE *file;
|
FILE *file;
|
||||||
int retcode=1;
|
int retcode=1;
|
||||||
int specific_login = (login[0] != 0);
|
int specific_login = (**loginp != 0);
|
||||||
char *home = NULL;
|
char *home = NULL;
|
||||||
bool home_alloc = FALSE;
|
bool home_alloc = FALSE;
|
||||||
bool netrc_alloc = FALSE;
|
bool netrc_alloc = FALSE;
|
||||||
@@ -109,7 +109,7 @@ int Curl_parsenetrc(const char *host,
|
|||||||
tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
|
tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
|
||||||
while(!done && tok) {
|
while(!done && tok) {
|
||||||
|
|
||||||
if(login[0] && password[0]) {
|
if(**loginp && **passwordp) {
|
||||||
done=TRUE;
|
done=TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -138,16 +138,22 @@ int Curl_parsenetrc(const char *host,
|
|||||||
/* we are now parsing sub-keywords concerning "our" host */
|
/* we are now parsing sub-keywords concerning "our" host */
|
||||||
if(state_login) {
|
if(state_login) {
|
||||||
if(specific_login) {
|
if(specific_login) {
|
||||||
state_our_login = Curl_raw_equal(login, tok);
|
state_our_login = Curl_raw_equal(*loginp, tok);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
strncpy(login, tok, LOGINSIZE-1);
|
free(*loginp);
|
||||||
|
*loginp = strdup(tok);
|
||||||
|
if(!*loginp)
|
||||||
|
return -1; /* allocation failed */
|
||||||
}
|
}
|
||||||
state_login=0;
|
state_login=0;
|
||||||
}
|
}
|
||||||
else if(state_password) {
|
else if(state_password) {
|
||||||
if(state_our_login || !specific_login) {
|
if(state_our_login || !specific_login) {
|
||||||
strncpy(password, tok, PASSWORDSIZE-1);
|
free(*passwordp);
|
||||||
|
*passwordp = strdup(tok);
|
||||||
|
if(!*passwordp)
|
||||||
|
return -1; /* allocation failed */
|
||||||
}
|
}
|
||||||
state_password=0;
|
state_password=0;
|
||||||
}
|
}
|
||||||
|
|||||||
16
lib/netrc.h
16
lib/netrc.h
@@ -22,19 +22,15 @@
|
|||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/* Make sure we have room for at least this size: */
|
|
||||||
#define LOGINSIZE 64
|
|
||||||
#define PASSWORDSIZE 64
|
|
||||||
|
|
||||||
/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
|
/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
|
||||||
int Curl_parsenetrc(const char *host,
|
int Curl_parsenetrc(const char *host,
|
||||||
char *login,
|
char **loginp,
|
||||||
char *password,
|
char **passwordp,
|
||||||
char *filename);
|
char *filename);
|
||||||
/* Assume: password[0]=0, host[0] != 0.
|
/* Assume: (*passwordp)[0]=0, host[0] != 0.
|
||||||
* If login[0] = 0, search for login and password within a machine section
|
* If (*loginp)[0] = 0, search for login and password within a machine
|
||||||
* in the netrc.
|
* section in the netrc.
|
||||||
* If login[0] != 0, search for password within machine and login.
|
* If (*loginp)[0] != 0, search for password within machine and login.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#endif /* HEADER_CURL_NETRC_H */
|
#endif /* HEADER_CURL_NETRC_H */
|
||||||
|
|||||||
18
lib/url.c
18
lib/url.c
@@ -4795,27 +4795,27 @@ static CURLcode parse_remote_port(struct SessionHandle *data,
|
|||||||
*/
|
*/
|
||||||
static void override_login(struct SessionHandle *data,
|
static void override_login(struct SessionHandle *data,
|
||||||
struct connectdata *conn,
|
struct connectdata *conn,
|
||||||
char *user, char *passwd, char *options)
|
char **userp, char **passwdp, char **optionsp)
|
||||||
{
|
{
|
||||||
if(data->set.str[STRING_USERNAME]) {
|
if(data->set.str[STRING_USERNAME]) {
|
||||||
strncpy(user, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH);
|
strncpy(*userp, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH);
|
||||||
user[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */
|
(*userp)[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data->set.str[STRING_PASSWORD]) {
|
if(data->set.str[STRING_PASSWORD]) {
|
||||||
strncpy(passwd, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH);
|
strncpy(*passwdp, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH);
|
||||||
passwd[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */
|
(*passwdp)[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data->set.str[STRING_OPTIONS]) {
|
if(data->set.str[STRING_OPTIONS]) {
|
||||||
strncpy(options, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH);
|
strncpy(*optionsp, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH);
|
||||||
options[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */
|
(*optionsp)[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->bits.netrc = FALSE;
|
conn->bits.netrc = FALSE;
|
||||||
if(data->set.use_netrc != CURL_NETRC_IGNORED) {
|
if(data->set.use_netrc != CURL_NETRC_IGNORED) {
|
||||||
if(Curl_parsenetrc(conn->host.name,
|
if(Curl_parsenetrc(conn->host.name,
|
||||||
user, passwd,
|
userp, passwdp,
|
||||||
data->set.str[STRING_NETRC_FILE])) {
|
data->set.str[STRING_NETRC_FILE])) {
|
||||||
infof(data, "Couldn't find host %s in the "
|
infof(data, "Couldn't find host %s in the "
|
||||||
DOT_CHAR "netrc file; using defaults\n",
|
DOT_CHAR "netrc file; using defaults\n",
|
||||||
@@ -5278,7 +5278,7 @@ static CURLcode create_conn(struct SessionHandle *data,
|
|||||||
|
|
||||||
/* Check for overridden login details and set them accordingly so they
|
/* Check for overridden login details and set them accordingly so they
|
||||||
they are known when protocol->setup_connection is called! */
|
they are known when protocol->setup_connection is called! */
|
||||||
override_login(data, conn, user, passwd, options);
|
override_login(data, conn, &user, &passwd, &options);
|
||||||
result = set_login(conn, user, passwd, options);
|
result = set_login(conn, user, passwd, options);
|
||||||
if(result != CURLE_OK)
|
if(result != CURLE_OK)
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
@@ -23,14 +23,14 @@
|
|||||||
|
|
||||||
#include "netrc.h"
|
#include "netrc.h"
|
||||||
|
|
||||||
static char login[LOGINSIZE];
|
static char *login;
|
||||||
static char password[PASSWORDSIZE];
|
static char *password;
|
||||||
static char filename[64];
|
static char filename[64];
|
||||||
|
|
||||||
static CURLcode unit_setup(void)
|
static CURLcode unit_setup(void)
|
||||||
{
|
{
|
||||||
password[0] = 0;
|
password = strdup("");
|
||||||
login[0] = 0;
|
login = strdup("");
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ UNITTEST_START
|
|||||||
/*
|
/*
|
||||||
* Test a non existent host in our netrc file.
|
* Test a non existent host in our netrc file.
|
||||||
*/
|
*/
|
||||||
result = Curl_parsenetrc("test.example.com", login, password, filename);
|
result = Curl_parsenetrc("test.example.com", &login, &password, filename);
|
||||||
fail_unless(result == 1, "Host not found should return 1");
|
fail_unless(result == 1, "Host not found should return 1");
|
||||||
fail_unless(password[0] == 0, "password should not have been changed");
|
fail_unless(password[0] == 0, "password should not have been changed");
|
||||||
fail_unless(login[0] == 0, "login should not have been changed");
|
fail_unless(login[0] == 0, "login should not have been changed");
|
||||||
@@ -55,8 +55,9 @@ UNITTEST_START
|
|||||||
/*
|
/*
|
||||||
* Test a non existent login in our netrc file.
|
* Test a non existent login in our netrc file.
|
||||||
*/
|
*/
|
||||||
memcpy(login, "me", 2);
|
free(login);
|
||||||
result = Curl_parsenetrc("example.com", login, password, filename);
|
login = strdup("me");
|
||||||
|
result = Curl_parsenetrc("example.com", &login, &password, filename);
|
||||||
fail_unless(result == 0, "Host should be found");
|
fail_unless(result == 0, "Host should be found");
|
||||||
fail_unless(password[0] == 0, "password should not have been changed");
|
fail_unless(password[0] == 0, "password should not have been changed");
|
||||||
fail_unless(strncmp(login, "me", 2) == 0, "login should not have been changed");
|
fail_unless(strncmp(login, "me", 2) == 0, "login should not have been changed");
|
||||||
@@ -64,8 +65,9 @@ UNITTEST_START
|
|||||||
/*
|
/*
|
||||||
* Test a non existent login and host in our netrc file.
|
* Test a non existent login and host in our netrc file.
|
||||||
*/
|
*/
|
||||||
memcpy(login, "me", 2);
|
free(login);
|
||||||
result = Curl_parsenetrc("test.example.com", login, password, filename);
|
login = strdup("me");
|
||||||
|
result = Curl_parsenetrc("test.example.com", &login, &password, filename);
|
||||||
fail_unless(result == 1, "Host should be found");
|
fail_unless(result == 1, "Host should be found");
|
||||||
fail_unless(password[0] == 0, "password should not have been changed");
|
fail_unless(password[0] == 0, "password should not have been changed");
|
||||||
fail_unless(strncmp(login, "me", 2) == 0, "login should not have been changed");
|
fail_unless(strncmp(login, "me", 2) == 0, "login should not have been changed");
|
||||||
@@ -74,8 +76,9 @@ UNITTEST_START
|
|||||||
* Test a non existent login (substring of an existing one) in our
|
* Test a non existent login (substring of an existing one) in our
|
||||||
* netrc file.
|
* netrc file.
|
||||||
*/
|
*/
|
||||||
memcpy(login, "admi", 4);
|
free(login);
|
||||||
result = Curl_parsenetrc("example.com", login, password, filename);
|
login = strdup("admi");
|
||||||
|
result = Curl_parsenetrc("example.com", &login, &password, filename);
|
||||||
fail_unless(result == 0, "Host should be found");
|
fail_unless(result == 0, "Host should be found");
|
||||||
fail_unless(password[0] == 0, "password should not have been changed");
|
fail_unless(password[0] == 0, "password should not have been changed");
|
||||||
fail_unless(strncmp(login, "admi", 4) == 0, "login should not have been changed");
|
fail_unless(strncmp(login, "admi", 4) == 0, "login should not have been changed");
|
||||||
@@ -84,8 +87,9 @@ UNITTEST_START
|
|||||||
* Test a non existent login (superstring of an existing one)
|
* Test a non existent login (superstring of an existing one)
|
||||||
* in our netrc file.
|
* in our netrc file.
|
||||||
*/
|
*/
|
||||||
memcpy(login, "adminn", 6);
|
free(login);
|
||||||
result = Curl_parsenetrc("example.com", login, password, filename);
|
login = strdup("adminn");
|
||||||
|
result = Curl_parsenetrc("example.com", &login, &password, filename);
|
||||||
fail_unless(result == 0, "Host should be found");
|
fail_unless(result == 0, "Host should be found");
|
||||||
fail_unless(password[0] == 0, "password should not have been changed");
|
fail_unless(password[0] == 0, "password should not have been changed");
|
||||||
fail_unless(strncmp(login, "adminn", 6) == 0, "login should not have been changed");
|
fail_unless(strncmp(login, "adminn", 6) == 0, "login should not have been changed");
|
||||||
@@ -94,8 +98,9 @@ UNITTEST_START
|
|||||||
* Test for the first existing host in our netrc file
|
* Test for the first existing host in our netrc file
|
||||||
* with login[0] = 0.
|
* with login[0] = 0.
|
||||||
*/
|
*/
|
||||||
login[0] = 0;
|
free(login);
|
||||||
result = Curl_parsenetrc("example.com", login, password, filename);
|
login = strdup("");
|
||||||
|
result = Curl_parsenetrc("example.com", &login, &password, filename);
|
||||||
fail_unless(result == 0, "Host should have been found");
|
fail_unless(result == 0, "Host should have been found");
|
||||||
fail_unless(strncmp(password, "passwd", 6) == 0,
|
fail_unless(strncmp(password, "passwd", 6) == 0,
|
||||||
"password should be 'passwd'");
|
"password should be 'passwd'");
|
||||||
@@ -105,8 +110,9 @@ UNITTEST_START
|
|||||||
* Test for the first existing host in our netrc file
|
* Test for the first existing host in our netrc file
|
||||||
* with login[0] != 0.
|
* with login[0] != 0.
|
||||||
*/
|
*/
|
||||||
password[0] = 0;
|
free(password);
|
||||||
result = Curl_parsenetrc("example.com", login, password, filename);
|
password = strdup("");
|
||||||
|
result = Curl_parsenetrc("example.com", &login, &password, filename);
|
||||||
fail_unless(result == 0, "Host should have been found");
|
fail_unless(result == 0, "Host should have been found");
|
||||||
fail_unless(strncmp(password, "passwd", 6) == 0,
|
fail_unless(strncmp(password, "passwd", 6) == 0,
|
||||||
"password should be 'passwd'");
|
"password should be 'passwd'");
|
||||||
@@ -116,9 +122,11 @@ UNITTEST_START
|
|||||||
* Test for the second existing host in our netrc file
|
* Test for the second existing host in our netrc file
|
||||||
* with login[0] = 0.
|
* with login[0] = 0.
|
||||||
*/
|
*/
|
||||||
password[0] = 0;
|
free(password);
|
||||||
login[0] = 0;
|
password = strdup("");
|
||||||
result = Curl_parsenetrc("curl.example.com", login, password, filename);
|
free(login);
|
||||||
|
login = strdup("");
|
||||||
|
result = Curl_parsenetrc("curl.example.com", &login, &password, filename);
|
||||||
fail_unless(result == 0, "Host should have been found");
|
fail_unless(result == 0, "Host should have been found");
|
||||||
fail_unless(strncmp(password, "none", 4) == 0,
|
fail_unless(strncmp(password, "none", 4) == 0,
|
||||||
"password should be 'none'");
|
"password should be 'none'");
|
||||||
@@ -128,8 +136,9 @@ UNITTEST_START
|
|||||||
* Test for the second existing host in our netrc file
|
* Test for the second existing host in our netrc file
|
||||||
* with login[0] != 0.
|
* with login[0] != 0.
|
||||||
*/
|
*/
|
||||||
password[0] = 0;
|
free(password);
|
||||||
result = Curl_parsenetrc("curl.example.com", login, password, filename);
|
password = strdup("");
|
||||||
|
result = Curl_parsenetrc("curl.example.com", &login, &password, filename);
|
||||||
fail_unless(result == 0, "Host should have been found");
|
fail_unless(result == 0, "Host should have been found");
|
||||||
fail_unless(strncmp(password, "none", 4) == 0,
|
fail_unless(strncmp(password, "none", 4) == 0,
|
||||||
"password should be 'none'");
|
"password should be 'none'");
|
||||||
|
|||||||
Reference in New Issue
Block a user