From: Daniel Stenberg Date: Thu, 9 Oct 2025 14:35:39 +0000 (+0200) Subject: vauth/digest: improve the digest parser X-Git-Tag: rc-8_17_0-1~29 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2a2a2e5d107f1ad7fbb5e88dab03ed37c8177e76;p=thirdparty%2Fcurl.git vauth/digest: improve the digest parser Previously, if for example the nonce would end with "realm=" etc it would get the wrong piece, due to the naive parser. Reported-by: Joshua Rogers Closes #18975 --- diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c index 4196ae725c..0a0b3580ed 100644 --- a/lib/vauth/digest.c +++ b/lib/vauth/digest.c @@ -193,26 +193,43 @@ static char *auth_digest_string_quoted(const char *source) /* Retrieves the value for a corresponding key from the challenge string * returns TRUE if the key could be found, FALSE if it does not exists */ -static bool auth_digest_get_key_value(const char *chlg, - const char *key, - char *value, - size_t max_val_len, - char end_char) +static bool auth_digest_get_key_value(const char *chlg, const char *key, + char *buf, size_t buflen) { - char *find_pos; - size_t i; - - find_pos = strstr(chlg, key); - if(!find_pos) - return FALSE; - - find_pos += strlen(key); - - for(i = 0; *find_pos && *find_pos != end_char && i < max_val_len - 1; ++i) - value[i] = *find_pos++; - value[i] = '\0'; + /* keyword=[value],keyword2=[value] + The values may or may not be quoted. + */ + + do { + struct Curl_str data; + struct Curl_str name; + if(!curlx_str_until(&chlg, &name, 64, '=') && + !curlx_str_single(&chlg, '=')) { + /* this is the key, get the value, possibly quoted */ + int rc = curlx_str_quotedword(&chlg, &data, 256); + if(rc == STRE_BEGQUOTE) + /* try unquoted until comma */ + rc = curlx_str_until(&chlg, &data, 256, ','); + if(rc) + return FALSE; /* weird */ + + if(curlx_str_cmp(&name, key)) { + /* if this is our key, return the value */ + if(curlx_strlen(&data) >= buflen) + /* doesn't fit */ + return FALSE; + memcpy(buf, curlx_str(&data), curlx_strlen(&data)); + buf[curlx_strlen(&data)] = 0; + return TRUE; + } + if(curlx_str_single(&chlg, ',')) + return FALSE; + } + else /* odd syntax */ + break; + } while(1); - return TRUE; + return FALSE; } static CURLcode auth_digest_get_qop_values(const char *options, int *value) @@ -268,21 +285,21 @@ static CURLcode auth_decode_digest_md5_message(const struct bufref *chlgref, return CURLE_BAD_CONTENT_ENCODING; /* Retrieve nonce string from the challenge */ - if(!auth_digest_get_key_value(chlg, "nonce=\"", nonce, nlen, '\"')) + if(!auth_digest_get_key_value(chlg, "nonce", nonce, nlen)) return CURLE_BAD_CONTENT_ENCODING; /* Retrieve realm string from the challenge */ - if(!auth_digest_get_key_value(chlg, "realm=\"", realm, rlen, '\"')) { + if(!auth_digest_get_key_value(chlg, "realm", realm, rlen)) { /* Challenge does not have a realm, set empty string [RFC2831] page 6 */ *realm = '\0'; } /* Retrieve algorithm string from the challenge */ - if(!auth_digest_get_key_value(chlg, "algorithm=", alg, alen, ',')) + if(!auth_digest_get_key_value(chlg, "algorithm", alg, alen)) return CURLE_BAD_CONTENT_ENCODING; /* Retrieve qop-options string from the challenge */ - if(!auth_digest_get_key_value(chlg, "qop=\"", qop, qlen, '\"')) + if(!auth_digest_get_key_value(chlg, "qop", qop, qlen)) return CURLE_BAD_CONTENT_ENCODING; return CURLE_OK;