Package: libcurl3
Version: 7.31.0-2
Tags: upstream patch
X-Debbugs-Cc: Colby Ranger cran...@google.com
libcurl truncates passwords to 255 characters when sending them with
basic authentication.
Test case:
# Prepare a long (300-character) password.
s=0123456789
s=$s$s$s$s$s$s$s$s$s$s
s=$s$s$s
# Start a server.
nc -l -p | tee out
pid=$!
# Ask curl to pass a long password to that server.
curl --user me:$s http://localhost:
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
Noticed by using git with a long password. Git sets the password with
curl_easy_setopt(result, CURLOPT_PASSWORD, http_auth.password);
The value is copied into a 256-byte buffer allocated on the stack in
lib/url.c::create_conn():
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 */
}
This doesn't affect the return value from curl_easy_setopt. From the
caller's point of view, there is no sign anything strange has
happened, except that authentication fails.
Thanks to Colby Ranger for the analysis. How about something like
this patch?
---
lib/url.c | 108 +-
1 file changed, 58 insertions(+), 50 deletions(-)
diff --git a/lib/url.c b/lib/url.c
index 7cec5bcc..ac9bf162 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -144,7 +144,7 @@ static void signalPipeClose(struct curl_llist *pipeline,
bool pipe_broke);
static CURLcode do_init(struct connectdata *conn);
static CURLcode parse_url_login(struct SessionHandle *data,
struct connectdata *conn,
-char *user, char *passwd, char *options);
+char **user, char **passwd, char **options);
static CURLcode parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
@@ -3687,7 +3687,8 @@ static CURLcode findprotocol(struct SessionHandle *data,
static CURLcode parseurlandfillconn(struct SessionHandle *data,
struct connectdata *conn,
bool *prot_missing,
-char *user, char *passwd, char *options)
+char **userp, char **passwdp,
+char **optionsp)
{
char *at;
char *fragment;
@@ -3931,7 +3932,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle
*data,
* Parse the login details from the URL and strip them out of
* the host name
*/
- result = parse_url_login(data, conn, user, passwd, options);
+ result = parse_url_login(data, conn, userp, passwdp, optionsp);
if(result != CURLE_OK)
return result;
@@ -4411,7 +4412,7 @@ static CURLcode parse_proxy_auth(struct SessionHandle
*data,
*/
static CURLcode parse_url_login(struct SessionHandle *data,
struct connectdata *conn,
-char *user, char *passwd, char *options)
+char **user, char **passwd, char **options)
{
CURLcode result = CURLE_OK;
char *userp = NULL;
@@ -4428,9 +4429,9 @@ static CURLcode parse_url_login(struct SessionHandle
*data,
char *ptr = strchr(conn-host.name, '@');
char *login = conn-host.name;
- user[0] = 0; /* to make everything well-defined */
- passwd[0] = 0;
- options[0] = 0;
+ DEBUGASSERT(*user == NULL);
+ DEBUGASSERT(*passwd == NULL);
+ DEBUGASSERT(*options == NULL);
/* We will now try to extract the
* possible login information in a string like:
@@ -4467,10 +4468,7 @@ static CURLcode parse_url_login(struct SessionHandle
*data,
return CURLE_OUT_OF_MEMORY;
}
- if(strlen(newname) MAX_CURL_USER_LENGTH)
-strcpy(user, newname);
-
- free(newname);
+ *user = newname;
}
if(passwdp) {
@@ -4483,10 +4481,7 @@ static CURLcode parse_url_login(struct SessionHandle
*data,
return CURLE_OUT_OF_MEMORY;
}
- if(strlen(newpasswd) MAX_CURL_PASSWORD_LENGTH)
-strcpy(passwd, newpasswd);
-
- free(newpasswd);
+ *passwd = newpasswd;
}
if(optionsp) {
@@ -4499,10 +4494,7 @@ static CURLcode parse_url_login(struct SessionHandle
*data,
return CURLE_OUT_OF_MEMORY;
}
- if(strlen(newoptions) MAX_CURL_OPTIONS_LENGTH)
-strcpy(options, newoptions);
-
- free(newoptions);
+ *options = newoptions;
}
}
@@ -5018,9 +5010,9 @@ static CURLcode