getinfo: make sure CURLINFO_EFFECTIVE_URL does not contain creds
No binary (build failed)
—
(log yok)
| @@ -63,6 +63,7 @@ void Curl_initinfo(struct Curl_easy *data) | |
| curlx_safefree(info->contenttype); | |
| curlx_safefree(info->wouldredirect); | |
| + | curlx_safefree(info->effective_url); |
| memset(&info->primary, 0, sizeof(info->primary)); | |
| info->retry_after = 0; | |
| @@ -76,15 +77,51 @@ void Curl_initinfo(struct Curl_easy *data) | |
| #endif | |
| } | |
| + | static CURLcode effective_url(struct Curl_easy *data, |
| + | const char **param_charp) |
| + | { |
| + | const char *s = Curl_bufref_ptr(&data->state.url); |
| + | *param_charp = s ? s : ""; |
| + | if(s) { |
| + | char *url = NULL; |
| + | /* Make a copy of the URL without credentials */ |
| + | CURLU *u = curl_url(); |
| + | CURLUcode uc; |
| + | if(!u) |
| + | return CURLE_OUT_OF_MEMORY; |
| + | |
| + | uc = curl_url_set(u, CURLUPART_URL, s, |
| + | CURLU_NON_SUPPORT_SCHEME | |
| + | (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)); |
| + | if(!uc) |
| + | uc = curl_url_set(u, CURLUPART_USER, NULL, 0); |
| + | if(!uc) |
| + | uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0); |
| + | if(!uc) |
| + | uc = curl_url_get(u, CURLUPART_URL, &url, CURLU_GET_EMPTY); |
| + | |
| + | curl_url_cleanup(u); |
| + | |
| + | if(uc || !url) |
| + | return CURLE_OUT_OF_MEMORY; |
| + | if(strcmp(url, s)) { |
| + | /* they are different */ |
| + | curlx_free(data->info.effective_url); |
| + | data->info.effective_url = url; |
| + | *param_charp = url; |
| + | } |
| + | else |
| + | curl_free(url); |
| + | } |
| + | return CURLE_OK; |
| + | } |
| + | |
| static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, | |
| const char **param_charp) | |
| { | |
| switch(info) { | |
| - | case CURLINFO_EFFECTIVE_URL: { |
| - | const char *s = Curl_bufref_ptr(&data->state.url); |
| - | *param_charp = s ? s : ""; |
| - | } |
| - | break; |
| + | case CURLINFO_EFFECTIVE_URL: |
| + | return effective_url(data, param_charp); |
| case CURLINFO_EFFECTIVE_METHOD: { | |
| const char *m = CURL_EASY_STR(data, STRING_CUSTOMREQUEST); | |
| if(!m) { | |
| @@ -503,6 +503,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) | |
| data->state.authhost.want = data->set.httpauth; | |
| data->state.authproxy.want = data->set.proxyauth; | |
| curlx_safefree(data->info.wouldredirect); | |
| + | curlx_safefree(data->info.effective_url); |
| Curl_data_priority_clear_state(data); | |
| if(data->set.http_auto_referer) | |
| Curl_bufref_free(&data->state.referer); | |
| @@ -270,6 +270,7 @@ CURLcode Curl_close(struct Curl_easy **datap) | |
| curlx_safefree(data->state.most_recent_ftp_entrypath); | |
| curlx_safefree(data->info.contenttype); | |
| curlx_safefree(data->info.wouldredirect); | |
| + | curlx_safefree(data->info.effective_url); |
| /* No longer a dirty share, if it exists */ | |
| if(Curl_share_easy_unlink(data)) | |
| @@ -409,6 +409,7 @@ struct PureInfo { | |
| curl_off_t numconnects; /* how many new connections libcurl created */ | |
| char *contenttype; /* the content type of the object */ | |
| char *wouldredirect; /* URL this would have been redirected to if asked to */ | |
| + | char *effective_url; /* when needed */ |
| curl_off_t retry_after; /* info from Retry-After: header */ | |
| const char *conn_scheme; | |
| int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */ | |
| @@ -1750,6 +1750,7 @@ TESTCASES = \ | |
| test1849 \ | |
| test1851 \ | |
| test1862 \ | |
| + | test1876 \ |
| test1900 \ | |
| test1901 \ | |
| test1902 \ | |
| @@ -0,0 +1,67 @@ | |
| + | <?xml version="1.0" encoding="US-ASCII"?> |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | netrc |
| + | </keywords> |
| + | </info> |
| + | |
| + | # Server-side |
| + | <reply> |
| + | <data crlf="headers" nocheck="yes"> |
| + | HTTP/1.1 301 redir |
| + | Content-Length: 0 |
| + | Content-Type: text/html |
| + | Location: %TESTNUMBER0002 |
| + | |
| + | </data> |
| + | |
| + | <data2 crlf="headers"> |
| + | HTTP/1.1 200 OK |
| + | Content-Length: 0 |
| + | Content-Type: text/html |
| + | |
| + | </data2> |
| + | |
| + | </reply> |
| + | |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | verify no credentials present in effective URL after redirect |
| + | </name> |
| + | <file name="%LOGDIR/netrc"> |
| + | machine %HOSTIP |
| + | login netrcuser |
| + | password netrcSECRET123 |
| + | </file> |
| + | |
| + | <command option="no-include"> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER --netrc-optional --netrc-file %LOGDIR/netrc -L -w 'EFFECTIVE_URL=%{url_effective}\n' |
| + | </command> |
| + | </client> |
| + | |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol crlf="headers"> |
| + | GET /%TESTNUMBER HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | Authorization: Basic %b64[netrcuser:netrcSECRET123]b64% |
| + | User-Agent: curl/%VERSION |
| + | Accept: */* |
| + | |
| + | GET /%TESTNUMBER0002 HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | Authorization: Basic %b64[netrcuser:netrcSECRET123]b64% |
| + | User-Agent: curl/%VERSION |
| + | Accept: */* |
| + | |
| + | </protocol> |
| + | <stdout> |
| + | EFFECTIVE_URL=http://%HOSTIP:%HTTPPORT/%TESTNUMBER0002 |
| + | </stdout> |
| + | </verify> |
| + | </testcase> |