url: do not URL decode proxy crendentials

The two options CURLOPT_PROXYUSERNAME and CURLOPT_PROXYPASSWORD set the
actual names as-is, not URL encoded.

Modified test 503 to use percent-encoded strings in the credential
strings that should be passed on as-is.

Reported-by: Sergey Ogryzkov
Fixes #13265
Closes #13270
This commit is contained in:
Daniel Stenberg 2024-04-03 11:32:55 +02:00
parent 29bfde9fea
commit d5e83eb745
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
4 changed files with 30 additions and 17 deletions

View File

@ -52,6 +52,8 @@
#include "hsts.h" #include "hsts.h"
#include "tftp.h" #include "tftp.h"
#include "strdup.h" #include "strdup.h"
#include "escape.h"
/* The last 3 #include files should be in this order */ /* The last 3 #include files should be in this order */
#include "curl_printf.h" #include "curl_printf.h"
#include "curl_memory.h" #include "curl_memory.h"
@ -1593,13 +1595,24 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break; break;
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXYUSERPWD: case CURLOPT_PROXYUSERPWD: {
/* /*
* user:password needed to use the proxy * user:password needed to use the proxy
*/ */
result = setstropt_userpwd(va_arg(param, char *), char *u = NULL;
&data->set.str[STRING_PROXYUSERNAME], char *p = NULL;
&data->set.str[STRING_PROXYPASSWORD]); result = setstropt_userpwd(va_arg(param, char *), &u, &p);
/* URL decode the components */
if(!result && u)
result = Curl_urldecode(u, 0, &data->set.str[STRING_PROXYUSERNAME], NULL,
REJECT_ZERO);
if(!result && p)
result = Curl_urldecode(p, 0, &data->set.str[STRING_PROXYPASSWORD], NULL,
REJECT_ZERO);
free(u);
free(p);
}
break; break;
case CURLOPT_PROXYUSERNAME: case CURLOPT_PROXYUSERNAME:
/* /*

View File

@ -2366,17 +2366,16 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
data->state.aptr.proxyuser : ""; data->state.aptr.proxyuser : "";
const char *proxypasswd = data->state.aptr.proxypasswd ? const char *proxypasswd = data->state.aptr.proxypasswd ?
data->state.aptr.proxypasswd : ""; data->state.aptr.proxypasswd : "";
CURLcode result = Curl_urldecode(proxyuser, 0, &conn->http_proxy.user, NULL, CURLcode result = CURLE_OUT_OF_MEMORY;
REJECT_ZERO);
if(!result) conn->http_proxy.user = strdup(proxyuser);
result = Curl_setstropt(&data->state.aptr.proxyuser, if(conn->http_proxy.user) {
conn->http_proxy.user); conn->http_proxy.passwd = strdup(proxypasswd);
if(!result) if(conn->http_proxy.passwd)
result = Curl_urldecode(proxypasswd, 0, &conn->http_proxy.passwd, result = CURLE_OK;
NULL, REJECT_ZERO); else
if(!result) Curl_safefree(conn->http_proxy.user);
result = Curl_setstropt(&data->state.aptr.proxypasswd, }
conn->http_proxy.passwd);
return result; return result;
} }

View File

@ -73,7 +73,7 @@ moo
<proxy> <proxy>
CONNECT machine.%TESTNUMBER:%HTTPPORT HTTP/1.1 CONNECT machine.%TESTNUMBER:%HTTPPORT HTTP/1.1
Host: machine.%TESTNUMBER:%HTTPPORT Host: machine.%TESTNUMBER:%HTTPPORT
Proxy-Authorization: Basic dGVzdDppbmc= Proxy-Authorization: Basic dGVzdCUyMDppbmclNDE=
Proxy-Connection: Keep-Alive Proxy-Connection: Keep-Alive
[DISCONNECT] [DISCONNECT]

View File

@ -53,7 +53,8 @@ int test(char *URL)
easy_setopt(c, CURLOPT_PROXY, libtest_arg2); /* set in first.c */ easy_setopt(c, CURLOPT_PROXY, libtest_arg2); /* set in first.c */
easy_setopt(c, CURLOPT_URL, URL); easy_setopt(c, CURLOPT_URL, URL);
easy_setopt(c, CURLOPT_USERPWD, "test:ing"); easy_setopt(c, CURLOPT_USERPWD, "test:ing");
easy_setopt(c, CURLOPT_PROXYUSERPWD, "test:ing"); easy_setopt(c, CURLOPT_PROXYUSERNAME, "test%20");
easy_setopt(c, CURLOPT_PROXYPASSWORD, "ing%41");
easy_setopt(c, CURLOPT_HTTPPROXYTUNNEL, 1L); easy_setopt(c, CURLOPT_HTTPPROXYTUNNEL, 1L);
easy_setopt(c, CURLOPT_HEADER, 1L); easy_setopt(c, CURLOPT_HEADER, 1L);
easy_setopt(c, CURLOPT_VERBOSE, 1L); easy_setopt(c, CURLOPT_VERBOSE, 1L);