]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Carefully verify digest responses
authorHenrik Nordstrom <henrik@henriknordstrom.net>
Tue, 2 Mar 2010 16:58:13 +0000 (17:58 +0100)
committerHenrik Nordstrom <henrik@henriknordstrom.net>
Tue, 2 Mar 2010 16:58:13 +0000 (17:58 +0100)
src/auth/digest/auth_digest.cc

index ceeb3d4fad0acfad7ff1fc61cca337d839bfbc47..5688ed15378e3505c15dd727029bfec96d425d66 100644 (file)
@@ -1197,7 +1197,7 @@ AuthDigestConfig::decode(char const *proxy_auth)
            break;
 
        default:
-            debugs(29, 2, "authDigestDecodeAuth: Unknown attribute '" << item << "' in '" << temp << "'");
+            debugs(29, 3, "authDigestDecodeAuth: Unknown attribute '" << item << "' in '" << temp << "'");
 
         }
     }
@@ -1216,73 +1216,93 @@ AuthDigestConfig::decode(char const *proxy_auth)
      * correct values - 400/401/407
      */
 
-    /* first the NONCE count */
+    /* 2069 requirements */
 
-    if (digest_request->cnonce && strlen(digest_request->nc) != 8) {
-        debugs(29, 4, "authenticateDigestDecode: nonce count length invalid");
+    /* do we have a username ? */
+    if (!username || username[0] == '\0') {
+        debugs(29, 2, "authenticateDigestDecode: Empty or not present username");
         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");
+    /* 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);
     }
 
-    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");
+    /* 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, but needs to be given */
-    if (!digest_request->uri) {
-        debugs(29, 4, "authenticateDigestDecode: Missing URI field");
+    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");
+        debugs(29, 2, "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");
+    /* check the algorithm is present and supported */
+    if (!digest_request->algorithm)
+        digest_request->algorithm = xstrndup("MD5", 4);
+    else if (strcmp(digest_request->algorithm, "MD5")
+             && strcmp(digest_request->algorithm, "MD5-sess")) {
+        debugs(29, 4, "authenticateDigestDecode: invalid algorithm specified!");
         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);
+    /* 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);
+       }
     }
 
-    /* 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!");
+    /** 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);
     }
 
-    /* check the algorithm is present and supported */
-    if (!digest_request->algorithm)
-        digest_request->algorithm = xstrndup("MD5", 4);
-    else if (strcmp(digest_request->algorithm, "MD5")
-             && strcmp(digest_request->algorithm, "MD5-sess")) {
-        debugs(29, 4, "authenticateDigestDecode: invalid algorithm specified!");
+    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);
     }