]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Parse external ACL key-pair in HelperReply
authorAmos Jeffries <squid3@treenet.co.nz>
Sat, 22 Sep 2012 09:08:28 +0000 (21:08 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Sat, 22 Sep 2012 09:08:28 +0000 (21:08 +1200)
Moves parsing of tag, user, password, message, and log key-pair to shared
helper parser. Enabling these keys to be implemented by other helpers.

Adds deprecation/unsupported warning to external ACL parser for other
key-pair.

TODO: support unknown key=pair in generic parser. At present the first
      unknown key will halt parsing of the whole line.

src/HelperReply.cc
src/HelperReply.h
src/external_acl.cc
src/helper.cc
src/helper.h

index daf9dcf929ab02a9c34d46e226198f7e1f422f07..7d8eecdcf8bff49069758f233de4e68c4f8a5dbd 100644 (file)
@@ -1,16 +1,13 @@
+/*
+ * DEBUG: section 84    Helper process maintenance
+ * AUTHOR: Amos Jeffries
+ */
 #include "squid.h"
 #include "HelperReply.h"
 #include "helper.h"
+#include "SquidString.h"
 
-#if 0
-HelperReply::HelperReply(const HelperReply &r) :
-        result(r.result)
-        other_(r.other()),
-{
-}
-#endif
-
-HelperReply::HelperReply(const char *buf, size_t len) :
+HelperReply::HelperReply(const char *buf, size_t len, bool urlQuoting) :
         result(HelperReply::Unknown),
         whichServer(NULL)
 {
@@ -56,6 +53,47 @@ HelperReply::HelperReply(const char *buf, size_t len) :
 
     // NULL-terminate so the helper callback handlers do not buffer-overrun
     other_.terminate();
+
+    bool found;
+    do {
+        found = false;
+        found |= parseKeyValue("tag=", 4, tag);
+        found |= parseKeyValue("user=", 5, user);
+        found |= parseKeyValue("password=", 9, password);
+        found |= parseKeyValue("message=", 8, message);
+        found |= parseKeyValue("log=", 8, log);
+    } while(found);
+
+    if (urlQuoting) {
+        // unescape the reply values
+        if (tag.hasContent())
+            rfc1738_unescape(tag.buf());
+        if (user.hasContent())
+            rfc1738_unescape(user.buf());
+        if (password.hasContent())
+            rfc1738_unescape(password.buf());
+        if (message.hasContent())
+            rfc1738_unescape(message.buf());
+        if (log.hasContent())
+            rfc1738_unescape(log.buf());
+    }
+}
+
+bool
+HelperReply::parseKeyValue(const char *key, size_t key_len, MemBuf &value)
+{
+    if (other().contentSize() > static_cast<mb_size_t>(key_len) && memcmp(other().content(), key, key_len) == 0) {
+        // parse the value out of the string. may be double-quoted
+        char *tmp = modifiableOther().content() + key_len;
+        const char *token = strwordtok(NULL, &tmp);
+        value.reset();
+        value.append(token,strlen(token));
+        const mb_size_t keyPairSize = tmp - other().content();
+        modifiableOther().consume(keyPairSize);
+        modifiableOther().consumeWhitespace();
+        return true;
+    }
+    return false;
 }
 
 std::ostream &
@@ -69,7 +107,7 @@ operator <<(std::ostream &os, const HelperReply &r)
         break;
     case HelperReply::Error:
         os << "ERR";
-        break; 
+        break;
     case HelperReply::BrokenHelper:
         os << "BH";
         break;
index 89d352a9c34d856921d73e12ecd5fe330964750d..e0f29ee1584f55279eddf4f7487d57d35a6036b1 100644 (file)
@@ -25,7 +25,7 @@ private:
 
 public:
     // create/parse details from the msg buffer provided
-    HelperReply(const char *buf, size_t len);
+    HelperReply(const char *buf, size_t len, bool urlQuoting = false);
     ~HelperReply() {}
 
     const MemBuf &other() const { return other_; }
@@ -36,6 +36,8 @@ public:
     /// and by token blob/arg parsing in Negotiate auth handler
     MemBuf &modifiableOther() const { return *const_cast<MemBuf*>(&other_); }
 
+    bool parseKeyValue(const char *key, size_t key_len, MemBuf &);
+
 public:
     /// The helper response 'result' field.
     enum Result_ {
@@ -51,7 +53,14 @@ public:
         NA
     } result;
 
-// TODO other key=pair values. when the callbacks actually use this object.
+    // some pre-determined keys
+    MemBuf tag;
+    MemBuf user;
+    MemBuf password;
+    MemBuf message;
+    MemBuf log;
+
+// TODO other (custom) key=pair values. when the callbacks actually use this object.
 // for now they retain their own parsing routines handling other()
 
     /// for stateful replies the responding helper 'server' needs to be preserved across callbacks
index a43274b6430f9d0e5a7685a64ce71e188dbf41ed..4caf7b40b37c69cc0a053881c5a547b6ef9c07fd 100644 (file)
@@ -1321,11 +1321,26 @@ externalAclHandleReply(void *data, const HelperReply &reply)
         entryData.result = ACCESS_ALLOWED;
     // XXX: handle other non-DENIED results better
 
+    if (reply.tag.hasContent())
+        entryData.tag = reply.tag;
+    if (reply.message.hasContent())
+        entryData.message = reply.message;
+    if (reply.log.hasContent())
+        entryData.log = reply.log;
+#if USE_AUTH
+    if (reply.user.hasContent())
+        entryData.user = reply.user;
+    if (reply.password.hasContent())
+        entryData.password = reply.password;
+#endif
+
+    // legacy reply parser
     if (reply.other().hasContent()) {
         char *temp = reply.modifiableOther().content();
         char *token = strwordtok(temp, &t);
 
         while ((token = strwordtok(NULL, &t))) {
+            debugs(82, DBG_IMPORTANT, "WARNING: key '" << token << "' is not supported by this Squid.");
             char *value = strchr(token, '=');
 
             if (value) {
@@ -1335,24 +1350,15 @@ externalAclHandleReply(void *data, const HelperReply &reply)
                 if (state->def->quote == external_acl::QUOTE_METHOD_URL)
                     rfc1738_unescape(value);
 
-                if (strcmp(token, "message") == 0)
-                    entryData.message = value;
-                else if (strcmp(token, "error") == 0)
+                if (strcmp(token, "error") == 0) {
                     entryData.message = value;
-                else if (strcmp(token, "tag") == 0)
-                    entryData.tag = value;
-                else if (strcmp(token, "log") == 0)
-                    entryData.log = value;
 #if USE_AUTH
-                else if (strcmp(token, "user") == 0)
-                    entryData.user = value;
-                else if (strcmp(token, "password") == 0)
-                    entryData.password = value;
-                else if (strcmp(token, "passwd") == 0)
+                } else if (strcmp(token, "passwd") == 0) {
                     entryData.password = value;
-                else if (strcmp(token, "login") == 0)
+                } else if (strcmp(token, "login") == 0) {
                     entryData.user = value;
 #endif
+                }
             }
         }
     }
@@ -1512,6 +1518,9 @@ externalAclInit(void)
 
         p->theHelper->addr = p->local_addr;
 
+        if (p->quote == external_acl::QUOTE_METHOD_URL)
+            p->theHelper->url_quoting = true;
+
         helperOpenServers(p->theHelper);
     }
 
