blob: fe5c869b68fda2833c17399ba049abbdc67b44a6 [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 Tarreaud28c3532012-04-19 19:28:33 +020030#include <proto/stick_table.h>
Willy Tarreaua84d3742007-05-07 00:36:48 +020031
Willy Tarreauc4262962010-05-10 23:42:40 +020032#include <ebsttree.h>
33
Willy Tarreaua9802632008-07-25 19:13:19 +020034/* The capabilities of filtering hooks describe the type of information
35 * available to each of them.
36 */
37const unsigned int filt_cap[] = {
38 [ACL_HOOK_REQ_FE_TCP] = ACL_USE_TCP4_ANY|ACL_USE_TCP6_ANY|ACL_USE_TCP_ANY,
Willy Tarreau06457872010-05-23 12:24:38 +020039 [ACL_HOOK_REQ_FE_TCP_CONTENT] = ACL_USE_TCP4_ANY|ACL_USE_TCP6_ANY|ACL_USE_TCP_ANY|ACL_USE_L6REQ_ANY,
40 [ACL_HOOK_REQ_FE_HTTP_IN] = ACL_USE_TCP4_ANY|ACL_USE_TCP6_ANY|ACL_USE_TCP_ANY|ACL_USE_L6REQ_ANY|ACL_USE_L7REQ_ANY|ACL_USE_HDR_ANY,
41 [ACL_HOOK_REQ_FE_SWITCH] = ACL_USE_TCP4_ANY|ACL_USE_TCP6_ANY|ACL_USE_TCP_ANY|ACL_USE_L6REQ_ANY|ACL_USE_L7REQ_ANY|ACL_USE_HDR_ANY,
42 [ACL_HOOK_REQ_BE_TCP_CONTENT] = ACL_USE_TCP4_ANY|ACL_USE_TCP6_ANY|ACL_USE_TCP_ANY|ACL_USE_L6REQ_ANY|ACL_USE_L7REQ_ANY|ACL_USE_HDR_ANY,
43 [ACL_HOOK_REQ_BE_HTTP_IN] = ACL_USE_TCP4_ANY|ACL_USE_TCP6_ANY|ACL_USE_TCP_ANY|ACL_USE_L6REQ_ANY|ACL_USE_L7REQ_ANY|ACL_USE_HDR_ANY,
44 [ACL_HOOK_REQ_BE_SWITCH] = ACL_USE_TCP4_ANY|ACL_USE_TCP6_ANY|ACL_USE_TCP_ANY|ACL_USE_L6REQ_ANY|ACL_USE_L7REQ_ANY|ACL_USE_HDR_ANY,
45 [ACL_HOOK_REQ_FE_HTTP_OUT] = ACL_USE_TCP4_ANY|ACL_USE_TCP6_ANY|ACL_USE_TCP_ANY|ACL_USE_L6REQ_ANY|ACL_USE_L7REQ_ANY|ACL_USE_HDR_ANY,
46 [ACL_HOOK_REQ_BE_HTTP_OUT] = ACL_USE_TCP4_ANY|ACL_USE_TCP6_ANY|ACL_USE_TCP_ANY|ACL_USE_L6REQ_ANY|ACL_USE_L7REQ_ANY|ACL_USE_HDR_ANY,
Willy Tarreaua9802632008-07-25 19:13:19 +020047
Willy Tarreau06457872010-05-23 12:24:38 +020048 [ACL_HOOK_RTR_BE_TCP_CONTENT] = ACL_USE_REQ_PERMANENT|ACL_USE_REQ_CACHEABLE|ACL_USE_L6RTR_ANY,
49 [ACL_HOOK_RTR_BE_HTTP_IN] = ACL_USE_REQ_PERMANENT|ACL_USE_REQ_CACHEABLE|ACL_USE_L6RTR_ANY|ACL_USE_L7RTR_ANY,
50 [ACL_HOOK_RTR_FE_TCP_CONTENT] = ACL_USE_REQ_PERMANENT|ACL_USE_REQ_CACHEABLE|ACL_USE_L6RTR_ANY|ACL_USE_L7RTR_ANY,
51 [ACL_HOOK_RTR_FE_HTTP_IN] = ACL_USE_REQ_PERMANENT|ACL_USE_REQ_CACHEABLE|ACL_USE_L6RTR_ANY|ACL_USE_L7RTR_ANY,
52 [ACL_HOOK_RTR_BE_HTTP_OUT] = ACL_USE_REQ_PERMANENT|ACL_USE_REQ_CACHEABLE|ACL_USE_L6RTR_ANY|ACL_USE_L7RTR_ANY,
53 [ACL_HOOK_RTR_FE_HTTP_OUT] = ACL_USE_REQ_PERMANENT|ACL_USE_REQ_CACHEABLE|ACL_USE_L6RTR_ANY|ACL_USE_L7RTR_ANY,
Willy Tarreaua9802632008-07-25 19:13:19 +020054};
55
Willy Tarreaua84d3742007-05-07 00:36:48 +020056/* List head of all known ACL keywords */
57static struct acl_kw_list acl_keywords = {
58 .list = LIST_HEAD_INIT(acl_keywords.list)
59};
60
61
Willy Tarreaua5909832007-06-17 20:40:25 +020062/*
Willy Tarreau58393e12008-07-20 10:39:22 +020063 * These functions are exported and may be used by any other component.
64 */
65
66/* ignore the current line */
Willy Tarreau7dcb6482012-04-27 17:52:25 +020067int acl_parse_nothing(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreaua5909832007-06-17 20:40:25 +020068{
Willy Tarreau58393e12008-07-20 10:39:22 +020069 return 1;
70}
71
Willy Tarreaua5909832007-06-17 20:40:25 +020072/* always return false */
Willy Tarreau37406352012-04-23 16:16:37 +020073int acl_match_nothing(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua5909832007-06-17 20:40:25 +020074{
Willy Tarreau11382812008-07-09 16:18:21 +020075 return ACL_PAT_FAIL;
Willy Tarreaua5909832007-06-17 20:40:25 +020076}
77
78
Willy Tarreaua84d3742007-05-07 00:36:48 +020079/* NB: For two strings to be identical, it is required that their lengths match */
Willy Tarreau37406352012-04-23 16:16:37 +020080int acl_match_str(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +020081{
Willy Tarreauc8d7c962007-06-17 08:20:33 +020082 int icase;
83
Willy Tarreauf853c462012-04-23 18:53:56 +020084 if (pattern->len != smp->data.str.len)
Willy Tarreau11382812008-07-09 16:18:21 +020085 return ACL_PAT_FAIL;
Willy Tarreauc8d7c962007-06-17 08:20:33 +020086
87 icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
Willy Tarreauf853c462012-04-23 18:53:56 +020088 if ((icase && strncasecmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0) ||
89 (!icase && strncmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0))
Willy Tarreau11382812008-07-09 16:18:21 +020090 return ACL_PAT_PASS;
91 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +020092}
93
Emeric Brun07ca4962012-10-17 13:38:19 +020094/* NB: For two binaries buf to be identical, it is required that their lengths match */
95int acl_match_bin(struct sample *smp, struct acl_pattern *pattern)
96{
97 if (pattern->len != smp->data.str.len)
98 return ACL_PAT_FAIL;
99
100 if (memcmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0)
101 return ACL_PAT_PASS;
102 return ACL_PAT_FAIL;
103}
104
Willy Tarreauc4262962010-05-10 23:42:40 +0200105/* Lookup a string in the expression's pattern tree. The node is returned if it
106 * exists, otherwise NULL.
107 */
Willy Tarreau37406352012-04-23 16:16:37 +0200108static void *acl_lookup_str(struct sample *smp, struct acl_expr *expr)
Willy Tarreauc4262962010-05-10 23:42:40 +0200109{
110 /* data are stored in a tree */
111 struct ebmb_node *node;
112 char prev;
113
114 /* we may have to force a trailing zero on the test pattern */
Willy Tarreauf853c462012-04-23 18:53:56 +0200115 prev = smp->data.str.str[smp->data.str.len];
Willy Tarreauc4262962010-05-10 23:42:40 +0200116 if (prev)
Willy Tarreauf853c462012-04-23 18:53:56 +0200117 smp->data.str.str[smp->data.str.len] = '\0';
118 node = ebst_lookup(&expr->pattern_tree, smp->data.str.str);
Willy Tarreauc4262962010-05-10 23:42:40 +0200119 if (prev)
Willy Tarreauf853c462012-04-23 18:53:56 +0200120 smp->data.str.str[smp->data.str.len] = prev;
Willy Tarreauc4262962010-05-10 23:42:40 +0200121 return node;
122}
123
Willy Tarreau21e5b0e2012-04-23 19:25:44 +0200124/* Executes a regex. It temporarily changes the data to add a trailing zero,
125 * and restores the previous character when leaving.
Willy Tarreauf3d25982007-05-08 22:45:09 +0200126 */
Willy Tarreau37406352012-04-23 16:16:37 +0200127int acl_match_reg(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreauf3d25982007-05-08 22:45:09 +0200128{
129 char old_char;
130 int ret;
131
Willy Tarreauf853c462012-04-23 18:53:56 +0200132 old_char = smp->data.str.str[smp->data.str.len];
133 smp->data.str.str[smp->data.str.len] = 0;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200134
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900135 if (regex_exec(pattern->ptr.reg, smp->data.str.str, smp->data.str.len) == 0)
Willy Tarreau11382812008-07-09 16:18:21 +0200136 ret = ACL_PAT_PASS;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200137 else
Willy Tarreau11382812008-07-09 16:18:21 +0200138 ret = ACL_PAT_FAIL;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200139
Willy Tarreauf853c462012-04-23 18:53:56 +0200140 smp->data.str.str[smp->data.str.len] = old_char;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200141 return ret;
142}
143
Willy Tarreaua84d3742007-05-07 00:36:48 +0200144/* Checks that the pattern matches the beginning of the tested string. */
Willy Tarreau37406352012-04-23 16:16:37 +0200145int acl_match_beg(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200146{
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200147 int icase;
148
Willy Tarreauf853c462012-04-23 18:53:56 +0200149 if (pattern->len > smp->data.str.len)
Willy Tarreau11382812008-07-09 16:18:21 +0200150 return ACL_PAT_FAIL;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200151
152 icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
Willy Tarreauf853c462012-04-23 18:53:56 +0200153 if ((icase && strncasecmp(pattern->ptr.str, smp->data.str.str, pattern->len) != 0) ||
154 (!icase && strncmp(pattern->ptr.str, smp->data.str.str, pattern->len) != 0))
Willy Tarreau11382812008-07-09 16:18:21 +0200155 return ACL_PAT_FAIL;
156 return ACL_PAT_PASS;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200157}
158
159/* Checks that the pattern matches the end of the tested string. */
Willy Tarreau37406352012-04-23 16:16:37 +0200160int acl_match_end(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200161{
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200162 int icase;
163
Willy Tarreauf853c462012-04-23 18:53:56 +0200164 if (pattern->len > smp->data.str.len)
Willy Tarreau11382812008-07-09 16:18:21 +0200165 return ACL_PAT_FAIL;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200166 icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
Willy Tarreauf853c462012-04-23 18:53:56 +0200167 if ((icase && strncasecmp(pattern->ptr.str, smp->data.str.str + smp->data.str.len - pattern->len, pattern->len) != 0) ||
168 (!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 +0200169 return ACL_PAT_FAIL;
170 return ACL_PAT_PASS;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200171}
172
173/* Checks that the pattern is included inside the tested string.
174 * NB: Suboptimal, should be rewritten using a Boyer-Moore method.
175 */
Willy Tarreau37406352012-04-23 16:16:37 +0200176int acl_match_sub(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200177{
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200178 int icase;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200179 char *end;
180 char *c;
181
Willy Tarreauf853c462012-04-23 18:53:56 +0200182 if (pattern->len > smp->data.str.len)
Willy Tarreau11382812008-07-09 16:18:21 +0200183 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200184
Willy Tarreauf853c462012-04-23 18:53:56 +0200185 end = smp->data.str.str + smp->data.str.len - pattern->len;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200186 icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
187 if (icase) {
Willy Tarreauf853c462012-04-23 18:53:56 +0200188 for (c = smp->data.str.str; c <= end; c++) {
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200189 if (tolower(*c) != tolower(*pattern->ptr.str))
190 continue;
191 if (strncasecmp(pattern->ptr.str, c, pattern->len) == 0)
Willy Tarreau11382812008-07-09 16:18:21 +0200192 return ACL_PAT_PASS;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200193 }
194 } else {
Willy Tarreauf853c462012-04-23 18:53:56 +0200195 for (c = smp->data.str.str; c <= end; c++) {
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200196 if (*c != *pattern->ptr.str)
197 continue;
198 if (strncmp(pattern->ptr.str, c, pattern->len) == 0)
Willy Tarreau11382812008-07-09 16:18:21 +0200199 return ACL_PAT_PASS;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200200 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200201 }
Willy Tarreau11382812008-07-09 16:18:21 +0200202 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200203}
204
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200205/* Background: Fast way to find a zero byte in a word
206 * http://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
207 * hasZeroByte = (v - 0x01010101UL) & ~v & 0x80808080UL;
208 *
209 * To look for 4 different byte values, xor the word with those bytes and
210 * then check for zero bytes:
211 *
212 * v = (((unsigned char)c * 0x1010101U) ^ delimiter)
213 * where <delimiter> is the 4 byte values to look for (as an uint)
214 * and <c> is the character that is being tested
215 */
216static inline unsigned int is_delimiter(unsigned char c, unsigned int mask)
217{
218 mask ^= (c * 0x01010101); /* propagate the char to all 4 bytes */
219 return (mask - 0x01010101) & ~mask & 0x80808080U;
220}
221
222static inline unsigned int make_4delim(unsigned char d1, unsigned char d2, unsigned char d3, unsigned char d4)
223{
224 return d1 << 24 | d2 << 16 | d3 << 8 | d4;
225}
226
Willy Tarreaua84d3742007-05-07 00:36:48 +0200227/* This one is used by other real functions. It checks that the pattern is
228 * included inside the tested string, but enclosed between the specified
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200229 * delimiters or at the beginning or end of the string. The delimiters are
230 * provided as an unsigned int made by make_4delim() and match up to 4 different
231 * delimiters. Delimiters are stripped at the beginning and end of the pattern.
Willy Tarreaua84d3742007-05-07 00:36:48 +0200232 */
Willy Tarreau37406352012-04-23 16:16:37 +0200233static int match_word(struct sample *smp, struct acl_pattern *pattern, unsigned int delimiters)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200234{
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200235 int may_match, icase;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200236 char *c, *end;
237 char *ps;
238 int pl;
239
240 pl = pattern->len;
241 ps = pattern->ptr.str;
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200242
243 while (pl > 0 && is_delimiter(*ps, delimiters)) {
Willy Tarreaua84d3742007-05-07 00:36:48 +0200244 pl--;
245 ps++;
246 }
247
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200248 while (pl > 0 && is_delimiter(ps[pl - 1], delimiters))
Willy Tarreaua84d3742007-05-07 00:36:48 +0200249 pl--;
250
Willy Tarreauf853c462012-04-23 18:53:56 +0200251 if (pl > smp->data.str.len)
Willy Tarreau11382812008-07-09 16:18:21 +0200252 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200253
254 may_match = 1;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200255 icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
Willy Tarreauf853c462012-04-23 18:53:56 +0200256 end = smp->data.str.str + smp->data.str.len - pl;
257 for (c = smp->data.str.str; c <= end; c++) {
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200258 if (is_delimiter(*c, delimiters)) {
Willy Tarreaua84d3742007-05-07 00:36:48 +0200259 may_match = 1;
260 continue;
261 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200262
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200263 if (!may_match)
264 continue;
265
266 if (icase) {
267 if ((tolower(*c) == tolower(*ps)) &&
268 (strncasecmp(ps, c, pl) == 0) &&
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200269 (c == end || is_delimiter(c[pl], delimiters)))
Willy Tarreau11382812008-07-09 16:18:21 +0200270 return ACL_PAT_PASS;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200271 } else {
272 if ((*c == *ps) &&
273 (strncmp(ps, c, pl) == 0) &&
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200274 (c == end || is_delimiter(c[pl], delimiters)))
Willy Tarreau11382812008-07-09 16:18:21 +0200275 return ACL_PAT_PASS;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200276 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200277 may_match = 0;
278 }
Willy Tarreau11382812008-07-09 16:18:21 +0200279 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200280}
281
282/* Checks that the pattern is included inside the tested string, but enclosed
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200283 * between the delimiters '?' or '/' or at the beginning or end of the string.
284 * Delimiters at the beginning or end of the pattern are ignored.
Willy Tarreaua84d3742007-05-07 00:36:48 +0200285 */
Willy Tarreau37406352012-04-23 16:16:37 +0200286int acl_match_dir(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200287{
Willy Tarreau37406352012-04-23 16:16:37 +0200288 return match_word(smp, pattern, make_4delim('/', '?', '?', '?'));
Willy Tarreaua84d3742007-05-07 00:36:48 +0200289}
290
291/* Checks that the pattern is included inside the tested string, but enclosed
Finn Arne Gangstade8c7ecc2011-09-09 16:09:50 +0200292 * between the delmiters '/', '?', '.' or ":" or at the beginning or end of
293 * the string. Delimiters at the beginning or end of the pattern are ignored.
Willy Tarreaua84d3742007-05-07 00:36:48 +0200294 */
Willy Tarreau37406352012-04-23 16:16:37 +0200295int acl_match_dom(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200296{
Willy Tarreau37406352012-04-23 16:16:37 +0200297 return match_word(smp, pattern, make_4delim('/', '?', '.', ':'));
Willy Tarreaua84d3742007-05-07 00:36:48 +0200298}
299
300/* Checks that the integer in <test> is included between min and max */
Willy Tarreau37406352012-04-23 16:16:37 +0200301int acl_match_int(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200302{
Willy Tarreauf853c462012-04-23 18:53:56 +0200303 if ((!pattern->val.range.min_set || pattern->val.range.min <= smp->data.uint) &&
304 (!pattern->val.range.max_set || smp->data.uint <= pattern->val.range.max))
Willy Tarreau11382812008-07-09 16:18:21 +0200305 return ACL_PAT_PASS;
306 return ACL_PAT_FAIL;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200307}
308
Willy Tarreau0e698542011-09-16 08:32:32 +0200309/* Checks that the length of the pattern in <test> is included between min and max */
Willy Tarreau37406352012-04-23 16:16:37 +0200310int acl_match_len(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreau0e698542011-09-16 08:32:32 +0200311{
Willy Tarreauf853c462012-04-23 18:53:56 +0200312 if ((!pattern->val.range.min_set || pattern->val.range.min <= smp->data.str.len) &&
313 (!pattern->val.range.max_set || smp->data.str.len <= pattern->val.range.max))
Willy Tarreau0e698542011-09-16 08:32:32 +0200314 return ACL_PAT_PASS;
315 return ACL_PAT_FAIL;
316}
317
Willy Tarreau37406352012-04-23 16:16:37 +0200318int acl_match_ip(struct sample *smp, struct acl_pattern *pattern)
Willy Tarreaua67fad92007-05-08 19:50:09 +0200319{
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200320 unsigned int v4; /* in network byte order */
321 struct in6_addr *v6;
322 int bits, pos;
323 struct in6_addr tmp6;
Willy Tarreaua67fad92007-05-08 19:50:09 +0200324
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200325 if (pattern->type == SMP_T_IPV4) {
326 if (smp->type == SMP_T_IPV4) {
327 v4 = smp->data.ipv4.s_addr;
328 }
329 else if (smp->type == SMP_T_IPV6) {
330 /* v4 match on a V6 sample. We want to check at least for
331 * the following forms :
332 * - ::ffff:ip:v4 (ipv4 mapped)
333 * - ::0000:ip:v4 (old ipv4 mapped)
334 * - 2002:ip:v4:: (6to4)
335 */
336 if (*(uint32_t*)&smp->data.ipv6.s6_addr[0] == 0 &&
337 *(uint32_t*)&smp->data.ipv6.s6_addr[4] == 0 &&
338 (*(uint32_t*)&smp->data.ipv6.s6_addr[8] == 0 ||
339 *(uint32_t*)&smp->data.ipv6.s6_addr[8] == htonl(0xFFFF))) {
340 v4 = *(uint32_t*)&smp->data.ipv6.s6_addr[12];
341 }
342 else if (*(uint16_t*)&smp->data.ipv6.s6_addr[0] == htons(0x2002)) {
343 v4 = htonl((ntohs(*(uint16_t*)&smp->data.ipv6.s6_addr[2]) << 16) +
344 ntohs(*(uint16_t*)&smp->data.ipv6.s6_addr[4]));
345 }
346 else
347 return ACL_PAT_FAIL;
348 }
349 else
350 return ACL_PAT_FAIL;
Willy Tarreaua67fad92007-05-08 19:50:09 +0200351
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200352 if (((v4 ^ pattern->val.ipv4.addr.s_addr) & pattern->val.ipv4.mask.s_addr) == 0)
353 return ACL_PAT_PASS;
354 else
355 return ACL_PAT_FAIL;
356 }
357 else if (pattern->type == SMP_T_IPV6) {
358 if (smp->type == SMP_T_IPV4) {
359 /* Convert the IPv4 sample address to IPv4 with the
360 * mapping method using the ::ffff: prefix.
361 */
362 memset(&tmp6, 0, 10);
363 *(uint16_t*)&tmp6.s6_addr[10] = htons(0xffff);
364 *(uint32_t*)&tmp6.s6_addr[12] = smp->data.ipv4.s_addr;
365 v6 = &tmp6;
366 }
367 else if (smp->type == SMP_T_IPV6) {
368 v6 = &smp->data.ipv6;
369 }
370 else {
371 return ACL_PAT_FAIL;
372 }
373
374 bits = pattern->val.ipv6.mask;
375 for (pos = 0; bits > 0; pos += 4, bits -= 32) {
376 v4 = *(uint32_t*)&v6->s6_addr[pos] ^ *(uint32_t*)&pattern->val.ipv6.addr.s6_addr[pos];
377 if (bits < 32)
Cyril Bonté4c01beb2012-10-23 21:28:31 +0200378 v4 &= htonl((~0U) << (32-bits));
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200379 if (v4)
380 return ACL_PAT_FAIL;
381 }
Willy Tarreau11382812008-07-09 16:18:21 +0200382 return ACL_PAT_PASS;
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200383 }
Willy Tarreau11382812008-07-09 16:18:21 +0200384 return ACL_PAT_FAIL;
Willy Tarreaua67fad92007-05-08 19:50:09 +0200385}
386
Willy Tarreaub337b532010-05-13 20:03:41 +0200387/* Lookup an IPv4 address in the expression's pattern tree using the longest
388 * match method. The node is returned if it exists, otherwise NULL.
389 */
Willy Tarreau37406352012-04-23 16:16:37 +0200390static void *acl_lookup_ip(struct sample *smp, struct acl_expr *expr)
Willy Tarreaub337b532010-05-13 20:03:41 +0200391{
392 struct in_addr *s;
393
Willy Tarreauf853c462012-04-23 18:53:56 +0200394 if (smp->type != SMP_T_IPV4)
Willy Tarreaub337b532010-05-13 20:03:41 +0200395 return ACL_PAT_FAIL;
396
Willy Tarreauf853c462012-04-23 18:53:56 +0200397 s = &smp->data.ipv4;
Willy Tarreaub337b532010-05-13 20:03:41 +0200398 return ebmb_lookup_longest(&expr->pattern_tree, &s->s_addr);
399}
400
Willy Tarreaua84d3742007-05-07 00:36:48 +0200401/* Parse a string. It is allocated and duplicated. */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200402int acl_parse_str(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200403{
404 int len;
405
Willy Tarreauae8b7962007-06-09 23:10:04 +0200406 len = strlen(*text);
Willy Tarreauc92ddbc2012-04-27 22:10:57 +0200407 pattern->type = SMP_T_CSTR;
Willy Tarreauc4262962010-05-10 23:42:40 +0200408
409 if (pattern->flags & ACL_PAT_F_TREE_OK) {
410 /* we're allowed to put the data in a tree whose root is pointed
411 * to by val.tree.
412 */
413 struct ebmb_node *node;
414
415 node = calloc(1, sizeof(*node) + len + 1);
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200416 if (!node) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200417 memprintf(err, "out of memory while loading string pattern");
Willy Tarreauc4262962010-05-10 23:42:40 +0200418 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200419 }
Willy Tarreauc4262962010-05-10 23:42:40 +0200420 memcpy(node->key, *text, len + 1);
421 if (ebst_insert(pattern->val.tree, node) != node)
422 free(node); /* was a duplicate */
423 pattern->flags |= ACL_PAT_F_TREE; /* this pattern now contains a tree */
424 return 1;
425 }
426
Willy Tarreauae8b7962007-06-09 23:10:04 +0200427 pattern->ptr.str = strdup(*text);
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200428 if (!pattern->ptr.str) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200429 memprintf(err, "out of memory while loading string pattern");
Willy Tarreaua84d3742007-05-07 00:36:48 +0200430 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200431 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200432 pattern->len = len;
433 return 1;
434}
435
Emeric Brun07ca4962012-10-17 13:38:19 +0200436/* Parse a binary written in hexa. It is allocated. */
437int acl_parse_bin(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
438{
439 int len;
440 const char *p = *text;
441 int i,j;
442
443 len = strlen(p);
444 if (len%2) {
445 memprintf(err, "an even number of hex digit is expected");
446 return 0;
447 }
448
449 pattern->type = SMP_T_CBIN;
450 pattern->len = len >> 1;
451 pattern->ptr.str = malloc(pattern->len);
452 if (!pattern->ptr.str) {
453 memprintf(err, "out of memory while loading string pattern");
454 return 0;
455 }
456
457 i = j = 0;
458 while (j < pattern->len) {
459 if (!ishex(p[i++]))
460 goto bad_input;
461 if (!ishex(p[i++]))
462 goto bad_input;
463 pattern->ptr.str[j++] = (hex2i(p[i-2]) << 4) + hex2i(p[i-1]);
464 }
465 return 1;
466
467bad_input:
468 memprintf(err, "an hex digit is expected (found '%c')", p[i-1]);
469 free(pattern->ptr.str);
470 return 0;
471}
472
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100473/* Parse and concatenate all further strings into one. */
474int
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200475acl_parse_strcat(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100476{
477
478 int len = 0, i;
479 char *s;
480
481 for (i = 0; *text[i]; i++)
482 len += strlen(text[i])+1;
483
Willy Tarreauc92ddbc2012-04-27 22:10:57 +0200484 pattern->type = SMP_T_CSTR;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100485 pattern->ptr.str = s = calloc(1, len);
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200486 if (!pattern->ptr.str) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200487 memprintf(err, "out of memory while loading pattern");
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100488 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200489 }
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100490
491 for (i = 0; *text[i]; i++)
492 s += sprintf(s, i?" %s":"%s", text[i]);
493
494 pattern->len = len;
495
496 return i;
497}
498
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +0200499/* Free data allocated by acl_parse_reg */
Willy Tarreau37406352012-04-23 16:16:37 +0200500static void acl_free_reg(void *ptr)
501{
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900502 regex_free(ptr);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +0200503}
504
Willy Tarreauf3d25982007-05-08 22:45:09 +0200505/* Parse a regex. It is allocated. */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200506int acl_parse_reg(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreauf3d25982007-05-08 22:45:09 +0200507{
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900508 regex *preg;
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200509 int icase;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200510
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900511 preg = calloc(1, sizeof(*preg));
Willy Tarreauf3d25982007-05-08 22:45:09 +0200512
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200513 if (!preg) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200514 memprintf(err, "out of memory while loading pattern");
Willy Tarreauf3d25982007-05-08 22:45:09 +0200515 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200516 }
Willy Tarreauf3d25982007-05-08 22:45:09 +0200517
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900518#ifdef USE_PCRE_JIT
519 icase = (pattern->flags & ACL_PAT_F_IGNORE_CASE) ? PCRE_CASELESS : 0;
520 preg->reg = pcre_compile(*text, PCRE_NO_AUTO_CAPTURE | icase, NULL, NULL,
521 NULL);
522 if (!preg->reg) {
523 free(preg);
524 memprintf(err, "regex '%s' is invalid", *text);
525 return 0;
526 }
527
528 preg->extra = pcre_study(preg->reg, PCRE_STUDY_JIT_COMPILE, NULL);
529 if (!preg->extra) {
530 pcre_free(preg->reg);
531 free(preg);
532 memprintf(err, "failed to compile regex '%s'", *text);
533 return 0;
534 }
535#else
Willy Tarreauc8d7c962007-06-17 08:20:33 +0200536 icase = (pattern->flags & ACL_PAT_F_IGNORE_CASE) ? REG_ICASE : 0;
537 if (regcomp(preg, *text, REG_EXTENDED | REG_NOSUB | icase) != 0) {
Willy Tarreauf3d25982007-05-08 22:45:09 +0200538 free(preg);
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200539 memprintf(err, "regex '%s' is invalid", *text);
Willy Tarreauf3d25982007-05-08 22:45:09 +0200540 return 0;
541 }
Hiroaki Nakamura70351322013-01-13 15:00:42 +0900542#endif
Willy Tarreauf3d25982007-05-08 22:45:09 +0200543
544 pattern->ptr.reg = preg;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +0200545 pattern->freeptrbuf = &acl_free_reg;
Willy Tarreauf3d25982007-05-08 22:45:09 +0200546 return 1;
547}
548
Willy Tarreauae8b7962007-06-09 23:10:04 +0200549/* Parse a range of positive integers delimited by either ':' or '-'. If only
550 * one integer is read, it is set as both min and max. An operator may be
551 * specified as the prefix, among this list of 5 :
552 *
553 * 0:eq, 1:gt, 2:ge, 3:lt, 4:le
554 *
555 * The default operator is "eq". It supports range matching. Ranges are
556 * rejected for other operators. The operator may be changed at any time.
557 * The operator is stored in the 'opaque' argument.
558 *
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200559 * If err is non-NULL, an error message will be returned there on errors and
560 * the caller will have to free it.
561 *
Willy Tarreaua84d3742007-05-07 00:36:48 +0200562 */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200563int acl_parse_int(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200564{
Willy Tarreauae8b7962007-06-09 23:10:04 +0200565 signed long long i;
566 unsigned int j, last, skip = 0;
567 const char *ptr = *text;
568
Willy Tarreauc92ddbc2012-04-27 22:10:57 +0200569 pattern->type = SMP_T_UINT;
Willy Tarreau8f8e6452007-06-17 21:51:38 +0200570 while (!isdigit((unsigned char)*ptr)) {
Willy Tarreau1c7cc5b2010-07-18 10:46:33 +0200571 switch (get_std_op(ptr)) {
572 case STD_OP_EQ: *opaque = 0; break;
573 case STD_OP_GT: *opaque = 1; break;
574 case STD_OP_GE: *opaque = 2; break;
575 case STD_OP_LT: *opaque = 3; break;
576 case STD_OP_LE: *opaque = 4; break;
577 default:
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200578 memprintf(err, "'%s' is neither a number nor a supported operator", ptr);
Willy Tarreauae8b7962007-06-09 23:10:04 +0200579 return 0;
Willy Tarreau1c7cc5b2010-07-18 10:46:33 +0200580 }
Willy Tarreauae8b7962007-06-09 23:10:04 +0200581
582 skip++;
583 ptr = text[skip];
584 }
Willy Tarreaua84d3742007-05-07 00:36:48 +0200585
586 last = i = 0;
587 while (1) {
Willy Tarreauae8b7962007-06-09 23:10:04 +0200588 j = *ptr++;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200589 if ((j == '-' || j == ':') && !last) {
590 last++;
591 pattern->val.range.min = i;
592 i = 0;
593 continue;
594 }
595 j -= '0';
596 if (j > 9)
597 // also catches the terminating zero
598 break;
599 i *= 10;
600 i += j;
601 }
Willy Tarreauae8b7962007-06-09 23:10:04 +0200602
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200603 if (last && *opaque >= 1 && *opaque <= 4) {
Willy Tarreauae8b7962007-06-09 23:10:04 +0200604 /* having a range with a min or a max is absurd */
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200605 memprintf(err, "integer range '%s' specified with a comparison operator", text[skip]);
Willy Tarreauae8b7962007-06-09 23:10:04 +0200606 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200607 }
Willy Tarreauae8b7962007-06-09 23:10:04 +0200608
Willy Tarreaua84d3742007-05-07 00:36:48 +0200609 if (!last)
610 pattern->val.range.min = i;
611 pattern->val.range.max = i;
Willy Tarreauae8b7962007-06-09 23:10:04 +0200612
613 switch (*opaque) {
614 case 0: /* eq */
615 pattern->val.range.min_set = 1;
616 pattern->val.range.max_set = 1;
617 break;
618 case 1: /* gt */
619 pattern->val.range.min++; /* gt = ge + 1 */
620 case 2: /* ge */
621 pattern->val.range.min_set = 1;
622 pattern->val.range.max_set = 0;
623 break;
624 case 3: /* lt */
625 pattern->val.range.max--; /* lt = le - 1 */
626 case 4: /* le */
627 pattern->val.range.min_set = 0;
628 pattern->val.range.max_set = 1;
629 break;
630 }
631 return skip + 1;
Willy Tarreaua84d3742007-05-07 00:36:48 +0200632}
633
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200634/* Parse a range of positive 2-component versions delimited by either ':' or
635 * '-'. The version consists in a major and a minor, both of which must be
636 * smaller than 65536, because internally they will be represented as a 32-bit
637 * integer.
638 * If only one version is read, it is set as both min and max. Just like for
639 * pure integers, an operator may be specified as the prefix, among this list
640 * of 5 :
641 *
642 * 0:eq, 1:gt, 2:ge, 3:lt, 4:le
643 *
644 * The default operator is "eq". It supports range matching. Ranges are
645 * rejected for other operators. The operator may be changed at any time.
646 * The operator is stored in the 'opaque' argument. This allows constructs
647 * such as the following one :
648 *
649 * acl obsolete_ssl ssl_req_proto lt 3
650 * acl unsupported_ssl ssl_req_proto gt 3.1
651 * acl valid_ssl ssl_req_proto 3.0-3.1
652 *
653 */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200654int acl_parse_dotted_ver(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200655{
656 signed long long i;
657 unsigned int j, last, skip = 0;
658 const char *ptr = *text;
659
660
661 while (!isdigit((unsigned char)*ptr)) {
Willy Tarreau1c7cc5b2010-07-18 10:46:33 +0200662 switch (get_std_op(ptr)) {
663 case STD_OP_EQ: *opaque = 0; break;
664 case STD_OP_GT: *opaque = 1; break;
665 case STD_OP_GE: *opaque = 2; break;
666 case STD_OP_LT: *opaque = 3; break;
667 case STD_OP_LE: *opaque = 4; break;
668 default:
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200669 memprintf(err, "'%s' is neither a number nor a supported operator", ptr);
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200670 return 0;
Willy Tarreau1c7cc5b2010-07-18 10:46:33 +0200671 }
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200672
673 skip++;
674 ptr = text[skip];
675 }
676
677 last = i = 0;
678 while (1) {
679 j = *ptr++;
680 if (j == '.') {
681 /* minor part */
682 if (i >= 65536)
683 return 0;
684 i <<= 16;
685 continue;
686 }
687 if ((j == '-' || j == ':') && !last) {
688 last++;
689 if (i < 65536)
690 i <<= 16;
691 pattern->val.range.min = i;
692 i = 0;
693 continue;
694 }
695 j -= '0';
696 if (j > 9)
697 // also catches the terminating zero
698 break;
699 i = (i & 0xFFFF0000) + (i & 0xFFFF) * 10;
700 i += j;
701 }
702
703 /* if we only got a major version, let's shift it now */
704 if (i < 65536)
705 i <<= 16;
706
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200707 if (last && *opaque >= 1 && *opaque <= 4) {
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200708 /* having a range with a min or a max is absurd */
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200709 memprintf(err, "version range '%s' specified with a comparison operator", text[skip]);
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200710 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200711 }
Willy Tarreau4a26d2f2008-07-15 16:05:33 +0200712
713 if (!last)
714 pattern->val.range.min = i;
715 pattern->val.range.max = i;
716
717 switch (*opaque) {
718 case 0: /* eq */
719 pattern->val.range.min_set = 1;
720 pattern->val.range.max_set = 1;
721 break;
722 case 1: /* gt */
723 pattern->val.range.min++; /* gt = ge + 1 */
724 case 2: /* ge */
725 pattern->val.range.min_set = 1;
726 pattern->val.range.max_set = 0;
727 break;
728 case 3: /* lt */
729 pattern->val.range.max--; /* lt = le - 1 */
730 case 4: /* le */
731 pattern->val.range.min_set = 0;
732 pattern->val.range.max_set = 1;
733 break;
734 }
735 return skip + 1;
736}
737
Willy Tarreaua67fad92007-05-08 19:50:09 +0200738/* Parse an IP address and an optional mask in the form addr[/mask].
739 * The addr may either be an IPv4 address or a hostname. The mask
740 * may either be a dotted mask or a number of bits. Returns 1 if OK,
Willy Tarreauc92ddbc2012-04-27 22:10:57 +0200741 * otherwise 0. NOTE: IP address patterns are typed (IPV4/IPV6).
Willy Tarreaua67fad92007-05-08 19:50:09 +0200742 */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200743int acl_parse_ip(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
Willy Tarreaua67fad92007-05-08 19:50:09 +0200744{
Willy Tarreaub337b532010-05-13 20:03:41 +0200745 struct eb_root *tree = NULL;
746 if (pattern->flags & ACL_PAT_F_TREE_OK)
747 tree = pattern->val.tree;
748
749 if (str2net(*text, &pattern->val.ipv4.addr, &pattern->val.ipv4.mask)) {
750 unsigned int mask = ntohl(pattern->val.ipv4.mask.s_addr);
751 struct ebmb_node *node;
752 /* check if the mask is contiguous so that we can insert the
753 * network into the tree. A continuous mask has only ones on
754 * the left. This means that this mask + its lower bit added
755 * once again is null.
756 */
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200757 pattern->type = SMP_T_IPV4;
Willy Tarreaub337b532010-05-13 20:03:41 +0200758 if (mask + (mask & -mask) == 0 && tree) {
759 mask = mask ? 33 - flsnz(mask & -mask) : 0; /* equals cidr value */
760 /* FIXME: insert <addr>/<mask> into the tree here */
761 node = calloc(1, sizeof(*node) + 4); /* reserve 4 bytes for IPv4 address */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200762 if (!node) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200763 memprintf(err, "out of memory while loading IPv4 pattern");
Willy Tarreaub337b532010-05-13 20:03:41 +0200764 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200765 }
Willy Tarreaub337b532010-05-13 20:03:41 +0200766 memcpy(node->key, &pattern->val.ipv4.addr, 4); /* network byte order */
767 node->node.pfx = mask;
768 if (ebmb_insert_prefix(tree, node, 4) != node)
769 free(node); /* was a duplicate */
770 pattern->flags |= ACL_PAT_F_TREE;
771 return 1;
772 }
Willy Tarreauae8b7962007-06-09 23:10:04 +0200773 return 1;
Willy Tarreaub337b532010-05-13 20:03:41 +0200774 }
Willy Tarreauceb4ac92012-04-28 00:41:46 +0200775 else if (str62net(*text, &pattern->val.ipv6.addr, &pattern->val.ipv6.mask)) {
776 /* no tree support right now */
777 pattern->type = SMP_T_IPV6;
778 return 1;
779 }
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200780 else {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200781 memprintf(err, "'%s' is not a valid IPv4 or IPv6 address", *text);
Willy Tarreauae8b7962007-06-09 23:10:04 +0200782 return 0;
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200783 }
Willy Tarreaua67fad92007-05-08 19:50:09 +0200784}
785
Willy Tarreaua84d3742007-05-07 00:36:48 +0200786/*
787 * Registers the ACL keyword list <kwl> as a list of valid keywords for next
788 * parsing sessions.
789 */
790void acl_register_keywords(struct acl_kw_list *kwl)
791{
792 LIST_ADDQ(&acl_keywords.list, &kwl->list);
793}
794
795/*
796 * Unregisters the ACL keyword list <kwl> from the list of valid keywords.
797 */
798void acl_unregister_keywords(struct acl_kw_list *kwl)
799{
800 LIST_DEL(&kwl->list);
801 LIST_INIT(&kwl->list);
802}
803
804/* Return a pointer to the ACL <name> within the list starting at <head>, or
805 * NULL if not found.
806 */
807struct acl *find_acl_by_name(const char *name, struct list *head)
808{
809 struct acl *acl;
810 list_for_each_entry(acl, head, list) {
811 if (strcmp(acl->name, name) == 0)
812 return acl;
813 }
814 return NULL;
815}
816
817/* Return a pointer to the ACL keyword <kw>, or NULL if not found. Note that if
818 * <kw> contains an opening parenthesis, only the left part of it is checked.
819 */
820struct acl_keyword *find_acl_kw(const char *kw)
821{
822 int index;
823 const char *kwend;
824 struct acl_kw_list *kwl;
825
826 kwend = strchr(kw, '(');
827 if (!kwend)
828 kwend = kw + strlen(kw);
829
830 list_for_each_entry(kwl, &acl_keywords.list, list) {
831 for (index = 0; kwl->kw[index].kw != NULL; index++) {
832 if ((strncmp(kwl->kw[index].kw, kw, kwend - kw) == 0) &&
833 kwl->kw[index].kw[kwend-kw] == 0)
834 return &kwl->kw[index];
835 }
836 }
837 return NULL;
838}
839
Willy Tarreaudfd7fca2011-03-09 07:27:02 +0100840/* NB: does nothing if <pat> is NULL */
Willy Tarreaua84d3742007-05-07 00:36:48 +0200841static void free_pattern(struct acl_pattern *pat)
842{
Willy Tarreaudfd7fca2011-03-09 07:27:02 +0100843 if (!pat)
844 return;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +0200845
846 if (pat->ptr.ptr) {
847 if (pat->freeptrbuf)
848 pat->freeptrbuf(pat->ptr.ptr);
849
Willy Tarreaua84d3742007-05-07 00:36:48 +0200850 free(pat->ptr.ptr);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +0200851 }
852
Willy Tarreaua84d3742007-05-07 00:36:48 +0200853 free(pat);
854}
855
856static void free_pattern_list(struct list *head)
857{
858 struct acl_pattern *pat, *tmp;
859 list_for_each_entry_safe(pat, tmp, head, list)
860 free_pattern(pat);
861}
862
Willy Tarreaue56cda92010-05-11 23:25:05 +0200863static void free_pattern_tree(struct eb_root *root)
864{
865 struct eb_node *node, *next;
866 node = eb_first(root);
867 while (node) {
868 next = eb_next(node);
869 free(node);
870 node = next;
871 }
872}
873
Willy Tarreaua84d3742007-05-07 00:36:48 +0200874static struct acl_expr *prune_acl_expr(struct acl_expr *expr)
875{
Willy Tarreau34db1082012-04-19 17:16:54 +0200876 struct arg *arg;
877
Willy Tarreaua84d3742007-05-07 00:36:48 +0200878 free_pattern_list(&expr->patterns);
Willy Tarreaue56cda92010-05-11 23:25:05 +0200879 free_pattern_tree(&expr->pattern_tree);
Willy Tarreaua84d3742007-05-07 00:36:48 +0200880 LIST_INIT(&expr->patterns);
Willy Tarreau34db1082012-04-19 17:16:54 +0200881
882 for (arg = expr->args; arg; arg++) {
883 if (arg->type == ARGT_STOP)
884 break;
Willy Tarreau496aa012012-06-01 10:38:29 +0200885 if (arg->type == ARGT_STR || arg->unresolved) {
Willy Tarreau34db1082012-04-19 17:16:54 +0200886 free(arg->data.str.str);
887 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +0200888 arg->unresolved = 0;
Willy Tarreau34db1082012-04-19 17:16:54 +0200889 }
Willy Tarreau34db1082012-04-19 17:16:54 +0200890 }
891
Willy Tarreau2e845be2012-10-19 19:49:09 +0200892 if (expr->args != empty_arg_list)
893 free(expr->args);
Willy Tarreaua84d3742007-05-07 00:36:48 +0200894 expr->kw->use_cnt--;
895 return expr;
896}
897
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200898
899/* Reads patterns from a file. If <err_msg> is non-NULL, an error message will
900 * be returned there on errors and the caller will have to free it.
901 */
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200902static int acl_read_patterns_from_file( struct acl_keyword *aclkw,
903 struct acl_expr *expr,
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200904 const char *filename, int patflags,
905 char **err)
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200906{
907 FILE *file;
908 char *c;
909 const char *args[2];
910 struct acl_pattern *pattern;
911 int opaque;
Willy Tarreau6a8097f2011-02-26 15:14:15 +0100912 int ret = 0;
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200913 int line = 0;
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200914
915 file = fopen(filename, "r");
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200916 if (!file) {
917 memprintf(err, "failed to open pattern file <%s>", filename);
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200918 return 0;
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200919 }
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200920
921 /* now parse all patterns. The file may contain only one pattern per
922 * line. If the line contains spaces, they will be part of the pattern.
923 * The pattern stops at the first CR, LF or EOF encountered.
924 */
925 opaque = 0;
Willy Tarreaue56cda92010-05-11 23:25:05 +0200926 pattern = NULL;
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200927 args[1] = "";
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100928 while (fgets(trash.str, trash.size, file) != NULL) {
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200929 line++;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100930 c = trash.str;
Willy Tarreau58215a02010-05-13 22:07:43 +0200931
932 /* ignore lines beginning with a dash */
933 if (*c == '#')
934 continue;
935
936 /* strip leading spaces and tabs */
937 while (*c == ' ' || *c == '\t')
938 c++;
939
Willy Tarreau58215a02010-05-13 22:07:43 +0200940
941 args[0] = c;
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200942 while (*c && *c != '\n' && *c != '\r')
943 c++;
944 *c = 0;
945
Willy Tarreau51091962011-01-03 21:04:10 +0100946 /* empty lines are ignored too */
947 if (c == args[0])
948 continue;
949
Willy Tarreaue56cda92010-05-11 23:25:05 +0200950 /* we keep the previous pattern along iterations as long as it's not used */
951 if (!pattern)
952 pattern = (struct acl_pattern *)malloc(sizeof(*pattern));
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200953 if (!pattern) {
954 memprintf(err, "out of memory when loading patterns from file <%s>", filename);
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200955 goto out_close;
Willy Tarreau08ad0b32012-04-27 17:25:24 +0200956 }
Willy Tarreaue56cda92010-05-11 23:25:05 +0200957
958 memset(pattern, 0, sizeof(*pattern));
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200959 pattern->flags = patflags;
960
Willy Tarreaue0db1e82013-01-04 16:31:47 +0100961 if (!(pattern->flags & ACL_PAT_F_IGNORE_CASE) &&
962 (aclkw->match == acl_match_str || aclkw->match == acl_match_ip)) {
Willy Tarreaue56cda92010-05-11 23:25:05 +0200963 /* we pre-set the data pointer to the tree's head so that functions
964 * which are able to insert in a tree know where to do that.
965 */
966 pattern->flags |= ACL_PAT_F_TREE_OK;
967 pattern->val.tree = &expr->pattern_tree;
968 }
969
Willy Tarreauc92ddbc2012-04-27 22:10:57 +0200970 pattern->type = SMP_TYPES; /* unspecified type by default */
Willy Tarreau7dcb6482012-04-27 17:52:25 +0200971 if (!aclkw->parse(args, pattern, &opaque, err))
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200972 goto out_free_pattern;
Willy Tarreaue56cda92010-05-11 23:25:05 +0200973
974 /* if the parser did not feed the tree, let's chain the pattern to the list */
975 if (!(pattern->flags & ACL_PAT_F_TREE)) {
976 LIST_ADDQ(&expr->patterns, &pattern->list);
977 pattern = NULL; /* get a new one */
978 }
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200979 }
Willy Tarreau6a8097f2011-02-26 15:14:15 +0100980
981 ret = 1; /* success */
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200982
983 out_free_pattern:
984 free_pattern(pattern);
985 out_close:
986 fclose(file);
Willy Tarreau6a8097f2011-02-26 15:14:15 +0100987 return ret;
Willy Tarreau2b5285d2010-05-09 23:45:24 +0200988}
989
Willy Tarreaub7451bb2012-04-27 12:38:15 +0200990/* Parse an ACL expression starting at <args>[0], and return it. If <err> is
991 * not NULL, it will be filled with a pointer to an error message in case of
992 * error. This pointer must be freeable or NULL.
993 *
Willy Tarreaua84d3742007-05-07 00:36:48 +0200994 * Right now, the only accepted syntax is :
995 * <subject> [<value>...]
996 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +0200997struct acl_expr *parse_acl_expr(const char **args, char **err)
Willy Tarreaua84d3742007-05-07 00:36:48 +0200998{
999 __label__ out_return, out_free_expr, out_free_pattern;
1000 struct acl_expr *expr;
1001 struct acl_keyword *aclkw;
1002 struct acl_pattern *pattern;
Willy Tarreauc8d7c962007-06-17 08:20:33 +02001003 int opaque, patflags;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001004 const char *arg;
1005
1006 aclkw = find_acl_kw(args[0]);
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001007 if (!aclkw || !aclkw->parse) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001008 memprintf(err, "unknown ACL keyword '%s'", *args);
Willy Tarreaua84d3742007-05-07 00:36:48 +02001009 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001010 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001011
1012 expr = (struct acl_expr *)calloc(1, sizeof(*expr));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001013 if (!expr) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001014 memprintf(err, "out of memory when parsing ACL expression");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001015 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001016 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001017
1018 expr->kw = aclkw;
1019 aclkw->use_cnt++;
1020 LIST_INIT(&expr->patterns);
Willy Tarreaue56cda92010-05-11 23:25:05 +02001021 expr->pattern_tree = EB_ROOT_UNIQUE;
Willy Tarreau2e845be2012-10-19 19:49:09 +02001022 expr->args = empty_arg_list;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001023
1024 arg = strchr(args[0], '(');
Willy Tarreau61612d42012-04-19 18:42:05 +02001025 if (aclkw->arg_mask) {
1026 int nbargs = 0;
Willy Tarreau34db1082012-04-19 17:16:54 +02001027 char *end;
Willy Tarreau34db1082012-04-19 17:16:54 +02001028
Willy Tarreau61612d42012-04-19 18:42:05 +02001029 if (arg != NULL) {
1030 /* there are 0 or more arguments in the form "subject(arg[,arg]*)" */
1031 arg++;
1032 end = strchr(arg, ')');
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001033 if (!end) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001034 memprintf(err, "missing closing ')' after arguments to ACL keyword '%s'", aclkw->kw);
Willy Tarreau61612d42012-04-19 18:42:05 +02001035 goto out_free_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001036 }
Willy Tarreau34db1082012-04-19 17:16:54 +02001037
Willy Tarreau61612d42012-04-19 18:42:05 +02001038 /* Parse the arguments. Note that currently we have no way to
1039 * report parsing errors, hence the NULL in the error pointers.
1040 * An error is also reported if some mandatory arguments are
1041 * missing.
1042 */
1043 nbargs = make_arg_list(arg, end - arg, aclkw->arg_mask, &expr->args,
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001044 err, NULL, NULL);
1045 if (nbargs < 0) {
1046 /* note that make_arg_list will have set <err> here */
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001047 memprintf(err, "in argument to '%s', %s", aclkw->kw, *err);
Willy Tarreau61612d42012-04-19 18:42:05 +02001048 goto out_free_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001049 }
Willy Tarreauae52f062012-04-26 12:13:35 +02001050
Willy Tarreau2e845be2012-10-19 19:49:09 +02001051 if (!expr->args)
1052 expr->args = empty_arg_list;
1053
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001054 if (aclkw->val_args && !aclkw->val_args(expr->args, err)) {
1055 /* invalid keyword argument, error must have been
1056 * set by val_args().
1057 */
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001058 memprintf(err, "in argument to '%s', %s", aclkw->kw, *err);
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001059 goto out_free_expr;
1060 }
Willy Tarreau61612d42012-04-19 18:42:05 +02001061 }
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001062 else if (ARGM(aclkw->arg_mask) == 1) {
1063 int type = (aclkw->arg_mask >> 4) & 15;
1064
1065 /* If a proxy is noted as a mandatory argument, we'll fake
1066 * an empty one so that acl_find_targets() resolves it as
1067 * the current one later.
1068 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001069 if (type != ARGT_FE && type != ARGT_BE && type != ARGT_TAB) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001070 memprintf(err, "ACL keyword '%s' expects %d arguments", aclkw->kw, ARGM(aclkw->arg_mask));
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001071 goto out_free_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001072 }
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001073
1074 /* Build an arg list containing the type as an empty string
1075 * and the usual STOP.
1076 */
1077 expr->args = calloc(2, sizeof(*expr->args));
1078 expr->args[0].type = type;
Willy Tarreaue3a46112012-06-15 08:02:34 +02001079 expr->args[0].unresolved = 1;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001080 expr->args[0].data.str.str = strdup("");
1081 expr->args[0].data.str.len = 1;
1082 expr->args[0].data.str.len = 0;
1083 expr->args[1].type = ARGT_STOP;
1084 }
Willy Tarreau61612d42012-04-19 18:42:05 +02001085 else if (ARGM(aclkw->arg_mask)) {
1086 /* there were some mandatory arguments */
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001087 memprintf(err, "ACL keyword '%s' expects %d arguments", aclkw->kw, ARGM(aclkw->arg_mask));
Willy Tarreaua84d3742007-05-07 00:36:48 +02001088 goto out_free_expr;
Willy Tarreau61612d42012-04-19 18:42:05 +02001089 }
1090 }
1091 else {
1092 if (arg) {
1093 /* no argument expected */
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001094 memprintf(err, "ACL keyword '%s' takes no argument", aclkw->kw);
Willy Tarreau61612d42012-04-19 18:42:05 +02001095 goto out_free_expr;
1096 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001097 }
1098
Willy Tarreaua84d3742007-05-07 00:36:48 +02001099 args++;
Willy Tarreauc8d7c962007-06-17 08:20:33 +02001100
1101 /* check for options before patterns. Supported options are :
1102 * -i : ignore case for all patterns by default
1103 * -f : read patterns from those files
1104 * -- : everything after this is not an option
1105 */
1106 patflags = 0;
1107 while (**args == '-') {
1108 if ((*args)[1] == 'i')
1109 patflags |= ACL_PAT_F_IGNORE_CASE;
Willy Tarreau2b5285d2010-05-09 23:45:24 +02001110 else if ((*args)[1] == 'f') {
Willy Tarreau08ad0b32012-04-27 17:25:24 +02001111 if (!acl_read_patterns_from_file(aclkw, expr, args[1], patflags | ACL_PAT_F_FROM_FILE, err))
Willy Tarreau2b5285d2010-05-09 23:45:24 +02001112 goto out_free_expr;
1113 args++;
1114 }
Willy Tarreauc8d7c962007-06-17 08:20:33 +02001115 else if ((*args)[1] == '-') {
1116 args++;
1117 break;
1118 }
1119 else
1120 break;
1121 args++;
1122 }
1123
1124 /* now parse all patterns */
Willy Tarreauae8b7962007-06-09 23:10:04 +02001125 opaque = 0;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001126 while (**args) {
Willy Tarreauae8b7962007-06-09 23:10:04 +02001127 int ret;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001128 pattern = (struct acl_pattern *)calloc(1, sizeof(*pattern));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001129 if (!pattern) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001130 memprintf(err, "out of memory when parsing ACL pattern");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001131 goto out_free_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001132 }
Willy Tarreauc8d7c962007-06-17 08:20:33 +02001133 pattern->flags = patflags;
1134
Willy Tarreauc92ddbc2012-04-27 22:10:57 +02001135 pattern->type = SMP_TYPES; /* unspecified type */
Willy Tarreau7dcb6482012-04-27 17:52:25 +02001136 ret = aclkw->parse(args, pattern, &opaque, err);
1137 if (!ret)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001138 goto out_free_pattern;
Willy Tarreau7dcb6482012-04-27 17:52:25 +02001139
Willy Tarreaua84d3742007-05-07 00:36:48 +02001140 LIST_ADDQ(&expr->patterns, &pattern->list);
Willy Tarreauae8b7962007-06-09 23:10:04 +02001141 args += ret;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001142 }
1143
1144 return expr;
1145
1146 out_free_pattern:
1147 free_pattern(pattern);
1148 out_free_expr:
1149 prune_acl_expr(expr);
1150 free(expr);
1151 out_return:
1152 return NULL;
1153}
1154
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02001155/* Purge everything in the acl <acl>, then return <acl>. */
1156struct acl *prune_acl(struct acl *acl) {
1157
1158 struct acl_expr *expr, *exprb;
1159
1160 free(acl->name);
1161
1162 list_for_each_entry_safe(expr, exprb, &acl->expr, list) {
1163 LIST_DEL(&expr->list);
1164 prune_acl_expr(expr);
1165 free(expr);
1166 }
1167
1168 return acl;
1169}
1170
Willy Tarreaua84d3742007-05-07 00:36:48 +02001171/* Parse an ACL with the name starting at <args>[0], and with a list of already
1172 * known ACLs in <acl>. If the ACL was not in the list, it will be added.
Willy Tarreau2a56c5e2010-03-15 16:13:29 +01001173 * A pointer to that ACL is returned. If the ACL has an empty name, then it's
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001174 * an anonymous one and it won't be merged with any other one. If <err> is not
1175 * NULL, it will be filled with an appropriate error. This pointer must be
1176 * freeable or NULL.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001177 *
1178 * args syntax: <aclname> <acl_expr>
1179 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001180struct acl *parse_acl(const char **args, struct list *known_acl, char **err)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001181{
1182 __label__ out_return, out_free_acl_expr, out_free_name;
1183 struct acl *cur_acl;
1184 struct acl_expr *acl_expr;
1185 char *name;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001186 const char *pos;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001187
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001188 if (**args && (pos = invalid_char(*args))) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001189 memprintf(err, "invalid character in ACL name : '%c'", *pos);
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001190 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001191 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001192
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001193 acl_expr = parse_acl_expr(args + 1, err);
1194 if (!acl_expr) {
1195 /* parse_acl_expr will have filled <err> here */
Willy Tarreaua84d3742007-05-07 00:36:48 +02001196 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001197 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001198
Willy Tarreau404e8ab2009-07-26 19:40:40 +02001199 /* Check for args beginning with an opening parenthesis just after the
1200 * subject, as this is almost certainly a typo. Right now we can only
1201 * emit a warning, so let's do so.
1202 */
Krzysztof Piotr Oledzki4cdd8312009-10-05 00:23:35 +02001203 if (!strchr(args[1], '(') && *args[2] == '(')
Willy Tarreau404e8ab2009-07-26 19:40:40 +02001204 Warning("parsing acl '%s' :\n"
1205 " matching '%s' for pattern '%s' is likely a mistake and probably\n"
1206 " not what you want. Maybe you need to remove the extraneous space before '('.\n"
1207 " If you are really sure this is not an error, please insert '--' between the\n"
1208 " match and the pattern to make this warning message disappear.\n",
1209 args[0], args[1], args[2]);
1210
Willy Tarreau2a56c5e2010-03-15 16:13:29 +01001211 if (*args[0])
1212 cur_acl = find_acl_by_name(args[0], known_acl);
1213 else
1214 cur_acl = NULL;
1215
Willy Tarreaua84d3742007-05-07 00:36:48 +02001216 if (!cur_acl) {
1217 name = strdup(args[0]);
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001218 if (!name) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001219 memprintf(err, "out of memory when parsing ACL");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001220 goto out_free_acl_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001221 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001222 cur_acl = (struct acl *)calloc(1, sizeof(*cur_acl));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001223 if (cur_acl == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001224 memprintf(err, "out of memory when parsing ACL");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001225 goto out_free_name;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001226 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001227
1228 LIST_INIT(&cur_acl->expr);
1229 LIST_ADDQ(known_acl, &cur_acl->list);
1230 cur_acl->name = name;
1231 }
1232
Willy Tarreaua9802632008-07-25 19:13:19 +02001233 cur_acl->requires |= acl_expr->kw->requires;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001234 LIST_ADDQ(&cur_acl->expr, &acl_expr->list);
1235 return cur_acl;
1236
1237 out_free_name:
1238 free(name);
1239 out_free_acl_expr:
1240 prune_acl_expr(acl_expr);
1241 free(acl_expr);
1242 out_return:
1243 return NULL;
1244}
1245
Willy Tarreau16fbe822007-06-17 11:54:31 +02001246/* Some useful ACLs provided by default. Only those used are allocated. */
1247
1248const struct {
1249 const char *name;
1250 const char *expr[4]; /* put enough for longest expression */
1251} default_acl_list[] = {
Willy Tarreau58393e12008-07-20 10:39:22 +02001252 { .name = "TRUE", .expr = {"always_true",""}},
1253 { .name = "FALSE", .expr = {"always_false",""}},
Willy Tarreau16fbe822007-06-17 11:54:31 +02001254 { .name = "LOCALHOST", .expr = {"src","127.0.0.1/8",""}},
Willy Tarreau2492d5b2009-07-11 00:06:00 +02001255 { .name = "HTTP", .expr = {"req_proto_http",""}},
Willy Tarreau16fbe822007-06-17 11:54:31 +02001256 { .name = "HTTP_1.0", .expr = {"req_ver","1.0",""}},
1257 { .name = "HTTP_1.1", .expr = {"req_ver","1.1",""}},
1258 { .name = "METH_CONNECT", .expr = {"method","CONNECT",""}},
1259 { .name = "METH_GET", .expr = {"method","GET","HEAD",""}},
1260 { .name = "METH_HEAD", .expr = {"method","HEAD",""}},
1261 { .name = "METH_OPTIONS", .expr = {"method","OPTIONS",""}},
1262 { .name = "METH_POST", .expr = {"method","POST",""}},
1263 { .name = "METH_TRACE", .expr = {"method","TRACE",""}},
1264 { .name = "HTTP_URL_ABS", .expr = {"url_reg","^[^/:]*://",""}},
1265 { .name = "HTTP_URL_SLASH", .expr = {"url_beg","/",""}},
1266 { .name = "HTTP_URL_STAR", .expr = {"url","*",""}},
1267 { .name = "HTTP_CONTENT", .expr = {"hdr_val(content-length)","gt","0",""}},
Emeric Brunbede3d02009-06-30 17:54:00 +02001268 { .name = "RDP_COOKIE", .expr = {"req_rdp_cookie_cnt","gt","0",""}},
Willy Tarreauc6317702008-07-20 09:29:50 +02001269 { .name = "REQ_CONTENT", .expr = {"req_len","gt","0",""}},
Willy Tarreaub6fb4202008-07-20 11:18:28 +02001270 { .name = "WAIT_END", .expr = {"wait_end",""}},
Willy Tarreau16fbe822007-06-17 11:54:31 +02001271 { .name = NULL, .expr = {""}}
1272};
1273
1274/* Find a default ACL from the default_acl list, compile it and return it.
1275 * If the ACL is not found, NULL is returned. In theory, it cannot fail,
1276 * except when default ACLs are broken, in which case it will return NULL.
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001277 * If <known_acl> is not NULL, the ACL will be queued at its tail. If <err> is
1278 * not NULL, it will be filled with an error message if an error occurs. This
1279 * pointer must be freeable or NULL.
Willy Tarreau16fbe822007-06-17 11:54:31 +02001280 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001281struct acl *find_acl_default(const char *acl_name, struct list *known_acl, char **err)
Willy Tarreau16fbe822007-06-17 11:54:31 +02001282{
1283 __label__ out_return, out_free_acl_expr, out_free_name;
1284 struct acl *cur_acl;
1285 struct acl_expr *acl_expr;
1286 char *name;
1287 int index;
1288
1289 for (index = 0; default_acl_list[index].name != NULL; index++) {
1290 if (strcmp(acl_name, default_acl_list[index].name) == 0)
1291 break;
1292 }
1293
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001294 if (default_acl_list[index].name == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001295 memprintf(err, "no such ACL : '%s'", acl_name);
Willy Tarreau16fbe822007-06-17 11:54:31 +02001296 return NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001297 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001298
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001299 acl_expr = parse_acl_expr((const char **)default_acl_list[index].expr, err);
1300 if (!acl_expr) {
1301 /* parse_acl_expr must have filled err here */
Willy Tarreau16fbe822007-06-17 11:54:31 +02001302 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001303 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001304
1305 name = strdup(acl_name);
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001306 if (!name) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001307 memprintf(err, "out of memory when building default ACL '%s'", acl_name);
Willy Tarreau16fbe822007-06-17 11:54:31 +02001308 goto out_free_acl_expr;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001309 }
1310
Willy Tarreau16fbe822007-06-17 11:54:31 +02001311 cur_acl = (struct acl *)calloc(1, sizeof(*cur_acl));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001312 if (cur_acl == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001313 memprintf(err, "out of memory when building default ACL '%s'", acl_name);
Willy Tarreau16fbe822007-06-17 11:54:31 +02001314 goto out_free_name;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001315 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001316
1317 cur_acl->name = name;
Willy Tarreaua55b7dc2009-07-12 09:21:30 +02001318 cur_acl->requires |= acl_expr->kw->requires;
Willy Tarreau16fbe822007-06-17 11:54:31 +02001319 LIST_INIT(&cur_acl->expr);
1320 LIST_ADDQ(&cur_acl->expr, &acl_expr->list);
1321 if (known_acl)
1322 LIST_ADDQ(known_acl, &cur_acl->list);
1323
1324 return cur_acl;
1325
1326 out_free_name:
1327 free(name);
1328 out_free_acl_expr:
1329 prune_acl_expr(acl_expr);
1330 free(acl_expr);
1331 out_return:
1332 return NULL;
1333}
Willy Tarreaua84d3742007-05-07 00:36:48 +02001334
1335/* Purge everything in the acl_cond <cond>, then return <cond>. */
1336struct acl_cond *prune_acl_cond(struct acl_cond *cond)
1337{
1338 struct acl_term_suite *suite, *tmp_suite;
1339 struct acl_term *term, *tmp_term;
1340
1341 /* iterate through all term suites and free all terms and all suites */
1342 list_for_each_entry_safe(suite, tmp_suite, &cond->suites, list) {
1343 list_for_each_entry_safe(term, tmp_term, &suite->terms, list)
1344 free(term);
1345 free(suite);
1346 }
1347 return cond;
1348}
1349
1350/* Parse an ACL condition starting at <args>[0], relying on a list of already
1351 * known ACLs passed in <known_acl>. The new condition is returned (or NULL in
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001352 * case of low memory). Supports multiple conditions separated by "or". If
1353 * <err> is not NULL, it will be filled with a pointer to an error message in
1354 * case of error, that the caller is responsible for freeing. The initial
1355 * location must either be freeable or NULL.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001356 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001357struct acl_cond *parse_acl_cond(const char **args, struct list *known_acl, int pol, char **err)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001358{
1359 __label__ out_return, out_free_suite, out_free_term;
Willy Tarreau74b98a82007-06-16 19:35:18 +02001360 int arg, neg;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001361 const char *word;
1362 struct acl *cur_acl;
1363 struct acl_term *cur_term;
1364 struct acl_term_suite *cur_suite;
1365 struct acl_cond *cond;
1366
1367 cond = (struct acl_cond *)calloc(1, sizeof(*cond));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001368 if (cond == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001369 memprintf(err, "out of memory when parsing condition");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001370 goto out_return;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001371 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001372
1373 LIST_INIT(&cond->list);
1374 LIST_INIT(&cond->suites);
1375 cond->pol = pol;
1376
1377 cur_suite = NULL;
Willy Tarreau74b98a82007-06-16 19:35:18 +02001378 neg = 0;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001379 for (arg = 0; *args[arg]; arg++) {
1380 word = args[arg];
1381
1382 /* remove as many exclamation marks as we can */
1383 while (*word == '!') {
1384 neg = !neg;
1385 word++;
1386 }
1387
1388 /* an empty word is allowed because we cannot force the user to
1389 * always think about not leaving exclamation marks alone.
1390 */
1391 if (!*word)
1392 continue;
1393
Willy Tarreau16fbe822007-06-17 11:54:31 +02001394 if (strcasecmp(word, "or") == 0 || strcmp(word, "||") == 0) {
Willy Tarreaua84d3742007-05-07 00:36:48 +02001395 /* new term suite */
1396 cur_suite = NULL;
1397 neg = 0;
1398 continue;
1399 }
1400
Willy Tarreau95fa4692010-02-01 13:05:50 +01001401 if (strcmp(word, "{") == 0) {
1402 /* we may have a complete ACL expression between two braces,
1403 * find the last one.
1404 */
1405 int arg_end = arg + 1;
1406 const char **args_new;
1407
1408 while (*args[arg_end] && strcmp(args[arg_end], "}") != 0)
1409 arg_end++;
1410
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001411 if (!*args[arg_end]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001412 memprintf(err, "missing closing '}' in condition");
Willy Tarreau95fa4692010-02-01 13:05:50 +01001413 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001414 }
Willy Tarreau95fa4692010-02-01 13:05:50 +01001415
1416 args_new = calloc(1, (arg_end - arg + 1) * sizeof(*args_new));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001417 if (!args_new) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001418 memprintf(err, "out of memory when parsing condition");
Willy Tarreau95fa4692010-02-01 13:05:50 +01001419 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001420 }
Willy Tarreau95fa4692010-02-01 13:05:50 +01001421
Willy Tarreau2a56c5e2010-03-15 16:13:29 +01001422 args_new[0] = "";
Willy Tarreau95fa4692010-02-01 13:05:50 +01001423 memcpy(args_new + 1, args + arg + 1, (arg_end - arg) * sizeof(*args_new));
1424 args_new[arg_end - arg] = "";
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001425 cur_acl = parse_acl(args_new, known_acl, err);
Willy Tarreau95fa4692010-02-01 13:05:50 +01001426 free(args_new);
1427
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001428 if (!cur_acl) {
1429 /* note that parse_acl() must have filled <err> here */
Willy Tarreau16fbe822007-06-17 11:54:31 +02001430 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001431 }
Willy Tarreau95fa4692010-02-01 13:05:50 +01001432 arg = arg_end;
1433 }
1434 else {
1435 /* search for <word> in the known ACL names. If we do not find
1436 * it, let's look for it in the default ACLs, and if found, add
1437 * it to the list of ACLs of this proxy. This makes it possible
1438 * to override them.
1439 */
1440 cur_acl = find_acl_by_name(word, known_acl);
1441 if (cur_acl == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001442 cur_acl = find_acl_default(word, known_acl, err);
1443 if (cur_acl == NULL) {
1444 /* note that find_acl_default() must have filled <err> here */
Willy Tarreau95fa4692010-02-01 13:05:50 +01001445 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001446 }
Willy Tarreau95fa4692010-02-01 13:05:50 +01001447 }
Willy Tarreau16fbe822007-06-17 11:54:31 +02001448 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001449
1450 cur_term = (struct acl_term *)calloc(1, sizeof(*cur_term));
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001451 if (cur_term == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001452 memprintf(err, "out of memory when parsing condition");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001453 goto out_free_suite;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001454 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001455
1456 cur_term->acl = cur_acl;
1457 cur_term->neg = neg;
Willy Tarreaua9802632008-07-25 19:13:19 +02001458 cond->requires |= cur_acl->requires;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001459
1460 if (!cur_suite) {
1461 cur_suite = (struct acl_term_suite *)calloc(1, sizeof(*cur_suite));
Willy Tarreauf678b7f2013-01-24 00:25:39 +01001462 if (cur_suite == NULL) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001463 memprintf(err, "out of memory when parsing condition");
Willy Tarreaua84d3742007-05-07 00:36:48 +02001464 goto out_free_term;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001465 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001466 LIST_INIT(&cur_suite->terms);
1467 LIST_ADDQ(&cond->suites, &cur_suite->list);
1468 }
1469 LIST_ADDQ(&cur_suite->terms, &cur_term->list);
Willy Tarreau74b98a82007-06-16 19:35:18 +02001470 neg = 0;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001471 }
1472
1473 return cond;
1474
1475 out_free_term:
1476 free(cur_term);
1477 out_free_suite:
1478 prune_acl_cond(cond);
1479 free(cond);
1480 out_return:
1481 return NULL;
1482}
1483
Willy Tarreau2bbba412010-01-28 16:48:33 +01001484/* Builds an ACL condition starting at the if/unless keyword. The complete
1485 * condition is returned. NULL is returned in case of error or if the first
1486 * word is neither "if" nor "unless". It automatically sets the file name and
1487 * the line number in the condition for better error reporting, and adds the
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001488 * ACL requirements to the proxy's acl_requires. If <err> is not NULL, it will
1489 * be filled with a pointer to an error message in case of error, that the
1490 * caller is responsible for freeing. The initial location must either be
1491 * freeable or NULL.
Willy Tarreau2bbba412010-01-28 16:48:33 +01001492 */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001493struct 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 +01001494{
1495 int pol = ACL_COND_NONE;
1496 struct acl_cond *cond = NULL;
1497
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001498 if (err)
1499 *err = NULL;
1500
Willy Tarreau2bbba412010-01-28 16:48:33 +01001501 if (!strcmp(*args, "if")) {
1502 pol = ACL_COND_IF;
1503 args++;
1504 }
1505 else if (!strcmp(*args, "unless")) {
1506 pol = ACL_COND_UNLESS;
1507 args++;
1508 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001509 else {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02001510 memprintf(err, "conditions must start with either 'if' or 'unless'");
Willy Tarreau2bbba412010-01-28 16:48:33 +01001511 return NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001512 }
Willy Tarreau2bbba412010-01-28 16:48:33 +01001513
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001514 cond = parse_acl_cond(args, &px->acl, pol, err);
1515 if (!cond) {
1516 /* note that parse_acl_cond must have filled <err> here */
Willy Tarreau2bbba412010-01-28 16:48:33 +01001517 return NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001518 }
Willy Tarreau2bbba412010-01-28 16:48:33 +01001519
1520 cond->file = file;
1521 cond->line = line;
1522 px->acl_requires |= cond->requires;
1523
1524 return cond;
1525}
1526
Willy Tarreau11382812008-07-09 16:18:21 +02001527/* Execute condition <cond> and return either ACL_PAT_FAIL, ACL_PAT_MISS or
Willy Tarreaub6866442008-07-14 23:54:42 +02001528 * ACL_PAT_PASS depending on the test results. ACL_PAT_MISS may only be
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001529 * returned if <opt> does not contain SMP_OPT_FINAL, indicating that incomplete
Willy Tarreau7a777ed2012-04-26 11:44:02 +02001530 * data is being examined. The function automatically sets SMP_OPT_ITERATE.
Willy Tarreaub6866442008-07-14 23:54:42 +02001531 * This function only computes the condition, it does not apply the polarity
1532 * required by IF/UNLESS, it's up to the caller to do this using something like
1533 * this :
Willy Tarreau11382812008-07-09 16:18:21 +02001534 *
1535 * res = acl_pass(res);
Willy Tarreaub6866442008-07-14 23:54:42 +02001536 * if (res == ACL_PAT_MISS)
1537 * return 0;
Willy Tarreau11382812008-07-09 16:18:21 +02001538 * if (cond->pol == ACL_COND_UNLESS)
1539 * res = !res;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001540 */
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001541int 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 +02001542{
1543 __label__ fetch_next;
1544 struct acl_term_suite *suite;
1545 struct acl_term *term;
1546 struct acl_expr *expr;
1547 struct acl *acl;
1548 struct acl_pattern *pattern;
Willy Tarreau37406352012-04-23 16:16:37 +02001549 struct sample smp;
Willy Tarreau11382812008-07-09 16:18:21 +02001550 int acl_res, suite_res, cond_res;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001551
Willy Tarreau7a777ed2012-04-26 11:44:02 +02001552 /* ACLs are iterated over all values, so let's always set the flag to
1553 * indicate this to the fetch functions.
1554 */
1555 opt |= SMP_OPT_ITERATE;
1556
Willy Tarreau11382812008-07-09 16:18:21 +02001557 /* We're doing a logical OR between conditions so we initialize to FAIL.
1558 * The MISS status is propagated down from the suites.
1559 */
Willy Tarreaua84d3742007-05-07 00:36:48 +02001560 cond_res = ACL_PAT_FAIL;
1561 list_for_each_entry(suite, &cond->suites, list) {
Willy Tarreau11382812008-07-09 16:18:21 +02001562 /* Evaluate condition suite <suite>. We stop at the first term
1563 * which returns ACL_PAT_FAIL. The MISS status is still propagated
1564 * in case of uncertainty in the result.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001565 */
1566
1567 /* we're doing a logical AND between terms, so we must set the
1568 * initial value to PASS.
1569 */
1570 suite_res = ACL_PAT_PASS;
1571 list_for_each_entry(term, &suite->terms, list) {
1572 acl = term->acl;
1573
1574 /* FIXME: use cache !
1575 * check acl->cache_idx for this.
1576 */
1577
1578 /* ACL result not cached. Let's scan all the expressions
1579 * and use the first one to match.
1580 */
1581 acl_res = ACL_PAT_FAIL;
1582 list_for_each_entry(expr, &acl->expr, list) {
Willy Tarreaud41f8d82007-06-10 10:06:18 +02001583 /* we need to reset context and flags */
Willy Tarreau37406352012-04-23 16:16:37 +02001584 memset(&smp, 0, sizeof(smp));
Willy Tarreaua84d3742007-05-07 00:36:48 +02001585 fetch_next:
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001586 if (!expr->kw->fetch(px, l4, l7, opt, expr->args, &smp)) {
Willy Tarreaub6866442008-07-14 23:54:42 +02001587 /* maybe we could not fetch because of missing data */
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001588 if (smp.flags & SMP_F_MAY_CHANGE && !(opt & SMP_OPT_FINAL))
Willy Tarreaub6866442008-07-14 23:54:42 +02001589 acl_res |= ACL_PAT_MISS;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001590 continue;
Willy Tarreaub6866442008-07-14 23:54:42 +02001591 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001592
Willy Tarreau197e10a2012-04-23 19:18:42 +02001593 if (smp.type == SMP_T_BOOL) {
1594 if (smp.data.uint)
Willy Tarreaua79534f2008-07-20 10:13:37 +02001595 acl_res |= ACL_PAT_PASS;
1596 else
1597 acl_res |= ACL_PAT_FAIL;
1598 }
1599 else {
Willy Tarreau020534d2010-05-16 21:45:45 +02001600 if (!eb_is_empty(&expr->pattern_tree)) {
Willy Tarreauc4262962010-05-10 23:42:40 +02001601 /* a tree is present, let's check what type it is */
1602 if (expr->kw->match == acl_match_str)
Willy Tarreau37406352012-04-23 16:16:37 +02001603 acl_res |= acl_lookup_str(&smp, expr) ? ACL_PAT_PASS : ACL_PAT_FAIL;
Willy Tarreaub337b532010-05-13 20:03:41 +02001604 else if (expr->kw->match == acl_match_ip)
Willy Tarreau37406352012-04-23 16:16:37 +02001605 acl_res |= acl_lookup_ip(&smp, expr) ? ACL_PAT_PASS : ACL_PAT_FAIL;
Willy Tarreauc4262962010-05-10 23:42:40 +02001606 }
1607
Willy Tarreaua79534f2008-07-20 10:13:37 +02001608 /* call the match() function for all tests on this value */
1609 list_for_each_entry(pattern, &expr->patterns, list) {
Willy Tarreaua79534f2008-07-20 10:13:37 +02001610 if (acl_res == ACL_PAT_PASS)
1611 break;
Willy Tarreau37406352012-04-23 16:16:37 +02001612 acl_res |= expr->kw->match(&smp, pattern);
Willy Tarreaua79534f2008-07-20 10:13:37 +02001613 }
Willy Tarreaua84d3742007-05-07 00:36:48 +02001614 }
1615 /*
Willy Tarreau11382812008-07-09 16:18:21 +02001616 * OK now acl_res holds the result of this expression
1617 * as one of ACL_PAT_FAIL, ACL_PAT_MISS or ACL_PAT_PASS.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001618 *
Willy Tarreau11382812008-07-09 16:18:21 +02001619 * Then if (!MISS) we can cache the result, and put
Willy Tarreau37406352012-04-23 16:16:37 +02001620 * (smp.flags & SMP_F_VOLATILE) in the cache flags.
Willy Tarreaua84d3742007-05-07 00:36:48 +02001621 *
1622 * FIXME: implement cache.
1623 *
1624 */
1625
Willy Tarreau11382812008-07-09 16:18:21 +02001626 /* we're ORing these terms, so a single PASS is enough */
1627 if (acl_res == ACL_PAT_PASS)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001628 break;
1629
Willy Tarreau37406352012-04-23 16:16:37 +02001630 if (smp.flags & SMP_F_NOT_LAST)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001631 goto fetch_next;
Willy Tarreaub6866442008-07-14 23:54:42 +02001632
1633 /* sometimes we know the fetched data is subject to change
1634 * later and give another chance for a new match (eg: request
1635 * size, time, ...)
1636 */
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001637 if (smp.flags & SMP_F_MAY_CHANGE && !(opt & SMP_OPT_FINAL))
Willy Tarreaub6866442008-07-14 23:54:42 +02001638 acl_res |= ACL_PAT_MISS;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001639 }
1640 /*
1641 * Here we have the result of an ACL (cached or not).
1642 * ACLs are combined, negated or not, to form conditions.
1643 */
1644
Willy Tarreaua84d3742007-05-07 00:36:48 +02001645 if (term->neg)
Willy Tarreau11382812008-07-09 16:18:21 +02001646 acl_res = acl_neg(acl_res);
Willy Tarreaua84d3742007-05-07 00:36:48 +02001647
1648 suite_res &= acl_res;
Willy Tarreau11382812008-07-09 16:18:21 +02001649
1650 /* we're ANDing these terms, so a single FAIL is enough */
1651 if (suite_res == ACL_PAT_FAIL)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001652 break;
1653 }
1654 cond_res |= suite_res;
Willy Tarreau11382812008-07-09 16:18:21 +02001655
1656 /* we're ORing these terms, so a single PASS is enough */
1657 if (cond_res == ACL_PAT_PASS)
Willy Tarreaua84d3742007-05-07 00:36:48 +02001658 break;
1659 }
Willy Tarreau11382812008-07-09 16:18:21 +02001660 return cond_res;
Willy Tarreaua84d3742007-05-07 00:36:48 +02001661}
1662
1663
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001664/* Reports a pointer to the first ACL used in condition <cond> which requires
1665 * at least one of the USE_FLAGS in <require>. Returns NULL if none matches.
1666 * The construct is almost the same as for acl_exec_cond() since we're walking
1667 * down the ACL tree as well. It is important that the tree is really walked
1668 * through and never cached, because that way, this function can be used as a
1669 * late check.
1670 */
Willy Tarreauf1e98b82010-01-28 17:59:39 +01001671struct acl *cond_find_require(const struct acl_cond *cond, unsigned int require)
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001672{
1673 struct acl_term_suite *suite;
1674 struct acl_term *term;
1675 struct acl *acl;
1676
1677 list_for_each_entry(suite, &cond->suites, list) {
1678 list_for_each_entry(term, &suite->terms, list) {
1679 acl = term->acl;
1680 if (acl->requires & require)
1681 return acl;
1682 }
1683 }
1684 return NULL;
1685}
1686
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001687/*
1688 * Find targets for userlist and groups in acl. Function returns the number
1689 * of errors or OK if everything is fine.
1690 */
1691int
1692acl_find_targets(struct proxy *p)
1693{
1694
1695 struct acl *acl;
1696 struct acl_expr *expr;
1697 struct acl_pattern *pattern;
1698 struct userlist *ul;
Willy Tarreau63364ee2012-04-19 19:11:13 +02001699 struct arg *arg;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001700 int cfgerr = 0;
1701
1702 list_for_each_entry(acl, &p->acl, list) {
1703 list_for_each_entry(expr, &acl->expr, list) {
Willy Tarreau2e845be2012-10-19 19:49:09 +02001704 for (arg = expr->args; arg && arg->type != ARGT_STOP; arg++) {
1705 if (!arg->unresolved)
Willy Tarreau496aa012012-06-01 10:38:29 +02001706 continue;
Willy Tarreau63364ee2012-04-19 19:11:13 +02001707 else if (arg->type == ARGT_SRV) {
1708 struct proxy *px;
1709 struct server *srv;
1710 char *pname, *sname;
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001711
Willy Tarreau7d1df412012-11-23 23:47:36 +01001712 if (!arg->data.str.len) {
Willy Tarreau63364ee2012-04-19 19:11:13 +02001713 Alert("proxy %s: acl '%s' %s(): missing server name.\n",
1714 p->id, acl->name, expr->kw->kw);
1715 cfgerr++;
1716 continue;
1717 }
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001718
Willy Tarreau7d1df412012-11-23 23:47:36 +01001719 pname = arg->data.str.str;
Willy Tarreau63364ee2012-04-19 19:11:13 +02001720 sname = strrchr(pname, '/');
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001721
Willy Tarreau63364ee2012-04-19 19:11:13 +02001722 if (sname)
1723 *sname++ = '\0';
1724 else {
1725 sname = pname;
1726 pname = NULL;
1727 }
1728
1729 px = p;
1730 if (pname) {
1731 px = findproxy(pname, PR_CAP_BE);
1732 if (!px) {
1733 Alert("proxy %s: acl '%s' %s(): unable to find proxy '%s'.\n",
1734 p->id, acl->name, expr->kw->kw, pname);
1735 cfgerr++;
1736 continue;
1737 }
1738 }
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001739
Willy Tarreau63364ee2012-04-19 19:11:13 +02001740 srv = findserver(px, sname);
1741 if (!srv) {
1742 Alert("proxy %s: acl '%s' %s(): unable to find server '%s'.\n",
1743 p->id, acl->name, expr->kw->kw, sname);
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001744 cfgerr++;
1745 continue;
1746 }
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001747
Willy Tarreau7d1df412012-11-23 23:47:36 +01001748 free(arg->data.str.str);
1749 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001750 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001751 arg->data.srv = srv;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001752 }
1753 else if (arg->type == ARGT_FE) {
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001754 struct proxy *prx = p;
1755 char *pname = p->id;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001756
Willy Tarreau7d1df412012-11-23 23:47:36 +01001757 if (arg->data.str.len) {
1758 pname = arg->data.str.str;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001759 prx = findproxy(pname, PR_CAP_FE);
Willy Tarreaud28c3532012-04-19 19:28:33 +02001760 }
1761
Willy Tarreaud28c3532012-04-19 19:28:33 +02001762 if (!prx) {
1763 Alert("proxy %s: acl '%s' %s(): unable to find frontend '%s'.\n",
1764 p->id, acl->name, expr->kw->kw, pname);
1765 cfgerr++;
1766 continue;
1767 }
1768
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001769 if (!(prx->cap & PR_CAP_FE)) {
1770 Alert("proxy %s: acl '%s' %s(): proxy '%s' has no frontend capability.\n",
1771 p->id, acl->name, expr->kw->kw, pname);
1772 cfgerr++;
1773 continue;
1774 }
1775
Willy Tarreau7d1df412012-11-23 23:47:36 +01001776 free(arg->data.str.str);
1777 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001778 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001779 arg->data.prx = prx;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001780 }
1781 else if (arg->type == ARGT_BE) {
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001782 struct proxy *prx = p;
1783 char *pname = p->id;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001784
Willy Tarreau7d1df412012-11-23 23:47:36 +01001785 if (arg->data.str.len) {
1786 pname = arg->data.str.str;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001787 prx = findproxy(pname, PR_CAP_BE);
Willy Tarreaud28c3532012-04-19 19:28:33 +02001788 }
1789
Willy Tarreaud28c3532012-04-19 19:28:33 +02001790 if (!prx) {
1791 Alert("proxy %s: acl '%s' %s(): unable to find backend '%s'.\n",
1792 p->id, acl->name, expr->kw->kw, pname);
1793 cfgerr++;
1794 continue;
1795 }
1796
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001797 if (!(prx->cap & PR_CAP_BE)) {
1798 Alert("proxy %s: acl '%s' %s(): proxy '%s' has no backend capability.\n",
1799 p->id, acl->name, expr->kw->kw, pname);
1800 cfgerr++;
1801 continue;
1802 }
1803
Willy Tarreau7d1df412012-11-23 23:47:36 +01001804 free(arg->data.str.str);
1805 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001806 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001807 arg->data.prx = prx;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001808 }
1809 else if (arg->type == ARGT_TAB) {
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001810 struct proxy *prx = p;
1811 char *pname = p->id;
Willy Tarreaud28c3532012-04-19 19:28:33 +02001812
Willy Tarreau7d1df412012-11-23 23:47:36 +01001813 if (arg->data.str.len) {
1814 pname = arg->data.str.str;
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001815 prx = find_stktable(pname);
Willy Tarreaud28c3532012-04-19 19:28:33 +02001816 }
1817
Willy Tarreaud28c3532012-04-19 19:28:33 +02001818 if (!prx) {
1819 Alert("proxy %s: acl '%s' %s(): unable to find table '%s'.\n",
1820 p->id, acl->name, expr->kw->kw, pname);
1821 cfgerr++;
1822 continue;
1823 }
1824
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02001825
1826 if (!prx->table.size) {
1827 Alert("proxy %s: acl '%s' %s(): no table in proxy '%s'.\n",
1828 p->id, acl->name, expr->kw->kw, pname);
1829 cfgerr++;
1830 continue;
1831 }
1832
Willy Tarreau7d1df412012-11-23 23:47:36 +01001833 free(arg->data.str.str);
1834 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001835 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001836 arg->data.prx = prx;
Willy Tarreau0b1cd942010-05-16 22:18:27 +02001837 }
Willy Tarreau63364ee2012-04-19 19:11:13 +02001838 else if (arg->type == ARGT_USR) {
Willy Tarreau7d1df412012-11-23 23:47:36 +01001839 if (!arg->data.str.len) {
Willy Tarreau63364ee2012-04-19 19:11:13 +02001840 Alert("proxy %s: acl '%s' %s(): missing userlist name.\n",
1841 p->id, acl->name, expr->kw->kw);
1842 cfgerr++;
1843 continue;
1844 }
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001845
Willy Tarreau63364ee2012-04-19 19:11:13 +02001846 if (p->uri_auth && p->uri_auth->userlist &&
Willy Tarreau7d1df412012-11-23 23:47:36 +01001847 !strcmp(p->uri_auth->userlist->name, arg->data.str.str))
Willy Tarreau63364ee2012-04-19 19:11:13 +02001848 ul = p->uri_auth->userlist;
1849 else
Willy Tarreau7d1df412012-11-23 23:47:36 +01001850 ul = auth_find_userlist(arg->data.str.str);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001851
Willy Tarreau63364ee2012-04-19 19:11:13 +02001852 if (!ul) {
1853 Alert("proxy %s: acl '%s' %s(%s): unable to find userlist.\n",
Willy Tarreau7d1df412012-11-23 23:47:36 +01001854 p->id, acl->name, expr->kw->kw, arg->data.str.str);
Willy Tarreau63364ee2012-04-19 19:11:13 +02001855 cfgerr++;
1856 continue;
1857 }
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001858
Willy Tarreau7d1df412012-11-23 23:47:36 +01001859 free(arg->data.str.str);
1860 arg->data.str.str = NULL;
Willy Tarreau496aa012012-06-01 10:38:29 +02001861 arg->unresolved = 0;
Willy Tarreau7d1df412012-11-23 23:47:36 +01001862 arg->data.usr = ul;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001863 }
Willy Tarreau63364ee2012-04-19 19:11:13 +02001864 } /* end of args processing */
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001865
Willy Tarreau46b39d02012-05-10 23:40:14 +02001866 /* don't try to resolve groups if we're not certain of having
1867 * resolved userlists first.
1868 */
1869 if (cfgerr)
1870 break;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001871
1872 if (!strcmp(expr->kw->kw, "http_auth_group")) {
Willy Tarreau63364ee2012-04-19 19:11:13 +02001873 /* note: argument resolved above thanks to ARGT_USR */
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001874
1875 if (LIST_ISEMPTY(&expr->patterns)) {
1876 Alert("proxy %s: acl %s %s(): no groups specified.\n",
1877 p->id, acl->name, expr->kw->kw);
1878 cfgerr++;
1879 continue;
1880 }
1881
1882 list_for_each_entry(pattern, &expr->patterns, list) {
Willy Tarreau7d1df412012-11-23 23:47:36 +01001883 /* this keyword only has one argument */
Willy Tarreau34db1082012-04-19 17:16:54 +02001884 pattern->val.group_mask = auth_resolve_groups(expr->args->data.usr, pattern->ptr.str);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001885
1886 free(pattern->ptr.str);
1887 pattern->ptr.str = NULL;
1888 pattern->len = 0;
1889
1890 if (!pattern->val.group_mask) {
1891 Alert("proxy %s: acl %s %s(): invalid group(s).\n",
1892 p->id, acl->name, expr->kw->kw);
1893 cfgerr++;
1894 continue;
1895 }
1896 }
1897 }
1898 }
1899 }
1900
1901 return cfgerr;
1902}
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001903
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001904
Willy Tarreaua84d3742007-05-07 00:36:48 +02001905/************************************************************************/
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001906/* All supported sample fetch functions must be declared here */
Willy Tarreaua84d3742007-05-07 00:36:48 +02001907/************************************************************************/
1908
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001909/* force TRUE to be returned at the fetch level */
1910static int
1911smp_fetch_true(struct proxy *px, struct session *s, void *l7, unsigned int opt,
1912 const struct arg *args, struct sample *smp)
1913{
1914 smp->type = SMP_T_BOOL;
1915 smp->data.uint = 1;
1916 return 1;
1917}
1918
1919/* force FALSE to be returned at the fetch level */
1920static int
1921smp_fetch_false(struct proxy *px, struct session *s, void *l7, unsigned int opt,
1922 const struct arg *args, struct sample *smp)
1923{
1924 smp->type = SMP_T_BOOL;
1925 smp->data.uint = 0;
1926 return 1;
1927}
1928
1929
1930/************************************************************************/
1931/* All supported sample and ACL keywords must be declared here. */
1932/************************************************************************/
1933
1934/* Note: must not be declared <const> as its list will be overwritten.
1935 * Note: fetches that may return multiple types must be declared as the lowest
1936 * common denominator, the type that can be casted into all other ones. For
1937 * instance IPv4/IPv6 must be declared IPv4.
1938 */
1939static struct sample_fetch_kw_list smp_kws = {{ },{
1940 { "always_false", smp_fetch_false, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN },
1941 { "always_true", smp_fetch_true, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN },
1942 { /* END */ },
1943}};
1944
1945
Willy Tarreau61612d42012-04-19 18:42:05 +02001946/* Note: must not be declared <const> as its list will be overwritten.
1947 * Please take care of keeping this list alphabetically sorted.
1948 */
Willy Tarreaua84d3742007-05-07 00:36:48 +02001949static struct acl_kw_list acl_kws = {{ },{
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001950 { "always_false", acl_parse_nothing, smp_fetch_false, acl_match_nothing, ACL_USE_NOTHING, 0 },
1951 { "always_true", acl_parse_nothing, smp_fetch_true, acl_match_nothing, ACL_USE_NOTHING, 0 },
1952 { /* END */ },
Willy Tarreaua84d3742007-05-07 00:36:48 +02001953}};
1954
1955
1956__attribute__((constructor))
1957static void __acl_init(void)
1958{
Willy Tarreaud4c33c82013-01-07 21:59:07 +01001959 sample_register_fetches(&smp_kws);
Willy Tarreaua84d3742007-05-07 00:36:48 +02001960 acl_register_keywords(&acl_kws);
1961}
1962
1963
1964/*
1965 * Local variables:
1966 * c-indent-level: 8
1967 * c-basic-offset: 8
1968 * End:
1969 */