]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug 740: allow external acl's to use reply headers in format
authorAmos Jeffries <squid3@treenet.co.nz>
Tue, 23 Sep 2008 13:02:32 +0000 (01:02 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Tue, 23 Sep 2008 13:02:32 +0000 (01:02 +1200)
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.

src/cf.data.pre
src/external_acl.cc

index 70711a73080132b0a6ac03b4a188dfaa46afd814..e97e2ddf2aa634ace1bb2d8df00639cd7736c8eb 100644 (file)
@@ -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)
index 513904c315b560aa7644d9f4312dc0456b36fa34..3b8fa441d639e15228853df8be671288a7b45f60 100644 (file)
@@ -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: