]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Upgrade Digest authentication to use key=value parameters
authorAmos Jeffries <squid3@treenet.co.nz>
Fri, 9 Nov 2012 04:23:08 +0000 (17:23 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 9 Nov 2012 04:23:08 +0000 (17:23 +1300)
* Update the Digest auth code in Squid to process the HelperReply key-pair
  notes list for data
+ output upgrade WARNING messages when old format responses are identified
+ handle TT result code (as an error with critical level ERROR message)
+ handle BH result code (as an error)

* Adds a ha1="" key to Digest auth response protocol to pass the HA1.

* Upgrade the Digest helpers to use OK/ERR/BH result codes and key=value
  parameters.

helpers/digest_auth/LDAP/digest_pw_auth.cc
helpers/digest_auth/eDirectory/digest_pw_auth.cc
helpers/digest_auth/file/digest_file_auth.cc
src/auth/digest/UserRequest.cc

index ebf6ea1c4e22842b826aab4f69b56f2a8517e793..0dd29c9ddcdbfd567e8ce38db3d0e0080e850f14 100644 (file)
@@ -64,10 +64,10 @@ OutputHHA1(RequestData * requestData)
     requestData->error = 0;
     GetHHA1(requestData);
     if (requestData->error) {
-        SEND_ERR("No such user");
+        SEND_ERR("message=\"No such user\"");
         return;
     }
-    printf("%s\n", requestData->HHA1);
+    printf("OK ha1=\"%s\"\n", requestData->HHA1);
 }
 
 static void
@@ -76,7 +76,7 @@ DoOneRequest(char *buf)
     RequestData requestData;
     ParseBuffer(buf, &requestData);
     if (!requestData.parsed) {
-        SEND_ERR("");
+        SEND_BH("message=\"Invalid line received\"");
         return;
     }
     OutputHHA1(&requestData);
index 6087df6cfdbbd632419966d9f44f5527cd400b5b..2640ac8dbaf3b3dd8d5d03fe545a3eb620f8ffc6 100644 (file)
@@ -64,10 +64,10 @@ OutputHHA1(RequestData * requestData)
     requestData->error = 0;
     GetHHA1(requestData);
     if (requestData->error) {
-        SEND_ERR("No such user");
+        SEND_ERR("message=\"No such user\"");
         return;
     }
-    printf("%s\n", requestData->HHA1);
+    printf("OK ha1=\"%s\"\n", requestData->HHA1);
 }
 
 static void
@@ -76,7 +76,7 @@ DoOneRequest(char *buf)
     RequestData requestData;
     ParseBuffer(buf, &requestData);
     if (!requestData.parsed) {
-        SEND_ERR("");
+        SEND_BH("message=\"Invalid line received\"");
         return;
     }
     OutputHHA1(&requestData);
index b0ed8be907ca1a3eb837fc5daccfa065236caf7a..0839ffe32e0fc688705eff89c95e672769de64e6 100644 (file)
@@ -38,8 +38,6 @@
 #include "helpers/defines.h"
 #include "text_backend.h"
 
-#define PROGRAM_NAME "digest_file_auth"
-
 static void
 GetHHA1(RequestData * requestData)
 {
@@ -68,10 +66,10 @@ OutputHHA1(RequestData * requestData)
     requestData->error = 0;
     GetHHA1(requestData);
     if (requestData->error) {
-        SEND_ERR("No such user");
+        SEND_ERR("message=\"No such user\"");
         return;
     }
-    printf("%s\n", requestData->HHA1);
+    printf("OK ha1=\"%s\"\n", requestData->HHA1);
 }
 
 static void
@@ -80,7 +78,7 @@ DoOneRequest(char *buf)
     RequestData requestData;
     ParseBuffer(buf, &requestData);
     if (!requestData.parsed) {
-        SEND_ERR("");
+        SEND_BH("message=\"Invalid line received\"");
         return;
     }
     OutputHHA1(&requestData);
