diff options
author | Jonathan Nieder <jrnieder@gmail.com> | 2013-08-19 00:57:54 -0700 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2013-08-20 11:16:38 +0200 |
commit | 15f76bf7bb92b315799541b0e5127c8d22a50733 (patch) | |
tree | adb74efc7238bc044492102234eaf23e15c02ade | |
parent | 36585b539543ca4471ab19c0d738a6e52a827aee (diff) |
Curl_setopt: handle arbitrary-length username and password
libcurl truncates usernames, passwords, and options set with
curl_easy_setopt to 255 (= MAX_CURL_PASSWORD_LENGTH - 1) characters.
This doesn't affect the return value from curl_easy_setopt(), so from
the caller's point of view, there is no sign anything strange has
happened, except that authentication fails.
For example:
# Prepare a long (300-char) password.
s=0123456789; s=$s$s$s$s$s$s$s$s$s$s; s=$s$s$s;
# Start a server.
nc -l -p 8888 | tee out & pid=$!
# Tell curl to pass the password to the server.
curl --user me:$s http://localhost:8888 & sleep 1; kill $pid
# Extract the password.
userpass=$(
awk '/Authorization: Basic/ {print $3}' <out |
tr -d '\r' |
base64 -d
)
password=${userpass#me:}
echo ${#password}
Expected result: 300
Actual result: 255
The fix is simple: allocate appropriately sized buffers on the heap
instead of trying to squeeze the provided values into fixed-size
on-stack buffers.
Bug: http://bugs.debian.org/719856
Reported-by: Colby Ranger
-rw-r--r-- | lib/url.c | 29 |
1 files changed, 19 insertions, 10 deletions
@@ -4793,23 +4793,29 @@ static CURLcode parse_remote_port(struct SessionHandle *data, * Override the login details from the URL with that in the CURLOPT_USERPWD * option or a .netrc file, if applicable. */ -static void override_login(struct SessionHandle *data, - struct connectdata *conn, - char **userp, char **passwdp, char **optionsp) +static int override_login(struct SessionHandle *data, + struct connectdata *conn, + char **userp, char **passwdp, char **optionsp) { if(data->set.str[STRING_USERNAME]) { - strncpy(*userp, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH); - (*userp)[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */ + free(*userp); + *userp = strdup(data->set.str[STRING_USERNAME]); + if(!*userp) + return CURLE_OUT_OF_MEMORY; } if(data->set.str[STRING_PASSWORD]) { - strncpy(*passwdp, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH); - (*passwdp)[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */ + free(*passwdp); + *passwdp = strdup(data->set.str[STRING_PASSWORD]); + if(!*passwdp) + return CURLE_OUT_OF_MEMORY; } if(data->set.str[STRING_OPTIONS]) { - strncpy(*optionsp, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH); - (*optionsp)[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */ + free(*optionsp); + *optionsp = strdup(data->set.str[STRING_OPTIONS]); + if(!*optionsp) + return CURLE_OUT_OF_MEMORY; } conn->bits.netrc = FALSE; @@ -4830,6 +4836,7 @@ static void override_login(struct SessionHandle *data, conn->bits.user_passwd = TRUE; /* enable user+password */ } } + return CURLE_OK; } /* @@ -5278,7 +5285,9 @@ 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); + result = override_login(data, conn, &user, &passwd, &options); + if(result != CURLE_OK) + goto out; result = set_login(conn, user, passwd, options); if(result != CURLE_OK) goto out; |