blob: 0b6adfdb019f6b37b31595c196096a93d4349b7e [file] [log] [blame]
Willy Tarreau79e57332018-10-02 16:01:16 +02001/*
2 * HTTP ACLs declaration
3 *
4 * Copyright 2000-2018 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <sys/types.h>
14
15#include <ctype.h>
16#include <string.h>
17#include <time.h>
18
Willy Tarreauac13aea2020-06-04 10:36:03 +020019#include <haproxy/auth.h>
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020020#include <haproxy/api.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020021#include <haproxy/chunk.h>
Willy Tarreaucd72d8c2020-06-02 19:11:26 +020022#include <haproxy/http.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +020023#include <haproxy/pattern.h>
Willy Tarreaud0ef4392020-06-02 09:38:52 +020024#include <haproxy/pool.h>
Willy Tarreau48fbcae2020-06-03 18:09:46 +020025#include <haproxy/tools.h>
Willy Tarreaud6788052020-05-27 15:59:00 +020026#include <haproxy/version.h>
Willy Tarreau79e57332018-10-02 16:01:16 +020027
Willy Tarreau79e57332018-10-02 16:01:16 +020028#include <proto/acl.h>
Willy Tarreauaa74c4e2020-06-04 10:19:23 +020029#include <haproxy/arg.h>
Willy Tarreau79e57332018-10-02 16:01:16 +020030
31
32/* We use the pre-parsed method if it is known, and store its number as an
33 * integer. If it is unknown, we use the pointer and the length.
34 */
35static int pat_parse_meth(const char *text, struct pattern *pattern, int mflags, char **err)
36{
37 int len, meth;
38
39 len = strlen(text);
40 meth = find_http_meth(text, len);
41
42 pattern->val.i = meth;
43 if (meth == HTTP_METH_OTHER) {
44 pattern->ptr.str = (char *)text;
45 pattern->len = len;
46 }
47 else {
48 pattern->ptr.str = NULL;
49 pattern->len = 0;
50 }
51 return 1;
52}
53
54/* See above how the method is stored in the global pattern */
55static struct pattern *pat_match_meth(struct sample *smp, struct pattern_expr *expr, int fill)
56{
57 int icase;
58 struct pattern_list *lst;
59 struct pattern *pattern;
60
61 list_for_each_entry(lst, &expr->patterns, list) {
62 pattern = &lst->pat;
63
64 /* well-known method */
65 if (pattern->val.i != HTTP_METH_OTHER) {
66 if (smp->data.u.meth.meth == pattern->val.i)
67 return pattern;
68 else
69 continue;
70 }
71
72 /* Other method, we must compare the strings */
73 if (pattern->len != smp->data.u.meth.str.data)
74 continue;
75
76 icase = expr->mflags & PAT_MF_IGNORE_CASE;
77 if ((icase && strncasecmp(pattern->ptr.str, smp->data.u.meth.str.area, smp->data.u.meth.str.data) == 0) ||
78 (!icase && strncmp(pattern->ptr.str, smp->data.u.meth.str.area, smp->data.u.meth.str.data) == 0))
79 return pattern;
80 }
81 return NULL;
82}
83
84/************************************************************************/
85/* All supported ACL keywords must be declared here. */
86/************************************************************************/
87
88/* Note: must not be declared <const> as its list will be overwritten.
89 * Please take care of keeping this list alphabetically sorted.
90 */
91static struct acl_kw_list acl_kws = {ILH, {
92 { "base", "base", PAT_MATCH_STR },
93 { "base_beg", "base", PAT_MATCH_BEG },
94 { "base_dir", "base", PAT_MATCH_DIR },
95 { "base_dom", "base", PAT_MATCH_DOM },
96 { "base_end", "base", PAT_MATCH_END },
97 { "base_len", "base", PAT_MATCH_LEN },
98 { "base_reg", "base", PAT_MATCH_REG },
99 { "base_sub", "base", PAT_MATCH_SUB },
100
101 { "cook", "req.cook", PAT_MATCH_STR },
102 { "cook_beg", "req.cook", PAT_MATCH_BEG },
103 { "cook_dir", "req.cook", PAT_MATCH_DIR },
104 { "cook_dom", "req.cook", PAT_MATCH_DOM },
105 { "cook_end", "req.cook", PAT_MATCH_END },
106 { "cook_len", "req.cook", PAT_MATCH_LEN },
107 { "cook_reg", "req.cook", PAT_MATCH_REG },
108 { "cook_sub", "req.cook", PAT_MATCH_SUB },
109
110 { "hdr", "req.hdr", PAT_MATCH_STR },
111 { "hdr_beg", "req.hdr", PAT_MATCH_BEG },
112 { "hdr_dir", "req.hdr", PAT_MATCH_DIR },
113 { "hdr_dom", "req.hdr", PAT_MATCH_DOM },
114 { "hdr_end", "req.hdr", PAT_MATCH_END },
115 { "hdr_len", "req.hdr", PAT_MATCH_LEN },
116 { "hdr_reg", "req.hdr", PAT_MATCH_REG },
117 { "hdr_sub", "req.hdr", PAT_MATCH_SUB },
118
119 /* these two declarations uses strings with list storage (in place
120 * of tree storage). The basic match is PAT_MATCH_STR, but the indexation
121 * and delete functions are relative to the list management. The parse
122 * and match method are related to the corresponding fetch methods. This
123 * is very particular ACL declaration mode.
124 */
125 { "http_auth_group", NULL, PAT_MATCH_STR, NULL, pat_idx_list_str, pat_del_list_ptr, NULL, pat_match_auth },
126 { "method", NULL, PAT_MATCH_STR, pat_parse_meth, pat_idx_list_str, pat_del_list_ptr, NULL, pat_match_meth },
127
128 { "path", "path", PAT_MATCH_STR },
129 { "path_beg", "path", PAT_MATCH_BEG },
130 { "path_dir", "path", PAT_MATCH_DIR },
131 { "path_dom", "path", PAT_MATCH_DOM },
132 { "path_end", "path", PAT_MATCH_END },
133 { "path_len", "path", PAT_MATCH_LEN },
134 { "path_reg", "path", PAT_MATCH_REG },
135 { "path_sub", "path", PAT_MATCH_SUB },
136
137 { "req_ver", "req.ver", PAT_MATCH_STR },
138 { "resp_ver", "res.ver", PAT_MATCH_STR },
139
140 { "scook", "res.cook", PAT_MATCH_STR },
141 { "scook_beg", "res.cook", PAT_MATCH_BEG },
142 { "scook_dir", "res.cook", PAT_MATCH_DIR },
143 { "scook_dom", "res.cook", PAT_MATCH_DOM },
144 { "scook_end", "res.cook", PAT_MATCH_END },
145 { "scook_len", "res.cook", PAT_MATCH_LEN },
146 { "scook_reg", "res.cook", PAT_MATCH_REG },
147 { "scook_sub", "res.cook", PAT_MATCH_SUB },
148
149 { "shdr", "res.hdr", PAT_MATCH_STR },
150 { "shdr_beg", "res.hdr", PAT_MATCH_BEG },
151 { "shdr_dir", "res.hdr", PAT_MATCH_DIR },
152 { "shdr_dom", "res.hdr", PAT_MATCH_DOM },
153 { "shdr_end", "res.hdr", PAT_MATCH_END },
154 { "shdr_len", "res.hdr", PAT_MATCH_LEN },
155 { "shdr_reg", "res.hdr", PAT_MATCH_REG },
156 { "shdr_sub", "res.hdr", PAT_MATCH_SUB },
157
158 { "url", "url", PAT_MATCH_STR },
159 { "url_beg", "url", PAT_MATCH_BEG },
160 { "url_dir", "url", PAT_MATCH_DIR },
161 { "url_dom", "url", PAT_MATCH_DOM },
162 { "url_end", "url", PAT_MATCH_END },
163 { "url_len", "url", PAT_MATCH_LEN },
164 { "url_reg", "url", PAT_MATCH_REG },
165 { "url_sub", "url", PAT_MATCH_SUB },
166
167 { "urlp", "urlp", PAT_MATCH_STR },
168 { "urlp_beg", "urlp", PAT_MATCH_BEG },
169 { "urlp_dir", "urlp", PAT_MATCH_DIR },
170 { "urlp_dom", "urlp", PAT_MATCH_DOM },
171 { "urlp_end", "urlp", PAT_MATCH_END },
172 { "urlp_len", "urlp", PAT_MATCH_LEN },
173 { "urlp_reg", "urlp", PAT_MATCH_REG },
174 { "urlp_sub", "urlp", PAT_MATCH_SUB },
175
176 { /* END */ },
177}};
178
Willy Tarreau0108d902018-11-25 19:14:37 +0100179INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
Willy Tarreau79e57332018-10-02 16:01:16 +0200180
181/*
182 * Local variables:
183 * c-indent-level: 8
184 * c-basic-offset: 8
185 * End:
186 */