digest: flush state on origin or credential change
No binary (build failed)
—
(log yok)
| @@ -94,6 +94,22 @@ CURLcode Curl_output_digest(struct Curl_easy *data, | |
| #endif | |
| } | |
| else { | |
| + | bool flush = FALSE; |
| + | DEBUGASSERT(data->conn->origin); |
| + | if(data->state.digest.origin && |
| + | !Curl_peer_same_destination(data->conn->origin, |
| + | data->state.digest.origin)) |
| + | flush = TRUE; |
| + | else if(data->state.digest.creds && |
| + | !Curl_creds_same(data->state.creds, data->state.digest.creds)) |
| + | flush = TRUE; |
| + | |
| + | if(flush) |
| + | /* flush host Digest state */ |
| + | Curl_auth_digest_cleanup(&data->state.digest); |
| + | |
| + | Curl_peer_link(&data->state.digest.origin, data->conn->origin); |
| + | Curl_creds_link(&data->state.digest.creds, data->state.creds); |
| digest = &data->state.digest; | |
| allocuserpwd = &data->req.hd_auth; | |
| creds = data->state.creds; | |
| @@ -148,13 +148,12 @@ typedef CURLcode (Curl_recv)(struct Curl_easy *data, /* transfer */ | |
| #ifndef CURL_DISABLE_DIGEST_AUTH | |
| /* Struct used for Digest challenge-response authentication */ | |
| struct digestdata { | |
| + | struct Curl_creds *creds; |
| + | struct Curl_peer *origin; |
| #ifdef USE_WINDOWS_SSPI | |
| BYTE *input_token; | |
| size_t input_token_len; | |
| CtxtHandle *http_context; | |
| - | /* linked credentials used to make the identity for http_context. |
| - | may be NULL. */ |
| - | struct Curl_creds *creds; |
| #else | |
| char *nonce; | |
| char *cnonce; | |
| @@ -1039,6 +1039,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, | |
| */ | |
| void Curl_auth_digest_cleanup(struct digestdata *digest) | |
| { | |
| + | Curl_peer_unlink(&digest->origin); |
| + | Curl_creds_unlink(&digest->creds); |
| curlx_safefree(digest->nonce); | |
| curlx_safefree(digest->cnonce); | |
| curlx_safefree(digest->realm); | |
| @@ -630,6 +630,7 @@ void Curl_auth_digest_cleanup(struct digestdata *digest) | |
| /* Free the copy of user/passwd used to make the identity for http_context */ | |
| Curl_creds_unlink(&digest->creds); | |
| + | Curl_peer_unlink(&digest->origin); |
| } | |
| #endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_DIGEST_AUTH */ | |
| @@ -221,7 +221,7 @@ test1653 test1654 test1655 test1656 test1657 test1658 test1659 test1660 \ | |
| test1661 test1662 test1663 test1664 test1665 test1666 test1667 test1668 \ | |
| test1669 test1670 test1671 test1672 test1673 test1674 test1675 test1676 \ | |
| test1677 test1680 test1681 test1682 test1683 test1684 \ | |
| - | test1685 \ |
| + | test1685 test1686 \ |
| \ | |
| test1700 test1701 test1702 test1703 test1704 test1705 test1706 test1707 \ | |
| test1708 test1709 test1710 test1711 test1712 test1713 test1714 test1715 \ | |
| @@ -0,0 +1,84 @@ | |
| + | <?xml version="1.0" encoding="US-ASCII"?> |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | Digest |
| + | </keywords> |
| + | </info> |
| + | |
| + | <reply> |
| + | <data crlf="headers" nocheck="yes"> |
| + | HTTP/1.1 401 Authorization Required |
| + | Server: Apache/1.3.27 (Darwin) PHP/4.1.2 |
| + | WWW-Authenticate: Digest realm="my-backyard", nonce="314156295" |
| + | Content-Length: 26 |
| + | |
| + | This is not the real page |
| + | </data> |
| + | |
| + | # This is supposed to be returned when the server gets a |
| + | # Authorization: Digest line passed-in from the client |
| + | <data1000 crlf="headers"> |
| + | HTTP/1.1 200 OK |
| + | Server: Apache/1.3.27 (Darwin) PHP/4.1.2 |
| + | Content-Type: text/html; charset=iso-8859-1 |
| + | Content-Length: 23 |
| + | |
| + | This IS the real page! |
| + | </data1000> |
| + | |
| + | </reply> |
| + | |
| + | <client> |
| + | <features> |
| + | !SSPI |
| + | crypto |
| + | digest |
| + | </features> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | HTTP Digest to different origins and switching credentials |
| + | </name> |
| + | <tool> |
| + | lib%TESTNUMBER |
| + | </tool> |
| + | <command> |
| + | %HOSTIP %HTTPPORT |
| + | </command> |
| + | </client> |
| + | |
| + | <verify> |
| + | <protocol crlf="headers"> |
| + | GET /api HTTP/1.1 |
| + | Host: first.test:%HTTPPORT |
| + | Accept: */* |
| + | |
| + | GET /api HTTP/1.1 |
| + | Host: first.test:%HTTPPORT |
| + | Authorization: Digest username="alice", realm="my-backyard", nonce="314156295", uri="/api", response="4ecc00e567c37a9d537727890c2e5b32" |
| + | Accept: */* |
| + | |
| + | GET /hook HTTP/1.1 |
| + | Host: second.test:%HTTPPORT |
| + | Accept: */* |
| + | |
| + | GET /hook HTTP/1.1 |
| + | Host: second.test:%HTTPPORT |
| + | Authorization: Digest username="alice", realm="my-backyard", nonce="314156295", uri="/hook", response="d3a7738fb6a23f5543fb8dacc0f0f253" |
| + | Accept: */* |
| + | |
| + | GET /hook HTTP/1.1 |
| + | Host: second.test:%HTTPPORT |
| + | Accept: */* |
| + | |
| + | GET /hook HTTP/1.1 |
| + | Host: second.test:%HTTPPORT |
| + | Authorization: Digest username="bob", realm="my-backyard", nonce="314156295", uri="/hook", response="777e68eddb77294d9cbd6134973cbbab" |
| + | Accept: */* |
| + | |
| + | </protocol> |
| + | </verify> |
| + | </testcase> |
| @@ -101,6 +101,7 @@ TESTS_C = \ | |
| lib1598.c lib1599.c \ | |
| lib1647.c lib1648.c lib1649.c \ | |
| lib1662.c \ | |
| + | lib1686.c \ |
| lib1900.c lib1901.c lib1902.c lib1903.c lib1905.c lib1906.c lib1907.c \ | |
| lib1908.c lib1910.c lib1911.c lib1912.c lib1913.c \ | |
| lib1915.c lib1916.c lib1918.c lib1919.c lib1920.c lib1921.c \ | |
| @@ -0,0 +1,96 @@ | |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * 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 |
| + | * |
| + | ***************************************************************************/ |
| + | #include "first.h" |
| + | |
| + | static size_t devnull_1686(char *p, size_t s, size_t n, void *u) |
| + | { |
| + | (void)p; |
| + | (void)u; |
| + | return s * n; |
| + | } |
| + | |
| + | #define FIRSTHOST "first.test" |
| + | #define SECONDHOST "second.test" |
| + | |
| + | static CURLcode test_lib1686(const char *hostip) |
| + | { |
| + | CURL *curl = NULL; |
| + | CURLcode result = CURLE_OK; |
| + | const char *httpport = libtest_arg2; |
| + | char firsturl[100]; |
| + | char secondurl[100]; |
| + | char firstres[100]; |
| + | char secondres[100]; |
| + | struct curl_slist *host = NULL; |
| + | struct curl_slist *host2 = NULL; |
| + | |
| + | if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { |
| + | curl_mfprintf(stderr, "curl_global_init() failed\n"); |
| + | return TEST_ERR_MAJOR_BAD; |
| + | } |
| + | |
| + | /* create strings for CURLOPT_RESOLVE */ |
| + | curl_msnprintf(firstres, sizeof(firstres), "%s:%s:%s", |
| + | FIRSTHOST, httpport, hostip); |
| + | curl_msnprintf(secondres, sizeof(secondres), "%s:%s:%s", |
| + | SECONDHOST, httpport, hostip); |
| + | |
| + | /* create URLs */ |
| + | curl_msnprintf(firsturl, sizeof(firsturl), "http://%s:%s/api", |
| + | FIRSTHOST, httpport); |
| + | curl_msnprintf(secondurl, sizeof(secondurl), "http://%s:%s/hook", |
| + | SECONDHOST, httpport); |
| + | |
| + | host = curl_slist_append(NULL, firstres); |
| + | if(!host) |
| + | goto test_cleanup; |
| + | host2 = curl_slist_append(host, secondres); |
| + | if(!host2) |
| + | goto test_cleanup; |
| + | host = host2; |
| + | |
| + | curl = curl_easy_init(); |
| + | if(curl) { |
| + | easy_setopt(curl, CURLOPT_RESOLVE, host); |
| + | easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); |
| + | easy_setopt(curl, CURLOPT_USERPWD, "alice:bond"); |
| + | easy_setopt(curl, CURLOPT_WRITEFUNCTION, devnull_1686); |
| + | |
| + | easy_setopt(curl, CURLOPT_URL, firsturl); |
| + | result = curl_easy_perform(curl); |
| + | |
| + | easy_setopt(curl, CURLOPT_URL, secondurl); |
| + | result = curl_easy_perform(curl); |
| + | |
| + | easy_setopt(curl, CURLOPT_USERPWD, "bob:secret"); |
| + | easy_setopt(curl, CURLOPT_URL, secondurl); |
| + | result = curl_easy_perform(curl); |
| + | } |
| + | |
| + | test_cleanup: |
| + | curl_easy_cleanup(curl); |
| + | curl_global_cleanup(); |
| + | curl_slist_free_all(host); |
| + | return result; |
| + | } |