curl-library
[PATCH curl 4/6] netrc: handle longer username and password
From: Jonathan Nieder <jrnieder_at_gmail.com>
Date: Mon, 19 Aug 2013 00:48:24 -0700
Date: Mon, 19 Aug 2013 00:48:24 -0700
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
--- lib/netrc.c | 20 ++++++++++++------- lib/netrc.h | 14 +++++--------- lib/url.c | 18 ++++++++--------- tests/unit/unit1304.c | 53 ++++++++++++++++++++++++++++++--------------------- 4 files changed, 58 insertions(+), 47 deletions(-) diff --git a/lib/netrc.c b/lib/netrc.c index 2c5942af..f51fdf34 100644 --- a/lib/netrc.c +++ b/lib/netrc.c @@ -52,13 +52,13 @@ enum host_lookup_state { * @unittest: 1304 */ int Curl_parsenetrc(const char *host, - char *login, - char *password, + char **loginp, + char **passwordp, char *netrcfile) { FILE *file; int retcode=1; - int specific_login = (login[0] != 0); + int specific_login = (**loginp != 0); char *home = NULL; bool home_alloc = FALSE; bool netrc_alloc = FALSE; @@ -109,7 +109,7 @@ int Curl_parsenetrc(const char *host, tok=strtok_r(netrcbuffer, " \t\n", &tok_buf); while(!done && tok) { - if(login[0] && password[0]) { + if(**loginp && **passwordp) { done=TRUE; break; } @@ -138,16 +138,22 @@ int Curl_parsenetrc(const char *host, /* we are now parsing sub-keywords concerning "our" host */ if(state_login) { if(specific_login) { - state_our_login = Curl_raw_equal(login, tok); + state_our_login = Curl_raw_equal(*loginp, tok); } else { - strncpy(login, tok, LOGINSIZE-1); + free(*loginp); + *loginp = strdup(tok); + if(!*loginp) + return -1; /* allocation failed */ } state_login=0; } else if(state_password) { 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; } diff --git a/lib/netrc.h b/lib/netrc.h index 4db764df..6bd9df6f 100644 --- a/lib/netrc.h +++ b/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 */ int Curl_parsenetrc(const char *host, - char *login, - char *password, + char **loginp, + char **passwordp, char *filename); - /* Assume: password[0]=0, host[0] != 0. - * If login[0] = 0, search for login and password within a machine section + /* Assume: (*passwordp)[0]=0, host[0] != 0. + * If (*loginp)[0] = 0, search for login and password within a machine 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 */ diff --git a/lib/url.c b/lib/url.c index 07555a90..8b628582 100644 --- a/lib/url.c +++ b/lib/url.c @@ -4795,27 +4795,27 @@ static CURLcode parse_remote_port(struct SessionHandle *data, */ static void override_login(struct SessionHandle *data, struct connectdata *conn, - char *user, char *passwd, char *options) + char **userp, char **passwdp, char **optionsp) { if(data->set.str[STRING_USERNAME]) { - strncpy(user, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH); - user[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */ + strncpy(*userp, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH); + (*userp)[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */ } if(data->set.str[STRING_PASSWORD]) { - strncpy(passwd, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH); - passwd[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */ + strncpy(*passwdp, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH); + (*passwdp)[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */ } if(data->set.str[STRING_OPTIONS]) { - strncpy(options, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH); - options[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */ + strncpy(*optionsp, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH); + (*optionsp)[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */ } conn->bits.netrc = FALSE; if(data->set.use_netrc != CURL_NETRC_IGNORED) { if(Curl_parsenetrc(conn->host.name, - user, passwd, + userp, passwdp, data->set.str[STRING_NETRC_FILE])) { infof(data, "Couldn't find host %s in the " 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 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); if(result != CURLE_OK) goto out; diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c index 8ddd8cae..9242e800 100644 --- a/tests/unit/unit1304.c +++ b/tests/unit/unit1304.c @@ -23,14 +23,14 @@ #include "netrc.h" -static char login[LOGINSIZE]; -static char password[PASSWORDSIZE]; +static char *login; +static char *password; static char filename[64]; static CURLcode unit_setup(void) { - password[0] = 0; - login[0] = 0; + password = strdup(""); + login = strdup(""); return CURLE_OK; } @@ -47,7 +47,7 @@ UNITTEST_START /* * 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(password[0] == 0, "password 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. */ - memcpy(login, "me", 2); - result = Curl_parsenetrc("example.com", login, password, filename); + free(login); + login = strdup("me"); + result = Curl_parsenetrc("example.com", &login, &password, filename); fail_unless(result == 0, "Host should be found"); fail_unless(password[0] == 0, "password 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. */ - memcpy(login, "me", 2); - result = Curl_parsenetrc("test.example.com", login, password, filename); + free(login); + login = strdup("me"); + result = Curl_parsenetrc("test.example.com", &login, &password, filename); fail_unless(result == 1, "Host should be found"); fail_unless(password[0] == 0, "password 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 * netrc file. */ - memcpy(login, "admi", 4); - result = Curl_parsenetrc("example.com", login, password, filename); + free(login); + login = strdup("admi"); + result = Curl_parsenetrc("example.com", &login, &password, filename); fail_unless(result == 0, "Host should be found"); fail_unless(password[0] == 0, "password 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) * in our netrc file. */ - memcpy(login, "adminn", 6); - result = Curl_parsenetrc("example.com", login, password, filename); + free(login); + login = strdup("adminn"); + result = Curl_parsenetrc("example.com", &login, &password, filename); fail_unless(result == 0, "Host should be found"); fail_unless(password[0] == 0, "password 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 * with login[0] = 0. */ - login[0] = 0; - result = Curl_parsenetrc("example.com", login, password, filename); + free(login); + login = strdup(""); + result = Curl_parsenetrc("example.com", &login, &password, filename); fail_unless(result == 0, "Host should have been found"); fail_unless(strncmp(password, "passwd", 6) == 0, "password should be 'passwd'"); @@ -105,8 +110,9 @@ UNITTEST_START * Test for the first existing host in our netrc file * with login[0] != 0. */ - password[0] = 0; - result = Curl_parsenetrc("example.com", login, password, filename); + free(password); + password = strdup(""); + result = Curl_parsenetrc("example.com", &login, &password, filename); fail_unless(result == 0, "Host should have been found"); fail_unless(strncmp(password, "passwd", 6) == 0, "password should be 'passwd'"); @@ -116,9 +122,11 @@ UNITTEST_START * Test for the second existing host in our netrc file * with login[0] = 0. */ - password[0] = 0; - login[0] = 0; - result = Curl_parsenetrc("curl.example.com", login, password, filename); + free(password); + password = strdup(""); + free(login); + login = strdup(""); + result = Curl_parsenetrc("curl.example.com", &login, &password, filename); fail_unless(result == 0, "Host should have been found"); fail_unless(strncmp(password, "none", 4) == 0, "password should be 'none'"); @@ -128,8 +136,9 @@ UNITTEST_START * Test for the second existing host in our netrc file * with login[0] != 0. */ - password[0] = 0; - result = Curl_parsenetrc("curl.example.com", login, password, filename); + free(password); + password = strdup(""); + result = Curl_parsenetrc("curl.example.com", &login, &password, filename); fail_unless(result == 0, "Host should have been found"); fail_unless(strncmp(password, "none", 4) == 0, "password should be 'none'"); -- 1.8.4.rc3 ------------------------------------------------------------------- List admin: http://cool.haxx.se/list/listinfo/curl-library Etiquette: http://curl.haxx.se/mail/etiquette.htmlReceived on 2013-08-19