blob: 2b3bbd5474a3c230570b74be78de78eed80a5bd8 [file] [log] [blame]
Willy Tarreaua84d3742007-05-07 00:36:48 +02001/*
2 * ACL management functions.
3 *
Willy Tarreaud4c33c82013-01-07 21:59:07 +01004 * Copyright 2000-2013 Willy Tarreau <w@1wt.eu>
Willy Tarreaua84d3742007-05-07 00:36:48 +02005 *
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
Willy Tarreauae8b7962007-06-09 23:10:04 +020013#include <ctype.h>
Willy Tarreaua84d3742007-05-07 00:36:48 +020014#include <stdio.h>
15#include <string.h>
16
17#include <common/config.h>
18#include <common/mini-clist.h>
19#include <common/standard.h>
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +010020#include <common/uri_auth.h>
Willy Tarreaua84d3742007-05-07 00:36:48 +020021
Willy Tarreau2b5285d2010-05-09 23:45:24 +020022#include <types/global.h>
23
Willy Tarreaua84d3742007-05-07 00:36:48 +020024#include <proto/acl.h>
Willy Tarreau34db1082012-04-19 17:16:54 +020025#include <proto/arg.h>
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +010026#include <proto/auth.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <proto/channel.h>
Willy Tarreau404e8ab2009-07-26 19:40:40 +020028#include <proto/log.h>
Willy Tarreau0b1cd942010-05-16 22:18:27 +020029#include <proto/proxy.h>
Willy Tarreau8ed669b2013-01-11 15:49:37 +010030#include <proto/sample.h>
Willy Tarreaud28c3532012-04-19 19:28:33 +020031#include <proto/stick_table.h>
Willy Tarreaua84d3742007-05-07 00:36:48 +020032
Willy Tarreauc4262962010-05-10 23:42:40 +020033#include <ebsttree.h>
34
Willy Tarreaua84d3742007-05-07 00:36:48 +020035/* List head of all known ACL keywords */
36static struct acl_kw_list acl_keywords = {
37 .list = LIST_HEAD_INIT(acl_keywords.list)
38};
39
40
Willy Tarreaua5909832007-06-17 20:40:25 +020041/*
Willy Tarreau58393e12008-07-20 10:39:22 +020042 * These functions are exported and may be used by any other component.
43 */
44
45/* ignore the current line */
Willy Tarreau7dcb6482012-04-27 17:52:25 +020046int acl_parse_nothing(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreaua5909832007-06-17 20:40:25 +020047{
Willy Tarreau58393e12008-07-20 10:39:22 +020048 return 1;
49}
50
Willy Tarreaua5909832007-06-17 20:40:25 +020051/* always return false */
Willy Tarreau37406352012-04-23 16:16:37 +020052int acl_match_nothing(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua5909832007-06-17 20:40:25 +020053{
Willy Tarreau11382812008-07-09 16:18:21 +020054 return ACL_PAT_FAIL;
Willy Tarreaua5909832007-06-17 20:40:25 +020055}
56
57
Willy Tarreaua84d3742007-05-07 00:36:48 +020058/* NB: For two strings to be identical, it is required that their lengths match */
Willy Tarreau37406352012-04-23 16:16:37 +020059int acl_match_str(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +020060{
Willy Tarreauc8d7c962007-06-17 08:20:33 +020061 int icase;
62
Willy Tarreauf853c462012-04-23 18:53:56 +020063 if (pattern->len != smp->data.str.len)
Willy Tarreau11382812008-07-09 16:18:21 +020064 return ACL_PAT_FAIL;
Willy Tarreauc8d7c962007-06-17 08:20:33 +020065
66 icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
Willy Tarreauf853c462012-04-23 18:53:56 +020067 if ((icase && strncasecmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0) ||
68 (!icase && strncmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0))
Willy Tarreau11382812008-07-09 16:18:21 +020069 return ACL_PAT_PASS;
70 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +020071}
72
Emeric Brun07ca4962012-10-17 13:38:19 +020073/* NB: For two binaries buf to be identical, it is required that their lengths match */
74int acl_match_bin(struct sample *smp, struct acl_pattern *pattern)
75{
76 if (pattern->len != smp->data.str.len)
77 return ACL_PAT_FAIL;
78
79 if (memcmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0)
80 return ACL_PAT_PASS;
81 return ACL_PAT_FAIL;
82}
83
Willy Tarreauc4262962010-05-10 23:42:40 +020084/* Lookup a string in the expression's pattern tree. The node is returned if it
85 * exists, otherwise NULL.
86 */
Willy Tarreau37406352012-04-23 16:16:37 +020087static void *acl_lookup_str(struct sample *smp, struct acl_expr *expr)
Willy Tarreauc4262962010-05-10 23:42:40 +020088{
89 /* data are stored in a tree */
90 struct ebmb_node *node;
91 char prev;
92
93 /* we may have to force a trailing zero on the test pattern */
Willy Tarreauf853c462012-04-23 18:53:56 +020094 prev = smp->data.str.str[smp->data.str.len];
Willy Tarreauc4262962010-05-10 23:42:40 +020095 if (prev)
Willy Tarreauf853c462012-04-23 18:53:56 +020096 smp->data.str.str[smp->data.str.len] = '\0';
97 node = ebst_lookup(&expr->pattern_tree, smp->data.str.str);
Willy Tarreauc4262962010-05-10 23:42:40 +020098 if (prev)
Willy Tarreauf853c462012-04-23 18:53:56 +020099 smp->data.str.str[smp->data.str.len] = prev;
Willy Tarreauc4262962010-05-10 23:42:40 +0200100 return node;
101}
102
Willy Tarreau21e5b0e2012-04-23 19:25:44 +0200103/* Executes a regex. It temporarily changes the data to add a trailing zero,
104 * and restores the previous character when leaving.
Willy Tarreauf3d25982007-05-08 22:45:09 +0200105 */
Willy Tarreau37406352012-04-23 16:16:37 +0200106int acl_match_reg(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreauf3d25982007-05-08 22:45:09 +0200107{
108 char old_char;
109 int ret;
110
Willy Tarreauf853c462012-04-23 18:53:56 +0200111 old_char = smp->data.str.str[smp->data.str.len];
112 smp->data.str.str[smp->data.str.len] = 0;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200113
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900114 if (regex_exec(pattern->ptr.reg, smp->data.str.str, smp->data.str.len) == 0)
Willy Tarreau11382812008-07-09 16:18:21 +0200115 ret = ACL_PAT_PASS;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200116 else
Willy Tarreau11382812008-07-09 16:18:21 +0200117 ret = ACL_PAT_FAIL;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200118
Willy Tarreauf853c462012-04-23 18:53:56 +0200119 smp->data.str.str[smp->data.str.len] = old_char;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200120 return ret;
121}
122
Willy Tarreaua84d3742007-05-07 00:36:48 +0200123/* Checks that the pattern matches the beginning of the tested string. */
Willy Tarreau37406352012-04-23 16:16:37 +0200124int acl_match_beg(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200125{
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200126 int icase;
127
Willy Tarreauf853c462012-04-23 18:53:56 +0200128 if (pattern->len > smp->data.str.len)
Willy Tarreau11382812008-07-09 16:18:21 +0200129 return ACL_PAT_FAIL;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200130
131 icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
Willy Tarreauf853c462012-04-23 18:53:56 +0200132 if ((icase && strncasecmp(pattern->ptr.str, smp->data.str.str, pattern->len) != 0) ||
133 (!icase && strncmp(pattern->ptr.str, smp->data.str.str, pattern->len) != 0))
Willy Tarreau11382812008-07-09 16:18:21 +0200134 return ACL_PAT_FAIL;
135 return ACL_PAT_PASS;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200136}
137
138/* Checks that the pattern matches the end of the tested string. */
Willy Tarreau37406352012-04-23 16:16:37 +0200139int acl_match_end(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200140{
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200141 int icase;
142
Willy Tarreauf853c462012-04-23 18:53:56 +0200143 if (pattern->len > smp->data.str.len)
Willy Tarreau11382812008-07-09 16:18:21 +0200144 return ACL_PAT_FAIL;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200145 icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
Willy Tarreauf853c462012-04-23 18:53:56 +0200146 if ((icase && strncasecmp(pattern->ptr.str, smp->data.str.str + smp->data.str.len - pattern->len, pattern->len) != 0) ||
147 (!icase && strncmp(pattern->ptr.str, smp->data.str.str + smp->data.str.len - pattern->len, pattern->len) != 0))
Willy Tarreau11382812008-07-09 16:18:21 +0200148 return ACL_PAT_FAIL;
149 return ACL_PAT_PASS;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200150}
151
152/* Checks that the pattern is included inside the tested string.
153 * NB: Suboptimal, should be rewritten using a Boyer-Moore method.
154 */
Willy Tarreau37406352012-04-23 16:16:37 +0200155int acl_match_sub(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200156{
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200157 int icase;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200158 char *end;
159 char *c;
160
Willy Tarreauf853c462012-04-23 18:53:56 +0200161 if (pattern->len > smp->data.str.len)
Willy Tarreau11382812008-07-09 16:18:21 +0200162 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200163
Willy Tarreauf853c462012-04-23 18:53:56 +0200164 end = smp->data.str.str + smp->data.str.len - pattern->len;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200165 icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
166 if (icase) {
Willy Tarreauf853c462012-04-23 18:53:56 +0200167 for (c = smp->data.str.str; c <= end; c++) {
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200168 if (tolower(*c) != tolower(*pattern->ptr.str))
169 continue;
170 if (strncasecmp(pattern->ptr.str, c, pattern->len) == 0)
Willy Tarreau11382812008-07-09 16:18:21 +0200171 return ACL_PAT_PASS;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200172 }
173 } else {
Willy Tarreauf853c462012-04-23 18:53:56 +0200174 for (c = smp->data.str.str; c <= end; c++) {
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200175 if (*c != *pattern->ptr.str)
176 continue;
177 if (strncmp(pattern->ptr.str, c, pattern->len) == 0)
Willy Tarreau11382812008-07-09 16:18:21 +0200178 return ACL_PAT_PASS;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200179 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200180 }
Willy Tarreau11382812008-07-09 16:18:21 +0200181 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200182}
183
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200184/* Background: Fast way to find a zero byte in a word
185 * http://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
186 * hasZeroByte = (v - 0x01010101UL) & ~v & 0x80808080UL;
187 *
188 * To look for 4 different byte values, xor the word with those bytes and
189 * then check for zero bytes:
190 *
191 * v = (((unsigned char)c * 0x1010101U) ^ delimiter)
192 * where <delimiter> is the 4 byte values to look for (as an uint)
193 * and <c> is the character that is being tested
194 */
195static inline unsigned int is_delimiter(unsigned char c, unsigned int mask)
196{
197 mask ^= (c * 0x01010101); /* propagate the char to all 4 bytes */
198 return (mask - 0x01010101) & ~mask & 0x80808080U;
199}
200
201static inline unsigned int make_4delim(unsigned char d1, unsigned char d2, unsigned char d3, unsigned char d4)
202{
203 return d1 << 24 | d2 << 16 | d3 << 8 | d4;
204}
205
Willy Tarreaua84d3742007-05-07 00:36:48 +0200206/* This one is used by other real functions. It checks that the pattern is
207 * included inside the tested string, but enclosed between the specified
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200208 * delimiters or at the beginning or end of the string. The delimiters are
209 * provided as an unsigned int made by make_4delim() and match up to 4 different
210 * delimiters. Delimiters are stripped at the beginning and end of the pattern.
Willy Tarreaua84d3742007-05-07 00:36:48 +0200211 */
Willy Tarreau37406352012-04-23 16:16:37 +0200212static int match_word(struct sample *smp, struct acl_pattern *pattern, unsigned int delimiters)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200213{
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200214 int may_match, icase;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200215 char *c, *end;
216 char *ps;
217 int pl;
218
219 pl = pattern->len;
220 ps = pattern->ptr.str;
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200221
222 while (pl > 0 && is_delimiter(*ps, delimiters)) {
Willy Tarreaua84d3742007-05-07 00:36:48 +0200223 pl--;
224 ps++;
225 }
226
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200227 while (pl > 0 && is_delimiter(ps[pl - 1], delimiters))
Willy Tarreaua84d3742007-05-07 00:36:48 +0200228 pl--;
229
Willy Tarreauf853c462012-04-23 18:53:56 +0200230 if (pl > smp->data.str.len)
Willy Tarreau11382812008-07-09 16:18:21 +0200231 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200232
233 may_match = 1;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200234 icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
Willy Tarreauf853c462012-04-23 18:53:56 +0200235 end = smp->data.str.str + smp->data.str.len - pl;
236 for (c = smp->data.str.str; c <= end; c++) {
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200237 if (is_delimiter(*c, delimiters)) {
Willy Tarreaua84d3742007-05-07 00:36:48 +0200238 may_match = 1;
239 continue;
240 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200241
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200242 if (!may_match)
243 continue;
244
245 if (icase) {
246 if ((tolower(*c) == tolower(*ps)) &&
247 (strncasecmp(ps, c, pl) == 0) &&
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200248 (c == end || is_delimiter(c[pl], delimiters)))
Willy Tarreau11382812008-07-09 16:18:21 +0200249 return ACL_PAT_PASS;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200250 } else {
251 if ((*c == *ps) &&
252 (strncmp(ps, c, pl) == 0) &&
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200253 (c == end || is_delimiter(c[pl], delimiters)))
Willy Tarreau11382812008-07-09 16:18:21 +0200254 return ACL_PAT_PASS;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200255 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200256 may_match = 0;
257 }
Willy Tarreau11382812008-07-09 16:18:21 +0200258 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200259}
260
261/* Checks that the pattern is included inside the tested string, but enclosed
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200262 * between the delimiters '?' or '/' or at the beginning or end of the string.
263 * Delimiters at the beginning or end of the pattern are ignored.
Willy Tarreaua84d3742007-05-07 00:36:48 +0200264 */
Willy Tarreau37406352012-04-23 16:16:37 +0200265int acl_match_dir(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200266{
Willy Tarreau37406352012-04-23 16:16:37 +0200267 return match_word(smp, pattern, make_4delim('/', '?', '?', '?'));
Willy Tarreaua84d3742007-05-07 00:36:48 +0200268}
269
270/* Checks that the pattern is included inside the tested string, but enclosed
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200271 * between the delmiters '/', '?', '.' or ":" or at the beginning or end of
272 * the string. Delimiters at the beginning or end of the pattern are ignored.
Willy Tarreaua84d3742007-05-07 00:36:48 +0200273 */
Willy Tarreau37406352012-04-23 16:16:37 +0200274int acl_match_dom(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200275{
Willy Tarreau37406352012-04-23 16:16:37 +0200276 return match_word(smp, pattern, make_4delim('/', '?', '.', ':'));
Willy Tarreaua84d3742007-05-07 00:36:48 +0200277}
278
279/* Checks that the integer in <test> is included between min and max */
Willy Tarreau37406352012-04-23 16:16:37 +0200280int acl_match_int(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200281{
Willy Tarreauf853c462012-04-23 18:53:56 +0200282 if ((!pattern->val.range.min_set || pattern->val.range.min <= smp->data.uint) &&
283 (!pattern->val.range.max_set || smp->data.uint <= pattern->val.range.max))
Willy Tarreau11382812008-07-09 16:18:21 +0200284 return ACL_PAT_PASS;
285 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200286}
287
Willy Tarreau0e698542011-09-16 08:32:32 +0200288/* Checks that the length of the pattern in <test> is included between min and max */
Willy Tarreau37406352012-04-23 16:16:37 +0200289int acl_match_len(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreau0e698542011-09-16 08:32:32 +0200290{
Willy Tarreauf853c462012-04-23 18:53:56 +0200291 if ((!pattern->val.range.min_set || pattern->val.range.min <= smp->data.str.len) &&
292 (!pattern->val.range.max_set || smp->data.str.len <= pattern->val.range.max))
Willy Tarreau0e698542011-09-16 08:32:32 +0200293 return ACL_PAT_PASS;
294 return ACL_PAT_FAIL;
295}
296
Willy Tarreau37406352012-04-23 16:16:37 +0200297int acl_match_ip(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua67fad92007-05-08 19:50:09 +0200298{
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200299 unsigned int v4; /* in network byte order */
300 struct in6_addr *v6;
301 int bits, pos;
302 struct in6_addr tmp6;
Willy Tarreaua67fad92007-05-08 19:50:09 +0200303
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200304 if (pattern->type == SMP_T_IPV4) {
305 if (smp->type == SMP_T_IPV4) {
306 v4 = smp->data.ipv4.s_addr;
307 }
308 else if (smp->type == SMP_T_IPV6) {
309 /* v4 match on a V6 sample. We want to check at least for
310 * the following forms :
311 * - ::ffff:ip:v4 (ipv4 mapped)
312 * - ::0000:ip:v4 (old ipv4 mapped)
313 * - 2002:ip:v4:: (6to4)
314 */
315 if (*(uint32_t*)&smp->data.ipv6.s6_addr[0] == 0 &&
316 *(uint32_t*)&smp->data.ipv6.s6_addr[4] == 0 &&
317 (*(uint32_t*)&smp->data.ipv6.s6_addr[8] == 0 ||
318 *(uint32_t*)&smp->data.ipv6.s6_addr[8] == htonl(0xFFFF))) {
319 v4 = *(uint32_t*)&smp->data.ipv6.s6_addr[12];
320 }
321 else if (*(uint16_t*)&smp->data.ipv6.s6_addr[0] == htons(0x2002)) {
322 v4 = htonl((ntohs(*(uint16_t*)&smp->data.ipv6.s6_addr[2]) << 16) +
323 ntohs(*(uint16_t*)&smp->data.ipv6.s6_addr[4]));
324 }
325 else
326 return ACL_PAT_FAIL;
327 }
328 else
329 return ACL_PAT_FAIL;
Willy Tarreaua67fad92007-05-08 19:50:09 +0200330
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200331 if (((v4 ^ pattern->val.ipv4.addr.s_addr) & pattern->val.ipv4.mask.s_addr) == 0)
332 return ACL_PAT_PASS;
333 else
334 return ACL_PAT_FAIL;
335 }
336 else if (pattern->type == SMP_T_IPV6) {
337 if (smp->type == SMP_T_IPV4) {
338 /* Convert the IPv4 sample address to IPv4 with the
339 * mapping method using the ::ffff: prefix.
340 */
341 memset(&tmp6, 0, 10);
342 *(uint16_t*)&tmp6.s6_addr[10] = htons(0xffff);
343 *(uint32_t*)&tmp6.s6_addr[12] = smp->data.ipv4.s_addr;
344 v6 = &tmp6;
345 }
346 else if (smp->type == SMP_T_IPV6) {
347 v6 = &smp->data.ipv6;
348 }
349 else {
350 return ACL_PAT_FAIL;
351 }
352
353 bits = pattern->val.ipv6.mask;
354 for (pos = 0; bits > 0; pos += 4, bits -= 32) {
355 v4 = *(uint32_t*)&v6->s6_addr[pos] ^ *(uint32_t*)&pattern->val.ipv6.addr.s6_addr[pos];
356 if (bits < 32)
Cyril Bonté4c01beb2012-10-23 21:28:31 +0200357 v4 &= htonl((~0U) << (32-bits));
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200358 if (v4)
359 return ACL_PAT_FAIL;
360 }
Willy Tarreau11382812008-07-09 16:18:21 +0200361 return ACL_PAT_PASS;
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200362 }
Willy Tarreau11382812008-07-09 16:18:21 +0200363 return ACL_PAT_FAIL;
Willy Tarreaua67fad92007-05-08 19:50:09 +0200364}
365
Willy Tarreaub337b532010-05-13 20:03:41 +0200366/* Lookup an IPv4 address in the expression's pattern tree using the longest
367 * match method. The node is returned if it exists, otherwise NULL.
368 */
Willy Tarreau37406352012-04-23 16:16:37 +0200369static void *acl_lookup_ip(struct sample *smp, struct acl_expr *expr)
Willy Tarreaub337b532010-05-13 20:03:41 +0200370{
371 struct in_addr *s;
372
Willy Tarreauf853c462012-04-23 18:53:56 +0200373 if (smp->type != SMP_T_IPV4)
Willy Tarreaub337b532010-05-13 20:03:41 +0200374 return ACL_PAT_FAIL;
375
Willy Tarreauf853c462012-04-23 18:53:56 +0200376 s = &smp->data.ipv4;
Willy Tarreaub337b532010-05-13 20:03:41 +0200377 return ebmb_lookup_longest(&expr->pattern_tree, &s->s_addr);
378}
379
Willy Tarreaua84d3742007-05-07 00:36:48 +0200380/* Parse a string. It is allocated and duplicated. */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200381int acl_parse_str(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200382{
383 int len;
384
Willy Tarreauae8b7962007-06-09 23:10:04 +0200385 len = strlen(*text);
Willy Tarreauc92ddbc2012-04-27 22:10:57 +0200386 pattern->type = SMP_T_CSTR;
Willy Tarreauc4262962010-05-10 23:42:40 +0200387
388 if (pattern->flags & ACL_PAT_F_TREE_OK) {
389 /* we're allowed to put the data in a tree whose root is pointed
390 * to by val.tree.
391 */
392 struct ebmb_node *node;
393
394 node = calloc(1, sizeof(*node) + len + 1);
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200395 if (!node) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200396 memprintf(err, "out of memory while loading string pattern");
Willy Tarreauc4262962010-05-10 23:42:40 +0200397 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200398 }
Willy Tarreauc4262962010-05-10 23:42:40 +0200399 memcpy(node->key, *text, len + 1);
400 if (ebst_insert(pattern->val.tree, node) != node)
401 free(node); /* was a duplicate */
402 pattern->flags |= ACL_PAT_F_TREE; /* this pattern now contains a tree */
403 return 1;
404 }
405
Willy Tarreauae8b7962007-06-09 23:10:04 +0200406 pattern->ptr.str = strdup(*text);
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200407 if (!pattern->ptr.str) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200408 memprintf(err, "out of memory while loading string pattern");
Willy Tarreaua84d3742007-05-07 00:36:48 +0200409 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200410 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200411 pattern->len = len;
412 return 1;
413}
414
Emeric Brun07ca4962012-10-17 13:38:19 +0200415/* Parse a binary written in hexa. It is allocated. */
416int acl_parse_bin(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
417{
418 int len;
419 const char *p = *text;
420 int i,j;
421
422 len = strlen(p);
423 if (len%2) {
424 memprintf(err, "an even number of hex digit is expected");
425 return 0;
426 }
427
428 pattern->type = SMP_T_CBIN;
429 pattern->len = len >> 1;
430 pattern->ptr.str = malloc(pattern->len);
431 if (!pattern->ptr.str) {
432 memprintf(err, "out of memory while loading string pattern");
433 return 0;
434 }
435
436 i = j = 0;
437 while (j < pattern->len) {
438 if (!ishex(p[i++]))
439 goto bad_input;
440 if (!ishex(p[i++]))
441 goto bad_input;
442 pattern->ptr.str[j++] = (hex2i(p[i-2]) << 4) + hex2i(p[i-1]);
443 }
444 return 1;
445
446bad_input:
447 memprintf(err, "an hex digit is expected (found '%c')", p[i-1]);
448 free(pattern->ptr.str);
449 return 0;
450}
451
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100452/* Parse and concatenate all further strings into one. */
453int
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200454acl_parse_strcat(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100455{
456
457 int len = 0, i;
458 char *s;
459
460 for (i = 0; *text[i]; i++)
461 len += strlen(text[i])+1;
462
Willy Tarreauc92ddbc2012-04-27 22:10:57 +0200463 pattern->type = SMP_T_CSTR;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100464 pattern->ptr.str = s = calloc(1, len);
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200465 if (!pattern->ptr.str) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200466 memprintf(err, "out of memory while loading pattern");
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100467 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200468 }
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100469
470 for (i = 0; *text[i]; i++)
471 s += sprintf(s, i?" %s":"%s", text[i]);
472
473 pattern->len = len;
474
475 return i;
476}
477
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +0200478/* Free data allocated by acl_parse_reg */
Willy Tarreau37406352012-04-23 16:16:37 +0200479static void acl_free_reg(void *ptr)
480{
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900481 regex_free(ptr);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +0200482}
483
Willy Tarreauf3d25982007-05-08 22:45:09 +0200484/* Parse a regex. It is allocated. */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200485int acl_parse_reg(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreauf3d25982007-05-08 22:45:09 +0200486{
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900487 regex *preg;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200488 int icase;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200489
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900490 preg = calloc(1, sizeof(*preg));
Willy Tarreauf3d25982007-05-08 22:45:09 +0200491
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200492 if (!preg) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200493 memprintf(err, "out of memory while loading pattern");
Willy Tarreauf3d25982007-05-08 22:45:09 +0200494 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200495 }
Willy Tarreauf3d25982007-05-08 22:45:09 +0200496
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900497#ifdef USE_PCRE_JIT
498 icase = (pattern->flags & ACL_PAT_F_IGNORE_CASE) ? PCRE_CASELESS : 0;
499 preg->reg = pcre_compile(*text, PCRE_NO_AUTO_CAPTURE | icase, NULL, NULL,
500 NULL);
501 if (!preg->reg) {
502 free(preg);
503 memprintf(err, "regex '%s' is invalid", *text);
504 return 0;
505 }
506
507 preg->extra = pcre_study(preg->reg, PCRE_STUDY_JIT_COMPILE, NULL);
508 if (!preg->extra) {
509 pcre_free(preg->reg);
510 free(preg);
511 memprintf(err, "failed to compile regex '%s'", *text);
512 return 0;
513 }
514#else
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200515 icase = (pattern->flags & ACL_PAT_F_IGNORE_CASE) ? REG_ICASE : 0;
516 if (regcomp(preg, *text, REG_EXTENDED | REG_NOSUB | icase) != 0) {
Willy Tarreauf3d25982007-05-08 22:45:09 +0200517 free(preg);
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200518 memprintf(err, "regex '%s' is invalid", *text);
Willy Tarreauf3d25982007-05-08 22:45:09 +0200519 return 0;
520 }
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900521#endif
Willy Tarreauf3d25982007-05-08 22:45:09 +0200522
523 pattern->ptr.reg = preg;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +0200524 pattern->freeptrbuf = &acl_free_reg;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200525 return 1;
526}
527
Willy Tarreauae8b7962007-06-09 23:10:04 +0200528/* Parse a range of positive integers delimited by either ':' or '-'. If only
529 * one integer is read, it is set as both min and max. An operator may be
530 * specified as the prefix, among this list of 5 :
531 *
532 * 0:eq, 1:gt, 2:ge, 3:lt, 4:le
533 *
534 * The default operator is "eq". It supports range matching. Ranges are
535 * rejected for other operators. The operator may be changed at any time.
536 * The operator is stored in the 'opaque' argument.
537 *
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200538 * If err is non-NULL, an error message will be returned there on errors and
539 * the caller will have to free it.
540 *
Willy Tarreaua84d3742007-05-07 00:36:48 +0200541 */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200542int acl_parse_int(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200543{
Willy Tarreauae8b7962007-06-09 23:10:04 +0200544 signed long long i;
545 unsigned int j, last, skip = 0;
546 const char *ptr = *text;
547
Willy Tarreauc92ddbc2012-04-27 22:10:57 +0200548 pattern->type = SMP_T_UINT;
Willy Tarreau8f8e6452007-06-17 21:51:38 +0200549 while (!isdigit((unsigned char)*ptr)) {
Willy Tarreau1c7cc5b2010-07-18 10:46:33 +0200550 switch (get_std_op(ptr)) {
551 case STD_OP_EQ: *opaque = 0; break;
552 case STD_OP_GT: *opaque = 1; break;
553 case STD_OP_GE: *opaque = 2; break;
554 case STD_OP_LT: *opaque = 3; break;
555 case STD_OP_LE: *opaque = 4; break;
556 default:
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200557 memprintf(err, "'%s' is neither a number nor a supported operator", ptr);
Willy Tarreauae8b7962007-06-09 23:10:04 +0200558 return 0;
Willy Tarreau1c7cc5b2010-07-18 10:46:33 +0200559 }
Willy Tarreauae8b7962007-06-09 23:10:04 +0200560
561 skip++;
562 ptr = text[skip];
563 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200564
565 last = i = 0;
566 while (1) {
Willy Tarreauae8b7962007-06-09 23:10:04 +0200567 j = *ptr++;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200568 if ((j == '-' || j == ':') && !last) {
569 last++;
570 pattern->val.range.min = i;
571 i = 0;
572 continue;
573 }
574 j -= '0';
575 if (j > 9)
576 // also catches the terminating zero
577 break;
578 i *= 10;
579 i += j;
580 }
Willy Tarreauae8b7962007-06-09 23:10:04 +0200581
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200582 if (last && *opaque >= 1 && *opaque <= 4) {
Willy Tarreauae8b7962007-06-09 23:10:04 +0200583 /* having a range with a min or a max is absurd */
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200584 memprintf(err, "integer range '%s' specified with a comparison operator", text[skip]);
Willy Tarreauae8b7962007-06-09 23:10:04 +0200585 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200586 }
Willy Tarreauae8b7962007-06-09 23:10:04 +0200587
Willy Tarreaua84d3742007-05-07 00:36:48 +0200588 if (!last)
589 pattern->val.range.min = i;
590 pattern->val.range.max = i;
Willy Tarreauae8b7962007-06-09 23:10:04 +0200591
592 switch (*opaque) {
593 case 0: /* eq */
594 pattern->val.range.min_set = 1;
595 pattern->val.range.max_set = 1;
596 break;
597 case 1: /* gt */
598 pattern->val.range.min++; /* gt = ge + 1 */
599 case 2: /* ge */
600 pattern->val.range.min_set = 1;
601 pattern->val.range.max_set = 0;
602 break;
603 case 3: /* lt */
604 pattern->val.range.max--; /* lt = le - 1 */
605 case 4: /* le */
606 pattern->val.range.min_set = 0;
607 pattern->val.range.max_set = 1;
608 break;
609 }
610 return skip + 1;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200611}
612
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200613/* Parse a range of positive 2-component versions delimited by either ':' or
614 * '-'. The version consists in a major and a minor, both of which must be
615 * smaller than 65536, because internally they will be represented as a 32-bit
616 * integer.
617 * If only one version is read, it is set as both min and max. Just like for
618 * pure integers, an operator may be specified as the prefix, among this list
619 * of 5 :
620 *
621 * 0:eq, 1:gt, 2:ge, 3:lt, 4:le
622 *
623 * The default operator is "eq". It supports range matching. Ranges are
624 * rejected for other operators. The operator may be changed at any time.
625 * The operator is stored in the 'opaque' argument. This allows constructs
626 * such as the following one :
627 *
628 * acl obsolete_ssl ssl_req_proto lt 3
629 * acl unsupported_ssl ssl_req_proto gt 3.1
630 * acl valid_ssl ssl_req_proto 3.0-3.1
631 *
632 */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200633int acl_parse_dotted_ver(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200634{
635 signed long long i;
636 unsigned int j, last, skip = 0;
637 const char *ptr = *text;
638
639
640 while (!isdigit((unsigned char)*ptr)) {
Willy Tarreau1c7cc5b2010-07-18 10:46:33 +0200641 switch (get_std_op(ptr)) {
642 case STD_OP_EQ: *opaque = 0; break;
643 case STD_OP_GT: *opaque = 1; break;
644 case STD_OP_GE: *opaque = 2; break;
645 case STD_OP_LT: *opaque = 3; break;
646 case STD_OP_LE: *opaque = 4; break;
647 default:
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200648 memprintf(err, "'%s' is neither a number nor a supported operator", ptr);
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200649 return 0;
Willy Tarreau1c7cc5b2010-07-18 10:46:33 +0200650 }
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200651
652 skip++;
653 ptr = text[skip];
654 }
655
656 last = i = 0;
657 while (1) {
658 j = *ptr++;
659 if (j == '.') {
660 /* minor part */
661 if (i >= 65536)
662 return 0;
663 i <<= 16;
664 continue;
665 }
666 if ((j == '-' || j == ':') && !last) {
667 last++;
668 if (i < 65536)
669 i <<= 16;
670 pattern->val.range.min = i;
671 i = 0;
672 continue;
673 }
674 j -= '0';
675 if (j > 9)
676 // also catches the terminating zero
677 break;
678 i = (i & 0xFFFF0000) + (i & 0xFFFF) * 10;
679 i += j;
680 }
681
682 /* if we only got a major version, let's shift it now */
683 if (i < 65536)
684 i <<= 16;
685
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200686 if (last && *opaque >= 1 && *opaque <= 4) {
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200687 /* having a range with a min or a max is absurd */
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200688 memprintf(err, "version range '%s' specified with a comparison operator", text[skip]);
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200689 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200690 }
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200691
692 if (!last)
693 pattern->val.range.min = i;
694 pattern->val.range.max = i;
695
696 switch (*opaque) {
697 case 0: /* eq */
698 pattern->val.range.min_set = 1;
699 pattern->val.range.max_set = 1;
700 break;
701 case 1: /* gt */
702 pattern->val.range.min++; /* gt = ge + 1 */
703 case 2: /* ge */
704 pattern->val.range.min_set = 1;
705 pattern->val.range.max_set = 0;
706 break;
707 case 3: /* lt */
708 pattern->val.range.max--; /* lt = le - 1 */
709 case 4: /* le */
710 pattern->val.range.min_set = 0;
711 pattern->val.range.max_set = 1;
712 break;
713 }
714 return skip + 1;
715}
716
Willy Tarreaua67fad92007-05-08 19:50:09 +0200717/* Parse an IP address and an optional mask in the form addr[/mask].
718 * The addr may either be an IPv4 address or a hostname. The mask
719 * may either be a dotted mask or a number of bits. Returns 1 if OK,
Willy Tarreauc92ddbc2012-04-27 22:10:57 +0200720 * otherwise 0. NOTE: IP address patterns are typed (IPV4/IPV6).
Willy Tarreaua67fad92007-05-08 19:50:09 +0200721 */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200722int acl_parse_ip(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreaua67fad92007-05-08 19:50:09 +0200723{
Willy Tarreaub337b532010-05-13 20:03:41 +0200724 struct eb_root *tree = NULL;
725 if (pattern->flags & ACL_PAT_F_TREE_OK)
726 tree = pattern->val.tree;
727
728 if (str2net(*text, &pattern->val.ipv4.addr, &pattern->val.ipv4.mask)) {
729 unsigned int mask = ntohl(pattern->val.ipv4.mask.s_addr);
730 struct ebmb_node *node;
731 /* check if the mask is contiguous so that we can insert the
732 * network into the tree. A continuous mask has only ones on
733 * the left. This means that this mask + its lower bit added
734 * once again is null.
735 */
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200736 pattern->type = SMP_T_IPV4;
Willy Tarreaub337b532010-05-13 20:03:41 +0200737 if (mask + (mask & -mask) == 0 && tree) {
738 mask = mask ? 33 - flsnz(mask & -mask) : 0; /* equals cidr value */
739 /* FIXME: insert <addr>/<mask> into the tree here */
740 node = calloc(1, sizeof(*node) + 4); /* reserve 4 bytes for IPv4 address */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200741 if (!node) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200742 memprintf(err, "out of memory while loading IPv4 pattern");
Willy Tarreaub337b532010-05-13 20:03:41 +0200743 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200744 }
Willy Tarreaub337b532010-05-13 20:03:41 +0200745 memcpy(node->key, &pattern->val.ipv4.addr, 4); /* network byte order */
746 node->node.pfx = mask;
747 if (ebmb_insert_prefix(tree, node, 4) != node)
748 free(node); /* was a duplicate */
749 pattern->flags |= ACL_PAT_F_TREE;
750 return 1;
751 }
Willy Tarreauae8b7962007-06-09 23:10:04 +0200752 return 1;
Willy Tarreaub337b532010-05-13 20:03:41 +0200753 }
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200754 else if (str62net(*text, &pattern->val.ipv6.addr, &pattern->val.ipv6.mask)) {
755 /* no tree support right now */
756 pattern->type = SMP_T_IPV6;
757 return 1;
758 }
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200759 else {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200760 memprintf(err, "'%s' is not a valid IPv4 or IPv6 address", *text);
Willy Tarreauae8b7962007-06-09 23:10:04 +0200761 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200762 }
Willy Tarreaua67fad92007-05-08 19:50:09 +0200763}
764
Willy Tarreaua84d3742007-05-07 00:36:48 +0200765/*
766 * Registers the ACL keyword list <kwl> as a list of valid keywords for next
767 * parsing sessions.
768 */
769void acl_register_keywords(struct acl_kw_list *kwl)
770{
771 LIST_ADDQ(&acl_keywords.list, &kwl->list);
772}
773
774/*
775 * Unregisters the ACL keyword list <kwl> from the list of valid keywords.
776 */
777void acl_unregister_keywords(struct acl_kw_list *kwl)
778{
779 LIST_DEL(&kwl->list);
780 LIST_INIT(&kwl->list);
781}
782
783/* Return a pointer to the ACL <name> within the list starting at <head>, or
784 * NULL if not found.
785 */
786struct acl *find_acl_by_name(const char *name, struct list *head)
787{
788 struct acl *acl;
789 list_for_each_entry(acl, head, list) {
790 if (strcmp(acl->name, name) == 0)
791 return acl;
792 }
793 return NULL;
794}
795
796/* Return a pointer to the ACL keyword <kw>, or NULL if not found. Note that if
797 * <kw> contains an opening parenthesis, only the left part of it is checked.
798 */
799struct acl_keyword *find_acl_kw(const char *kw)
800{
801 int index;
802 const char *kwend;
803 struct acl_kw_list *kwl;
804
805 kwend = strchr(kw, '(');
806 if (!kwend)
807 kwend = kw + strlen(kw);
808
809 list_for_each_entry(kwl, &acl_keywords.list, list) {
810 for (index = 0; kwl->kw[index].kw != NULL; index++) {
811 if ((strncmp(kwl->kw[index].kw, kw, kwend - kw) == 0) &&
812 kwl->kw[index].kw[kwend-kw] == 0)
813 return &kwl->kw[index];
814 }
815 }
816 return NULL;
817}
818
Willy Tarreaudfd7fca2011-03-09 07:27:02 +0100819/* NB: does nothing if <pat> is NULL */
Willy Tarreaua84d3742007-05-07 00:36:48 +0200820static void free_pattern(struct acl_pattern *pat)
821{
Willy Tarreaudfd7fca2011-03-09 07:27:02 +0100822 if (!pat)
823 return;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +0200824
825 if (pat->ptr.ptr) {
826 if (pat->freeptrbuf)
827 pat->freeptrbuf(pat->ptr.ptr);
828
Willy Tarreaua84d3742007-05-07 00:36:48 +0200829 free(pat->ptr.ptr);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +0200830 }
831
Willy Tarreaua84d3742007-05-07 00:36:48 +0200832 free(pat);
833}
834
835static void free_pattern_list(struct list *head)
836{
837 struct acl_pattern *pat, *tmp;
838 list_for_each_entry_safe(pat, tmp, head, list)
839 free_pattern(pat);
840}
841
Willy Tarreaue56cda92010-05-11 23:25:05 +0200842static void free_pattern_tree(struct eb_root *root)
843{
844 struct eb_node *node, *next;
845 node = eb_first(root);
846 while (node) {
847 next = eb_next(node);
848 free(node);
849 node = next;
850 }
851}
852
Willy Tarreaua84d3742007-05-07 00:36:48 +0200853static struct acl_expr *prune_acl_expr(struct acl_expr *expr)
854{
Willy Tarreau34db1082012-04-19 17:16:54 +0200855 struct arg *arg;
856
Willy Tarreaua84d3742007-05-07 00:36:48 +0200857 free_pattern_list(&expr->patterns);
Willy Tarreaue56cda92010-05-11 23:25:05 +0200858 free_pattern_tree(&expr->pattern_tree);
Willy Tarreaua84d3742007-05-07 00:36:48 +0200859 LIST_INIT(&expr->patterns);
Willy Tarreau34db1082012-04-19 17:16:54 +0200860
861 for (arg = expr->args; arg; arg++) {
862 if (arg->type == ARGT_STOP)
863 break;
Willy Tarreau496aa012012-06-01 10:38:29 +0200864 if (arg->type == ARGT_STR || arg->unresolved) {
Willy Tarreau34db1082012-04-19 17:16:54 +0200865 free(arg->data.str.str);
866 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +0200867 arg->unresolved = 0;
Willy Tarreau34db1082012-04-19 17:16:54 +0200868 }
Willy Tarreau34db1082012-04-19 17:16:54 +0200869 }
870
Willy Tarreau2e845be2012-10-19 19:49:09 +0200871 if (expr->args != empty_arg_list)
872 free(expr->args);
Willy Tarreaua84d3742007-05-07 00:36:48 +0200873 expr->kw->use_cnt--;
874 return expr;
875}
876
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200877
878/* Reads patterns from a file. If <err_msg> is non-NULL, an error message will
879 * be returned there on errors and the caller will have to free it.
880 */
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200881static int acl_read_patterns_from_file( struct acl_keyword *aclkw,
882 struct acl_expr *expr,
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200883 const char *filename, int patflags,
884 char **err)
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200885{
886 FILE *file;
887 char *c;
888 const char *args[2];
889 struct acl_pattern *pattern;
890 int opaque;
Willy Tarreau6a8097f2011-02-26 15:14:15 +0100891 int ret = 0;
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200892 int line = 0;
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200893
894 file = fopen(filename, "r");
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200895 if (!file) {
896 memprintf(err, "failed to open pattern file <%s>", filename);
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200897 return 0;
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200898 }
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200899
900 /* now parse all patterns. The file may contain only one pattern per
901 * line. If the line contains spaces, they will be part of the pattern.
902 * The pattern stops at the first CR, LF or EOF encountered.
903 */
904 opaque = 0;
Willy Tarreaue56cda92010-05-11 23:25:05 +0200905 pattern = NULL;
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200906 args[1] = "";
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100907 while (fgets(trash.str, trash.size, file) != NULL) {
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200908 line++;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100909 c = trash.str;
Willy Tarreau58215a02010-05-13 22:07:43 +0200910
911 /* ignore lines beginning with a dash */
912 if (*c == '#')
913 continue;
914
915 /* strip leading spaces and tabs */
916 while (*c == ' ' || *c == '\t')
917 c++;
918
Willy Tarreau58215a02010-05-13 22:07:43 +0200919
920 args[0] = c;
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200921 while (*c && *c != '\n' && *c != '\r')
922 c++;
923 *c = 0;
924
Willy Tarreau51091962011-01-03 21:04:10 +0100925 /* empty lines are ignored too */
926 if (c == args[0])
927 continue;
928
Willy Tarreaue56cda92010-05-11 23:25:05 +0200929 /* we keep the previous pattern along iterations as long as it's not used */
930 if (!pattern)
931 pattern = (struct acl_pattern *)malloc(sizeof(*pattern));
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200932 if (!pattern) {
933 memprintf(err, "out of memory when loading patterns from file <%s>", filename);
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200934 goto out_close;
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200935 }
Willy Tarreaue56cda92010-05-11 23:25:05 +0200936
937 memset(pattern, 0, sizeof(*pattern));
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200938 pattern->flags = patflags;
939
Willy Tarreaue0db1e82013-01-04 16:31:47 +0100940 if (!(pattern->flags & ACL_PAT_F_IGNORE_CASE) &&
941 (aclkw->match == acl_match_str || aclkw->match == acl_match_ip)) {
Willy Tarreaue56cda92010-05-11 23:25:05 +0200942 /* we pre-set the data pointer to the tree's head so that functions
943 * which are able to insert in a tree know where to do that.
944 */
945 pattern->flags |= ACL_PAT_F_TREE_OK;
946 pattern->val.tree = &expr->pattern_tree;
947 }
948
Willy Tarreauc92ddbc2012-04-27 22:10:57 +0200949 pattern->type = SMP_TYPES; /* unspecified type by default */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200950 if (!aclkw->parse(args, pattern, &opaque, err))
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200951 goto out_free_pattern;
Willy Tarreaue56cda92010-05-11 23:25:05 +0200952
953 /* if the parser did not feed the tree, let's chain the pattern to the list */
954 if (!(pattern->flags & ACL_PAT_F_TREE)) {
955 LIST_ADDQ(&expr->patterns, &pattern->list);
956 pattern = NULL; /* get a new one */
957 }
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200958 }
Willy Tarreau6a8097f2011-02-26 15:14:15 +0100959
960 ret = 1; /* success */
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200961
962 out_free_pattern:
963 free_pattern(pattern);
964 out_close:
965 fclose(file);
Willy Tarreau6a8097f2011-02-26 15:14:15 +0100966 return ret;
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200967}
968
Willy Tarreaub7451bb2012-04-27 12:38:15 +0200969/* Parse an ACL expression starting at <args>[0], and return it. If <err> is
970 * not NULL, it will be filled with a pointer to an error message in case of
971 * error. This pointer must be freeable or NULL.
972 *
Willy Tarreaua84d3742007-05-07 00:36:48 +0200973 * Right now, the only accepted syntax is :
974 * <subject> [<value>...]
975 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +0200976struct acl_expr *parse_acl_expr(const char **args, char **err)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200977{
978 __label__ out_return, out_free_expr, out_free_pattern;
979 struct acl_expr *expr;
980 struct acl_keyword *aclkw;
981 struct acl_pattern *pattern;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200982 int opaque, patflags;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200983 const char *arg;
984
985 aclkw = find_acl_kw(args[0]);
Willy Tarreaub7451bb2012-04-27 12:38:15 +0200986 if (!aclkw || !aclkw->parse) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200987 memprintf(err, "unknown ACL keyword '%s'", *args);
Willy Tarreaua84d3742007-05-07 00:36:48 +0200988 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +0200989 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200990
991 expr = (struct acl_expr *)calloc(1, sizeof(*expr));
Willy Tarreaub7451bb2012-04-27 12:38:15 +0200992 if (!expr) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200993 memprintf(err, "out of memory when parsing ACL expression");
Willy Tarreaua84d3742007-05-07 00:36:48 +0200994 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +0200995 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200996
997 expr->kw = aclkw;
998 aclkw->use_cnt++;
999 LIST_INIT(&expr->patterns);
Willy Tarreaue56cda92010-05-11 23:25:05 +02001000 expr->pattern_tree = EB_ROOT_UNIQUE;
Willy Tarreau2e845be2012-10-19 19:49:09 +02001001 expr->args = empty_arg_list;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001002
1003 arg = strchr(args[0], '(');
Willy Tarreauc48c90d2013-01-11 16:56:48 +01001004 if (aclkw->smp->arg_mask) {
Willy Tarreau61612d42012-04-19 18:42:05 +02001005 int nbargs = 0;
Willy Tarreau34db1082012-04-19 17:16:54 +02001006 char *end;
Willy Tarreau34db1082012-04-19 17:16:54 +02001007
Willy Tarreau61612d42012-04-19 18:42:05 +02001008 if (arg != NULL) {
1009 /* there are 0 or more arguments in the form "subject(arg[,arg]*)" */
1010 arg++;
1011 end = strchr(arg, ')');
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001012 if (!end) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001013 memprintf(err, "missing closing ')' after arguments to ACL keyword '%s'", aclkw->kw);
Willy Tarreau61612d42012-04-19 18:42:05 +02001014 goto out_free_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001015 }
Willy Tarreau34db1082012-04-19 17:16:54 +02001016
Willy Tarreau61612d42012-04-19 18:42:05 +02001017 /* Parse the arguments. Note that currently we have no way to
1018 * report parsing errors, hence the NULL in the error pointers.
1019 * An error is also reported if some mandatory arguments are
1020 * missing.
1021 */
Willy Tarreauc48c90d2013-01-11 16:56:48 +01001022 nbargs = make_arg_list(arg, end - arg, aclkw->smp->arg_mask, &expr->args,
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001023 err, NULL, NULL);
1024 if (nbargs < 0) {
1025 /* note that make_arg_list will have set <err> here */
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001026 memprintf(err, "in argument to '%s', %s", aclkw->kw, *err);
Willy Tarreau61612d42012-04-19 18:42:05 +02001027 goto out_free_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001028 }
Willy Tarreauae52f062012-04-26 12:13:35 +02001029
Willy Tarreau2e845be2012-10-19 19:49:09 +02001030 if (!expr->args)
1031 expr->args = empty_arg_list;
1032
Willy Tarreau9baae632013-01-11 17:06:15 +01001033 if (aclkw->smp->val_args && !aclkw->smp->val_args(expr->args, err)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001034 /* invalid keyword argument, error must have been
1035 * set by val_args().
1036 */
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001037 memprintf(err, "in argument to '%s', %s", aclkw->kw, *err);
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001038 goto out_free_expr;
1039 }
Willy Tarreau61612d42012-04-19 18:42:05 +02001040 }
Willy Tarreauc48c90d2013-01-11 16:56:48 +01001041 else if (ARGM(aclkw->smp->arg_mask) == 1) {
1042 int type = (aclkw->smp->arg_mask >> 4) & 15;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001043
1044 /* If a proxy is noted as a mandatory argument, we'll fake
1045 * an empty one so that acl_find_targets() resolves it as
1046 * the current one later.
1047 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001048 if (type != ARGT_FE && type != ARGT_BE && type != ARGT_TAB) {
Willy Tarreauc48c90d2013-01-11 16:56:48 +01001049 memprintf(err, "ACL keyword '%s' expects %d arguments", aclkw->kw, ARGM(aclkw->smp->arg_mask));
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001050 goto out_free_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001051 }
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001052
1053 /* Build an arg list containing the type as an empty string
1054 * and the usual STOP.
1055 */
1056 expr->args = calloc(2, sizeof(*expr->args));
1057 expr->args[0].type = type;
Willy Tarreaue3a46112012-06-15 08:02:34 +02001058 expr->args[0].unresolved = 1;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001059 expr->args[0].data.str.str = strdup("");
1060 expr->args[0].data.str.len = 1;
1061 expr->args[0].data.str.len = 0;
1062 expr->args[1].type = ARGT_STOP;
1063 }
Willy Tarreauc48c90d2013-01-11 16:56:48 +01001064 else if (ARGM(aclkw->smp->arg_mask)) {
Willy Tarreau61612d42012-04-19 18:42:05 +02001065 /* there were some mandatory arguments */
Willy Tarreauc48c90d2013-01-11 16:56:48 +01001066 memprintf(err, "ACL keyword '%s' expects %d arguments", aclkw->kw, ARGM(aclkw->smp->arg_mask));
Willy Tarreaua84d3742007-05-07 00:36:48 +02001067 goto out_free_expr;
Willy Tarreau61612d42012-04-19 18:42:05 +02001068 }
1069 }
1070 else {
1071 if (arg) {
1072 /* no argument expected */
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001073 memprintf(err, "ACL keyword '%s' takes no argument", aclkw->kw);
Willy Tarreau61612d42012-04-19 18:42:05 +02001074 goto out_free_expr;
1075 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001076 }
1077
Willy Tarreaua84d3742007-05-07 00:36:48 +02001078 args++;
Willy Tarreauc8d7c962007-06-17 08:20:33 +02001079
1080 /* check for options before patterns. Supported options are :
1081 * -i : ignore case for all patterns by default
1082 * -f : read patterns from those files
1083 * -- : everything after this is not an option
1084 */
1085 patflags = 0;
1086 while (**args == '-') {
1087 if ((*args)[1] == 'i')
1088 patflags |= ACL_PAT_F_IGNORE_CASE;
Willy Tarreau2b5285d2010-05-09 23:45:24 +02001089 else if ((*args)[1] == 'f') {
Willy Tarreau08ad0b32012-04-27 17:25:24 +02001090 if (!acl_read_patterns_from_file(aclkw, expr, args[1], patflags | ACL_PAT_F_FROM_FILE, err))
Willy Tarreau2b5285d2010-05-09 23:45:24 +02001091 goto out_free_expr;
1092 args++;
1093 }
Willy Tarreauc8d7c962007-06-17 08:20:33 +02001094 else if ((*args)[1] == '-') {
1095 args++;
1096 break;
1097 }
1098 else
1099 break;
1100 args++;
1101 }
1102
1103 /* now parse all patterns */
Willy Tarreauae8b7962007-06-09 23:10:04 +02001104 opaque = 0;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001105 while (**args) {
Willy Tarreauae8b7962007-06-09 23:10:04 +02001106 int ret;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001107 pattern = (struct acl_pattern *)calloc(1, sizeof(*pattern));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001108 if (!pattern) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001109 memprintf(err, "out of memory when parsing ACL pattern");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001110 goto out_free_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001111 }
Willy Tarreauc8d7c962007-06-17 08:20:33 +02001112 pattern->flags = patflags;
1113
Willy Tarreauc92ddbc2012-04-27 22:10:57 +02001114 pattern->type = SMP_TYPES; /* unspecified type */
Willy Tarreau7dcb6482012-04-27 17:52:25 +02001115 ret = aclkw->parse(args, pattern, &opaque, err);
1116 if (!ret)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001117 goto out_free_pattern;
Willy Tarreau7dcb6482012-04-27 17:52:25 +02001118
Willy Tarreaua84d3742007-05-07 00:36:48 +02001119 LIST_ADDQ(&expr->patterns, &pattern->list);
Willy Tarreauae8b7962007-06-09 23:10:04 +02001120 args += ret;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001121 }
1122
1123 return expr;
1124
1125 out_free_pattern:
1126 free_pattern(pattern);
1127 out_free_expr:
1128 prune_acl_expr(expr);
1129 free(expr);
1130 out_return:
1131 return NULL;
1132}
1133
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02001134/* Purge everything in the acl <acl>, then return <acl>. */
1135struct acl *prune_acl(struct acl *acl) {
1136
1137 struct acl_expr *expr, *exprb;
1138
1139 free(acl->name);
1140
1141 list_for_each_entry_safe(expr, exprb, &acl->expr, list) {
1142 LIST_DEL(&expr->list);
1143 prune_acl_expr(expr);
1144 free(expr);
1145 }
1146
1147 return acl;
1148}
1149
Willy Tarreaua84d3742007-05-07 00:36:48 +02001150/* Parse an ACL with the name starting at <args>[0], and with a list of already
1151 * known ACLs in <acl>. If the ACL was not in the list, it will be added.
Willy Tarreau2a56c5e2010-03-15 16:13:29 +01001152 * A pointer to that ACL is returned. If the ACL has an empty name, then it's
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001153 * an anonymous one and it won't be merged with any other one. If <err> is not
1154 * NULL, it will be filled with an appropriate error. This pointer must be
1155 * freeable or NULL.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001156 *
1157 * args syntax: <aclname> <acl_expr>
1158 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001159struct acl *parse_acl(const char **args, struct list *known_acl, char **err)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001160{
1161 __label__ out_return, out_free_acl_expr, out_free_name;
1162 struct acl *cur_acl;
1163 struct acl_expr *acl_expr;
1164 char *name;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001165 const char *pos;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001166
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001167 if (**args && (pos = invalid_char(*args))) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001168 memprintf(err, "invalid character in ACL name : '%c'", *pos);
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001169 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001170 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001171
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001172 acl_expr = parse_acl_expr(args + 1, err);
1173 if (!acl_expr) {
1174 /* parse_acl_expr will have filled <err> here */
Willy Tarreaua84d3742007-05-07 00:36:48 +02001175 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001176 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001177
Willy Tarreau404e8ab2009-07-26 19:40:40 +02001178 /* Check for args beginning with an opening parenthesis just after the
1179 * subject, as this is almost certainly a typo. Right now we can only
1180 * emit a warning, so let's do so.
1181 */
Krzysztof Piotr Oledzki4cdd8312009-10-05 00:23:35 +02001182 if (!strchr(args[1], '(') && *args[2] == '(')
Willy Tarreau404e8ab2009-07-26 19:40:40 +02001183 Warning("parsing acl '%s' :\n"
1184 " matching '%s' for pattern '%s' is likely a mistake and probably\n"
1185 " not what you want. Maybe you need to remove the extraneous space before '('.\n"
1186 " If you are really sure this is not an error, please insert '--' between the\n"
1187 " match and the pattern to make this warning message disappear.\n",
1188 args[0], args[1], args[2]);
1189
Willy Tarreau2a56c5e2010-03-15 16:13:29 +01001190 if (*args[0])
1191 cur_acl = find_acl_by_name(args[0], known_acl);
1192 else
1193 cur_acl = NULL;
1194
Willy Tarreaua84d3742007-05-07 00:36:48 +02001195 if (!cur_acl) {
1196 name = strdup(args[0]);
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001197 if (!name) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001198 memprintf(err, "out of memory when parsing ACL");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001199 goto out_free_acl_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001200 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001201 cur_acl = (struct acl *)calloc(1, sizeof(*cur_acl));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001202 if (cur_acl == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001203 memprintf(err, "out of memory when parsing ACL");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001204 goto out_free_name;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001205 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001206
1207 LIST_INIT(&cur_acl->expr);
1208 LIST_ADDQ(known_acl, &cur_acl->list);
1209 cur_acl->name = name;
1210 }
1211
Willy Tarreaua9802632008-07-25 19:13:19 +02001212 cur_acl->requires |= acl_expr->kw->requires;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001213 LIST_ADDQ(&cur_acl->expr, &acl_expr->list);
1214 return cur_acl;
1215
1216 out_free_name:
1217 free(name);
1218 out_free_acl_expr:
1219 prune_acl_expr(acl_expr);
1220 free(acl_expr);
1221 out_return:
1222 return NULL;
1223}
1224
Willy Tarreau16fbe822007-06-17 11:54:31 +02001225/* Some useful ACLs provided by default. Only those used are allocated. */
1226
1227const struct {
1228 const char *name;
1229 const char *expr[4]; /* put enough for longest expression */
1230} default_acl_list[] = {
Willy Tarreau58393e12008-07-20 10:39:22 +02001231 { .name = "TRUE", .expr = {"always_true",""}},
1232 { .name = "FALSE", .expr = {"always_false",""}},
Willy Tarreau16fbe822007-06-17 11:54:31 +02001233 { .name = "LOCALHOST", .expr = {"src","127.0.0.1/8",""}},
Willy Tarreau2492d5b2009-07-11 00:06:00 +02001234 { .name = "HTTP", .expr = {"req_proto_http",""}},
Willy Tarreau16fbe822007-06-17 11:54:31 +02001235 { .name = "HTTP_1.0", .expr = {"req_ver","1.0",""}},
1236 { .name = "HTTP_1.1", .expr = {"req_ver","1.1",""}},
1237 { .name = "METH_CONNECT", .expr = {"method","CONNECT",""}},
1238 { .name = "METH_GET", .expr = {"method","GET","HEAD",""}},
1239 { .name = "METH_HEAD", .expr = {"method","HEAD",""}},
1240 { .name = "METH_OPTIONS", .expr = {"method","OPTIONS",""}},
1241 { .name = "METH_POST", .expr = {"method","POST",""}},
1242 { .name = "METH_TRACE", .expr = {"method","TRACE",""}},
1243 { .name = "HTTP_URL_ABS", .expr = {"url_reg","^[^/:]*://",""}},
1244 { .name = "HTTP_URL_SLASH", .expr = {"url_beg","/",""}},
1245 { .name = "HTTP_URL_STAR", .expr = {"url","*",""}},
1246 { .name = "HTTP_CONTENT", .expr = {"hdr_val(content-length)","gt","0",""}},
Emeric Brunbede3d02009-06-30 17:54:00 +02001247 { .name = "RDP_COOKIE", .expr = {"req_rdp_cookie_cnt","gt","0",""}},
Willy Tarreauc6317702008-07-20 09:29:50 +02001248 { .name = "REQ_CONTENT", .expr = {"req_len","gt","0",""}},
Willy Tarreaub6fb4202008-07-20 11:18:28 +02001249 { .name = "WAIT_END", .expr = {"wait_end",""}},
Willy Tarreau16fbe822007-06-17 11:54:31 +02001250 { .name = NULL, .expr = {""}}
1251};
1252
1253/* Find a default ACL from the default_acl list, compile it and return it.
1254 * If the ACL is not found, NULL is returned. In theory, it cannot fail,
1255 * except when default ACLs are broken, in which case it will return NULL.
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001256 * If <known_acl> is not NULL, the ACL will be queued at its tail. If <err> is
1257 * not NULL, it will be filled with an error message if an error occurs. This
1258 * pointer must be freeable or NULL.
Willy Tarreau16fbe822007-06-17 11:54:31 +02001259 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001260struct acl *find_acl_default(const char *acl_name, struct list *known_acl, char **err)
Willy Tarreau16fbe822007-06-17 11:54:31 +02001261{
1262 __label__ out_return, out_free_acl_expr, out_free_name;
1263 struct acl *cur_acl;
1264 struct acl_expr *acl_expr;
1265 char *name;
1266 int index;
1267
1268 for (index = 0; default_acl_list[index].name != NULL; index++) {
1269 if (strcmp(acl_name, default_acl_list[index].name) == 0)
1270 break;
1271 }
1272
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001273 if (default_acl_list[index].name == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001274 memprintf(err, "no such ACL : '%s'", acl_name);
Willy Tarreau16fbe822007-06-17 11:54:31 +02001275 return NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001276 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001277
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001278 acl_expr = parse_acl_expr((const char **)default_acl_list[index].expr, err);
1279 if (!acl_expr) {
1280 /* parse_acl_expr must have filled err here */
Willy Tarreau16fbe822007-06-17 11:54:31 +02001281 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001282 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001283
1284 name = strdup(acl_name);
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001285 if (!name) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001286 memprintf(err, "out of memory when building default ACL '%s'", acl_name);
Willy Tarreau16fbe822007-06-17 11:54:31 +02001287 goto out_free_acl_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001288 }
1289
Willy Tarreau16fbe822007-06-17 11:54:31 +02001290 cur_acl = (struct acl *)calloc(1, sizeof(*cur_acl));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001291 if (cur_acl == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001292 memprintf(err, "out of memory when building default ACL '%s'", acl_name);
Willy Tarreau16fbe822007-06-17 11:54:31 +02001293 goto out_free_name;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001294 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001295
1296 cur_acl->name = name;
Willy Tarreaua55b7dc2009-07-12 09:21:30 +02001297 cur_acl->requires |= acl_expr->kw->requires;
Willy Tarreau16fbe822007-06-17 11:54:31 +02001298 LIST_INIT(&cur_acl->expr);
1299 LIST_ADDQ(&cur_acl->expr, &acl_expr->list);
1300 if (known_acl)
1301 LIST_ADDQ(known_acl, &cur_acl->list);
1302
1303 return cur_acl;
1304
1305 out_free_name:
1306 free(name);
1307 out_free_acl_expr:
1308 prune_acl_expr(acl_expr);
1309 free(acl_expr);
1310 out_return:
1311 return NULL;
1312}
Willy Tarreaua84d3742007-05-07 00:36:48 +02001313
1314/* Purge everything in the acl_cond <cond>, then return <cond>. */
1315struct acl_cond *prune_acl_cond(struct acl_cond *cond)
1316{
1317 struct acl_term_suite *suite, *tmp_suite;
1318 struct acl_term *term, *tmp_term;
1319
1320 /* iterate through all term suites and free all terms and all suites */
1321 list_for_each_entry_safe(suite, tmp_suite, &cond->suites, list) {
1322 list_for_each_entry_safe(term, tmp_term, &suite->terms, list)
1323 free(term);
1324 free(suite);
1325 }
1326 return cond;
1327}
1328
1329/* Parse an ACL condition starting at <args>[0], relying on a list of already
1330 * known ACLs passed in <known_acl>. The new condition is returned (or NULL in
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001331 * case of low memory). Supports multiple conditions separated by "or". If
1332 * <err> is not NULL, it will be filled with a pointer to an error message in
1333 * case of error, that the caller is responsible for freeing. The initial
1334 * location must either be freeable or NULL.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001335 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001336struct acl_cond *parse_acl_cond(const char **args, struct list *known_acl, int pol, char **err)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001337{
1338 __label__ out_return, out_free_suite, out_free_term;
Willy Tarreau74b98a82007-06-16 19:35:18 +02001339 int arg, neg;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001340 const char *word;
1341 struct acl *cur_acl;
1342 struct acl_term *cur_term;
1343 struct acl_term_suite *cur_suite;
1344 struct acl_cond *cond;
1345
1346 cond = (struct acl_cond *)calloc(1, sizeof(*cond));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001347 if (cond == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001348 memprintf(err, "out of memory when parsing condition");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001349 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001350 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001351
1352 LIST_INIT(&cond->list);
1353 LIST_INIT(&cond->suites);
1354 cond->pol = pol;
1355
1356 cur_suite = NULL;
Willy Tarreau74b98a82007-06-16 19:35:18 +02001357 neg = 0;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001358 for (arg = 0; *args[arg]; arg++) {
1359 word = args[arg];
1360
1361 /* remove as many exclamation marks as we can */
1362 while (*word == '!') {
1363 neg = !neg;
1364 word++;
1365 }
1366
1367 /* an empty word is allowed because we cannot force the user to
1368 * always think about not leaving exclamation marks alone.
1369 */
1370 if (!*word)
1371 continue;
1372
Willy Tarreau16fbe822007-06-17 11:54:31 +02001373 if (strcasecmp(word, "or") == 0 || strcmp(word, "||") == 0) {
Willy Tarreaua84d3742007-05-07 00:36:48 +02001374 /* new term suite */
1375 cur_suite = NULL;
1376 neg = 0;
1377 continue;
1378 }
1379
Willy Tarreau95fa4692010-02-01 13:05:50 +01001380 if (strcmp(word, "{") == 0) {
1381 /* we may have a complete ACL expression between two braces,
1382 * find the last one.
1383 */
1384 int arg_end = arg + 1;
1385 const char **args_new;
1386
1387 while (*args[arg_end] && strcmp(args[arg_end], "}") != 0)
1388 arg_end++;
1389
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001390 if (!*args[arg_end]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001391 memprintf(err, "missing closing '}' in condition");
Willy Tarreau95fa4692010-02-01 13:05:50 +01001392 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001393 }
Willy Tarreau95fa4692010-02-01 13:05:50 +01001394
1395 args_new = calloc(1, (arg_end - arg + 1) * sizeof(*args_new));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001396 if (!args_new) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001397 memprintf(err, "out of memory when parsing condition");
Willy Tarreau95fa4692010-02-01 13:05:50 +01001398 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001399 }
Willy Tarreau95fa4692010-02-01 13:05:50 +01001400
Willy Tarreau2a56c5e2010-03-15 16:13:29 +01001401 args_new[0] = "";
Willy Tarreau95fa4692010-02-01 13:05:50 +01001402 memcpy(args_new + 1, args + arg + 1, (arg_end - arg) * sizeof(*args_new));
1403 args_new[arg_end - arg] = "";
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001404 cur_acl = parse_acl(args_new, known_acl, err);
Willy Tarreau95fa4692010-02-01 13:05:50 +01001405 free(args_new);
1406
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001407 if (!cur_acl) {
1408 /* note that parse_acl() must have filled <err> here */
Willy Tarreau16fbe822007-06-17 11:54:31 +02001409 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001410 }
Willy Tarreau95fa4692010-02-01 13:05:50 +01001411 arg = arg_end;
1412 }
1413 else {
1414 /* search for <word> in the known ACL names. If we do not find
1415 * it, let's look for it in the default ACLs, and if found, add
1416 * it to the list of ACLs of this proxy. This makes it possible
1417 * to override them.
1418 */
1419 cur_acl = find_acl_by_name(word, known_acl);
1420 if (cur_acl == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001421 cur_acl = find_acl_default(word, known_acl, err);
1422 if (cur_acl == NULL) {
1423 /* note that find_acl_default() must have filled <err> here */
Willy Tarreau95fa4692010-02-01 13:05:50 +01001424 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001425 }
Willy Tarreau95fa4692010-02-01 13:05:50 +01001426 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001427 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001428
1429 cur_term = (struct acl_term *)calloc(1, sizeof(*cur_term));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001430 if (cur_term == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001431 memprintf(err, "out of memory when parsing condition");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001432 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001433 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001434
1435 cur_term->acl = cur_acl;
1436 cur_term->neg = neg;
Willy Tarreaua9802632008-07-25 19:13:19 +02001437 cond->requires |= cur_acl->requires;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001438
1439 if (!cur_suite) {
1440 cur_suite = (struct acl_term_suite *)calloc(1, sizeof(*cur_suite));
Willy Tarreauf678b7f2013-01-24 00:25:39 +01001441 if (cur_suite == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001442 memprintf(err, "out of memory when parsing condition");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001443 goto out_free_term;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001444 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001445 LIST_INIT(&cur_suite->terms);
1446 LIST_ADDQ(&cond->suites, &cur_suite->list);
1447 }
1448 LIST_ADDQ(&cur_suite->terms, &cur_term->list);
Willy Tarreau74b98a82007-06-16 19:35:18 +02001449 neg = 0;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001450 }
1451
1452 return cond;
1453
1454 out_free_term:
1455 free(cur_term);
1456 out_free_suite:
1457 prune_acl_cond(cond);
1458 free(cond);
1459 out_return:
1460 return NULL;
1461}
1462
Willy Tarreau2bbba412010-01-28 16:48:33 +01001463/* Builds an ACL condition starting at the if/unless keyword. The complete
1464 * condition is returned. NULL is returned in case of error or if the first
1465 * word is neither "if" nor "unless". It automatically sets the file name and
1466 * the line number in the condition for better error reporting, and adds the
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001467 * ACL requirements to the proxy's acl_requires. If <err> is not NULL, it will
1468 * be filled with a pointer to an error message in case of error, that the
1469 * caller is responsible for freeing. The initial location must either be
1470 * freeable or NULL.
Willy Tarreau2bbba412010-01-28 16:48:33 +01001471 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001472struct acl_cond *build_acl_cond(const char *file, int line, struct proxy *px, const char **args, char **err)
Willy Tarreau2bbba412010-01-28 16:48:33 +01001473{
1474 int pol = ACL_COND_NONE;
1475 struct acl_cond *cond = NULL;
1476
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001477 if (err)
1478 *err = NULL;
1479
Willy Tarreau2bbba412010-01-28 16:48:33 +01001480 if (!strcmp(*args, "if")) {
1481 pol = ACL_COND_IF;
1482 args++;
1483 }
1484 else if (!strcmp(*args, "unless")) {
1485 pol = ACL_COND_UNLESS;
1486 args++;
1487 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001488 else {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001489 memprintf(err, "conditions must start with either 'if' or 'unless'");
Willy Tarreau2bbba412010-01-28 16:48:33 +01001490 return NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001491 }
Willy Tarreau2bbba412010-01-28 16:48:33 +01001492
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001493 cond = parse_acl_cond(args, &px->acl, pol, err);
1494 if (!cond) {
1495 /* note that parse_acl_cond must have filled <err> here */
Willy Tarreau2bbba412010-01-28 16:48:33 +01001496 return NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001497 }
Willy Tarreau2bbba412010-01-28 16:48:33 +01001498
1499 cond->file = file;
1500 cond->line = line;
1501 px->acl_requires |= cond->requires;
1502
1503 return cond;
1504}
1505
Willy Tarreau11382812008-07-09 16:18:21 +02001506/* Execute condition <cond> and return either ACL_PAT_FAIL, ACL_PAT_MISS or
Willy Tarreaub6866442008-07-14 23:54:42 +02001507 * ACL_PAT_PASS depending on the test results. ACL_PAT_MISS may only be
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001508 * returned if <opt> does not contain SMP_OPT_FINAL, indicating that incomplete
Willy Tarreau7a777ed2012-04-26 11:44:02 +02001509 * data is being examined. The function automatically sets SMP_OPT_ITERATE.
Willy Tarreaub6866442008-07-14 23:54:42 +02001510 * This function only computes the condition, it does not apply the polarity
1511 * required by IF/UNLESS, it's up to the caller to do this using something like
1512 * this :
Willy Tarreau11382812008-07-09 16:18:21 +02001513 *
1514 * res = acl_pass(res);
Willy Tarreaub6866442008-07-14 23:54:42 +02001515 * if (res == ACL_PAT_MISS)
1516 * return 0;
Willy Tarreau11382812008-07-09 16:18:21 +02001517 * if (cond->pol == ACL_COND_UNLESS)
1518 * res = !res;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001519 */
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001520int acl_exec_cond(struct acl_cond *cond, struct proxy *px, struct session *l4, void *l7, unsigned int opt)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001521{
1522 __label__ fetch_next;
1523 struct acl_term_suite *suite;
1524 struct acl_term *term;
1525 struct acl_expr *expr;
1526 struct acl *acl;
1527 struct acl_pattern *pattern;
Willy Tarreau37406352012-04-23 16:16:37 +02001528 struct sample smp;
Willy Tarreau11382812008-07-09 16:18:21 +02001529 int acl_res, suite_res, cond_res;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001530
Willy Tarreau7a777ed2012-04-26 11:44:02 +02001531 /* ACLs are iterated over all values, so let's always set the flag to
1532 * indicate this to the fetch functions.
1533 */
1534 opt |= SMP_OPT_ITERATE;
1535
Willy Tarreau11382812008-07-09 16:18:21 +02001536 /* We're doing a logical OR between conditions so we initialize to FAIL.
1537 * The MISS status is propagated down from the suites.
1538 */
Willy Tarreaua84d3742007-05-07 00:36:48 +02001539 cond_res = ACL_PAT_FAIL;
1540 list_for_each_entry(suite, &cond->suites, list) {
Willy Tarreau11382812008-07-09 16:18:21 +02001541 /* Evaluate condition suite <suite>. We stop at the first term
1542 * which returns ACL_PAT_FAIL. The MISS status is still propagated
1543 * in case of uncertainty in the result.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001544 */
1545
1546 /* we're doing a logical AND between terms, so we must set the
1547 * initial value to PASS.
1548 */
1549 suite_res = ACL_PAT_PASS;
1550 list_for_each_entry(term, &suite->terms, list) {
1551 acl = term->acl;
1552
1553 /* FIXME: use cache !
1554 * check acl->cache_idx for this.
1555 */
1556
1557 /* ACL result not cached. Let's scan all the expressions
1558 * and use the first one to match.
1559 */
1560 acl_res = ACL_PAT_FAIL;
1561 list_for_each_entry(expr, &acl->expr, list) {
Willy Tarreaud41f8d82007-06-10 10:06:18 +02001562 /* we need to reset context and flags */
Willy Tarreau37406352012-04-23 16:16:37 +02001563 memset(&smp, 0, sizeof(smp));
Willy Tarreaua84d3742007-05-07 00:36:48 +02001564 fetch_next:
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001565 if (!expr->kw->smp->process(px, l4, l7, opt, expr->args, &smp)) {
Willy Tarreaub6866442008-07-14 23:54:42 +02001566 /* maybe we could not fetch because of missing data */
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001567 if (smp.flags & SMP_F_MAY_CHANGE && !(opt & SMP_OPT_FINAL))
Willy Tarreaub6866442008-07-14 23:54:42 +02001568 acl_res |= ACL_PAT_MISS;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001569 continue;
Willy Tarreaub6866442008-07-14 23:54:42 +02001570 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001571
Willy Tarreau197e10a2012-04-23 19:18:42 +02001572 if (smp.type == SMP_T_BOOL) {
1573 if (smp.data.uint)
Willy Tarreaua79534f2008-07-20 10:13:37 +02001574 acl_res |= ACL_PAT_PASS;
1575 else
1576 acl_res |= ACL_PAT_FAIL;
1577 }
1578 else {
Willy Tarreau020534d2010-05-16 21:45:45 +02001579 if (!eb_is_empty(&expr->pattern_tree)) {
Willy Tarreauc4262962010-05-10 23:42:40 +02001580 /* a tree is present, let's check what type it is */
1581 if (expr->kw->match == acl_match_str)
Willy Tarreau37406352012-04-23 16:16:37 +02001582 acl_res |= acl_lookup_str(&smp, expr) ? ACL_PAT_PASS : ACL_PAT_FAIL;
Willy Tarreaub337b532010-05-13 20:03:41 +02001583 else if (expr->kw->match == acl_match_ip)
Willy Tarreau37406352012-04-23 16:16:37 +02001584 acl_res |= acl_lookup_ip(&smp, expr) ? ACL_PAT_PASS : ACL_PAT_FAIL;
Willy Tarreauc4262962010-05-10 23:42:40 +02001585 }
1586
Willy Tarreaua79534f2008-07-20 10:13:37 +02001587 /* call the match() function for all tests on this value */
1588 list_for_each_entry(pattern, &expr->patterns, list) {
Willy Tarreaua79534f2008-07-20 10:13:37 +02001589 if (acl_res == ACL_PAT_PASS)
1590 break;
Willy Tarreau37406352012-04-23 16:16:37 +02001591 acl_res |= expr->kw->match(&smp, pattern);
Willy Tarreaua79534f2008-07-20 10:13:37 +02001592 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001593 }
1594 /*
Willy Tarreau11382812008-07-09 16:18:21 +02001595 * OK now acl_res holds the result of this expression
1596 * as one of ACL_PAT_FAIL, ACL_PAT_MISS or ACL_PAT_PASS.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001597 *
Willy Tarreau11382812008-07-09 16:18:21 +02001598 * Then if (!MISS) we can cache the result, and put
Willy Tarreau37406352012-04-23 16:16:37 +02001599 * (smp.flags & SMP_F_VOLATILE) in the cache flags.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001600 *
1601 * FIXME: implement cache.
1602 *
1603 */
1604
Willy Tarreau11382812008-07-09 16:18:21 +02001605 /* we're ORing these terms, so a single PASS is enough */
1606 if (acl_res == ACL_PAT_PASS)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001607 break;
1608
Willy Tarreau37406352012-04-23 16:16:37 +02001609 if (smp.flags & SMP_F_NOT_LAST)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001610 goto fetch_next;
Willy Tarreaub6866442008-07-14 23:54:42 +02001611
1612 /* sometimes we know the fetched data is subject to change
1613 * later and give another chance for a new match (eg: request
1614 * size, time, ...)
1615 */
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001616 if (smp.flags & SMP_F_MAY_CHANGE && !(opt & SMP_OPT_FINAL))
Willy Tarreaub6866442008-07-14 23:54:42 +02001617 acl_res |= ACL_PAT_MISS;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001618 }
1619 /*
1620 * Here we have the result of an ACL (cached or not).
1621 * ACLs are combined, negated or not, to form conditions.
1622 */
1623
Willy Tarreaua84d3742007-05-07 00:36:48 +02001624 if (term->neg)
Willy Tarreau11382812008-07-09 16:18:21 +02001625 acl_res = acl_neg(acl_res);
Willy Tarreaua84d3742007-05-07 00:36:48 +02001626
1627 suite_res &= acl_res;
Willy Tarreau11382812008-07-09 16:18:21 +02001628
1629 /* we're ANDing these terms, so a single FAIL is enough */
1630 if (suite_res == ACL_PAT_FAIL)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001631 break;
1632 }
1633 cond_res |= suite_res;
Willy Tarreau11382812008-07-09 16:18:21 +02001634
1635 /* we're ORing these terms, so a single PASS is enough */
1636 if (cond_res == ACL_PAT_PASS)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001637 break;
1638 }
Willy Tarreau11382812008-07-09 16:18:21 +02001639 return cond_res;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001640}
1641
1642
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001643/* Reports a pointer to the first ACL used in condition <cond> which requires
1644 * at least one of the USE_FLAGS in <require>. Returns NULL if none matches.
1645 * The construct is almost the same as for acl_exec_cond() since we're walking
1646 * down the ACL tree as well. It is important that the tree is really walked
1647 * through and never cached, because that way, this function can be used as a
1648 * late check.
1649 */
Willy Tarreauf1e98b82010-01-28 17:59:39 +01001650struct acl *cond_find_require(const struct acl_cond *cond, unsigned int require)
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001651{
1652 struct acl_term_suite *suite;
1653 struct acl_term *term;
1654 struct acl *acl;
1655
1656 list_for_each_entry(suite, &cond->suites, list) {
1657 list_for_each_entry(term, &suite->terms, list) {
1658 acl = term->acl;
1659 if (acl->requires & require)
1660 return acl;
1661 }
1662 }
1663 return NULL;
1664}
1665
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001666/*
1667 * Find targets for userlist and groups in acl. Function returns the number
1668 * of errors or OK if everything is fine.
1669 */
1670int
1671acl_find_targets(struct proxy *p)
1672{
1673
1674 struct acl *acl;
1675 struct acl_expr *expr;
1676 struct acl_pattern *pattern;
1677 struct userlist *ul;
Willy Tarreau63364ee2012-04-19 19:11:13 +02001678 struct arg *arg;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001679 int cfgerr = 0;
1680
1681 list_for_each_entry(acl, &p->acl, list) {
1682 list_for_each_entry(expr, &acl->expr, list) {
Willy Tarreau2e845be2012-10-19 19:49:09 +02001683 for (arg = expr->args; arg && arg->type != ARGT_STOP; arg++) {
1684 if (!arg->unresolved)
Willy Tarreau496aa012012-06-01 10:38:29 +02001685 continue;
Willy Tarreau63364ee2012-04-19 19:11:13 +02001686 else if (arg->type == ARGT_SRV) {
1687 struct proxy *px;
1688 struct server *srv;
1689 char *pname, *sname;
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001690
Willy Tarreau7d1df412012-11-23 23:47:36 +01001691 if (!arg->data.str.len) {
Willy Tarreau63364ee2012-04-19 19:11:13 +02001692 Alert("proxy %s: acl '%s' %s(): missing server name.\n",
1693 p->id, acl->name, expr->kw->kw);
1694 cfgerr++;
1695 continue;
1696 }
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001697
Willy Tarreau7d1df412012-11-23 23:47:36 +01001698 pname = arg->data.str.str;
Willy Tarreau63364ee2012-04-19 19:11:13 +02001699 sname = strrchr(pname, '/');
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001700
Willy Tarreau63364ee2012-04-19 19:11:13 +02001701 if (sname)
1702 *sname++ = '\0';
1703 else {
1704 sname = pname;
1705 pname = NULL;
1706 }
1707
1708 px = p;
1709 if (pname) {
1710 px = findproxy(pname, PR_CAP_BE);
1711 if (!px) {
1712 Alert("proxy %s: acl '%s' %s(): unable to find proxy '%s'.\n",
1713 p->id, acl->name, expr->kw->kw, pname);
1714 cfgerr++;
1715 continue;
1716 }
1717 }
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001718
Willy Tarreau63364ee2012-04-19 19:11:13 +02001719 srv = findserver(px, sname);
1720 if (!srv) {
1721 Alert("proxy %s: acl '%s' %s(): unable to find server '%s'.\n",
1722 p->id, acl->name, expr->kw->kw, sname);
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001723 cfgerr++;
1724 continue;
1725 }
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001726
Willy Tarreau7d1df412012-11-23 23:47:36 +01001727 free(arg->data.str.str);
1728 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001729 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001730 arg->data.srv = srv;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001731 }
1732 else if (arg->type == ARGT_FE) {
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001733 struct proxy *prx = p;
1734 char *pname = p->id;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001735
Willy Tarreau7d1df412012-11-23 23:47:36 +01001736 if (arg->data.str.len) {
1737 pname = arg->data.str.str;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001738 prx = findproxy(pname, PR_CAP_FE);
Willy Tarreaud28c3532012-04-19 19:28:33 +02001739 }
1740
Willy Tarreaud28c3532012-04-19 19:28:33 +02001741 if (!prx) {
1742 Alert("proxy %s: acl '%s' %s(): unable to find frontend '%s'.\n",
1743 p->id, acl->name, expr->kw->kw, pname);
1744 cfgerr++;
1745 continue;
1746 }
1747
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001748 if (!(prx->cap & PR_CAP_FE)) {
1749 Alert("proxy %s: acl '%s' %s(): proxy '%s' has no frontend capability.\n",
1750 p->id, acl->name, expr->kw->kw, pname);
1751 cfgerr++;
1752 continue;
1753 }
1754
Willy Tarreau7d1df412012-11-23 23:47:36 +01001755 free(arg->data.str.str);
1756 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001757 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001758 arg->data.prx = prx;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001759 }
1760 else if (arg->type == ARGT_BE) {
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001761 struct proxy *prx = p;
1762 char *pname = p->id;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001763
Willy Tarreau7d1df412012-11-23 23:47:36 +01001764 if (arg->data.str.len) {
1765 pname = arg->data.str.str;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001766 prx = findproxy(pname, PR_CAP_BE);
Willy Tarreaud28c3532012-04-19 19:28:33 +02001767 }
1768
Willy Tarreaud28c3532012-04-19 19:28:33 +02001769 if (!prx) {
1770 Alert("proxy %s: acl '%s' %s(): unable to find backend '%s'.\n",
1771 p->id, acl->name, expr->kw->kw, pname);
1772 cfgerr++;
1773 continue;
1774 }
1775
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001776 if (!(prx->cap & PR_CAP_BE)) {
1777 Alert("proxy %s: acl '%s' %s(): proxy '%s' has no backend capability.\n",
1778 p->id, acl->name, expr->kw->kw, pname);
1779 cfgerr++;
1780 continue;
1781 }
1782
Willy Tarreau7d1df412012-11-23 23:47:36 +01001783 free(arg->data.str.str);
1784 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001785 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001786 arg->data.prx = prx;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001787 }
1788 else if (arg->type == ARGT_TAB) {
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001789 struct proxy *prx = p;
1790 char *pname = p->id;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001791
Willy Tarreau7d1df412012-11-23 23:47:36 +01001792 if (arg->data.str.len) {
1793 pname = arg->data.str.str;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001794 prx = find_stktable(pname);
Willy Tarreaud28c3532012-04-19 19:28:33 +02001795 }
1796
Willy Tarreaud28c3532012-04-19 19:28:33 +02001797 if (!prx) {
1798 Alert("proxy %s: acl '%s' %s(): unable to find table '%s'.\n",
1799 p->id, acl->name, expr->kw->kw, pname);
1800 cfgerr++;
1801 continue;
1802 }
1803
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001804
1805 if (!prx->table.size) {
1806 Alert("proxy %s: acl '%s' %s(): no table in proxy '%s'.\n",
1807 p->id, acl->name, expr->kw->kw, pname);
1808 cfgerr++;
1809 continue;
1810 }
1811
Willy Tarreau7d1df412012-11-23 23:47:36 +01001812 free(arg->data.str.str);
1813 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001814 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001815 arg->data.prx = prx;
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001816 }
Willy Tarreau63364ee2012-04-19 19:11:13 +02001817 else if (arg->type == ARGT_USR) {
Willy Tarreau7d1df412012-11-23 23:47:36 +01001818 if (!arg->data.str.len) {
Willy Tarreau63364ee2012-04-19 19:11:13 +02001819 Alert("proxy %s: acl '%s' %s(): missing userlist name.\n",
1820 p->id, acl->name, expr->kw->kw);
1821 cfgerr++;
1822 continue;
1823 }
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001824
Willy Tarreau63364ee2012-04-19 19:11:13 +02001825 if (p->uri_auth && p->uri_auth->userlist &&
Willy Tarreau7d1df412012-11-23 23:47:36 +01001826 !strcmp(p->uri_auth->userlist->name, arg->data.str.str))
Willy Tarreau63364ee2012-04-19 19:11:13 +02001827 ul = p->uri_auth->userlist;
1828 else
Willy Tarreau7d1df412012-11-23 23:47:36 +01001829 ul = auth_find_userlist(arg->data.str.str);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001830
Willy Tarreau63364ee2012-04-19 19:11:13 +02001831 if (!ul) {
1832 Alert("proxy %s: acl '%s' %s(%s): unable to find userlist.\n",
Willy Tarreau7d1df412012-11-23 23:47:36 +01001833 p->id, acl->name, expr->kw->kw, arg->data.str.str);
Willy Tarreau63364ee2012-04-19 19:11:13 +02001834 cfgerr++;
1835 continue;
1836 }
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001837
Willy Tarreau7d1df412012-11-23 23:47:36 +01001838 free(arg->data.str.str);
1839 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001840 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001841 arg->data.usr = ul;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001842 }
Willy Tarreau63364ee2012-04-19 19:11:13 +02001843 } /* end of args processing */
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001844
Willy Tarreau46b39d02012-05-10 23:40:14 +02001845 /* don't try to resolve groups if we're not certain of having
1846 * resolved userlists first.
1847 */
1848 if (cfgerr)
1849 break;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001850
1851 if (!strcmp(expr->kw->kw, "http_auth_group")) {
Willy Tarreau63364ee2012-04-19 19:11:13 +02001852 /* note: argument resolved above thanks to ARGT_USR */
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001853
1854 if (LIST_ISEMPTY(&expr->patterns)) {
1855 Alert("proxy %s: acl %s %s(): no groups specified.\n",
1856 p->id, acl->name, expr->kw->kw);
1857 cfgerr++;
1858 continue;
1859 }
1860
1861 list_for_each_entry(pattern, &expr->patterns, list) {
Willy Tarreau7d1df412012-11-23 23:47:36 +01001862 /* this keyword only has one argument */
Willy Tarreau34db1082012-04-19 17:16:54 +02001863 pattern->val.group_mask = auth_resolve_groups(expr->args->data.usr, pattern->ptr.str);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001864
1865 free(pattern->ptr.str);
1866 pattern->ptr.str = NULL;
1867 pattern->len = 0;
1868
1869 if (!pattern->val.group_mask) {
1870 Alert("proxy %s: acl %s %s(): invalid group(s).\n",
1871 p->id, acl->name, expr->kw->kw);
1872 cfgerr++;
1873 continue;
1874 }
1875 }
1876 }
1877 }
1878 }
1879
1880 return cfgerr;
1881}
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001882
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001883/* initializes ACLs by resolving the sample fetch names they rely upon.
1884 * Returns 0 on success, otherwise an error.
1885 */
1886int init_acl()
1887{
1888 int err = 0;
1889 int index;
1890 const char *name;
1891 struct acl_kw_list *kwl;
1892 struct sample_fetch *smp;
1893
1894 list_for_each_entry(kwl, &acl_keywords.list, list) {
1895 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1896 name = kwl->kw[index].fetch_kw;
1897 if (!name)
1898 name = kwl->kw[index].kw;
1899
1900 smp = find_sample_fetch(name, strlen(name));
1901 if (!smp) {
1902 Alert("Critical internal error: ACL keyword '%s' relies on sample fetch '%s' which was not registered!\n",
1903 kwl->kw[index].kw, name);
1904 err++;
1905 continue;
1906 }
1907 kwl->kw[index].smp = smp;
1908 }
1909 }
1910 return err;
1911}
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001912
Willy Tarreaua84d3742007-05-07 00:36:48 +02001913/************************************************************************/
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001914/* All supported sample fetch functions must be declared here */
Willy Tarreaua84d3742007-05-07 00:36:48 +02001915/************************************************************************/
1916
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001917/* force TRUE to be returned at the fetch level */
1918static int
1919smp_fetch_true(struct proxy *px, struct session *s, void *l7, unsigned int opt,
1920 const struct arg *args, struct sample *smp)
1921{
1922 smp->type = SMP_T_BOOL;
1923 smp->data.uint = 1;
1924 return 1;
1925}
1926
1927/* force FALSE to be returned at the fetch level */
1928static int
1929smp_fetch_false(struct proxy *px, struct session *s, void *l7, unsigned int opt,
1930 const struct arg *args, struct sample *smp)
1931{
1932 smp->type = SMP_T_BOOL;
1933 smp->data.uint = 0;
1934 return 1;
1935}
1936
1937
1938/************************************************************************/
1939/* All supported sample and ACL keywords must be declared here. */
1940/************************************************************************/
1941
1942/* Note: must not be declared <const> as its list will be overwritten.
1943 * Note: fetches that may return multiple types must be declared as the lowest
1944 * common denominator, the type that can be casted into all other ones. For
1945 * instance IPv4/IPv6 must be declared IPv4.
1946 */
1947static struct sample_fetch_kw_list smp_kws = {{ },{
1948 { "always_false", smp_fetch_false, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN },
1949 { "always_true", smp_fetch_true, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN },
1950 { /* END */ },
1951}};
1952
1953
Willy Tarreau61612d42012-04-19 18:42:05 +02001954/* Note: must not be declared <const> as its list will be overwritten.
1955 * Please take care of keeping this list alphabetically sorted.
1956 */
Willy Tarreaua84d3742007-05-07 00:36:48 +02001957static struct acl_kw_list acl_kws = {{ },{
Willy Tarreauc48c90d2013-01-11 16:56:48 +01001958 { "always_false", NULL, acl_parse_nothing, acl_match_nothing, ACL_USE_NOTHING },
1959 { "always_true", NULL, acl_parse_nothing, acl_match_nothing, ACL_USE_NOTHING },
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001960 { /* END */ },
Willy Tarreaua84d3742007-05-07 00:36:48 +02001961}};
1962
1963
1964__attribute__((constructor))
1965static void __acl_init(void)
1966{
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001967 sample_register_fetches(&smp_kws);
Willy Tarreaua84d3742007-05-07 00:36:48 +02001968 acl_register_keywords(&acl_kws);
1969}
1970
1971
1972/*
1973 * Local variables:
1974 * c-indent-level: 8
1975 * c-basic-offset: 8
1976 * End:
1977 */