# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: henrik@henriknordstrom.net-20100302165813-\
#   xhabeaopfdvbi372
# target_branch: ../trunk/
# testament_sha1: 9ef7f250de84e6076ea7f172491f9695736e71f4
# timestamp: 2010-03-02 17:59:33 +0100
# base_revision_id: squidadm@squid-cache.org-20100301011317-\
#   5miwqblkua9c5gzq
# 
# Begin patch
=== modified file 'src/HttpHeaderTools.cc'
--- src/HttpHeaderTools.cc	2009-09-10 03:08:35 +0000
+++ src/HttpHeaderTools.cc	2010-03-02 14:08:22 +0000
@@ -335,25 +335,29 @@
 {
     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;
 }
 
 /**

=== modified file 'src/auth/digest/auth_digest.cc'
--- src/auth/digest/auth_digest.cc	2010-02-14 00:09:05 +0000
+++ src/auth/digest/auth_digest.cc	2010-03-02 16:58:13 +0000
@@ -67,6 +67,33 @@
 
 CBDATA_TYPE(DigestAuthenticateStateData);
 
+enum http_digest_attr_type {
+    DIGEST_USERNAME=1,
+    DIGEST_REALM,
+    DIGEST_QOP,
+    DIGEST_ALGORITHM,
+    DIGEST_URI,
+    DIGEST_NONCE,
+    DIGEST_NC,
+    DIGEST_CNONCE,
+    DIGEST_RESPONSE,
+    DIGEST_ENUM_END
+};
+
+static const HttpHeaderFieldAttrs DigestAttrs[DIGEST_ENUM_END] = {
+    {"username",  (http_hdr_type)DIGEST_USERNAME},
+    {"realm", (http_hdr_type)DIGEST_REALM},
+    {"qop", (http_hdr_type)DIGEST_QOP},
+    {"algorithm", (http_hdr_type)DIGEST_ALGORITHM},
+    {"uri", (http_hdr_type)DIGEST_URI},
+    {"nonce", (http_hdr_type)DIGEST_NONCE},
+    {"nc", (http_hdr_type)DIGEST_NC},
+    {"cnonce", (http_hdr_type)DIGEST_CNONCE},
+    {"response", (http_hdr_type)DIGEST_RESPONSE},
+};
+
+static HttpHeaderFieldInfo *DigestFieldsInfo = NULL;
+
 /*
  *
  * Nonce Functions
@@ -505,6 +532,9 @@
     if (digestauthenticators)
         helperShutdown(digestauthenticators);
 
+    httpHeaderDestroyFieldsInfo(DigestFieldsInfo, DIGEST_ENUM_END);
+    DigestFieldsInfo = NULL;
+
     authdigest_initialised = 0;
 
     if (!shutting_down) {
@@ -867,6 +897,7 @@
 AuthDigestConfig::init(AuthConfig * scheme)
 {
     if (authenticate) {
+	DigestFieldsInfo = httpHeaderBuildFieldsInfo(DigestAttrs, DIGEST_ENUM_END);
         authenticateDigestNonceSetup();
         authdigest_initialised = 1;
 
@@ -1090,124 +1121,84 @@
     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.limitInit(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, 3, "authDigestDecodeAuth: Unknown attribute '" << item << "' in '" << temp << "'");
+
         }
     }
 
@@ -1225,60 +1216,36 @@
      * correct values - 400/401/407
      */
 
