blob: a4215fc2bd94b769c662186dd4e8f9dd075aed39 [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 Tarreaua91d0a52013-03-25 08:12:18 +01001212 /* We want to know what features the ACL needs (typically HTTP parsing),
1213 * and where it may be used. If an ACL relies on multiple matches, it is
1214 * OK if at least one of them may match in the context where it is used.
1215 */
1216 cur_acl->use |= acl_expr->kw->smp->use;
1217 cur_acl->val |= acl_expr->kw->smp->val;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001218 LIST_ADDQ(&cur_acl->expr, &acl_expr->list);
1219 return cur_acl;
1220
1221 out_free_name:
1222 free(name);
1223 out_free_acl_expr:
1224 prune_acl_expr(acl_expr);
1225 free(acl_expr);
1226 out_return:
1227 return NULL;
1228}
1229
Willy Tarreau16fbe822007-06-17 11:54:31 +02001230/* Some useful ACLs provided by default. Only those used are allocated. */
1231
1232const struct {
1233 const char *name;
1234 const char *expr[4]; /* put enough for longest expression */
1235} default_acl_list[] = {
Willy Tarreau58393e12008-07-20 10:39:22 +02001236 { .name = "TRUE", .expr = {"always_true",""}},
1237 { .name = "FALSE", .expr = {"always_false",""}},
Willy Tarreau16fbe822007-06-17 11:54:31 +02001238 { .name = "LOCALHOST", .expr = {"src","127.0.0.1/8",""}},
Willy Tarreau2492d5b2009-07-11 00:06:00 +02001239 { .name = "HTTP", .expr = {"req_proto_http",""}},
Willy Tarreau16fbe822007-06-17 11:54:31 +02001240 { .name = "HTTP_1.0", .expr = {"req_ver","1.0",""}},
1241 { .name = "HTTP_1.1", .expr = {"req_ver","1.1",""}},
1242 { .name = "METH_CONNECT", .expr = {"method","CONNECT",""}},
1243 { .name = "METH_GET", .expr = {"method","GET","HEAD",""}},
1244 { .name = "METH_HEAD", .expr = {"method","HEAD",""}},
1245 { .name = "METH_OPTIONS", .expr = {"method","OPTIONS",""}},
1246 { .name = "METH_POST", .expr = {"method","POST",""}},
1247 { .name = "METH_TRACE", .expr = {"method","TRACE",""}},
1248 { .name = "HTTP_URL_ABS", .expr = {"url_reg","^[^/:]*://",""}},
1249 { .name = "HTTP_URL_SLASH", .expr = {"url_beg","/",""}},
1250 { .name = "HTTP_URL_STAR", .expr = {"url","*",""}},
1251 { .name = "HTTP_CONTENT", .expr = {"hdr_val(content-length)","gt","0",""}},
Emeric Brunbede3d02009-06-30 17:54:00 +02001252 { .name = "RDP_COOKIE", .expr = {"req_rdp_cookie_cnt","gt","0",""}},
Willy Tarreauc6317702008-07-20 09:29:50 +02001253 { .name = "REQ_CONTENT", .expr = {"req_len","gt","0",""}},
Willy Tarreaub6fb4202008-07-20 11:18:28 +02001254 { .name = "WAIT_END", .expr = {"wait_end",""}},
Willy Tarreau16fbe822007-06-17 11:54:31 +02001255 { .name = NULL, .expr = {""}}
1256};
1257
1258/* Find a default ACL from the default_acl list, compile it and return it.
1259 * If the ACL is not found, NULL is returned. In theory, it cannot fail,
1260 * except when default ACLs are broken, in which case it will return NULL.
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001261 * If <known_acl> is not NULL, the ACL will be queued at its tail. If <err> is
1262 * not NULL, it will be filled with an error message if an error occurs. This
1263 * pointer must be freeable or NULL.
Willy Tarreau16fbe822007-06-17 11:54:31 +02001264 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001265struct acl *find_acl_default(const char *acl_name, struct list *known_acl, char **err)
Willy Tarreau16fbe822007-06-17 11:54:31 +02001266{
1267 __label__ out_return, out_free_acl_expr, out_free_name;
1268 struct acl *cur_acl;
1269 struct acl_expr *acl_expr;
1270 char *name;
1271 int index;
1272
1273 for (index = 0; default_acl_list[index].name != NULL; index++) {
1274 if (strcmp(acl_name, default_acl_list[index].name) == 0)
1275 break;
1276 }
1277
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001278 if (default_acl_list[index].name == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001279 memprintf(err, "no such ACL : '%s'", acl_name);
Willy Tarreau16fbe822007-06-17 11:54:31 +02001280 return NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001281 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001282
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001283 acl_expr = parse_acl_expr((const char **)default_acl_list[index].expr, err);
1284 if (!acl_expr) {
1285 /* parse_acl_expr must have filled err here */
Willy Tarreau16fbe822007-06-17 11:54:31 +02001286 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001287 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001288
1289 name = strdup(acl_name);
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001290 if (!name) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001291 memprintf(err, "out of memory when building default ACL '%s'", acl_name);
Willy Tarreau16fbe822007-06-17 11:54:31 +02001292 goto out_free_acl_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001293 }
1294
Willy Tarreau16fbe822007-06-17 11:54:31 +02001295 cur_acl = (struct acl *)calloc(1, sizeof(*cur_acl));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001296 if (cur_acl == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001297 memprintf(err, "out of memory when building default ACL '%s'", acl_name);
Willy Tarreau16fbe822007-06-17 11:54:31 +02001298 goto out_free_name;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001299 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001300
1301 cur_acl->name = name;
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001302 cur_acl->use |= acl_expr->kw->smp->use;
1303 cur_acl->val |= acl_expr->kw->smp->val;
Willy Tarreau16fbe822007-06-17 11:54:31 +02001304 LIST_INIT(&cur_acl->expr);
1305 LIST_ADDQ(&cur_acl->expr, &acl_expr->list);
1306 if (known_acl)
1307 LIST_ADDQ(known_acl, &cur_acl->list);
1308
1309 return cur_acl;
1310
1311 out_free_name:
1312 free(name);
1313 out_free_acl_expr:
1314 prune_acl_expr(acl_expr);
1315 free(acl_expr);
1316 out_return:
1317 return NULL;
1318}
Willy Tarreaua84d3742007-05-07 00:36:48 +02001319
1320/* Purge everything in the acl_cond <cond>, then return <cond>. */
1321struct acl_cond *prune_acl_cond(struct acl_cond *cond)
1322{
1323 struct acl_term_suite *suite, *tmp_suite;
1324 struct acl_term *term, *tmp_term;
1325
1326 /* iterate through all term suites and free all terms and all suites */
1327 list_for_each_entry_safe(suite, tmp_suite, &cond->suites, list) {
1328 list_for_each_entry_safe(term, tmp_term, &suite->terms, list)
1329 free(term);
1330 free(suite);
1331 }
1332 return cond;
1333}
1334
1335/* Parse an ACL condition starting at <args>[0], relying on a list of already
1336 * known ACLs passed in <known_acl>. The new condition is returned (or NULL in
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001337 * case of low memory). Supports multiple conditions separated by "or". If
1338 * <err> is not NULL, it will be filled with a pointer to an error message in
1339 * case of error, that the caller is responsible for freeing. The initial
1340 * location must either be freeable or NULL.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001341 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001342struct acl_cond *parse_acl_cond(const char **args, struct list *known_acl, int pol, char **err)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001343{
1344 __label__ out_return, out_free_suite, out_free_term;
Willy Tarreau74b98a82007-06-16 19:35:18 +02001345 int arg, neg;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001346 const char *word;
1347 struct acl *cur_acl;
1348 struct acl_term *cur_term;
1349 struct acl_term_suite *cur_suite;
1350 struct acl_cond *cond;
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001351 unsigned int suite_val;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001352
1353 cond = (struct acl_cond *)calloc(1, sizeof(*cond));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001354 if (cond == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001355 memprintf(err, "out of memory when parsing condition");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001356 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001357 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001358
1359 LIST_INIT(&cond->list);
1360 LIST_INIT(&cond->suites);
1361 cond->pol = pol;
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001362 cond->val = 0;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001363
1364 cur_suite = NULL;
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001365 suite_val = ~0U;
Willy Tarreau74b98a82007-06-16 19:35:18 +02001366 neg = 0;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001367 for (arg = 0; *args[arg]; arg++) {
1368 word = args[arg];
1369
1370 /* remove as many exclamation marks as we can */
1371 while (*word == '!') {
1372 neg = !neg;
1373 word++;
1374 }
1375
1376 /* an empty word is allowed because we cannot force the user to
1377 * always think about not leaving exclamation marks alone.
1378 */
1379 if (!*word)
1380 continue;
1381
Willy Tarreau16fbe822007-06-17 11:54:31 +02001382 if (strcasecmp(word, "or") == 0 || strcmp(word, "||") == 0) {
Willy Tarreaua84d3742007-05-07 00:36:48 +02001383 /* new term suite */
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001384 cond->val |= suite_val;
1385 suite_val = ~0U;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001386 cur_suite = NULL;
1387 neg = 0;
1388 continue;
1389 }
1390
Willy Tarreau95fa4692010-02-01 13:05:50 +01001391 if (strcmp(word, "{") == 0) {
1392 /* we may have a complete ACL expression between two braces,
1393 * find the last one.
1394 */
1395 int arg_end = arg + 1;
1396 const char **args_new;
1397
1398 while (*args[arg_end] && strcmp(args[arg_end], "}") != 0)
1399 arg_end++;
1400
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001401 if (!*args[arg_end]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001402 memprintf(err, "missing closing '}' in condition");
Willy Tarreau95fa4692010-02-01 13:05:50 +01001403 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001404 }
Willy Tarreau95fa4692010-02-01 13:05:50 +01001405
1406 args_new = calloc(1, (arg_end - arg + 1) * sizeof(*args_new));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001407 if (!args_new) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001408 memprintf(err, "out of memory when parsing condition");
Willy Tarreau95fa4692010-02-01 13:05:50 +01001409 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001410 }
Willy Tarreau95fa4692010-02-01 13:05:50 +01001411
Willy Tarreau2a56c5e2010-03-15 16:13:29 +01001412 args_new[0] = "";
Willy Tarreau95fa4692010-02-01 13:05:50 +01001413 memcpy(args_new + 1, args + arg + 1, (arg_end - arg) * sizeof(*args_new));
1414 args_new[arg_end - arg] = "";
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001415 cur_acl = parse_acl(args_new, known_acl, err);
Willy Tarreau95fa4692010-02-01 13:05:50 +01001416 free(args_new);
1417
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001418 if (!cur_acl) {
1419 /* note that parse_acl() must have filled <err> here */
Willy Tarreau16fbe822007-06-17 11:54:31 +02001420 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001421 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001422 word = args[arg + 1];
Willy Tarreau95fa4692010-02-01 13:05:50 +01001423 arg = arg_end;
1424 }
1425 else {
1426 /* search for <word> in the known ACL names. If we do not find
1427 * it, let's look for it in the default ACLs, and if found, add
1428 * it to the list of ACLs of this proxy. This makes it possible
1429 * to override them.
1430 */
1431 cur_acl = find_acl_by_name(word, known_acl);
1432 if (cur_acl == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001433 cur_acl = find_acl_default(word, known_acl, err);
1434 if (cur_acl == NULL) {
1435 /* note that find_acl_default() must have filled <err> here */
Willy Tarreau95fa4692010-02-01 13:05:50 +01001436 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001437 }
Willy Tarreau95fa4692010-02-01 13:05:50 +01001438 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001439 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001440
1441 cur_term = (struct acl_term *)calloc(1, sizeof(*cur_term));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001442 if (cur_term == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001443 memprintf(err, "out of memory when parsing condition");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001444 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001445 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001446
1447 cur_term->acl = cur_acl;
1448 cur_term->neg = neg;
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001449
1450 /* Here it is a bit complex. The acl_term_suite is a conjunction
1451 * of many terms. It may only be used if all of its terms are
1452 * usable at the same time. So the suite's validity domain is an
1453 * AND between all ACL keywords' ones. But, the global condition
1454 * is valid if at least one term suite is OK. So it's an OR between
1455 * all of their validity domains. We could emit a warning as soon
1456 * as suite_val is null because it means that the last ACL is not
1457 * compatible with the previous ones. Let's remain simple for now.
1458 */
1459 cond->use |= cur_acl->use;
1460 suite_val &= cur_acl->val;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001461
1462 if (!cur_suite) {
1463 cur_suite = (struct acl_term_suite *)calloc(1, sizeof(*cur_suite));
Willy Tarreauf678b7f2013-01-24 00:25:39 +01001464 if (cur_suite == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001465 memprintf(err, "out of memory when parsing condition");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001466 goto out_free_term;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001467 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001468 LIST_INIT(&cur_suite->terms);
1469 LIST_ADDQ(&cond->suites, &cur_suite->list);
1470 }
1471 LIST_ADDQ(&cur_suite->terms, &cur_term->list);
Willy Tarreau74b98a82007-06-16 19:35:18 +02001472 neg = 0;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001473 }
1474
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001475 cond->val |= suite_val;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001476 return cond;
1477
1478 out_free_term:
1479 free(cur_term);
1480 out_free_suite:
1481 prune_acl_cond(cond);
1482 free(cond);
1483 out_return:
1484 return NULL;
1485}
1486
Willy Tarreau2bbba412010-01-28 16:48:33 +01001487/* Builds an ACL condition starting at the if/unless keyword. The complete
1488 * condition is returned. NULL is returned in case of error or if the first
1489 * word is neither "if" nor "unless". It automatically sets the file name and
Willy Tarreau25320b22013-03-24 07:22:08 +01001490 * the line number in the condition for better error reporting, and sets the
1491 * HTTP intiailization requirements in the proxy. If <err> is not NULL, it will
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001492 * be filled with a pointer to an error message in case of error, that the
1493 * caller is responsible for freeing. The initial location must either be
1494 * freeable or NULL.
Willy Tarreau2bbba412010-01-28 16:48:33 +01001495 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001496struct 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 +01001497{
1498 int pol = ACL_COND_NONE;
1499 struct acl_cond *cond = NULL;
1500
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001501 if (err)
1502 *err = NULL;
1503
Willy Tarreau2bbba412010-01-28 16:48:33 +01001504 if (!strcmp(*args, "if")) {
1505 pol = ACL_COND_IF;
1506 args++;
1507 }
1508 else if (!strcmp(*args, "unless")) {
1509 pol = ACL_COND_UNLESS;
1510 args++;
1511 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001512 else {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001513 memprintf(err, "conditions must start with either 'if' or 'unless'");
Willy Tarreau2bbba412010-01-28 16:48:33 +01001514 return NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001515 }
Willy Tarreau2bbba412010-01-28 16:48:33 +01001516
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001517 cond = parse_acl_cond(args, &px->acl, pol, err);
1518 if (!cond) {
1519 /* note that parse_acl_cond must have filled <err> here */
Willy Tarreau2bbba412010-01-28 16:48:33 +01001520 return NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001521 }
Willy Tarreau2bbba412010-01-28 16:48:33 +01001522
1523 cond->file = file;
1524 cond->line = line;
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001525 px->http_needed |= !!(cond->use & SMP_USE_HTTP_ANY);
Willy Tarreau2bbba412010-01-28 16:48:33 +01001526 return cond;
1527}
1528
Willy Tarreau11382812008-07-09 16:18:21 +02001529/* Execute condition <cond> and return either ACL_PAT_FAIL, ACL_PAT_MISS or
Willy Tarreaub6866442008-07-14 23:54:42 +02001530 * ACL_PAT_PASS depending on the test results. ACL_PAT_MISS may only be
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001531 * returned if <opt> does not contain SMP_OPT_FINAL, indicating that incomplete
Willy Tarreau7a777ed2012-04-26 11:44:02 +02001532 * data is being examined. The function automatically sets SMP_OPT_ITERATE.
Willy Tarreaub6866442008-07-14 23:54:42 +02001533 * This function only computes the condition, it does not apply the polarity
1534 * required by IF/UNLESS, it's up to the caller to do this using something like
1535 * this :
Willy Tarreau11382812008-07-09 16:18:21 +02001536 *
1537 * res = acl_pass(res);
Willy Tarreaub6866442008-07-14 23:54:42 +02001538 * if (res == ACL_PAT_MISS)
1539 * return 0;
Willy Tarreau11382812008-07-09 16:18:21 +02001540 * if (cond->pol == ACL_COND_UNLESS)
1541 * res = !res;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001542 */
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001543int 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 +02001544{
1545 __label__ fetch_next;
1546 struct acl_term_suite *suite;
1547 struct acl_term *term;
1548 struct acl_expr *expr;
1549 struct acl *acl;
1550 struct acl_pattern *pattern;
Willy Tarreau37406352012-04-23 16:16:37 +02001551 struct sample smp;
Willy Tarreau11382812008-07-09 16:18:21 +02001552 int acl_res, suite_res, cond_res;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001553
Willy Tarreau7a777ed2012-04-26 11:44:02 +02001554 /* ACLs are iterated over all values, so let's always set the flag to
1555 * indicate this to the fetch functions.
1556 */
1557 opt |= SMP_OPT_ITERATE;
1558
Willy Tarreau11382812008-07-09 16:18:21 +02001559 /* We're doing a logical OR between conditions so we initialize to FAIL.
1560 * The MISS status is propagated down from the suites.
1561 */
Willy Tarreaua84d3742007-05-07 00:36:48 +02001562 cond_res = ACL_PAT_FAIL;
1563 list_for_each_entry(suite, &cond->suites, list) {
Willy Tarreau11382812008-07-09 16:18:21 +02001564 /* Evaluate condition suite <suite>. We stop at the first term
1565 * which returns ACL_PAT_FAIL. The MISS status is still propagated
1566 * in case of uncertainty in the result.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001567 */
1568
1569 /* we're doing a logical AND between terms, so we must set the
1570 * initial value to PASS.
1571 */
1572 suite_res = ACL_PAT_PASS;
1573 list_for_each_entry(term, &suite->terms, list) {
1574 acl = term->acl;
1575
1576 /* FIXME: use cache !
1577 * check acl->cache_idx for this.
1578 */
1579
1580 /* ACL result not cached. Let's scan all the expressions
1581 * and use the first one to match.
1582 */
1583 acl_res = ACL_PAT_FAIL;
1584 list_for_each_entry(expr, &acl->expr, list) {
Willy Tarreaud41f8d82007-06-10 10:06:18 +02001585 /* we need to reset context and flags */
Willy Tarreau37406352012-04-23 16:16:37 +02001586 memset(&smp, 0, sizeof(smp));
Willy Tarreaua84d3742007-05-07 00:36:48 +02001587 fetch_next:
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001588 if (!expr->kw->smp->process(px, l4, l7, opt, expr->args, &smp)) {
Willy Tarreaub6866442008-07-14 23:54:42 +02001589 /* maybe we could not fetch because of missing data */
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001590 if (smp.flags & SMP_F_MAY_CHANGE && !(opt & SMP_OPT_FINAL))
Willy Tarreaub6866442008-07-14 23:54:42 +02001591 acl_res |= ACL_PAT_MISS;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001592 continue;
Willy Tarreaub6866442008-07-14 23:54:42 +02001593 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001594
Willy Tarreau197e10a2012-04-23 19:18:42 +02001595 if (smp.type == SMP_T_BOOL) {
1596 if (smp.data.uint)
Willy Tarreaua79534f2008-07-20 10:13:37 +02001597 acl_res |= ACL_PAT_PASS;
1598 else
1599 acl_res |= ACL_PAT_FAIL;
1600 }
1601 else {
Willy Tarreau020534d2010-05-16 21:45:45 +02001602 if (!eb_is_empty(&expr->pattern_tree)) {
Willy Tarreauc4262962010-05-10 23:42:40 +02001603 /* a tree is present, let's check what type it is */
1604 if (expr->kw->match == acl_match_str)
Willy Tarreau37406352012-04-23 16:16:37 +02001605 acl_res |= acl_lookup_str(&smp, expr) ? ACL_PAT_PASS : ACL_PAT_FAIL;
Willy Tarreaub337b532010-05-13 20:03:41 +02001606 else if (expr->kw->match == acl_match_ip)
Willy Tarreau37406352012-04-23 16:16:37 +02001607 acl_res |= acl_lookup_ip(&smp, expr) ? ACL_PAT_PASS : ACL_PAT_FAIL;
Willy Tarreauc4262962010-05-10 23:42:40 +02001608 }
1609
Willy Tarreaua79534f2008-07-20 10:13:37 +02001610 /* call the match() function for all tests on this value */
1611 list_for_each_entry(pattern, &expr->patterns, list) {
Willy Tarreaua79534f2008-07-20 10:13:37 +02001612 if (acl_res == ACL_PAT_PASS)
1613 break;
Willy Tarreau37406352012-04-23 16:16:37 +02001614 acl_res |= expr->kw->match(&smp, pattern);
Willy Tarreaua79534f2008-07-20 10:13:37 +02001615 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001616 }
1617 /*
Willy Tarreau11382812008-07-09 16:18:21 +02001618 * OK now acl_res holds the result of this expression
1619 * as one of ACL_PAT_FAIL, ACL_PAT_MISS or ACL_PAT_PASS.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001620 *
Willy Tarreau11382812008-07-09 16:18:21 +02001621 * Then if (!MISS) we can cache the result, and put
Willy Tarreau37406352012-04-23 16:16:37 +02001622 * (smp.flags & SMP_F_VOLATILE) in the cache flags.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001623 *
1624 * FIXME: implement cache.
1625 *
1626 */
1627
Willy Tarreau11382812008-07-09 16:18:21 +02001628 /* we're ORing these terms, so a single PASS is enough */
1629 if (acl_res == ACL_PAT_PASS)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001630 break;
1631
Willy Tarreau37406352012-04-23 16:16:37 +02001632 if (smp.flags & SMP_F_NOT_LAST)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001633 goto fetch_next;
Willy Tarreaub6866442008-07-14 23:54:42 +02001634
1635 /* sometimes we know the fetched data is subject to change
1636 * later and give another chance for a new match (eg: request
1637 * size, time, ...)
1638 */
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001639 if (smp.flags & SMP_F_MAY_CHANGE && !(opt & SMP_OPT_FINAL))
Willy Tarreaub6866442008-07-14 23:54:42 +02001640 acl_res |= ACL_PAT_MISS;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001641 }
1642 /*
1643 * Here we have the result of an ACL (cached or not).
1644 * ACLs are combined, negated or not, to form conditions.
1645 */
1646
Willy Tarreaua84d3742007-05-07 00:36:48 +02001647 if (term->neg)
Willy Tarreau11382812008-07-09 16:18:21 +02001648 acl_res = acl_neg(acl_res);
Willy Tarreaua84d3742007-05-07 00:36:48 +02001649
1650 suite_res &= acl_res;
Willy Tarreau11382812008-07-09 16:18:21 +02001651
1652 /* we're ANDing these terms, so a single FAIL is enough */
1653 if (suite_res == ACL_PAT_FAIL)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001654 break;
1655 }
1656 cond_res |= suite_res;
Willy Tarreau11382812008-07-09 16:18:21 +02001657
1658 /* we're ORing these terms, so a single PASS is enough */
1659 if (cond_res == ACL_PAT_PASS)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001660 break;
1661 }
Willy Tarreau11382812008-07-09 16:18:21 +02001662 return cond_res;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001663}
1664
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001665/* Returns a pointer to the first ACL conflicting with usage at place <where>
1666 * which is one of the SMP_VAL_* bits indicating a check place, or NULL if
1667 * no conflict is found. Only full conflicts are detected (ACL is not usable).
1668 * Use the next function to check for useless keywords.
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001669 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001670const struct acl *acl_cond_conflicts(const struct acl_cond *cond, unsigned int where)
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001671{
1672 struct acl_term_suite *suite;
1673 struct acl_term *term;
1674 struct acl *acl;
1675
1676 list_for_each_entry(suite, &cond->suites, list) {
1677 list_for_each_entry(term, &suite->terms, list) {
1678 acl = term->acl;
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001679 if (!(acl->val & where))
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001680 return acl;
1681 }
1682 }
1683 return NULL;
1684}
1685
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001686/* Returns a pointer to the first ACL and its first keyword to conflict with
1687 * usage at place <where> which is one of the SMP_VAL_* bits indicating a check
1688 * place. Returns true if a conflict is found, with <acl> and <kw> set (if non
1689 * null), or false if not conflict is found. The first useless keyword is
1690 * returned.
1691 */
1692int acl_cond_kw_conflicts(const struct acl_cond *cond, unsigned int where, struct acl const **acl, struct acl_keyword const **kw)
1693{
1694 struct acl_term_suite *suite;
1695 struct acl_term *term;
1696 struct acl_expr *expr;
1697
1698 list_for_each_entry(suite, &cond->suites, list) {
1699 list_for_each_entry(term, &suite->terms, list) {
1700 list_for_each_entry(expr, &term->acl->expr, list) {
1701 if (!(expr->kw->smp->val & where)) {
1702 if (acl)
1703 *acl = term->acl;
1704 if (kw)
1705 *kw = expr->kw;
1706 return 1;
1707 }
1708 }
1709 }
1710 }
1711 return 0;
1712}
1713
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001714/*
1715 * Find targets for userlist and groups in acl. Function returns the number
1716 * of errors or OK if everything is fine.
1717 */
1718int
1719acl_find_targets(struct proxy *p)
1720{
1721
1722 struct acl *acl;
1723 struct acl_expr *expr;
1724 struct acl_pattern *pattern;
1725 struct userlist *ul;
Willy Tarreau63364ee2012-04-19 19:11:13 +02001726 struct arg *arg;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001727 int cfgerr = 0;
1728
1729 list_for_each_entry(acl, &p->acl, list) {
1730 list_for_each_entry(expr, &acl->expr, list) {
Willy Tarreau2e845be2012-10-19 19:49:09 +02001731 for (arg = expr->args; arg && arg->type != ARGT_STOP; arg++) {
1732 if (!arg->unresolved)
Willy Tarreau496aa012012-06-01 10:38:29 +02001733 continue;
Willy Tarreau63364ee2012-04-19 19:11:13 +02001734 else if (arg->type == ARGT_SRV) {
1735 struct proxy *px;
1736 struct server *srv;
1737 char *pname, *sname;
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001738
Willy Tarreau7d1df412012-11-23 23:47:36 +01001739 if (!arg->data.str.len) {
Willy Tarreau63364ee2012-04-19 19:11:13 +02001740 Alert("proxy %s: acl '%s' %s(): missing server name.\n",
1741 p->id, acl->name, expr->kw->kw);
1742 cfgerr++;
1743 continue;
1744 }
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001745
Willy Tarreau7d1df412012-11-23 23:47:36 +01001746 pname = arg->data.str.str;
Willy Tarreau63364ee2012-04-19 19:11:13 +02001747 sname = strrchr(pname, '/');
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001748
Willy Tarreau63364ee2012-04-19 19:11:13 +02001749 if (sname)
1750 *sname++ = '\0';
1751 else {
1752 sname = pname;
1753 pname = NULL;
1754 }
1755
1756 px = p;
1757 if (pname) {
1758 px = findproxy(pname, PR_CAP_BE);
1759 if (!px) {
1760 Alert("proxy %s: acl '%s' %s(): unable to find proxy '%s'.\n",
1761 p->id, acl->name, expr->kw->kw, pname);
1762 cfgerr++;
1763 continue;
1764 }
1765 }
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001766
Willy Tarreau63364ee2012-04-19 19:11:13 +02001767 srv = findserver(px, sname);
1768 if (!srv) {
1769 Alert("proxy %s: acl '%s' %s(): unable to find server '%s'.\n",
1770 p->id, acl->name, expr->kw->kw, sname);
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001771 cfgerr++;
1772 continue;
1773 }
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001774
Willy Tarreau7d1df412012-11-23 23:47:36 +01001775 free(arg->data.str.str);
1776 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001777 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001778 arg->data.srv = srv;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001779 }
1780 else if (arg->type == ARGT_FE) {
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001781 struct proxy *prx = p;
1782 char *pname = p->id;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001783
Willy Tarreau7d1df412012-11-23 23:47:36 +01001784 if (arg->data.str.len) {
1785 pname = arg->data.str.str;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001786 prx = findproxy(pname, PR_CAP_FE);
Willy Tarreaud28c3532012-04-19 19:28:33 +02001787 }
1788
Willy Tarreaud28c3532012-04-19 19:28:33 +02001789 if (!prx) {
1790 Alert("proxy %s: acl '%s' %s(): unable to find frontend '%s'.\n",
1791 p->id, acl->name, expr->kw->kw, pname);
1792 cfgerr++;
1793 continue;
1794 }
1795
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001796 if (!(prx->cap & PR_CAP_FE)) {
1797 Alert("proxy %s: acl '%s' %s(): proxy '%s' has no frontend capability.\n",
1798 p->id, acl->name, expr->kw->kw, pname);
1799 cfgerr++;
1800 continue;
1801 }
1802
Willy Tarreau7d1df412012-11-23 23:47:36 +01001803 free(arg->data.str.str);
1804 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001805 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001806 arg->data.prx = prx;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001807 }
1808 else if (arg->type == ARGT_BE) {
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001809 struct proxy *prx = p;
1810 char *pname = p->id;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001811
Willy Tarreau7d1df412012-11-23 23:47:36 +01001812 if (arg->data.str.len) {
1813 pname = arg->data.str.str;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001814 prx = findproxy(pname, PR_CAP_BE);
Willy Tarreaud28c3532012-04-19 19:28:33 +02001815 }
1816
Willy Tarreaud28c3532012-04-19 19:28:33 +02001817 if (!prx) {
1818 Alert("proxy %s: acl '%s' %s(): unable to find backend '%s'.\n",
1819 p->id, acl->name, expr->kw->kw, pname);
1820 cfgerr++;
1821 continue;
1822 }
1823
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001824 if (!(prx->cap & PR_CAP_BE)) {
1825 Alert("proxy %s: acl '%s' %s(): proxy '%s' has no backend capability.\n",
1826 p->id, acl->name, expr->kw->kw, pname);
1827 cfgerr++;
1828 continue;
1829 }
1830
Willy Tarreau7d1df412012-11-23 23:47:36 +01001831 free(arg->data.str.str);
1832 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001833 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001834 arg->data.prx = prx;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001835 }
1836 else if (arg->type == ARGT_TAB) {
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001837 struct proxy *prx = p;
1838 char *pname = p->id;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001839
Willy Tarreau7d1df412012-11-23 23:47:36 +01001840 if (arg->data.str.len) {
1841 pname = arg->data.str.str;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001842 prx = find_stktable(pname);
Willy Tarreaud28c3532012-04-19 19:28:33 +02001843 }
1844
Willy Tarreaud28c3532012-04-19 19:28:33 +02001845 if (!prx) {
1846 Alert("proxy %s: acl '%s' %s(): unable to find table '%s'.\n",
1847 p->id, acl->name, expr->kw->kw, pname);
1848 cfgerr++;
1849 continue;
1850 }
1851
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001852
1853 if (!prx->table.size) {
1854 Alert("proxy %s: acl '%s' %s(): no table in proxy '%s'.\n",
1855 p->id, acl->name, expr->kw->kw, pname);
1856 cfgerr++;
1857 continue;
1858 }
1859
Willy Tarreau7d1df412012-11-23 23:47:36 +01001860 free(arg->data.str.str);
1861 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001862 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001863 arg->data.prx = prx;
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001864 }
Willy Tarreau63364ee2012-04-19 19:11:13 +02001865 else if (arg->type == ARGT_USR) {
Willy Tarreau7d1df412012-11-23 23:47:36 +01001866 if (!arg->data.str.len) {
Willy Tarreau63364ee2012-04-19 19:11:13 +02001867 Alert("proxy %s: acl '%s' %s(): missing userlist name.\n",
1868 p->id, acl->name, expr->kw->kw);
1869 cfgerr++;
1870 continue;
1871 }
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001872
Willy Tarreau63364ee2012-04-19 19:11:13 +02001873 if (p->uri_auth && p->uri_auth->userlist &&
Willy Tarreau7d1df412012-11-23 23:47:36 +01001874 !strcmp(p->uri_auth->userlist->name, arg->data.str.str))
Willy Tarreau63364ee2012-04-19 19:11:13 +02001875 ul = p->uri_auth->userlist;
1876 else
Willy Tarreau7d1df412012-11-23 23:47:36 +01001877 ul = auth_find_userlist(arg->data.str.str);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001878
Willy Tarreau63364ee2012-04-19 19:11:13 +02001879 if (!ul) {
1880 Alert("proxy %s: acl '%s' %s(%s): unable to find userlist.\n",
Willy Tarreau7d1df412012-11-23 23:47:36 +01001881 p->id, acl->name, expr->kw->kw, arg->data.str.str);
Willy Tarreau63364ee2012-04-19 19:11:13 +02001882 cfgerr++;
1883 continue;
1884 }
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001885
Willy Tarreau7d1df412012-11-23 23:47:36 +01001886 free(arg->data.str.str);
1887 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001888 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001889 arg->data.usr = ul;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001890 }
Willy Tarreau63364ee2012-04-19 19:11:13 +02001891 } /* end of args processing */
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001892
Willy Tarreau46b39d02012-05-10 23:40:14 +02001893 /* don't try to resolve groups if we're not certain of having
1894 * resolved userlists first.
1895 */
1896 if (cfgerr)
1897 break;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001898
1899 if (!strcmp(expr->kw->kw, "http_auth_group")) {
Willy Tarreau63364ee2012-04-19 19:11:13 +02001900 /* note: argument resolved above thanks to ARGT_USR */
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001901
1902 if (LIST_ISEMPTY(&expr->patterns)) {
1903 Alert("proxy %s: acl %s %s(): no groups specified.\n",
1904 p->id, acl->name, expr->kw->kw);
1905 cfgerr++;
1906 continue;
1907 }
1908
1909 list_for_each_entry(pattern, &expr->patterns, list) {
Willy Tarreau7d1df412012-11-23 23:47:36 +01001910 /* this keyword only has one argument */
Willy Tarreau34db1082012-04-19 17:16:54 +02001911 pattern->val.group_mask = auth_resolve_groups(expr->args->data.usr, pattern->ptr.str);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001912
1913 free(pattern->ptr.str);
1914 pattern->ptr.str = NULL;
1915 pattern->len = 0;
1916
1917 if (!pattern->val.group_mask) {
1918 Alert("proxy %s: acl %s %s(): invalid group(s).\n",
1919 p->id, acl->name, expr->kw->kw);
1920 cfgerr++;
1921 continue;
1922 }
1923 }
1924 }
1925 }
1926 }
1927
1928 return cfgerr;
1929}
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001930
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001931/* initializes ACLs by resolving the sample fetch names they rely upon.
1932 * Returns 0 on success, otherwise an error.
1933 */
1934int init_acl()
1935{
1936 int err = 0;
1937 int index;
1938 const char *name;
1939 struct acl_kw_list *kwl;
1940 struct sample_fetch *smp;
1941
1942 list_for_each_entry(kwl, &acl_keywords.list, list) {
1943 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1944 name = kwl->kw[index].fetch_kw;
1945 if (!name)
1946 name = kwl->kw[index].kw;
1947
1948 smp = find_sample_fetch(name, strlen(name));
1949 if (!smp) {
1950 Alert("Critical internal error: ACL keyword '%s' relies on sample fetch '%s' which was not registered!\n",
1951 kwl->kw[index].kw, name);
1952 err++;
1953 continue;
1954 }
1955 kwl->kw[index].smp = smp;
1956 }
1957 }
1958 return err;
1959}
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001960
Willy Tarreaua84d3742007-05-07 00:36:48 +02001961/************************************************************************/
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001962/* All supported sample fetch functions must be declared here */
Willy Tarreaua84d3742007-05-07 00:36:48 +02001963/************************************************************************/
1964
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001965/* force TRUE to be returned at the fetch level */
1966static int
1967smp_fetch_true(struct proxy *px, struct session *s, void *l7, unsigned int opt,
1968 const struct arg *args, struct sample *smp)
1969{
1970 smp->type = SMP_T_BOOL;
1971 smp->data.uint = 1;
1972 return 1;
1973}
1974
1975/* force FALSE to be returned at the fetch level */
1976static int
1977smp_fetch_false(struct proxy *px, struct session *s, void *l7, unsigned int opt,
1978 const struct arg *args, struct sample *smp)
1979{
1980 smp->type = SMP_T_BOOL;
1981 smp->data.uint = 0;
1982 return 1;
1983}
1984
1985
1986/************************************************************************/
1987/* All supported sample and ACL keywords must be declared here. */
1988/************************************************************************/
1989
1990/* Note: must not be declared <const> as its list will be overwritten.
1991 * Note: fetches that may return multiple types must be declared as the lowest
1992 * common denominator, the type that can be casted into all other ones. For
1993 * instance IPv4/IPv6 must be declared IPv4.
1994 */
1995static struct sample_fetch_kw_list smp_kws = {{ },{
1996 { "always_false", smp_fetch_false, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN },
1997 { "always_true", smp_fetch_true, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN },
1998 { /* END */ },
1999}};
2000
2001
Willy Tarreau61612d42012-04-19 18:42:05 +02002002/* Note: must not be declared <const> as its list will be overwritten.
2003 * Please take care of keeping this list alphabetically sorted.
2004 */
Willy Tarreaua84d3742007-05-07 00:36:48 +02002005static struct acl_kw_list acl_kws = {{ },{
Willy Tarreaud86e29d2013-03-25 08:21:05 +01002006 { "always_false", NULL, acl_parse_nothing, acl_match_nothing },
2007 { "always_true", NULL, acl_parse_nothing, acl_match_nothing },
Willy Tarreaud4c33c82013-01-07 21:59:07 +01002008 { /* END */ },
Willy Tarreaua84d3742007-05-07 00:36:48 +02002009}};
2010
2011
2012__attribute__((constructor))
2013static void __acl_init(void)
2014{
Willy Tarreaud4c33c82013-01-07 21:59:07 +01002015 sample_register_fetches(&smp_kws);
Willy Tarreaua84d3742007-05-07 00:36:48 +02002016 acl_register_keywords(&acl_kws);
2017}
2018
2019
2020/*
2021 * Local variables:
2022 * c-indent-level: 8
2023 * c-basic-offset: 8
2024 * End:
2025 */