index cd2386696701902c58cd4658a7b799b9168ea973..ea4c3e2df3c8f67d4556ce6d2f3b6140e39acbb3 100644 (file)
@@ -280,33 +280,69 @@ Auth::Digest::UserRequest::HandleReply(void *data, const HelperReply &reply)
     assert(replyData->auth_user_request != NULL);
     Auth::UserRequest::Pointer auth_user_request = replyData->auth_user_request;
 
+    static bool oldHelperWarningDone = false;
     switch (reply.result) {
-    case HelperReply::Error: {
-        /* allow this because the digest_request pointer is purely local */
-        Auth::Digest::UserRequest *digest_request = dynamic_cast<Auth::Digest::UserRequest *>(auth_user_request.getRaw());
-        assert(digest_request);
+    case HelperReply::Unknown: {
+        // Squid 3.3 and older the digest helper only returns a HA1 hash (no "OK")
+        // the HA1 will be found in content() for these responses.
+        if (!oldHelperWarningDone) {
+            debugs(29, DBG_IMPORTANT, "WARNING: Digest auth helper returned old format HA1 response. It needs to be upgraded.");
+            oldHelperWarningDone=true;
+        }
 
-        digest_request->user()->credentials(Auth::Failed);
-        digest_request->flags.invalid_password = 1;
+        /* allow this because the digest_request pointer is purely local */
+        Auth::Digest::User *digest_user = dynamic_cast<Auth::Digest::User *>(auth_user_request->user().getRaw());
+        assert(digest_user != NULL);
 
-        if (reply.other().hasContent())
-            digest_request->setDenyMessage(reply.other().content());
+        CvtBin(reply.other().content(), digest_user->HA1);
+        digest_user->HA1created = 1;
     }
     break;
 
-    case HelperReply::Unknown: // Squid 3.2 and older the digest helper only returns a HA1 hash (no "OK")
     case HelperReply::Okay: {
         /* allow this because the digest_request pointer is purely local */
         Auth::Digest::User *digest_user = dynamic_cast<Auth::Digest::User *>(auth_user_request->user().getRaw());
         assert(digest_user != NULL);
 
-        CvtBin(reply.other().content(), digest_user->HA1);
-        digest_user->HA1created = 1;
+        Note::Pointer ha1Note = reply.responseKeys.findByName("ha1");
+        if (ha1Note != NULL) {
+            CvtBin(ha1Note->values[0]->value.termedBuf(), digest_user->HA1);
+            digest_user->HA1created = 1;
+        } else {
+            debugs(29, DBG_IMPORTANT, "ERROR: Digest auth helper did not produce a HA1. Using the wrong helper program? received: " << reply);
+        }
     }
     break;
 
-    default:
-        ; // XXX: handle other states properly.
+    case HelperReply::TT:
+        debugs(29, DBG_IMPORTANT, "ERROR: Digest auth does not support the result code received. Using the wrong helper program? received: " << reply);
+        // fall through to next case. Handle this as an ERR response.
+
+    case HelperReply::BrokenHelper:
+        // TODO retry the broken lookup on another helper?
+        // fall through to next case for now. Handle this as an ERR response silently.
+
+    case HelperReply::Error: {
+        /* allow this because the digest_request pointer is purely local */
+        Auth::Digest::UserRequest *digest_request = dynamic_cast<Auth::Digest::UserRequest *>(auth_user_request.getRaw());
+        assert(digest_request);
+
+        digest_request->user()->credentials(Auth::Failed);
+        digest_request->flags.invalid_password = 1;
+
+        Note::Pointer msgNote = reply.responseKeys.findByName("message");
+        if (msgNote != NULL) {
+            digest_request->setDenyMessage(msgNote->values[0]->value.termedBuf());
+        } else if (reply.other().hasContent()) {
+            // old helpers did send ERR result but a bare message string instead of message= key name.
+            digest_request->setDenyMessage(reply.other().content());
+            if (!oldHelperWarningDone) {
+                debugs(29, DBG_IMPORTANT, "WARNING: Digest auth helper returned old format ERR response. It needs to be upgraded.");
+                oldHelperWarningDone=true;
+            }
+        }
+    }
+    break;
     }
 
     void *cbdata = NULL;