index b955ea2ebfecc2f1b65bc432e909b69bf2958218..cad75bf0d7890546f84d1b640d5b092b8b8c66be 100644 (file)
@@ -834,7 +834,7 @@ helperReturnBuffer(int request_number, helper_server * srv, helper * hlp, char *
 
         void *cbdata = NULL;
         if (cbdataReferenceValidDone(r->data, &cbdata))
-            callback(cbdata, HelperReply(msg, (msg_end-msg)));
+            callback(cbdata, HelperReply(msg, (msg_end-msg), hlp->url_quoting));
 
         -- srv->stats.pending;
 
index 131ab991c3da09f260fcdb16abc06291431c04f6..2cf43f3bf33b729c380b880b29865f02ee39d3b0 100644 (file)
@@ -48,7 +48,7 @@ typedef void HLPCB(void *, const HelperReply &reply);
 class helper
 {
 public:
-    inline helper(const char *name) : cmdline(NULL), id_name(name), eom('\n') {}
+    inline helper(const char *name) : cmdline(NULL), id_name(name), eom('\n'), url_quoting(false) {}
     ~helper();
 
 public:
@@ -62,6 +62,7 @@ public:
     time_t last_queue_warn;
     time_t last_restart;
     char eom;   ///< The char which marks the end of (response) message, normally '\n'
+    bool url_quoting;
 
     struct _stats {
         int requests;