Repository: trafficserver Updated Branches: refs/heads/master 105a0c610 -> 2cfed613f
TS-3300: add a @internal ACL filter Add support for the @internal ACL filter operator. This allows remap ACLs to filter on whether a request is internal or not, allowing remap rules to be restricted to plugins. Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/2cfed613 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/2cfed613 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/2cfed613 Branch: refs/heads/master Commit: 2cfed613f79f42e900ceed0d2c48b01329e586a9 Parents: 105a0c6 Author: James Peach <[email protected]> Authored: Wed Jan 14 21:07:21 2015 -0800 Committer: James Peach <[email protected]> Committed: Thu Jan 29 09:12:22 2015 -0800 ---------------------------------------------------------------------- CHANGES | 2 ++ doc/reference/configuration/remap.config.en.rst | 15 +++++++--- proxy/http/remap/AclFiltering.cc | 20 ++++++-------- proxy/http/remap/AclFiltering.h | 6 ++-- proxy/http/remap/RemapConfig.cc | 27 +++++++++++++++--- proxy/http/remap/RemapConfig.h | 19 +++++++------ proxy/http/remap/UrlRewrite.cc | 29 ++++++++++++++------ 7 files changed, 79 insertions(+), 39 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2cfed613/CHANGES ---------------------------------------------------------------------- diff --git a/CHANGES b/CHANGES index c97edda..c08adb1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ -*- coding: utf-8 -*- Changes with Apache Traffic Server 5.3.0 + *) [TS-3300] Add a @internal ACL filter. + *) [TS-2884] TSActionCancel() on TSNetAccept() causes spinning thread *) [TS-3324] If a chunked fetch from origin dies due to inactivity timeout, truncated cache entry can be created http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2cfed613/doc/reference/configuration/remap.config.en.rst ---------------------------------------------------------------------- diff --git a/doc/reference/configuration/remap.config.en.rst b/doc/reference/configuration/remap.config.en.rst index c34b2a4..db1bc5f 100644 --- a/doc/reference/configuration/remap.config.en.rst +++ b/doc/reference/configuration/remap.config.en.rst @@ -407,27 +407,34 @@ being used. Once defined, ``.activatefilter`` can used to activate a filter for all mappings that follow until deactivated with ``.deactivatefilter``. +The ``@internal`` operator can be used to filter on whether a request +is generated by |TS| itself, usually by a plugin. This operator +is helpful for remapping internal requests without allowing access +to external users. By default both internal and external requests +are allowed. + Examples -------- :: .definefilter disable_delete_purge @action=deny @method=delete @method=purge - .definefilter internal_only @action=allow @src_ip=192.168.0.1-192.168.0.254 @src_ip=10.0.0.1-10.0.0.254 + .definefilter local_only @action=allow @src_ip=192.168.0.1-192.168.0.254 @src_ip=10.0.0.1-10.0.0.254 .activatefilter disable_delete_purge map http://foo.example.com/ http://bar.example.com/ - .activatefilter internal_only + .activatefilter local_only map http://www.example.com/admin http://internal.example.com/admin - .deactivatefilter internal_only + .deactivatefilter local_only map http://www.example.com/ http://internal.example.com/ + map http://auth.example.com/ http://auth.internal.example.com/ @action=allow @internal The filter `disable_delete_purge` will be applied to all of the mapping rules. (It is activated before any mappings and is never -deactivated.) The filter `internal_only` will only be applied to the +deactivated.) The filter `local_only` will only be applied to the second mapping. Including Additional Remap Files http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2cfed613/proxy/http/remap/AclFiltering.cc ---------------------------------------------------------------------- diff --git a/proxy/http/remap/AclFiltering.cc b/proxy/http/remap/AclFiltering.cc index 79d6954..ff05caa 100644 --- a/proxy/http/remap/AclFiltering.cc +++ b/proxy/http/remap/AclFiltering.cc @@ -48,7 +48,7 @@ acl_filter_rule::reset(void) src_ip_valid = 0; } -acl_filter_rule::acl_filter_rule():next(NULL), filter_name_size(0), filter_name(NULL), allow_flag(1), +acl_filter_rule::acl_filter_rule():next(NULL), filter_name(NULL), allow_flag(1), src_ip_valid(0), active_queue_flag(0), argc(0) { standard_method_lookup.resize(HTTP_WKSIDX_METHODS_CNT); @@ -77,15 +77,13 @@ acl_filter_rule::add_argv(int _argc, char *_argv[]) return real_cnt; } -int +void acl_filter_rule::name(const char *_name) { - filter_name_size = 0; filter_name = (char *)ats_free_null(filter_name); - if (_name && _name[0] && (filter_name = ats_strdup(_name)) != NULL) { - filter_name_size = strlen(filter_name); + if (_name) { + filter_name = ats_strdup(_name); } - return filter_name_size; } void @@ -93,9 +91,9 @@ acl_filter_rule::print(void) { int i; printf("-----------------------------------------------------------------------------------------\n"); - 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("Filter \"%s\" status: allow_flag=%s, src_ip_valid=%s, internal=%s, active_queue_flag=%d\n", + filter_name ? filter_name : "<NONAME>", allow_flag ? "true" : "false", + src_ip_valid ? "true" : "false", internal ? "true" : "false", (int) active_queue_flag); printf("standard methods="); for (i = 0; i < HTTP_WKSIDX_METHODS_CNT; i++) { if (standard_method_lookup[i]) { @@ -127,7 +125,7 @@ acl_filter_rule::find_byname(acl_filter_rule *list, const char *_name) acl_filter_rule *rp = 0; if (likely(list && _name && (_name_size = strlen(_name)) > 0)) { for (rp = list; rp; rp = rp->next) { - if (rp->filter_name_size == _name_size && !strcasecmp(rp->filter_name, _name)) + if (strcasecmp(rp->filter_name, _name) == 0) break; } } @@ -141,7 +139,7 @@ acl_filter_rule::delete_byname(acl_filter_rule **rpp, const char *_name) acl_filter_rule *rp; if (likely(rpp && _name && (_name_size = strlen(_name)) > 0)) { for (; (rp = *rpp) != NULL; rpp = &rp->next) { - if (rp->filter_name_size == _name_size && !strcasecmp(rp->filter_name, _name)) { + if (strcasecmp(rp->filter_name, _name) == 0) { *rpp = rp->next; delete rp; break; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2cfed613/proxy/http/remap/AclFiltering.h ---------------------------------------------------------------------- diff --git a/proxy/http/remap/AclFiltering.h b/proxy/http/remap/AclFiltering.h index a8d187a..428d4d5 100644 --- a/proxy/http/remap/AclFiltering.h +++ b/proxy/http/remap/AclFiltering.h @@ -64,11 +64,11 @@ private: public: acl_filter_rule *next; - int filter_name_size; // size of optional filter name char *filter_name; // optional filter name unsigned int allow_flag:1, // action allow deny src_ip_valid:1, // src_ip range valid - active_queue_flag:1; // filter is in active state (used by .useflt directive) + active_queue_flag:1, // filter is in active state (used by .useflt directive) + internal:1; // filter internal HTTP requests // we need arguments as string array for directive processing int argc; // argument counter (only for filter defs) @@ -86,7 +86,7 @@ public: src_ip_info_t src_ip_array[ACL_FILTER_MAX_SRC_IP]; acl_filter_rule(); ~acl_filter_rule(); - int name(const char *_name = NULL); + void name(const char *_name = NULL); int add_argv(int _argc, char *_argv[]); void print(void); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2cfed613/proxy/http/remap/RemapConfig.cc ---------------------------------------------------------------------- diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc index fcbafaf..95b055d 100644 --- a/proxy/http/remap/RemapConfig.cc +++ b/proxy/http/remap/RemapConfig.cc @@ -368,8 +368,10 @@ remap_validate_filter_args(acl_filter_rule ** rule_pp, const char ** argv, int a } for (i = 0; i < argc; i++) { + bool hasarg; + if ((ul = remap_check_option((const char **)&argv[i], 1, 0, NULL, &argptr)) == 0) { - Debug("url_rewrite", "[validate_filter_args] Unknow remap option - %s", argv[i]); + Debug("url_rewrite", "[validate_filter_args] Unknown remap option - %s", argv[i]); snprintf(errStrBuf, errStrBufSize, "Unknown option - \"%s\"", argv[i]); errStrBuf[errStrBufSize - 1] = 0; if (new_rule_flg) { @@ -378,7 +380,11 @@ remap_validate_filter_args(acl_filter_rule ** rule_pp, const char ** argv, int a } return (const char *) errStrBuf; } - if (!argptr || !argptr[0]) { + + // Every filter operator requires an argument except @internal. + hasarg = !(ul & REMAP_OPTFLG_INTERNAL); + + if (hasarg && (!argptr || !argptr[0])) { Debug("url_rewrite", "[validate_filter_args] Empty argument in %s", argv[i]); snprintf(errStrBuf, errStrBufSize, "Empty argument in \"%s\"", argv[i]); errStrBuf[errStrBufSize - 1] = 0; @@ -423,7 +429,9 @@ remap_validate_filter_args(acl_filter_rule ** rule_pp, const char ** argv, int a rule->nonstandard_methods.insert(argptr); } rule->method_restriction_enabled = true; - } else if (ul & REMAP_OPTFLG_SRC_IP) { /* "src_ip=" option */ + } + + 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"); snprintf(errStrBuf, errStrBufSize, "Defined more than %d \"src_ip=\" filters!", ACL_FILTER_MAX_SRC_IP); @@ -460,7 +468,9 @@ remap_validate_filter_args(acl_filter_rule ** rule_pp, const char ** argv, int a rule->src_ip_cnt++; rule->src_ip_valid = 1; } - } else if (ul & REMAP_OPTFLG_ACTION) { /* "action=" option */ + } + + if (ul & REMAP_OPTFLG_ACTION) { /* "action=" option */ if (is_inkeylist(argptr, "0", "off", "deny", "disable", NULL)) { rule->allow_flag = 0; } else if (is_inkeylist(argptr, "1", "on", "allow", "enable", NULL)) { @@ -476,6 +486,10 @@ remap_validate_filter_args(acl_filter_rule ** rule_pp, const char ** argv, int a return (const char *) errStrBuf; } } + + if (ul & REMAP_OPTFLG_INTERNAL) { + rule->internal = 1; + } } if (is_debug_tag_set("url_rewrite")) @@ -540,6 +554,11 @@ remap_check_option(const char ** argv, int argc, unsigned long findmode, int *_r if (argptr) *argptr = &argv[i][6]; ret_flags |= REMAP_OPTFLG_MAP_ID; + } else if (!strncasecmp(argv[i], "internal", 8)) { + if ((findmode & REMAP_OPTFLG_INTERNAL) != 0) { + idx = i; + } + ret_flags |= REMAP_OPTFLG_INTERNAL; } if ((findmode & ret_flags) && !argptr) { http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2cfed613/proxy/http/remap/RemapConfig.h ---------------------------------------------------------------------- diff --git a/proxy/http/remap/RemapConfig.h b/proxy/http/remap/RemapConfig.h index d9e0a12..4647966 100644 --- a/proxy/http/remap/RemapConfig.h +++ b/proxy/http/remap/RemapConfig.h @@ -31,15 +31,16 @@ class UrlRewrite; #define BUILD_TABLE_MAX_ARGS 2048 // Remap inline options -#define REMAP_OPTFLG_MAP_WITH_REFERER 0x01 /* "map_with_referer" option */ -#define REMAP_OPTFLG_PLUGIN 0x02 /* "plugin=" option (per remap plugin) */ -#define REMAP_OPTFLG_PPARAM 0x04 /* "pparam=" option (per remap plugin option) */ -#define REMAP_OPTFLG_METHOD 0x08 /* "method=" option (used for ACL filtering) */ -#define REMAP_OPTFLG_SRC_IP 0x10 /* "src_ip=" option (used for ACL filtering) */ -#define REMAP_OPTFLG_ACTION 0x20 /* "action=" option (used for ACL filtering) */ -#define REMAP_OPTFLG_MAP_ID 0x800 /* associate a map ID with this rule */ -#define REMAP_OPTFLG_INVERT 0x80000000 /* "invert" the rule (for src_ip at least) */ -#define REMAP_OPTFLG_ALL_FILTERS (REMAP_OPTFLG_METHOD|REMAP_OPTFLG_SRC_IP|REMAP_OPTFLG_ACTION) +#define REMAP_OPTFLG_MAP_WITH_REFERER 0x0001u /* "map_with_referer" option */ +#define REMAP_OPTFLG_PLUGIN 0x0002u /* "plugin=" option (per remap plugin) */ +#define REMAP_OPTFLG_PPARAM 0x0004u /* "pparam=" option (per remap plugin option) */ +#define REMAP_OPTFLG_METHOD 0x0008u /* "method=" option (used for ACL filtering) */ +#define REMAP_OPTFLG_SRC_IP 0x0010u /* "src_ip=" option (used for ACL filtering) */ +#define REMAP_OPTFLG_ACTION 0x0020u /* "action=" option (used for ACL filtering) */ +#define REMAP_OPTFLG_INTERNAL 0x0040u /* only allow internal requests to hit this remap */ +#define REMAP_OPTFLG_MAP_ID 0x0800u /* associate a map ID with this rule */ +#define REMAP_OPTFLG_INVERT 0x80000000u /* "invert" the rule (for src_ip at least) */ +#define REMAP_OPTFLG_ALL_FILTERS (REMAP_OPTFLG_METHOD|REMAP_OPTFLG_SRC_IP|REMAP_OPTFLG_ACTION|REMAP_OPTFLG_INTERNAL) struct BUILD_TABLE_INFO { http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2cfed613/proxy/http/remap/UrlRewrite.cc ---------------------------------------------------------------------- diff --git a/proxy/http/remap/UrlRewrite.cc b/proxy/http/remap/UrlRewrite.cc index 5c8180e..d440623 100644 --- a/proxy/http/remap/UrlRewrite.cc +++ b/proxy/http/remap/UrlRewrite.cc @@ -27,6 +27,7 @@ #include "UrlMappingPathIndex.h" #include "RemapConfig.h" #include "I_Layout.h" +#include "HttpSM.h" #define modulePrefix "[ReverseProxy]" @@ -416,42 +417,53 @@ UrlRewrite::ReverseMap(HTTPHdr *response_header) void UrlRewrite::PerformACLFiltering(HttpTransact::State *s, url_mapping *map) { - if (unlikely(!s || s->acl_filtering_performed || !s->client_connection_enabled)) + if (unlikely(!s || s->acl_filtering_performed || !s->client_connection_enabled)) { return; + } s->acl_filtering_performed = true; // small protection against reverse mapping if (map->filter) { - 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; rp = rp->next) { + + for (acl_filter_rule * rp = map->filter; rp && client_enabled_flag; rp = rp->next) { bool match = true; + if (rp->method_restriction_enabled) { if (method_wksidx != -1) { match = rp->standard_method_lookup[method_wksidx]; - } - else if (!rp->nonstandard_methods.empty()) { + } 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) { match = false; for (int j = 0; j < rp->src_ip_cnt && !match; j++) { - res = rp->src_ip_array[j].contains(s->client_info.addr) ? 1 : 0; + bool in_range = rp->src_ip_array[j].contains(s->client_info.addr); if (rp->src_ip_array[j].invert) { - if (res != 1) + if (!in_range) { match = true; + } } else { - if (res == 1) + if (in_range) { match = true; + } } } } + + if (rp->internal) { + match = s->state_machine->ua_session->get_netvc()->get_is_internal_request(); + Debug("url_rewrite", "%s an internal request", match ? "matched" : "didn't 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; @@ -465,6 +477,7 @@ UrlRewrite::PerformACLFiltering(HttpTransact::State *s, url_mapping *map) } } /* end of for(rp = map->filter;rp;rp = rp->next) */ + s->client_connection_enabled = client_enabled_flag; } }
