diff options
Diffstat (limited to 'src/http_acl.c')
-rw-r--r-- | src/http_acl.c | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/src/http_acl.c b/src/http_acl.c new file mode 100644 index 0000000..bf29fc3 --- /dev/null +++ b/src/http_acl.c @@ -0,0 +1,185 @@ +/* + * HTTP ACLs declaration + * + * Copyright 2000-2018 Willy Tarreau <w@1wt.eu> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include <sys/types.h> + +#include <ctype.h> +#include <string.h> +#include <time.h> + +#include <haproxy/acl.h> +#include <haproxy/api.h> +#include <haproxy/arg.h> +#include <haproxy/auth.h> +#include <haproxy/chunk.h> +#include <haproxy/http.h> +#include <haproxy/pattern.h> +#include <haproxy/pool.h> +#include <haproxy/tools.h> +#include <haproxy/version.h> + + +/* We use the pre-parsed method if it is known, and store its number as an + * integer. If it is unknown, we use the pointer and the length. + */ +static int pat_parse_meth(const char *text, struct pattern *pattern, int mflags, char **err) +{ + int len, meth; + + len = strlen(text); + meth = find_http_meth(text, len); + + pattern->val.i = meth; + if (meth == HTTP_METH_OTHER) { + pattern->ptr.str = (char *)text; + pattern->len = len; + } + else { + pattern->ptr.str = NULL; + pattern->len = 0; + } + return 1; +} + +/* See above how the method is stored in the global pattern */ +static struct pattern *pat_match_meth(struct sample *smp, struct pattern_expr *expr, int fill) +{ + int icase; + struct pattern_list *lst; + struct pattern *pattern; + + list_for_each_entry(lst, &expr->patterns, list) { + pattern = &lst->pat; + + /* well-known method */ + if (pattern->val.i != HTTP_METH_OTHER) { + if (smp->data.u.meth.meth == pattern->val.i) + return pattern; + else + continue; + } + + /* Other method, we must compare the strings */ + if (pattern->len != smp->data.u.meth.str.data) + continue; + + icase = expr->mflags & PAT_MF_IGNORE_CASE; + if ((icase && strncasecmp(pattern->ptr.str, smp->data.u.meth.str.area, smp->data.u.meth.str.data) == 0) || + (!icase && strncmp(pattern->ptr.str, smp->data.u.meth.str.area, smp->data.u.meth.str.data) == 0)) + return pattern; + } + return NULL; +} + +/************************************************************************/ +/* All supported ACL keywords must be declared here. */ +/************************************************************************/ + +/* Note: must not be declared <const> as its list will be overwritten. + * Please take care of keeping this list alphabetically sorted. + */ +static struct acl_kw_list acl_kws = {ILH, { + { "base", "base", PAT_MATCH_STR }, + { "base_beg", "base", PAT_MATCH_BEG }, + { "base_dir", "base", PAT_MATCH_DIR }, + { "base_dom", "base", PAT_MATCH_DOM }, + { "base_end", "base", PAT_MATCH_END }, + { "base_len", "base", PAT_MATCH_LEN }, + { "base_reg", "base", PAT_MATCH_REG }, + { "base_sub", "base", PAT_MATCH_SUB }, + + { "cook", "req.cook", PAT_MATCH_STR }, + { "cook_beg", "req.cook", PAT_MATCH_BEG }, + { "cook_dir", "req.cook", PAT_MATCH_DIR }, + { "cook_dom", "req.cook", PAT_MATCH_DOM }, + { "cook_end", "req.cook", PAT_MATCH_END }, + { "cook_len", "req.cook", PAT_MATCH_LEN }, + { "cook_reg", "req.cook", PAT_MATCH_REG }, + { "cook_sub", "req.cook", PAT_MATCH_SUB }, + + { "hdr", "req.hdr", PAT_MATCH_STR }, + { "hdr_beg", "req.hdr", PAT_MATCH_BEG }, + { "hdr_dir", "req.hdr", PAT_MATCH_DIR }, + { "hdr_dom", "req.hdr", PAT_MATCH_DOM }, + { "hdr_end", "req.hdr", PAT_MATCH_END }, + { "hdr_len", "req.hdr", PAT_MATCH_LEN }, + { "hdr_reg", "req.hdr", PAT_MATCH_REG }, + { "hdr_sub", "req.hdr", PAT_MATCH_SUB }, + + /* these two declarations uses strings with list storage (in place + * of tree storage). The basic match is PAT_MATCH_STR, but the indexation + * and delete functions are relative to the list management. The parse + * and match method are related to the corresponding fetch methods. This + * is very particular ACL declaration mode. + */ + { "http_auth_group", NULL, PAT_MATCH_STR, NULL, pat_idx_list_str, NULL, NULL, pat_match_auth }, + { "method", NULL, PAT_MATCH_STR, pat_parse_meth, pat_idx_list_str, NULL, NULL, pat_match_meth }, + + { "path", "path", PAT_MATCH_STR }, + { "path_beg", "path", PAT_MATCH_BEG }, + { "path_dir", "path", PAT_MATCH_DIR }, + { "path_dom", "path", PAT_MATCH_DOM }, + { "path_end", "path", PAT_MATCH_END }, + { "path_len", "path", PAT_MATCH_LEN }, + { "path_reg", "path", PAT_MATCH_REG }, + { "path_sub", "path", PAT_MATCH_SUB }, + + { "req_ver", "req.ver", PAT_MATCH_STR }, + { "resp_ver", "res.ver", PAT_MATCH_STR }, + + { "scook", "res.cook", PAT_MATCH_STR }, + { "scook_beg", "res.cook", PAT_MATCH_BEG }, + { "scook_dir", "res.cook", PAT_MATCH_DIR }, + { "scook_dom", "res.cook", PAT_MATCH_DOM }, + { "scook_end", "res.cook", PAT_MATCH_END }, + { "scook_len", "res.cook", PAT_MATCH_LEN }, + { "scook_reg", "res.cook", PAT_MATCH_REG }, + { "scook_sub", "res.cook", PAT_MATCH_SUB }, + + { "shdr", "res.hdr", PAT_MATCH_STR }, + { "shdr_beg", "res.hdr", PAT_MATCH_BEG }, + { "shdr_dir", "res.hdr", PAT_MATCH_DIR }, + { "shdr_dom", "res.hdr", PAT_MATCH_DOM }, + { "shdr_end", "res.hdr", PAT_MATCH_END }, + { "shdr_len", "res.hdr", PAT_MATCH_LEN }, + { "shdr_reg", "res.hdr", PAT_MATCH_REG }, + { "shdr_sub", "res.hdr", PAT_MATCH_SUB }, + + { "url", "url", PAT_MATCH_STR }, + { "url_beg", "url", PAT_MATCH_BEG }, + { "url_dir", "url", PAT_MATCH_DIR }, + { "url_dom", "url", PAT_MATCH_DOM }, + { "url_end", "url", PAT_MATCH_END }, + { "url_len", "url", PAT_MATCH_LEN }, + { "url_reg", "url", PAT_MATCH_REG }, + { "url_sub", "url", PAT_MATCH_SUB }, + + { "urlp", "urlp", PAT_MATCH_STR }, + { "urlp_beg", "urlp", PAT_MATCH_BEG }, + { "urlp_dir", "urlp", PAT_MATCH_DIR }, + { "urlp_dom", "urlp", PAT_MATCH_DOM }, + { "urlp_end", "urlp", PAT_MATCH_END }, + { "urlp_len", "urlp", PAT_MATCH_LEN }, + { "urlp_reg", "urlp", PAT_MATCH_REG }, + { "urlp_sub", "urlp", PAT_MATCH_SUB }, + + { /* END */ }, +}}; + +INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws); + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * End: + */ |