From 645960c1dbf9075df30f689c302dea411daf2aeb Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 16 Dec 2011 19:11:42 +0100 Subject: MEDIUM: acl: use temp_pattern to store any string-type information 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 | 80 +++++++++++++++++++++++++++--------------------------- src/backend.c | 13 +++++---- src/proto_http.c | 21 +++++++------- src/proto_tcp.c | 5 +-- 4 files changed, 60 insertions(+), 59 deletions(-) diff --git a/src/acl.c b/src/acl.c index c23e5c3..9a20cc2 100644 --- 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 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 */ diff --git a/src/backend.c b/src/backend.c index 0f3bccd..5e88f62 100644 --- a/src/backend.c +++ b/src/backend.c @@ -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 and should return */ - addr.sin_addr.s_addr = strtoul(test.ptr, &p, 10); + /* Considering an rdp cookie detected using acl, str ended with and should return */ + addr.sin_addr.s_addr = strtoul(temp_pattern.data.str.str, &p, 10); if (*p != '.') goto no_cookie; p++; diff --git a/src/proto_http.c b/src/proto_http.c index b60048e..10a4bdd 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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; diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 207fec0..ea3692c 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -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; } -- 1.7.2.3