You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bc...@apache.org on 2014/05/30 23:57:52 UTC

[2/6] git commit: [TS-1981] Adding arbitrary methods to url remap, and fix the same problem in IpAllow

[TS-1981] Adding arbitrary methods to url remap, and fix the same problem in IpAllow


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/0094d4b1
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/0094d4b1
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/0094d4b1

Branch: refs/heads/5.0.x
Commit: 0094d4b11091bba7496b19445c380ccb2443cda0
Parents: 923269b
Author: Brian Geffon <br...@apache.org>
Authored: Fri May 30 13:42:17 2014 -0700
Committer: Brian Geffon <br...@apache.org>
Committed: Fri May 30 13:42:17 2014 -0700

----------------------------------------------------------------------
 proxy/IPAllow.cc                 | 42 ++++++++++++++-------
 proxy/IPAllow.h                  | 69 ++++++++++++++++++++++-------------
 proxy/http/HttpClientSession.cc  |  2 +-
 proxy/http/HttpClientSession.h   |  5 ++-
 proxy/http/HttpSessionAccept.cc  |  8 ++--
 proxy/http/HttpTransact.cc       | 23 +++++++++---
 proxy/http/remap/AclFiltering.cc | 29 ++++++++++-----
 proxy/http/remap/AclFiltering.h  | 16 +++++---
 proxy/http/remap/RemapConfig.cc  | 49 ++++---------------------
 proxy/http/remap/UrlRewrite.cc   | 31 ++++++++++------
 10 files changed, 154 insertions(+), 120 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0094d4b1/proxy/IPAllow.cc
----------------------------------------------------------------------
diff --git a/proxy/IPAllow.cc b/proxy/IPAllow.cc
index de2a72f..bd8d81b 100644
--- a/proxy/IPAllow.cc
+++ b/proxy/IPAllow.cc
@@ -44,10 +44,7 @@ enum AclOp {
   ACL_OP_DENY, ///< Deny access.
 };
 
-// Mask for all methods.
-// This can't be computed properly at process start, so it's delayed
-// until the instance is initialized.
-uint32_t IpAllow::ALL_METHOD_MASK;
+const AclRecord IpAllow::ALL_METHOD_ACL(AclRecord::ALL_METHOD_MASK);
 
 int IpAllow::configid = 0;
 
@@ -138,8 +135,8 @@ IpAllow::Print() {
       s << " - " << ats_ip_ntop(spot->max(), text, sizeof text);
     }
     s << " method=";
-    uint32_t mask = ALL_METHOD_MASK & ar->_method_mask;
-    if (ALL_METHOD_MASK == mask) {
+    uint32_t mask = AclRecord::ALL_METHOD_MASK & ar->_method_mask;
+    if (AclRecord::ALL_METHOD_MASK == mask) {
       s << "ALL";
     } else if (0 == mask) {
       s << "NONE";
@@ -155,6 +152,18 @@ IpAllow::Print() {
         }
       }
     }
+    if (!ar->_nonstandard_methods.empty()) {
+      s << " nonstandard method=";
+      bool leader = false; // need leading vbar?
+      for (AclRecord::MethodSet::iterator iter = ar->_nonstandard_methods.begin(),
+             end = ar->_nonstandard_methods.end(); iter != end; ++iter) {
+        if (leader) {
+          s << '|';
+        }
+        s << *iter;
+        leader = true;
+      }
+    }
   }
   Debug("ip-allow", "%s", s.str().c_str());
 }
@@ -216,6 +225,8 @@ IpAllow::BuildTable()
           // Search for "action=ip_allow method=PURGE method=GET ..." or "action=ip_deny method=PURGE method=GET ...".
           char *label, *val;
           uint32_t acl_method_mask = 0;
