http: ignore Proxy-Authenticate unless the response comes from a proxy
No binary (build failed)
—
(log yok)
| @@ -3465,8 +3465,15 @@ static CURLcode http_header_p(struct Curl_easy *data, | |
| } | |
| #endif | |
| if((407 == k->httpcode) && HD_IS(hd, hdlen, "Proxy-authenticate:")) { | |
| - | char *auth = Curl_copy_header_value(hd); |
| - | CURLcode result = auth ? CURLE_OK : CURLE_OUT_OF_MEMORY; |
| + | char *auth; |
| + | CURLcode result; |
| + | #ifndef CURL_DISABLE_PROXY |
| + | if(!data->conn->bits.origin_is_proxy) |
| + | /* this response is not from a forward proxy, not for us */ |
| + | return CURLE_OK; |
| + | #endif |
| + | auth = Curl_copy_header_value(hd); |
| + | result = auth ? CURLE_OK : CURLE_OUT_OF_MEMORY; |
| if(!result) { | |
| result = Curl_http_input_auth(data, TRUE, auth); | |
| curlx_free(auth); | |
| @@ -41,9 +41,10 @@ static void digest_flush_stale(struct Curl_easy *data, | |
| struct Curl_creds *creds) | |
| { | |
| bool flush = FALSE; | |
| - | if(digest->origin && !Curl_peer_equal(peer, digest->origin)) { |
| + | if(!digest->origin || !Curl_peer_equal(peer, digest->origin)) { |
| CURL_TRC_M(data, "http_digest, reset on peer change to %s:%u", | |
| - | peer->hostname, peer->port); |
| + | peer ? peer->hostname : "-", |
| + | (unsigned int)(peer ? peer->port : 0)); |
| flush = TRUE; | |
| } | |
| else if(digest->creds && !Curl_creds_same(creds, digest->creds)) { | |
| @@ -1634,6 +1634,7 @@ TESTCASES = \ | |
| test1613 \ | |
| test1614 \ | |
| test1615 \ | |
| + | test1616 \ |
| test1617 \ | |
| test1618 \ | |
| test1619 \ | |
| @@ -0,0 +1,108 @@ | |
| + | <?xml version="1.0" encoding="US-ASCII"?> |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP GET |
| + | HTTP proxy |
| + | HTTP proxy Digest auth |
| + | </keywords> |
| + | </info> |
| + | |
| + | # Server-side |
| + | <reply> |
| + | <data1 crlf="headers"> |
| + | HTTP/1.1 200 OK |
| + | Content-Length: 12 |
| + | Connection: close |
| + | |
| + | proxied one |
| + | </data1> |
| + | |
| + | <data2 crlf="headers"> |
| + | HTTP/1.1 407 Proxy Authentication Required |
| + | Proxy-Authenticate: Digest realm="attacker", nonce="1053604598" |
| + | Content-Length: 7 |
| + | Connection: close |
| + | |
| + | direct |
| + | </data2> |
| + | |
| + | <data4 crlf="headers"> |
| + | HTTP/1.1 407 Proxy Authentication Required |
| + | Proxy-Authenticate: Digest realm="tunnel-attacker", nonce="1053604598" |
| + | Content-Length: 9 |
| + | Connection: close |
| + | |
| + | tunneled |
| + | </data4> |
| + | |
| + | <connect> |
| + | HTTP/1.1 200 Mighty fine indeed |
| + | |
| + | </connect> |
| + | |
| + | <datacheck> |
| + | proxied one |
| + | direct |
| + | proxied one |
| + | tunneled |
| + | proxied one |
| + | </datacheck> |
| + | </reply> |
| + | |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <tool> |
| + | lib%TESTNUMBER |
| + | </tool> |
| + | <features> |
| + | !SSPI |
| + | crypto |
| + | proxy |
| + | digest |
| + | </features> |
| + | <name> |
| + | HTTP 407 from a non-proxied host must not set proxy Digest state |
| + | </name> |
| + | <command> |
| + | http://test.remote.example.com/%TESTNUMBER0001 %HOSTIP %HTTPPORT %TESTNUMBER |
| + | </command> |
| + | </client> |
| + | |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol crlf="headers"> |
| + | GET http://test.remote.example.com/%TESTNUMBER0001 HTTP/1.1 |
| + | Host: test.remote.example.com |
| + | Accept: */* |
| + | Proxy-Connection: Keep-Alive |
| + | |
| + | GET /%TESTNUMBER0002 HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | Accept: */* |
| + | |
| + | GET http://test.remote.example.com/%TESTNUMBER0001 HTTP/1.1 |
| + | Host: test.remote.example.com |
| + | Accept: */* |
| + | Proxy-Connection: Keep-Alive |
| + | |
| + | CONNECT test.remote.example.com:%HTTPPORT HTTP/1.1 |
| + | Host: test.remote.example.com:%HTTPPORT |
| + | Proxy-Connection: Keep-Alive |
| + | |
| + | GET /%TESTNUMBER0004 HTTP/1.1 |
| + | Host: test.remote.example.com:%HTTPPORT |
| + | Accept: */* |
| + | |
| + | GET http://test.remote.example.com/%TESTNUMBER0001 HTTP/1.1 |
| + | Host: test.remote.example.com |
| + | Accept: */* |
| + | Proxy-Connection: Keep-Alive |
| + | |
| + | </protocol> |
| + | </verify> |
| + | </testcase> |
| @@ -237,6 +237,7 @@ TESTS_C = \ | |
| lib1598.c \ | |
| lib1599.c \ | |
| lib1605.c \ | |
| + | lib1616.c \ |
| lib1647.c \ | |
| lib1648.c \ | |
| lib1649.c \ | |
| @@ -0,0 +1,104 @@ | |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| + | * |
| + | * This software is licensed as described in the file COPYING, which |
| + | * you should have received as part of this distribution. The terms |
| + | * are also available at https://curl.se/docs/copyright.html. |
| + | * |
| + | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| + | * copies of the Software, and permit persons to whom the Software is |
| + | * furnished to do so, under the terms of the COPYING file. |
| + | * |
| + | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| + | * KIND, either express or implied. |
| + | * |
| + | * SPDX-License-Identifier: curl |
| + | * |
| + | ***************************************************************************/ |
| + | /* |
| + | * argv1 = URL fetched through the proxy |
| + | * argv2 = proxy host |
| + | * argv3 = proxy port |
| + | * argv4 = test number |
| + | */ |
| + | |
| + | #include "first.h" |
| + | |
| + | static CURLcode test_lib1616(const char *URL) |
| + | { |
| + | CURLcode result = CURLE_OK; |
| + | CURL *curl = NULL; |
| + | char proxy[128]; |
| + | char direct[256]; |
| + | char tunneled[256]; |
| + | |
| + | if(test_argc < 4) |
| + | return TEST_ERR_MAJOR_BAD; |
| + | |
| + | curl_msnprintf(proxy, sizeof(proxy), "http://%s:%s", |
| + | libtest_arg2, libtest_arg3); |
| + | curl_msnprintf(direct, sizeof(direct), "http://%s:%s/%s0002", |
| + | libtest_arg2, libtest_arg3, libtest_arg4); |
| + | curl_msnprintf(tunneled, sizeof(tunneled), |
| + | "http://test.remote.example.com:%s/%s0004", |
| + | libtest_arg3, libtest_arg4); |
| + | |
| + | res_global_init(CURL_GLOBAL_ALL); |
| + | if(result) |
| + | return result; |
| + | |
| + | curl = curl_easy_init(); |
| + | if(!curl) { |
| + | curl_mfprintf(stderr, "curl_easy_init() failed\n"); |
| + | curl_global_cleanup(); |
| + | return TEST_ERR_MAJOR_BAD; |
| + | } |
| + | |
| + | start_test_timing(); |
| + | |
| + | easy_setopt(curl, CURLOPT_PROXY, proxy); |
| + | easy_setopt(curl, CURLOPT_NOPROXY, libtest_arg2); |
| + | easy_setopt(curl, CURLOPT_PROXYAUTH, (long)CURLAUTH_DIGEST); |
| + | easy_setopt(curl, CURLOPT_PROXYUSERPWD, "silly:person"); |
| + | |
| + | easy_setopt(curl, CURLOPT_URL, URL); |
| + | result = curl_easy_perform(curl); |
| + | if(result) |
| + | goto test_cleanup; |
| + | |
| + | /* the excluded host is reached directly and answers 407 */ |
| + | easy_setopt(curl, CURLOPT_URL, direct); |
| + | result = curl_easy_perform(curl); |
| + | if(result) |
| + | goto test_cleanup; |
| + | |
| + | /* the same proxy as before must not get a Proxy-Authorization header */ |
| + | easy_setopt(curl, CURLOPT_URL, URL); |
| + | result = curl_easy_perform(curl); |
| + | if(result) |
| + | goto test_cleanup; |
| + | |
| + | /* an origin reached through a CONNECT tunnel answers 407 as well */ |
| + | easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L); |
| + | easy_setopt(curl, CURLOPT_URL, tunneled); |
| + | result = curl_easy_perform(curl); |
| + | if(result) |
| + | goto test_cleanup; |
| + | |
| + | /* and that must not reach the proxy either */ |
| + | easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 0L); |
| + | easy_setopt(curl, CURLOPT_URL, URL); |
| + | result = curl_easy_perform(curl); |
| + | |
| + | test_cleanup: |
| + | |
| + | curl_easy_cleanup(curl); |
| + | curl_global_cleanup(); |
| + | return result; |
| + | } |