]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: acl: use temp_pattern to store any string-type information
authorWilly Tarreau <w@1wt.eu>
Fri, 16 Dec 2011 18:11:42 +0000 (19:11 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 30 Dec 2011 16:33:26 +0000 (17:33 +0100)
Now strings and data blocks are stored in the temp_pattern's chunk
and matched against this one.

The rdp_cookie currently makes extensive use of acl_fetch_rdp_cookie()
and will be a good candidate for the initial rework so that ACLs use
the patterns framework and not the other way around.

src/acl.c
src/backend.c
src/proto_http.c
src/proto_tcp.c

index c23e5c31c366e869ebba84de015b831baa8e62e4..9a20cc25f9462a07cab0add71349fb9f102f5771 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -423,8 +423,8 @@ acl_fetch_ssl_hello_sni(struct proxy *px, struct session *l4, void *l7, int dir,
                        name_len = (data[7] << 8) + data[8];
 
                        if (name_type == 0) { /* hostname */
-                               test->ptr = data + 9;
-                               test->len = name_len;
+                               temp_pattern.data.str.str = data + 9;
+                               temp_pattern.data.str.len = name_len;
                                test->flags = ACL_TEST_F_VOLATILE;
                                //fprintf(stderr, "found SNI : <");
                                //write(2, test->ptr, test->len);
@@ -513,8 +513,8 @@ acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
        }
 
        /* data points to cookie value */
-       test->ptr = (char *)data;
-       test->len = 0;
+       temp_pattern.data.str.str = (char *)data;
+       temp_pattern.data.str.len = 0;
 
        while (bleft > 0 && *data != '\r') {
                data++;
@@ -527,7 +527,7 @@ acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
        if (data[0] != '\r' || data[1] != '\n')
                goto not_cookie;
 
-       test->len = (char *)data - test->ptr;
+       temp_pattern.data.str.len = (char *)data - temp_pattern.data.str.str;
        test->flags = ACL_TEST_F_VOLATILE;
        return 1;
 
@@ -545,8 +545,8 @@ acl_fetch_rdp_cookie_cnt(struct proxy *px, struct session *l4, void *l7, int dir
 
        ret = acl_fetch_rdp_cookie(px, l4, l7, dir, expr, test);
 
-       test->ptr = NULL;
-       test->len = 0;
+       temp_pattern.data.str.str = NULL;
+       temp_pattern.data.str.len = 0;
 
        if (test->flags & ACL_TEST_F_MAY_CHANGE)
                return 0;
@@ -587,12 +587,12 @@ int acl_match_str(struct acl_test *test, struct acl_pattern *pattern)
 {
        int icase;
 
-       if (pattern->len != test->len)
+       if (pattern->len != temp_pattern.data.str.len)
                return ACL_PAT_FAIL;
 
        icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
-       if ((icase && strncasecmp(pattern->ptr.str, test->ptr, test->len) == 0) ||
-           (!icase && strncmp(pattern->ptr.str, test->ptr, test->len) == 0))
+       if ((icase && strncasecmp(pattern->ptr.str, temp_pattern.data.str.str, temp_pattern.data.str.len) == 0) ||
+           (!icase && strncmp(pattern->ptr.str, temp_pattern.data.str.str, temp_pattern.data.str.len) == 0))
                return ACL_PAT_PASS;
        return ACL_PAT_FAIL;
 }
@@ -607,12 +607,12 @@ void *acl_lookup_str(struct acl_test *test, struct acl_expr *expr)
        char prev;
 
        /* we may have to force a trailing zero on the test pattern */
-       prev = test->ptr[test->len];
+       prev = temp_pattern.data.str.str[temp_pattern.data.str.len];
        if (prev)
-               test->ptr[test->len] = '\0';
-       node = ebst_lookup(&expr->pattern_tree, test->ptr);
+               temp_pattern.data.str.str[temp_pattern.data.str.len] = '\0';
+       node = ebst_lookup(&expr->pattern_tree, temp_pattern.data.str.str);
        if (prev)
-               test->ptr[test->len] = prev;
+               temp_pattern.data.str.str[temp_pattern.data.str.len] = prev;
        return node;
 }
 
@@ -629,28 +629,28 @@ int acl_match_reg(struct acl_test *test, struct acl_pattern *pattern)
        if (unlikely(test->flags & ACL_TEST_F_READ_ONLY)) {
                char *new_str;
 
-               new_str = calloc(1, test->len + 1);
+               new_str = calloc(1, temp_pattern.data.str.len + 1);
                if (!new_str)
                        return ACL_PAT_FAIL;
 
-               memcpy(new_str, test->ptr, test->len);
-               new_str[test->len] = 0;
+               memcpy(new_str, temp_pattern.data.str.str, temp_pattern.data.str.len);
+               new_str[temp_pattern.data.str.len] = 0;
                if (test->flags & ACL_TEST_F_MUST_FREE)
-                       free(test->ptr);
-               test->ptr = new_str;
+                       free(temp_pattern.data.str.str);
+               temp_pattern.data.str.str = new_str;
                test->flags |= ACL_TEST_F_MUST_FREE;
                test->flags &= ~ACL_TEST_F_READ_ONLY;
        }
 
-       old_char = test->ptr[test->len];
-       test->ptr[test->len] = 0;
+       old_char = temp_pattern.data.str.str[temp_pattern.data.str.len];
+       temp_pattern.data.str.str[temp_pattern.data.str.len] = 0;
 
-       if (regexec(pattern->ptr.reg, test->ptr, 0, NULL, 0) == 0)
+       if (regexec(pattern->ptr.reg, temp_pattern.data.str.str, 0, NULL, 0) == 0)
                ret = ACL_PAT_PASS;
        else
                ret = ACL_PAT_FAIL;
 
-       test->ptr[test->len] = old_char;
+       temp_pattern.data.str.str[temp_pattern.data.str.len] = old_char;
        return ret;
 }
 
@@ -659,12 +659,12 @@ int acl_match_beg(struct acl_test *test, struct acl_pattern *pattern)
 {
        int icase;
 
-       if (pattern->len > test->len)
+       if (pattern->len > temp_pattern.data.str.len)
                return ACL_PAT_FAIL;
 
        icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
-       if ((icase && strncasecmp(pattern->ptr.str, test->ptr, pattern->len) != 0) ||
-           (!icase && strncmp(pattern->ptr.str, test->ptr, pattern->len) != 0))
+       if ((icase && strncasecmp(pattern->ptr.str, temp_pattern.data.str.str, pattern->len) != 0) ||
+           (!icase && strncmp(pattern->ptr.str, temp_pattern.data.str.str, pattern->len) != 0))
                return ACL_PAT_FAIL;
        return ACL_PAT_PASS;
 }
@@ -674,11 +674,11 @@ int acl_match_end(struct acl_test *test, struct acl_pattern *pattern)
 {
        int icase;
 
-       if (pattern->len > test->len)
+       if (pattern->len > temp_pattern.data.str.len)
                return ACL_PAT_FAIL;
        icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
-       if ((icase && strncasecmp(pattern->ptr.str, test->ptr + test->len - pattern->len, pattern->len) != 0) ||
-           (!icase && strncmp(pattern->ptr.str, test->ptr + test->len - pattern->len, pattern->len) != 0))
+       if ((icase && strncasecmp(pattern->ptr.str, temp_pattern.data.str.str + temp_pattern.data.str.len - pattern->len, pattern->len) != 0) ||
+           (!icase && strncmp(pattern->ptr.str, temp_pattern.data.str.str + temp_pattern.data.str.len - pattern->len, pattern->len) != 0))
                return ACL_PAT_FAIL;
        return ACL_PAT_PASS;
 }
@@ -692,20 +692,20 @@ int acl_match_sub(struct acl_test *test, struct acl_pattern *pattern)
        char *end;
        char *c;
 
-       if (pattern->len > test->len)
+       if (pattern->len > temp_pattern.data.str.len)
                return ACL_PAT_FAIL;
 
-       end = test->ptr + test->len - pattern->len;
+       end = temp_pattern.data.str.str + temp_pattern.data.str.len - pattern->len;
        icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
        if (icase) {
-               for (c = test->ptr; c <= end; c++) {
+               for (c = temp_pattern.data.str.str; c <= end; c++) {
                        if (tolower(*c) != tolower(*pattern->ptr.str))
                                continue;
                        if (strncasecmp(pattern->ptr.str, c, pattern->len) == 0)
                                return ACL_PAT_PASS;
                }
        } else {
-               for (c = test->ptr; c <= end; c++) {
+               for (c = temp_pattern.data.str.str; c <= end; c++) {
                        if (*c != *pattern->ptr.str)
                                continue;
                        if (strncmp(pattern->ptr.str, c, pattern->len) == 0)
@@ -761,13 +761,13 @@ static int match_word(struct acl_test *test, struct acl_pattern *pattern, unsign
        while (pl > 0 && is_delimiter(ps[pl - 1], delimiters))
                pl--;
 
-       if (pl > test->len)
+       if (pl > temp_pattern.data.str.len)
                return ACL_PAT_FAIL;
 
        may_match = 1;
        icase = pattern->flags & ACL_PAT_F_IGNORE_CASE;
-       end = test->ptr + test->len - pl;
-       for (c = test->ptr; c <= end; c++) {
+       end = temp_pattern.data.str.str + temp_pattern.data.str.len - pl;
+       for (c = temp_pattern.data.str.str; c <= end; c++) {
                if (is_delimiter(*c, delimiters)) {
                        may_match = 1;
                        continue;
@@ -822,8 +822,8 @@ int acl_match_int(struct acl_test *test, struct acl_pattern *pattern)
 /* Checks that the length of the pattern in <test> is included between min and max */
 int acl_match_len(struct acl_test *test, struct acl_pattern *pattern)
 {
-       if ((!pattern->val.range.min_set || pattern->val.range.min <= test->len) &&
-           (!pattern->val.range.max_set || test->len <= pattern->val.range.max))
+       if ((!pattern->val.range.min_set || pattern->val.range.min <= temp_pattern.data.str.len) &&
+           (!pattern->val.range.max_set || temp_pattern.data.str.len <= pattern->val.range.max))
                return ACL_PAT_PASS;
        return ACL_PAT_FAIL;
 }
@@ -1851,8 +1851,8 @@ int acl_exec_cond(struct acl_cond *cond, struct proxy *px, struct session *l4, v
 
                                /* now we may have some cleanup to do */
                                if (test.flags & ACL_TEST_F_MUST_FREE) {
-                                       free(test.ptr);
-                                       test.len = 0;
+                                       free(temp_pattern.data.str.str);
+                                       temp_pattern.data.str.len = 0;
                                }
 
                                /* we're ORing these terms, so a single PASS is enough */
index 0f3bccd76ac47c4e7b1c0455b1bbaaeb36f29344..5e88f62c97891dec618a71d7832e16d26e720f7f 100644 (file)
@@ -413,7 +413,9 @@ struct server *get_server_rch(struct session *s)
        expr.arg_len = px->hh_len;
 
        ret = acl_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, &expr, &test);
-       if (ret == 0 || (test.flags & ACL_TEST_F_MAY_CHANGE) || test.len == 0)
+       len = temp_pattern.data.str.len;
+
+       if (ret == 0 || (test.flags & ACL_TEST_F_MAY_CHANGE) || len == 0)
                return NULL;
 
        /* note: we won't hash if there's only one server left */
@@ -423,8 +425,7 @@ struct server *get_server_rch(struct session *s)
        /* Found a the hh_name in the headers.
         * we will compute the hash based on this value ctx.val.
         */
-       len = test.len;
-       p = (char *)test.ptr;
+       p = temp_pattern.data.str.str;
        while (len) {
                hash = *p + (hash << 6) + (hash << 16) - hash;
                len--;
@@ -1112,14 +1113,14 @@ int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit)
        expr.arg_len = s->be->rdp_cookie_len;
 
        ret = acl_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, &expr, &test);
-       if (ret == 0 || (test.flags & ACL_TEST_F_MAY_CHANGE) || test.len == 0)
+       if (ret == 0 || (test.flags & ACL_TEST_F_MAY_CHANGE) || temp_pattern.data.str.len == 0)
                goto no_cookie;
 
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
 
-       /* Considering an rdp cookie detected using acl, test.ptr ended with <cr><lf> and should return */
-       addr.sin_addr.s_addr = strtoul(test.ptr, &p, 10);
+       /* Considering an rdp cookie detected using acl, str ended with <cr><lf> and should return */
+       addr.sin_addr.s_addr = strtoul(temp_pattern.data.str.str, &p, 10);
        if (*p != '.')
                goto no_cookie;
        p++;
index b60048e15e5bb835fdc1a8aa92f65ba867ab814c..10a4bddb7f467d01427c25d32bd80a68f9202863 100644 (file)
@@ -7866,8 +7866,8 @@ acl_fetch_rqver(struct proxy *px, struct session *l4, void *l7, int dir,
        if (len <= 0)
                return 0;
 
-       test->ptr = ptr;
-       test->len = len;
+       temp_pattern.data.str.str = ptr;
+       temp_pattern.data.str.len = len;
 
        test->flags = ACL_TEST_F_READ_ONLY | ACL_TEST_F_VOL_1ST;
        return 1;
@@ -7894,8 +7894,8 @@ acl_fetch_stver(struct proxy *px, struct session *l4, void *l7, int dir,
        if (len <= 0)
                return 0;
 
-       test->ptr = ptr;
-       test->len = len;
+       temp_pattern.data.str.str = ptr;
+       temp_pattern.data.str.len = len;
 
        test->flags = ACL_TEST_F_READ_ONLY | ACL_TEST_F_VOL_1ST;
        return 1;
@@ -7941,8 +7941,8 @@ acl_fetch_url(struct proxy *px, struct session *l4, void *l7, int dir,
                /* ensure the indexes are not affected */
                return 0;
 
-       test->len = txn->req.sl.rq.u_l;
-       test->ptr = txn->req.sol + txn->req.sl.rq.u;
+       temp_pattern.data.str.len = txn->req.sl.rq.u_l;
+       temp_pattern.data.str.str = txn->req.sol + txn->req.sl.rq.u;
 
        /* we do not need to set READ_ONLY because the data is in a buffer */
        test->flags = ACL_TEST_F_VOL_1ST;
@@ -8031,8 +8031,9 @@ acl_fetch_hdr(struct proxy *px, struct session *l4, void *l7, char *sol,
        if (http_find_header2(expr->arg.str, expr->arg_len, sol, idx, ctx)) {
                test->flags |= ACL_TEST_F_FETCH_MORE;
                test->flags |= ACL_TEST_F_VOL_HDR;
-               test->len = ctx->vlen;
-               test->ptr = (char *)ctx->line + ctx->val;
+               temp_pattern.data.str.str = (char *)ctx->line + ctx->val;
+               temp_pattern.data.str.len = ctx->vlen;
+
                return 1;
        }
 
@@ -8292,12 +8293,12 @@ acl_fetch_path(struct proxy *px, struct session *l4, void *l7, int dir,
                return 0;
 
        /* OK, we got the '/' ! */
-       test->ptr = ptr;
+       temp_pattern.data.str.str = ptr;
 
        while (ptr < end && *ptr != '?')
                ptr++;
 
-       test->len = ptr - test->ptr;
+       temp_pattern.data.str.len = ptr - temp_pattern.data.str.str;
 
        /* we do not need to set READ_ONLY because the data is in a buffer */
        test->flags = ACL_TEST_F_VOL_1ST;
index 207fec0940d1da676d48a75fd24a4d623906e9d3..ea3692cbbcc0f21144bdf71149d695ecfd573257 100644 (file)
@@ -1580,11 +1580,10 @@ pattern_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir
        expr.arg_len = arg_p[0].data.str.len;
 
        ret = acl_fetch_rdp_cookie(px, l4, NULL, ACL_DIR_REQ, &expr, &test);
-       if (ret == 0 || (test.flags & ACL_TEST_F_MAY_CHANGE) || test.len == 0)
+       if (ret == 0 || (test.flags & ACL_TEST_F_MAY_CHANGE) || temp_pattern.data.str.len == 0)
                return 0;
 
-       /* init chunk as read only */
-       chunk_initlen(&data->str, test.ptr, 0, test.len);
+       data->str = temp_pattern.data.str;
        return 1;
 }