From af5fbb14bb4fd86cdc5bf2c9f1f2b3b5d8d2af66 Mon Sep 17 00:00:00 2001 From: Jay Satiro Date: Tue, 26 Jul 2016 01:46:23 -0400 Subject: [PATCH] digest_sspi: Handle 'stale=TRUE' directive in HTTP digest - If the server has provided another challenge use it as the replacement input token if stale=TRUE. Otherwise previous credentials have failed so return CURLE_LOGIN_DENIED. Prior to this change the stale directive was ignored and if another challenge was received it would cause error CURLE_BAD_CONTENT_ENCODING. Ref: https://tools.ietf.org/html/rfc2617#page-10 Bug: https://github.com/curl/curl/issues/928 Reported-by: tarek112@users.noreply.github.com --- lib/vauth/digest_sspi.c | 43 ++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c index f9ee8a8fd970e2..15f3d8c14b3179 100644 --- a/lib/vauth/digest_sspi.c +++ b/lib/vauth/digest_sspi.c @@ -335,12 +335,43 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg, { size_t chlglen = strlen(chlg); - /* We had an input token before and we got another one now. This means we - provided bad credentials in the previous request. */ - if(digest->input_token) - return CURLE_BAD_CONTENT_ENCODING; + /* We had an input token before so if there's another one now that means we + provided bad credentials in the previous request or it's stale. */ + if(digest->input_token) { + bool stale = false; + const char *p = chlg; + + /* Check for the 'stale' directive */ + for(;;) { + char value[DIGEST_MAX_VALUE_LENGTH]; + char content[DIGEST_MAX_CONTENT_LENGTH]; + + while(*p && ISSPACE(*p)) + p++; + + if(!Curl_auth_digest_get_pair(p, value, content, &p)) + break; + + if(Curl_strcasecompare(value, "stale") + && Curl_strcasecompare(content, "true")) { + stale = true; + break; + } - /* Simply store the challenge for use later */ + while(*p && ISSPACE(*p)) + p++; + + if(',' == *p) + p++; + } + + if(stale) + Curl_auth_digest_cleanup(digest); + else + return CURLE_LOGIN_DENIED; + } + + /* Store the challenge for use later */ digest->input_token = (BYTE *) Curl_memdup(chlg, chlglen + 1); if(!digest->input_token) return CURLE_OUT_OF_MEMORY; @@ -552,8 +583,6 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, if(!resp) { free(output_token); - Curl_safefree(digest->http_context); - return CURLE_OUT_OF_MEMORY; }