-    /* first the NONCE count */
-
-    if (digest_request->cnonce && strlen(digest_request->nc) != 8) {
-        debugs(29, 4, "authenticateDigestDecode: nonce count length invalid");
-        return authDigestLogUsername(username, digest_request);
-    }
-
-    /* now the nonce */
-    nonce = authenticateDigestNonceFindNonce(digest_request->nonceb64);
-
-    if (!nonce) {
-        /* we couldn't find a matching nonce! */
-        debugs(29, 4, "authenticateDigestDecode: Unexpected or invalid nonce received");
-        return authDigestLogUsername(username, digest_request);
-    }
-
-    digest_request->nonce = nonce;
-    authDigestNonceLink(nonce);
-
-    /* check the qop is what we expected. Note that for compatability with
-     * RFC 2069 we should support a missing qop. Tough. */
-
-    if (digest_request->qop && strcmp(digest_request->qop, QOP_AUTH) != 0) {
-        /* we received a qop option we didn't send */
-        debugs(29, 4, "authenticateDigestDecode: Invalid qop option received");
+    /* 2069 requirements */
+
+    /* do we have a username ? */
+    if (!username || username[0] == '\0') {
+        debugs(29, 2, "authenticateDigestDecode: Empty or not present username");
+        return authDigestLogUsername(username, digest_request);
+    }
+
+    /* do we have a realm ? */
+    if (!digest_request->realm || digest_request->realm[0] == '\0') {
+        debugs(29, 2, "authenticateDigestDecode: Empty or not present realm");
+        return authDigestLogUsername(username, digest_request);
+    }
+
+    /* and a nonce? */
+    if (!digest_request->nonceb64 || digest_request->nonceb64[0] == '\0') {
+        debugs(29, 2, "authenticateDigestDecode: Empty or not present nonce");
         return authDigestLogUsername(username, digest_request);
     }
 
     /* we can't check the URI just yet. We'll check it in the
-     * authenticate phase */
+     * authenticate phase, but needs to be given */
+    if (!digest_request->uri || digest_request->uri[0] == '\0') {
+        debugs(29, 2, "authenticateDigestDecode: Missing URI field");
+        return authDigestLogUsername(username, digest_request);
+    }
 
     /* is the response the correct length? */
-
     if (!digest_request->response || strlen(digest_request->response) != 32) {
-        debugs(29, 4, "authenticateDigestDecode: Response length invalid");
-        return authDigestLogUsername(username, digest_request);
-    }
-
-    /* do we have a username ? */
-    if (!username || username[0] == '\0') {
-        debugs(29, 4, "authenticateDigestDecode: Empty or not present username");
-        return authDigestLogUsername(username, digest_request);
-    }
-
-    /* check that we're not being hacked / the username hasn't changed */
-    if (nonce->user && strcmp(username, nonce->user->username())) {
-        debugs(29, 4, "authenticateDigestDecode: Username for the nonce does not equal the username for the request");
-        return authDigestLogUsername(username, digest_request);
-    }
-
-    /* if we got a qop, did we get a cnonce or did we get a cnonce wihtout a qop? */
-    if ((digest_request->qop && !digest_request->cnonce)
-            || (!digest_request->qop && digest_request->cnonce)) {
-        debugs(29, 4, "authenticateDigestDecode: qop without cnonce, or vice versa!");
+        debugs(29, 2, "authenticateDigestDecode: Response length invalid");
         return authDigestLogUsername(username, digest_request);
     }
 
@@ -1291,6 +1258,54 @@
         return authDigestLogUsername(username, digest_request);
     }
 
+    /* 2617 requirements, indicated by qop */
+    if (digest_request->qop) {
+
+	/* check the qop is what we expected. */
+	if (strcmp(digest_request->qop, QOP_AUTH) != 0) {
+	    /* we received a qop option we didn't send */
+	    debugs(29, 2, "authenticateDigestDecode: Invalid qop option received");
+	    return authDigestLogUsername(username, digest_request);
+	}
+
+	/* check cnonce */
+	if (!digest_request->cnonce || digest_request->cnonce[0] == '\0') {
+	    debugs(29, 2, "authenticateDigestDecode: Missing URI field");
+	    return authDigestLogUsername(username, digest_request);
+	}
+
+	/* check nc */
+	if (strlen(digest_request->nc) != 8 || strspn(digest_request->nc, "0123456789abcdefABCDEF") != 8) {
+	    debugs(29, 2, "authenticateDigestDecode: invalid nonce count");
+	    return authDigestLogUsername(username, digest_request);
+	}
+    } else {
+	/* cnonce and nc both require qop */
+	if (digest_request->cnonce || digest_request->nc) {
+	    debugs(29, 4, "authenticateDigestDecode: missing qop!");
+	    return authDigestLogUsername(username, digest_request);
+	}
+    }
+
+    /** below nonce state dependent **/
+
+    /* now the nonce */
+    nonce = authenticateDigestNonceFindNonce(digest_request->nonceb64);
+    if (!nonce) {
+        /* we couldn't find a matching nonce! */
+        debugs(29, 2, "authenticateDigestDecode: Unexpected or invalid nonce received");
+        return authDigestLogUsername(username, digest_request);
+    }
+
+    digest_request->nonce = nonce;
+    authDigestNonceLink(nonce);
+
+    /* check that we're not being hacked / the username hasn't changed */
+    if (nonce->user && strcmp(username, nonce->user->username())) {
+        debugs(29, 2, "authenticateDigestDecode: Username for the nonce does not equal the username for the request");
+        return authDigestLogUsername(username, digest_request);
+    }
+
     /* the method we'll check at the authenticate step as well */
 
 

# Begin bundle
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