+          AclRecord::MethodSet nonstandard_methods;
+          bool deny_nonstandard_methods = false;
           AclOp op = ACL_OP_DENY; // "shut up", I explained to the compiler.
           bool op_found = false, method_found = false;
           for (int i = 0; i < MATCHER_MAX_TOKENS; i++) {
@@ -248,30 +259,35 @@ IpAllow::BuildTable()
                     method_found = false;  // in case someone does method=GET|ALL
                     break;
                   } else {
-                    int method_idx = hdrtoken_tokenize(method_name, strlen(method_name));
+                    int method_name_len = strlen(method_name);
+                    int method_idx = hdrtoken_tokenize(method_name, method_name_len);
                     if (method_idx < HTTP_WKSIDX_CONNECT || method_idx >= HTTP_WKSIDX_CONNECT + HTTP_WKSIDX_METHODS_CNT) {
-                      Warning("Method name '%s' on line %d is not valid. Ignoring.", method_name, line_num);
+                      nonstandard_methods.insert(method_name);
+                      Debug("ip-allow", "Found nonstandard method [%s] on line %d", method_name, line_num);
                     } else { // valid method.
-                      method_found = true;
-                      acl_method_mask |= MethodIdxToMask(method_idx);
+                      acl_method_mask |= AclRecord::MethodIdxToMask(method_idx);
                     }
+                    method_found = true;
                   }
                 }
               }
             }
             // If method not specified, default to ALL
             if (!method_found) {
-              method_found = true, acl_method_mask = ALL_METHOD_MASK;
+              method_found = true;
+              acl_method_mask = AclRecord::ALL_METHOD_MASK;
+              nonstandard_methods.clear();
             }
             // When deny, use bitwise complement.  (Make the rule 'allow for all
             // methods except those specified')
             if (op == ACL_OP_DENY) {
-              acl_method_mask = ALL_METHOD_MASK & ~acl_method_mask;
+              acl_method_mask = AclRecord::ALL_METHOD_MASK & ~acl_method_mask;
+              deny_nonstandard_methods = true;
             }
           }
 
           if (method_found) {
-            _acls.push_back(AclRecord(acl_method_mask, line_num));
+            _acls.push_back(AclRecord(acl_method_mask, line_num, nonstandard_methods, deny_nonstandard_methods));
             // Color with index because at this point the address
             // is volatile.
             _map.fill(

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0094d4b1/proxy/IPAllow.h
----------------------------------------------------------------------
diff --git a/proxy/IPAllow.h b/proxy/IPAllow.h
index 2c2d232..695d351 100644
--- a/proxy/IPAllow.h
+++ b/proxy/IPAllow.h
@@ -37,6 +37,9 @@
 #include "ts/Vec.h"
 #include "ProxyConfig.h"
 
+#include <string>
+#include <set>
+
 // forward declare in name only so it can be a friend.
 struct IpAllowUpdate;
 
@@ -51,14 +54,41 @@ static uint64_t const IP_ALLOW_TIMEOUT = HRTIME_HOUR;
     It has the methods permitted and the source line.
 */
 struct AclRecord {
-  int _method_mask;
+  uint32_t _method_mask;
   int _src_line;
+  typedef std::set<std::string> MethodSet;
+  MethodSet _nonstandard_methods;
+  bool _deny_nonstandard_methods;
+  static const uint32_t ALL_METHOD_MASK = ~0; // Mask for all methods.
 
   /// Default constructor.
   /// Present only to make Vec<> happy, do not use.
-  AclRecord() : _method_mask(0), _src_line(0) { }
+  AclRecord() : _method_mask(0), _src_line(0), _deny_nonstandard_methods(false) { }
+
+  AclRecord(uint32_t method_mask) : _method_mask(method_mask), _src_line(0),
+                                    _deny_nonstandard_methods(false) { }
+
+  AclRecord(uint32_t method_mask, int ln, const MethodSet &nonstandard_methods, bool deny_nonstandard_methods)
+    : _method_mask(method_mask), _src_line(ln), _nonstandard_methods(nonstandard_methods),
+      _deny_nonstandard_methods(deny_nonstandard_methods) { }
+
+  static uint32_t MethodIdxToMask(int wksidx) { return 1 << (wksidx - HTTP_WKSIDX_CONNECT); }
 
-  AclRecord(uint32_t method_mask, int ln) : _method_mask(method_mask), _src_line(ln) { }
+  bool isEmpty() const {
+    return (_method_mask == 0) && _nonstandard_methods.empty();
+  }
+
+  bool isMethodAllowed(int method_wksidx) const {
+    return _method_mask & MethodIdxToMask(method_wksidx);
+  }
+  
+  bool isNonstandardMethodAllowed(const std::string &method_str) const {
+    if (_method_mask == ALL_METHOD_MASK) {
+      return true;
+    }
+    bool method_in_set = _nonstandard_methods.count(method_str);
+    return _deny_nonstandard_methods ? !method_in_set : method_in_set;
+  }
 };
 
 /** Singleton class for access controls.
@@ -74,8 +104,8 @@ public:
   IpAllow(const char *config_var, const char *name, const char *action_val);
    ~IpAllow();
   void Print();
-  uint32_t match(IpEndpoint const* ip) const;
-  uint32_t match(sockaddr const* ip) const;
+  AclRecord *match(IpEndpoint const* ip) const;
+  AclRecord *match(sockaddr const* ip) const;
 
   static void startup();
   static void reconfigure();
@@ -83,18 +113,16 @@ public:
   static IpAllow * acquire();
   static void release(IpAllow * params);
 
-  static bool CheckMask(uint32_t, int);
   /// @return A mask that permits all methods.
-  static uint32_t AllMethodMask() {
-    return ALL_METHOD_MASK;
+  static const AclRecord *AllMethodAcl() {
+    return &ALL_METHOD_ACL;
   }
 
   typedef ConfigProcessor::scoped_config<IpAllow, IpAllow> scoped_config;
 
 private:
-  static uint32_t MethodIdxToMask(int);
-  static uint32_t ALL_METHOD_MASK;
   static int configid;
+  static const AclRecord ALL_METHOD_ACL;
 
   int BuildTable();
 
@@ -105,29 +133,18 @@ private:
   Vec<AclRecord> _acls;
 };
 
-inline uint32_t IpAllow::MethodIdxToMask(int idx) { return 1 << (idx - HTTP_WKSIDX_CONNECT); }
-
-inline uint32_t
+inline AclRecord *
 IpAllow::match(IpEndpoint const* ip) const {
   return this->match(&ip->sa);
 }
 
-inline uint32_t
+inline AclRecord *
 IpAllow::match(sockaddr const* ip) const {
-  uint32_t zret = 0;
-  void* raw;
+  void *raw;
   if (_map.contains(ip, &raw)) {
-    AclRecord* acl = static_cast<AclRecord*>(raw);
-    if (acl) {
-      zret = acl->_method_mask;
-    }
+    return static_cast<AclRecord*>(raw);
   }
-  return zret;
-}
-
-inline bool
-IpAllow::CheckMask(uint32_t mask, int method_idx) {
-  return ((mask & MethodIdxToMask(method_idx)) != 0);
+  return NULL;
 }
 
 #endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0094d4b1/proxy/http/HttpClientSession.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpClientSession.cc b/proxy/http/HttpClientSession.cc
index 1239113..9952cf1 100644
--- a/proxy/http/HttpClientSession.cc
+++ b/proxy/http/HttpClientSession.cc
@@ -68,7 +68,7 @@ HttpClientSession::HttpClientSession()
     cur_hooks(0), backdoor_connect(false),
     hooks_set(0),
     outbound_port(0), f_outbound_transparent(false),
-    host_res_style(HOST_RES_IPV4), acl_method_mask(0),
+    host_res_style(HOST_RES_IPV4), acl_record(NULL),
     m_active(false), debug_on(false)
 {
   memset(user_args, 0, sizeof(user_args));

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0094d4b1/proxy/http/HttpClientSession.h
----------------------------------------------------------------------
diff --git a/proxy/http/HttpClientSession.h b/proxy/http/HttpClientSession.h
index 8daf04f..cb4c5ba 100644
--- a/proxy/http/HttpClientSession.h
+++ b/proxy/http/HttpClientSession.h
@@ -37,6 +37,7 @@
 #include "InkAPIInternal.h"
 #include "HTTP.h"
 #include "HttpConfig.h"
+#include "IPAllow.h"
 
 extern ink_mutex debug_cs_list_mutex;
 
@@ -152,8 +153,8 @@ public:
   bool f_transparent_passthrough;
   /// DNS resolution preferences.
   HostResStyle host_res_style;
-  /// acl method mask - cache IpAllow::match() call
-  uint32_t acl_method_mask;
+  /// acl record - cache IpAllow::match() call
+  const AclRecord *acl_record;
 
   // for DI. An active connection is one that a request has
   // been successfully parsed (PARSE_DONE) and it remains to

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0094d4b1/proxy/http/HttpSessionAccept.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSessionAccept.cc b/proxy/http/HttpSessionAccept.cc
index e485764..942a215 100644
--- a/proxy/http/HttpSessionAccept.cc
+++ b/proxy/http/HttpSessionAccept.cc
@@ -31,15 +31,15 @@ void
 HttpSessionAccept::accept(NetVConnection * netvc, MIOBuffer * iobuf, IOBufferReader * reader)
 {
   sockaddr const* client_ip = netvc->get_remote_addr();
-  uint32_t acl_method_mask = 0;
+  const AclRecord *acl_record = NULL;
   ip_port_text_buffer ipb;
   IpAllow::scoped_config ipallow;
 
   // The backdoor port is now only bound to "localhost", so no
   // reason to check for if it's incoming from "localhost" or not.
   if (backdoor) {
-    acl_method_mask = IpAllow::AllMethodMask();
-  } else if (ipallow && ((acl_method_mask = ipallow->match(client_ip)) == 0)) {
+    acl_record = IpAllow::AllMethodAcl();
+  } else if (ipallow && (((acl_record = ipallow->match(client_ip)) == NULL) || (acl_record->isEmpty()))) {
     ////////////////////////////////////////////////////
     // if client address forbidden, close immediately //
     ////////////////////////////////////////////////////
@@ -64,7 +64,7 @@ HttpSessionAccept::accept(NetVConnection * netvc, MIOBuffer * iobuf, IOBufferRea
   new_session->outbound_ip6 = outbound_ip6;
   new_session->outbound_port = outbound_port;
   new_session->host_res_style = ats_host_res_from(client_ip->sa_family, host_res_preference);
-  new_session->acl_method_mask = acl_method_mask;
+  new_session->acl_record = acl_record;
 
   new_session->new_connection(netvc, backdoor, iobuf, reader);
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0094d4b1/proxy/http/HttpTransact.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index 9efb233..7d028f8 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -6497,12 +6497,25 @@ HttpTransact::process_quick_http_filter(State* s, int method)
     return;
   }
 
-  if (s->state_machine->ua_session && (!IpAllow::CheckMask(s->state_machine->ua_session->acl_method_mask, method))) {
-    if (is_debug_tag_set("ip-allow")) {
-      ip_text_buffer ipb;
-      Debug("ip-allow", "Quick filter denial on %s:%s with mask %x", ats_ip_ntop(&s->client_info.addr.sa, ipb, sizeof(ipb)), hdrtoken_index_to_wks(method), s->state_machine->ua_session->acl_method_mask);
+  if (s->state_machine->ua_session) {
+    const AclRecord *acl_record = s->state_machine->ua_session->acl_record;
+    bool deny_request = (acl_record == NULL);
+    if (acl_record && (acl_record->_method_mask != AclRecord::ALL_METHOD_MASK)) {
+      if (method != -1) {
+        deny_request = !acl_record->isMethodAllowed(method);
+      } else {
+        int method_str_len;
+        const char *method_str = s->hdr_info.client_request.method_get(&method_str_len);
+        deny_request = !acl_record->isNonstandardMethodAllowed(std::string(method_str, method_str_len));
+      }
+    }
+    if (deny_request) {
+      if (is_debug_tag_set("ip-allow")) {
+        ip_text_buffer ipb;
+        Debug("ip-allow", "Quick filter denial on %s:%s with mask %x", ats_ip_ntop(&s->client_info.addr.sa, ipb, sizeof(ipb)), hdrtoken_index_to_wks(method), acl_record->_method_mask);
+      }
+      s->client_connection_enabled = false;
     }
-    s->client_connection_enabled = false;
   }
 }
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0094d4b1/proxy/http/remap/AclFiltering.cc
----------------------------------------------------------------------
diff --git a/proxy/http/remap/AclFiltering.cc b/proxy/http/remap/AclFiltering.cc
index 105eeff..79d6954 100644
--- a/proxy/http/remap/AclFiltering.cc
+++ b/proxy/http/remap/AclFiltering.cc
@@ -24,6 +24,7 @@
 #include "AclFiltering.h"
 #include "Main.h"
 #include "Error.h"
+#include "HTTP.h"
 
 // ===============================================================================
 //                              acl_filter_rule
@@ -36,11 +37,11 @@ acl_filter_rule::reset(void)
   for (i = (argc = 0); i < ACL_FILTER_MAX_ARGV; i++) {
     argv[i] = (char *)ats_free_null(argv[i]);
   }
-  for (i = (method_cnt = 0); i < ACL_FILTER_MAX_METHODS; i++) {
-    method_array[i] = 0;
-    method_idx[i] = 0;
+  method_restriction_enabled = false;
+  for (i = 0; i < HTTP_WKSIDX_METHODS_CNT; i++) {
+    standard_method_lookup[i] = false;
   }
-  method_valid = 0;
+  nonstandard_methods.clear();
   for (i = (src_ip_cnt = 0); i < ACL_FILTER_MAX_SRC_IP; i++) {
     src_ip_array[i].reset();
   }
@@ -48,8 +49,9 @@ acl_filter_rule::reset(void)
 }
 
 acl_filter_rule::acl_filter_rule():next(NULL), filter_name_size(0), filter_name(NULL), allow_flag(1),
-method_valid(0), src_ip_valid(0), active_queue_flag(0), argc(0)
+src_ip_valid(0), active_queue_flag(0), argc(0)
 {
+  standard_method_lookup.resize(HTTP_WKSIDX_METHODS_CNT);
   ink_zero(argv);
   reset();
 }
@@ -91,12 +93,19 @@ acl_filter_rule::print(void)
 {
   int i;
   printf("-----------------------------------------------------------------------------------------\n");
-  printf("Filter \"%s\" status: allow_flag=%d, method_valid=%d, src_ip_valid=%d, active_queue_flag=%d\n",
-         filter_name ? filter_name : "<NONAME>", (int) allow_flag, (int) method_valid,
+  printf("Filter \"%s\" status: allow_flag=%d, src_ip_valid=%d, active_queue_flag=%d\n",
+         filter_name ? filter_name : "<NONAME>", (int) allow_flag,
          (int) src_ip_valid, (int) active_queue_flag);
-  printf("method_cnt=%d %s", method_cnt, method_cnt > 0 ? ": " : "");
-  for (i = 0; i < method_cnt; i++)
-    printf("0x%X ", method_array[i]);
+  printf("standard methods=");
+  for (i = 0; i < HTTP_WKSIDX_METHODS_CNT; i++) {
+    if (standard_method_lookup[i]) {
+      printf("0x%x ", HTTP_WKSIDX_CONNECT + i);
+    }
+  }
+  printf("nonstandard methods=");
+  for (MethodMap::iterator iter = nonstandard_methods.begin(), end = nonstandard_methods.end(); iter != end; ++iter) {
+    printf("%s ", iter->c_str());
+  }
   printf("\n");
   printf("src_ip_cnt=%d\n", src_ip_cnt);
   for (i = 0; i < src_ip_cnt; i++) {

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0094d4b1/proxy/http/remap/AclFiltering.h
----------------------------------------------------------------------
diff --git a/proxy/http/remap/AclFiltering.h b/proxy/http/remap/AclFiltering.h
index 4dd684a..a8d187a 100644
--- a/proxy/http/remap/AclFiltering.h
+++ b/proxy/http/remap/AclFiltering.h
@@ -27,10 +27,13 @@
 #include "Main.h"
 //#include "YAddr.h"
 
+#include <string>
+#include <set>
+#include <vector>
+
 // ===============================================================================
 // ACL like filtering defs (per one remap rule)
 
-static int const ACL_FILTER_MAX_METHODS = 16;
 static int const ACL_FILTER_MAX_SRC_IP = 128;
 static int const ACL_FILTER_MAX_ARGV = 512;
 
@@ -64,7 +67,6 @@ public:
   int filter_name_size;         // size of optional filter name
   char *filter_name;            // optional filter name
   unsigned int allow_flag:1,    // action allow deny
-    method_valid:1,             // method valid for verification
     src_ip_valid:1,             // src_ip range valid
     active_queue_flag:1;        // filter is in active state (used by .useflt directive)
 
@@ -72,10 +74,12 @@ public:
   int argc;                     // argument counter (only for filter defs)
   char *argv[ACL_FILTER_MAX_ARGV];      // argument strings (only for filter defs)
 
-  // method
-  int method_cnt;               // how many valid methods we have
-  int method_array[ACL_FILTER_MAX_METHODS];     // any HTTP method (actually only WKSIDX from HTTP.cc)
-  int method_idx[ACL_FILTER_MAX_METHODS];       // HTTP method index (actually method flag)
+  // methods
+  bool method_restriction_enabled;
+  std::vector<bool> standard_method_lookup;
+
+  typedef std::set<std::string> MethodMap;
+  MethodMap nonstandard_methods;
 
   // src_ip
   int src_ip_cnt;               // how many valid src_ip rules we have

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0094d4b1/proxy/http/remap/RemapConfig.cc
----------------------------------------------------------------------
diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc
index 0961da6..70fdbb7 100644
--- a/proxy/http/remap/RemapConfig.cc
+++ b/proxy/http/remap/RemapConfig.cc
@@ -390,18 +390,9 @@ remap_validate_filter_args(acl_filter_rule ** rule_pp, const char ** argv, int a
     }
 
     if (ul & REMAP_OPTFLG_METHOD) {     /* "method=" option */
-      if (rule->method_cnt >= ACL_FILTER_MAX_METHODS) {
-        Debug("url_rewrite", "[validate_filter_args] Too many \"method=\" filters");
-        snprintf(errStrBuf, errStrBufSize, "Defined more than %d \"method=\" filters!", ACL_FILTER_MAX_METHODS);
-        errStrBuf[errStrBufSize - 1] = 0;
-        if (new_rule_flg) {
-          delete rule;
-          *rule_pp = NULL;
-        }
-        return (const char *) errStrBuf;
-      }
       // Please remember that the order of hash idx creation is very important and it is defined
       // in HTTP.cc file
+      m = -1;
       if (!strcasecmp(argptr, "CONNECT"))
         m = HTTP_WKSIDX_CONNECT;
       else if (!strcasecmp(argptr, "DELETE"))
@@ -424,38 +415,14 @@ remap_validate_filter_args(acl_filter_rule ** rule_pp, const char ** argv, int a
         m = HTTP_WKSIDX_TRACE;
       else if (!strcasecmp(argptr, "PUSH"))
         m = HTTP_WKSIDX_PUSH;
-      else {
-        Debug("url_rewrite", "[validate_filter_args] Unknown method value %s", argptr);
-        snprintf(errStrBuf, errStrBufSize, "Unknown method \"%s\"", argptr);
-        errStrBuf[errStrBufSize - 1] = 0;
-        if (new_rule_flg) {
-          delete rule;
-          *rule_pp = NULL;
-        }
-        return (const char *) errStrBuf;
-      }
-      for (j = 0; j < rule->method_cnt; j++) {
-        if (rule->method_array[j] == m) {
-          m = 0;
-          break;                /* we already have it in the list */
-        }
-      }
-      if ((j = m) != 0) {
-        j = j - HTTP_WKSIDX_CONNECT;    // get method index
-        if (j<0 || j>= ACL_FILTER_MAX_METHODS) {
-          Debug("url_rewrite", "[validate_filter_args] Incorrect method index! Method sequence in HTTP.cc is broken");
-          snprintf(errStrBuf, errStrBufSize, "Incorrect method index %d", j);
-          errStrBuf[errStrBufSize - 1] = 0;
-          if (new_rule_flg) {
-            delete rule;
-            *rule_pp = NULL;
-          }
-          return (const char *) errStrBuf;
-        }
-        rule->method_idx[j] = m;
-        rule->method_array[rule->method_cnt++] = m;
-        rule->method_valid = 1;
+      if (m != -1) {
+        m = m - HTTP_WKSIDX_CONNECT;    // get method index
+        rule->standard_method_lookup[m] = true;
+      } else {
+        Debug("url_rewrite", "[validate_filter_args] Using nonstandard method [%s]", argptr);
+        rule->nonstandard_methods.insert(argptr);
       }
+      rule->method_restriction_enabled = true;
     } else if (ul & REMAP_OPTFLG_SRC_IP) {      /* "src_ip=" option */
       if (rule->src_ip_cnt >= ACL_FILTER_MAX_SRC_IP) {
         Debug("url_rewrite", "[validate_filter_args] Too many \"src_ip=\" filters");

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0094d4b1/proxy/http/remap/UrlRewrite.cc
----------------------------------------------------------------------
diff --git a/proxy/http/remap/UrlRewrite.cc b/proxy/http/remap/UrlRewrite.cc
index ab61b3b..549add6 100644
--- a/proxy/http/remap/UrlRewrite.cc
+++ b/proxy/http/remap/UrlRewrite.cc
@@ -425,18 +425,21 @@ UrlRewrite::PerformACLFiltering(HttpTransact::State *s, url_mapping *map)
   s->acl_filtering_performed = true;    // small protection against reverse mapping
 
   if (map->filter) {
-    int i, res, method;
-    i = (method = s->hdr_info.client_request.method_get_wksidx()) - HTTP_WKSIDX_CONNECT;
+    int res;
+    int method = s->hdr_info.client_request.method_get_wksidx();
+    int method_wksidx = (method != -1) ? (method - HTTP_WKSIDX_CONNECT) : -1;
     bool client_enabled_flag = true;
     ink_release_assert(ats_is_ip(&s->client_info.addr));
-    for (acl_filter_rule * rp = map->filter; rp && client_enabled_flag; rp = rp->next) { // stop as soon as a filter denies
+    for (acl_filter_rule * rp = map->filter; rp; rp = rp->next) {
       bool match = true;
-      if (rp->method_valid) {
-        if (likely(i >= 0 && i < ACL_FILTER_MAX_METHODS)) {
-            match = rp->method_idx[i] == method;
+      if (rp->method_restriction_enabled) {
+        if (method_wksidx != -1) {
+          match = rp->standard_method_lookup[method_wksidx];
         }
-        else {
-            match = false;
+        else if (!rp->nonstandard_methods.empty()) {
+          int method_str_len;
+          const char *method_str = s->hdr_info.client_request.method_get(&method_str_len);
+          match = rp->nonstandard_methods.count(std::string(method_str, method_str_len));
         }
       }
       if (match && rp->src_ip_valid) {
@@ -452,14 +455,18 @@ UrlRewrite::PerformACLFiltering(HttpTransact::State *s, url_mapping *map)
           }
         }
       }
-      if (match) {
+      if (match && client_enabled_flag) {     //make sure that a previous filter did not DENY
         Debug("url_rewrite", "matched ACL filter rule, %s request", rp->allow_flag ? "allowing" : "denying");
         client_enabled_flag = rp->allow_flag ? true : false;
       } else {
-        Debug("url_rewrite", "did NOT match ACL filter rule, %s request", rp->allow_flag ? "denying" : "allowing");
-        client_enabled_flag = rp->allow_flag ? false : true;
+        if (!client_enabled_flag) {
+          Debug("url_rewrite", "Previous ACL filter rule denied request, continuing to deny it");
+        } else {
+          Debug("url_rewrite", "did NOT match ACL filter rule, %s request", rp->allow_flag ? "denying" : "allowing");
+          client_enabled_flag = rp->allow_flag ? false : true;
+        }
       }
-
+      
     }                         /* end of for(rp = map->filter;rp;rp = rp->next) */
     s->client_connection_enabled = client_enabled_flag;
   }