From: Amos Jeffries Date: Sat, 22 Sep 2012 09:08:28 +0000 (+1200) Subject: Parse external ACL key-pair in HelperReply X-Git-Tag: SQUID_3_4_0_1~471^2~22 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ab332e279a3fafc75080218b58e96d54270f42d2;p=thirdparty%2Fsquid.git Parse external ACL key-pair in HelperReply 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. --- diff --git a/src/HelperReply.cc b/src/HelperReply.cc index daf9dcf929..7d8eecdcf8 100644 --- a/src/HelperReply.cc +++ b/src/HelperReply.cc @@ -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(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; diff --git a/src/HelperReply.h b/src/HelperReply.h index 89d352a9c3..e0f29ee158 100644 --- a/src/HelperReply.h +++ b/src/HelperReply.h @@ -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(&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 diff --git a/src/external_acl.cc b/src/external_acl.cc index a43274b643..4caf7b40b3 100644 --- a/src/external_acl.cc +++ b/src/external_acl.cc @@ -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); } diff --git a/src/helper.cc b/src/helper.cc index b955ea2ebf..cad75bf0d7 100644 --- a/src/helper.cc +++ b/src/helper.cc @@ -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; diff --git a/src/helper.h b/src/helper.h index 131ab991c3..2cf43f3bf3 100644 --- a/src/helper.h +++ b/src/helper.h @@ -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;