From 9abd1514bb93ca5e24b70b319f54d5ef6d074e5c Mon Sep 17 00:00:00 2001 From: Henrik Nordstrom Date: Tue, 2 Mar 2010 15:08:22 +0100 Subject: [PATCH] Parser starting to take shape --- src/HttpHeaderTools.cc | 36 ++++---- src/auth/digest/auth_digest.cc | 150 ++++++++++++--------------------- 2 files changed, 75 insertions(+), 111 deletions(-) diff --git a/src/HttpHeaderTools.cc b/src/HttpHeaderTools.cc index 3a2b7d3ad0..875a98d62f 100644 --- a/src/HttpHeaderTools.cc +++ b/src/HttpHeaderTools.cc @@ -335,25 +335,29 @@ httpHeaderParseQuotedString(const char *start, String *val) { const char *end, *pos; val->clean(); - assert (*start == '"'); + if (*start != '"') { + debugs(66, 2, "failed to parse a quoted-string header field near '" << start << "'"); + return 0; + } pos = start + 1; - while (1) { - if (!(end = index (pos,'"'))) { - debugs(66, 2, "failed to parse a quoted-string header field near '" << start << "'"); - return 0; - } - - /* check for quoted-chars */ - if (*(end - 1) != '\\') { - /* done */ - val->append(start + 1, end-start-1); - return 1; - } - - /* try for the end again */ - pos = end + 1; + while (*pos != '"') { + if (*pos == '\\') { + pos++; + } + if (!*pos) { + debugs(66, 2, "failed to parse a quoted-string header field near '" << start << "'"); + val->clean(); + return 0; + } + end = pos + strcspn(pos, "\"\\"); + val->append(pos, end-pos); + pos = end; } + /* Make sure it's defined even if empty "" */ + if (!val->defined()) + val->limitInit("", 0); + return 1; } /** diff --git a/src/auth/digest/auth_digest.cc b/src/auth/digest/auth_digest.cc index f6b338e25e..46c61f191d 100644 --- a/src/auth/digest/auth_digest.cc +++ b/src/auth/digest/auth_digest.cc @@ -67,7 +67,7 @@ static MemAllocator *digest_nonce_pool = NULL; CBDATA_TYPE(DigestAuthenticateStateData); -enum { +enum http_digest_attr_type { DIGEST_USERNAME=1, DIGEST_REALM, DIGEST_QOP, @@ -1103,7 +1103,7 @@ AuthDigestConfig::decode(char const *proxy_auth) const char *pos = NULL; char *username = NULL; digest_nonce_h *nonce; - int ilen; + size_t ilen; debugs(29, 9, "authenticateDigestDecodeAuth: beginning"); @@ -1121,124 +1121,84 @@ AuthDigestConfig::decode(char const *proxy_auth) String temp(proxy_auth); while (strListGetItem(&temp, ',', &item, &ilen, &pos)) { - if ((p = strchr(item, '=')) && (p - item < ilen)) - ilen = p++ - item; - - if (!strncmp(item, "username", ilen)) { - /* white space */ - - while (xisspace(*p)) - p++; - - /* quote mark */ - p++; - + String value(); + size_t nlen; + /* isolate directive name */ + if ((p = (const char *)memchr(item, '=', ilen)) && (p - item < ilen)) { + nlen = p++ - item; + if (!httpHeaderParseQuotedString(p, &value)) + value.initLimit(p, ilen - (p - item)); + } else + nlen = ilen; + + if (!value.defined()) { + debugs(29, 9, "authDigestDecodeAuth: Failed to parse attribute '" << temp << "' in '" << proxy_auth << "'"); + continue; + } + + /* find type */ + http_digest_attr_type type = (http_digest_attr_type)httpHeaderIdByName(item, nlen, DigestFieldsInfo, DIGEST_ENUM_END); + + switch (type) { + case DIGEST_USERNAME: safe_free(username); - username = xstrndup(p, strchr(p, '"') + 1 - p); - + username = xstrndup(value.rawBuf(), value.size() + 1); debugs(29, 9, "authDigestDecodeAuth: Found Username '" << username << "'"); - } else if (!strncmp(item, "realm", ilen)) { - /* white space */ - - while (xisspace(*p)) - p++; - - /* quote mark */ - p++; + break; + case DIGEST_REALM: safe_free(digest_request->realm); - digest_request->realm = xstrndup(p, strchr(p, '"') + 1 - p); - + digest_request->realm = xstrndup(value.rawBuf(), value.size() + 1); debugs(29, 9, "authDigestDecodeAuth: Found realm '" << digest_request->realm << "'"); - } else if (!strncmp(item, "qop", ilen)) { - /* white space */ - - while (xisspace(*p)) - p++; - - if (*p == '\"') - /* quote mark */ - p++; + break; + case DIGEST_QOP: safe_free(digest_request->qop); - digest_request->qop = xstrndup(p, strcspn(p, "\" \t\r\n()<>@,;:\\/[]?={}") + 1); - + digest_request->qop = xstrndup(value.rawBuf(), value.size() + 1); debugs(29, 9, "authDigestDecodeAuth: Found qop '" << digest_request->qop << "'"); - } else if (!strncmp(item, "algorithm", ilen)) { - /* white space */ - - while (xisspace(*p)) - p++; - - if (*p == '\"') - /* quote mark */ - p++; + break; + case DIGEST_ALGORITHM: safe_free(digest_request->algorithm); - digest_request->algorithm = xstrndup(p, strcspn(p, "\" \t\r\n()<>@,;:\\/[]?={}") + 1); - + digest_request->algorithm = xstrndup(value.rawBuf(), value.size() + 1); debugs(29, 9, "authDigestDecodeAuth: Found algorithm '" << digest_request->algorithm << "'"); - } else if (!strncmp(item, "uri", ilen)) { - /* white space */ - - while (xisspace(*p)) - p++; - - /* quote mark */ - p++; + break; + case DIGEST_URI: safe_free(digest_request->uri); - digest_request->uri = xstrndup(p, strchr(p, '"') + 1 - p); - + digest_request->uri = xstrndup(value.rawBuf(), value.size() + 1); debugs(29, 9, "authDigestDecodeAuth: Found uri '" << digest_request->uri << "'"); - } else if (!strncmp(item, "nonce", ilen)) { - /* white space */ - - while (xisspace(*p)) - p++; - - /* quote mark */ - p++; + break; + case DIGEST_NONCE: safe_free(digest_request->nonceb64); - digest_request->nonceb64 = xstrndup(p, strchr(p, '"') + 1 - p); - + digest_request->nonceb64 = xstrndup(value.rawBuf(), value.size() + 1); debugs(29, 9, "authDigestDecodeAuth: Found nonce '" << digest_request->nonceb64 << "'"); - } else if (!strncmp(item, "nc", ilen)) { - /* white space */ - - while (xisspace(*p)) - p++; - - xstrncpy(digest_request->nc, p, 9); + break; + case DIGEST_NC: + if (value.size() != 8) { + debugs(29, 9, "authDigestDecodeAuth: Invalid nc '" << value << "' in '" << temp << "'"); + } + xstrncpy(digest_request->nc, value.rawBuf(), value.size() + 1); debugs(29, 9, "authDigestDecodeAuth: Found noncecount '" << digest_request->nc << "'"); - } else if (!strncmp(item, "cnonce", ilen)) { - /* white space */ - - while (xisspace(*p)) - p++; - - /* quote mark */ - p++; + break; + case DIGEST_CNONCE: safe_free(digest_request->cnonce); - digest_request->cnonce = xstrndup(p, strchr(p, '"') + 1 - p); - + digest_request->cnonce = xstrndup(value.rawBuf(), value.size() + 1); debugs(29, 9, "authDigestDecodeAuth: Found cnonce '" << digest_request->cnonce << "'"); - } else if (!strncmp(item, "response", ilen)) { - /* white space */ - - while (xisspace(*p)) - p++; - - /* quote mark */ - p++; + break; + case DIGEST_RESPONSE: safe_free(digest_request->response); - digest_request->response = xstrndup(p, strchr(p, '"') + 1 - p); - + digest_request->response = xstrndup(value.rawBuf(), value.size() + 1); debugs(29, 9, "authDigestDecodeAuth: Found response '" << digest_request->response << "'"); + break; + + default: + debugs(29, 2, "authDigestDecodeAuth: Unknown attribute '" << item << "' in '" << temp << "'"); + } } -- 2.47.2