From d5ed571948a088468a2f4b9b457677e99fb80510 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 23 Jun 2020 16:23:51 +0200 Subject: [PATCH] url: allow user + password to contain "control codes" for HTTP(S) Reported-by: Jon Johnson Jr Fixes #5582 Closes #5592 --- lib/http.c | 6 ++++-- lib/url.c | 29 +++++++++++++++++++---------- lib/urldata.h | 2 ++ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/http.c b/lib/http.c index 482f9ad0a..19e471ee6 100644 --- a/lib/http.c +++ b/lib/http.c @@ -125,7 +125,8 @@ const struct Curl_handler Curl_handler_http = { ZERO_NULL, /* connection_check */ PORT_HTTP, /* defport */ CURLPROTO_HTTP, /* protocol */ - PROTOPT_CREDSPERREQUEST /* flags */ + PROTOPT_CREDSPERREQUEST | /* flags */ + PROTOPT_USERPWDCTRL }; #ifdef USE_SSL @@ -150,7 +151,8 @@ const struct Curl_handler Curl_handler_https = { ZERO_NULL, /* connection_check */ PORT_HTTPS, /* defport */ CURLPROTO_HTTPS, /* protocol */ - PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN /* flags */ + PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */ + PROTOPT_USERPWDCTRL }; #endif diff --git a/lib/url.c b/lib/url.c index 8163fb58b..4e5587d34 100644 --- a/lib/url.c +++ b/lib/url.c @@ -1894,23 +1894,32 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, if(result) return result; - uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, - CURLU_URLDECODE); + /* we don't use the URL API's URL decoder option here since it rejects + control codes and we want to allow them for some schemes in the user and + password fields */ + uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0); if(!uc) { - conn->user = strdup(data->state.up.user); - if(!conn->user) - return CURLE_OUT_OF_MEMORY; + char *decoded; + result = Curl_urldecode(NULL, data->state.up.user, 0, &decoded, NULL, + conn->handler->flags&PROTOPT_USERPWDCTRL ? + REJECT_ZERO : REJECT_CTRL); + if(result) + return result; + conn->user = decoded; conn->bits.user_passwd = TRUE; } else if(uc != CURLUE_NO_USER) return Curl_uc_to_curlcode(uc); - uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, - CURLU_URLDECODE); + uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0); if(!uc) { - conn->passwd = strdup(data->state.up.password); - if(!conn->passwd) - return CURLE_OUT_OF_MEMORY; + char *decoded; + result = Curl_urldecode(NULL, data->state.up.password, 0, &decoded, NULL, + conn->handler->flags&PROTOPT_USERPWDCTRL ? + REJECT_ZERO : REJECT_CTRL); + if(result) + return result; + conn->passwd = decoded; conn->bits.user_passwd = TRUE; } else if(uc != CURLUE_NO_PASSWORD) diff --git a/lib/urldata.h b/lib/urldata.h index 74b43abaa..3e44be87e 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -766,6 +766,8 @@ struct Curl_handler { HTTP proxy as HTTP proxies may know this protocol and act as a gateway */ #define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */ +#define PROTOPT_USERPWDCTRL (1<<13) /* Allow "control bytes" (< 32 ascii) in + user name and password */ #define CONNCHECK_NONE 0 /* No checks */ #define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */