mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 07:37:02 +02:00
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.
This commit is contained in:
parent
31d1b01211
commit
664092ccc1
80
src/acl.c
80
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 */
|
||||
|
@ -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++;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user