From: Amos Jeffries Date: Tue, 23 Sep 2008 13:02:32 +0000 (+1200) Subject: Bug 740: allow external acl's to use reply headers in format X-Git-Tag: SQUID_3_1_0_1~49^2~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b0ca1e8d8c937b776b70ecfd39334b144b2066f;p=thirdparty%2Fsquid.git Bug 740: allow external acl's to use reply headers in format Adds a small bit of token syntax to external_acl_type format. %>{Header} HTTP request header %>{Hdr:member} HTTP request header list member %>{Hdr:;member} HTTP request header list member using ; as list separator. ; can be any non-alphanumeric character. %<{Header} HTTP reply header %<{Hdr:member} HTTP reply header list member %<{Hdr:;member} HTTP reply header list member using ; as list separator. ; can be any non-alphanumeric character. Basically the < and > are new following the existing meaning of their direction in other tokens to match request/reply. Old format of %{} is left as request header but with WARNING (1) level noise at configure time indicating the new syntax. --- diff --git a/src/cf.data.pre b/src/cf.data.pre index 70711a7308..e97e2ddf2a 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -411,13 +411,23 @@ DOC_START %USER_CERTCHAIN SSL User certificate chain in PEM format %USER_CERT_xx SSL User certificate subject attribute xx %USER_CA_xx SSL User certificate issuer attribute xx - %{Header} HTTP request header - %{Hdr:member} HTTP request header list member - %{Hdr:;member} + + %>{Header} HTTP request header + %>{Hdr:member} + HTTP request header list member + %>{Hdr:;member} HTTP request header list member using ; as list separator. ; can be any non-alphanumeric character. + %<{Header} HTTP reply header + %<{Hdr:member} + HTTP reply header list member + %<{Hdr:;member} + HTTP reply header list member using ; as + list separator. ; can be any non-alphanumeric + character. + In addition to the above, any string specified in the referencing acl will also be included in the helper request line, after the specified formats (see the "acl external" directive) diff --git a/src/external_acl.cc b/src/external_acl.cc index 513904c315..3b8fa441d6 100644 --- a/src/external_acl.cc +++ b/src/external_acl.cc @@ -55,6 +55,7 @@ #endif #include "client_side.h" #include "HttpRequest.h" +#include "HttpReply.h" #include "authenticate.h" #include "helper.h" #include "MemBuf.h" @@ -149,10 +150,17 @@ struct _external_acl_format EXT_ACL_PORT, EXT_ACL_PATH, EXT_ACL_METHOD, - EXT_ACL_HEADER, - EXT_ACL_HEADER_MEMBER, - EXT_ACL_HEADER_ID, - EXT_ACL_HEADER_ID_MEMBER, + + EXT_ACL_HEADER_REQUEST, + EXT_ACL_HEADER_REQUEST_MEMBER, + EXT_ACL_HEADER_REQUEST_ID, + EXT_ACL_HEADER_REQUEST_ID_MEMBER, + + EXT_ACL_HEADER_REPLY, + EXT_ACL_HEADER_REPLY_MEMBER, + EXT_ACL_HEADER_REPLY_ID, + EXT_ACL_HEADER_REPLY_ID_MEMBER, + #if USE_SSL EXT_ACL_USER_CERT, EXT_ACL_CA_CERT, @@ -208,6 +216,66 @@ free_external_acl(void *data) hashFreeMemory(p->cache); } +/** + * Parse the External ACL format %<{.*} and %>{.*} token(s) to pass a specific + * request or reply header to external helper. + * + \param header - the token being parsed (without the identifying prefix) + \param type - format enum identifier for this element, pulled from identifying prefix + \param format - structure to contain all the info about this format element. + */ +void +parse_header_token(external_acl_format *format, char *header, const _external_acl_format type) +{ + /* header format */ + char *member, *end; + + /** Cut away the closing brace */ + end = strchr(header, '}'); + if (end && strlen(end) == 1) + *end = '\0'; + else + self_destruct(); + + member = strchr(header, ':'); + + if (member) { + /* Split in header and member */ + *member++ = '\0'; + + if (!xisalnum(*member)) + format->separator = *member++; + else + format->separator = ','; + + format->member = xstrdup(member); + + if(type == _external_acl_format::EXT_ACL_HEADER_REQUEST) + format->type = _external_acl_format::EXT_ACL_HEADER_REQUEST_MEMBER; + else + format->type = _external_acl_format::EXT_ACL_HEADER_REQUEST_MEMBER; + } else { + format->type = type; + } + + format->header = xstrdup(header); + format->header_id = httpHeaderIdByNameDef(header, strlen(header)); + + if (format->header_id != -1) { + if (member) { + if(type == _external_acl_format::EXT_ACL_HEADER_REQUEST) + format->type = _external_acl_format::EXT_ACL_HEADER_REQUEST_ID_MEMBER; + else + format->type = _external_acl_format::EXT_ACL_HEADER_REPLY_ID_MEMBER; + } else { + if(type == _external_acl_format::EXT_ACL_HEADER_REQUEST) + format->type = _external_acl_format::EXT_ACL_HEADER_REQUEST_ID; + else + format->type = _external_acl_format::EXT_ACL_HEADER_REPLY_ID; + } + } +} + void parse_externalAclHelper(external_acl ** list) { @@ -299,44 +367,15 @@ parse_externalAclHelper(external_acl ** list) format = cbdataAlloc(external_acl_format); if (strncmp(token, "%{", 2) == 0) { - /* header format */ - char *header, *member, *end; - header = token + 2; - end = strchr(header, '}'); - /* cut away the closing brace */ - - if (end && strlen(end) == 1) - *end = '\0'; - else - self_destruct(); - - member = strchr(header, ':'); - - if (member) { - /* Split in header and member */ - *member++ = '\0'; + // deprecated. but assume the old configs all referred to request headers. + debugs(82, DBG_IMPORTANT, "WARNING: external_acl_type format %{...} is being replaced by %>{...} for : " << token); + parse_header_token(format, (token+2), EXT_ACL_HEADER_REQUEST); - if (!xisalnum(*member)) - format->separator = *member++; - else - format->separator = ','; + if (strncmp(token, "%>{", 3) == 0) { + parse_header_token(format, (token+3), EXT_ACL_HEADER_REQUEST); + if (strncmp(token, "%<{", 3) == 0) { + parse_header_token(format, (token+3), EXT_ACL_HEADER_REPLY); - format->member = xstrdup(member); - - format->type = _external_acl_format::EXT_ACL_HEADER_MEMBER; - } else { - format->type = _external_acl_format::EXT_ACL_HEADER; - } - - format->header = xstrdup(header); - format->header_id = httpHeaderIdByNameDef(header, strlen(header)); - - if (format->header_id != -1) { - if (member) - format->type = _external_acl_format::EXT_ACL_HEADER_ID_MEMBER; - else - format->type = _external_acl_format::EXT_ACL_HEADER_ID; - } } else if (strcmp(token, "%LOGIN") == 0) { format->type = _external_acl_format::EXT_ACL_LOGIN; a->require_auth = true; @@ -782,6 +821,7 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data) wordlist *arg; external_acl_format *format; HttpRequest *request = ch->request; + HttpReply *reply = ch->reply; mb.reset(); for (format = acl_data->def->format; format; format = format->next) { @@ -850,25 +890,53 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data) str = RequestMethodStr(request->method); break; - case _external_acl_format::EXT_ACL_HEADER: + case _external_acl_format::EXT_ACL_HEADER_REQUEST: sb = request->header.getByName(format->header); str = sb.buf(); break; - case _external_acl_format::EXT_ACL_HEADER_ID: + case _external_acl_format::EXT_ACL_HEADER_REQUEST_ID: sb = request->header.getStrOrList(format->header_id); str = sb.buf(); break; - case _external_acl_format::EXT_ACL_HEADER_MEMBER: + case _external_acl_format::EXT_ACL_HEADER_REQUEST_MEMBER: sb = request->header.getByNameListMember(format->header, format->member, format->separator); str = sb.buf(); break; - case _external_acl_format::EXT_ACL_HEADER_ID_MEMBER: + case _external_acl_format::EXT_ACL_HEADER_REQUEST_ID_MEMBER: sb = request->header.getListMember(format->header_id, format->member, format->separator); str = sb.buf(); break; + + case _external_acl_format::EXT_ACL_HEADER_REPLY: + if(reply) { + sb = reply->header.getByName(format->header); + str = sb.buf(); + } + break; + + case _external_acl_format::EXT_ACL_HEADER_REPLY_ID: + if(reply) { + sb = reply->header.getStrOrList(format->header_id); + str = sb.buf(); + } + break; + + case _external_acl_format::EXT_ACL_HEADER_REPLY_MEMBER: + if(reply) { + sb = reply->header.getByNameListMember(format->header, format->member, format->separator); + str = sb.buf(); + } + break; + + case _external_acl_format::EXT_ACL_HEADER_REPLY_ID_MEMBER: + if(reply) { + sb = reply->header.getListMember(format->header_id, format->member, format->separator); + str = sb.buf(); + } + break; #if USE_SSL case _external_acl_format::EXT_ACL_USER_CERT_RAW: