mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-02 10:12:03 +00:00
MEDIUM: acl/pattern: switch rdp_cookie functions stack up-down
Previously, both pattern, backend and persist_rdp_cookie would build fake ACL expressions to fetch an RDP cookie by calling acl_fetch_rdp_cookie(). Now we switch roles. The RDP cookie fetch function is provided as a sample fetch function that all others rely on, including ACL. The code is exactly the same, only the args handling moved from expr->args to args. The code was moved to proto_tcp.c, but probably that a dedicated file would be more suited to content handling.
This commit is contained in:
parent
b8c8f1f611
commit
32389b7d04
@ -177,10 +177,6 @@ int acl_fetch_nothing(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
/* always return false */
|
||||
int acl_match_nothing(struct sample *smp, struct acl_pattern *pattern);
|
||||
|
||||
/* Fetch the RDP cookie identified in the expression. */
|
||||
int acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
struct acl_expr *expr, struct sample *smp);
|
||||
|
||||
/* Checks that the pattern matches the end of the tested string. */
|
||||
int acl_match_end(struct sample *smp, struct acl_pattern *pattern);
|
||||
|
||||
|
@ -37,6 +37,7 @@ int srv_redispatch_connect(struct session *t);
|
||||
const char *backend_lb_algo_str(int algo);
|
||||
int backend_parse_balance(const char **args, char *err,
|
||||
int errlen, struct proxy *curproxy);
|
||||
int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit);
|
||||
|
||||
int be_downtime(struct proxy *px);
|
||||
void recount_servers(struct proxy *px);
|
||||
|
@ -33,8 +33,8 @@ void tcpv6_add_listener(struct listener *listener);
|
||||
int tcp_connect_server(struct stream_interface *si);
|
||||
int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit);
|
||||
int tcp_inspect_response(struct session *s, struct buffer *rep, int an_bit);
|
||||
int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit);
|
||||
int tcp_exec_req_rules(struct session *s);
|
||||
int smp_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir, const struct arg *args, struct sample *smp);
|
||||
|
||||
/* Converts the TCP source address to a stick_table key usable for table
|
||||
* lookups. Returns either NULL if the source cannot be converted (eg: not
|
||||
|
114
src/acl.c
114
src/acl.c
@ -453,118 +453,6 @@ acl_fetch_ssl_hello_sni(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fetch the RDP cookie identified in the expression.
|
||||
* Note: this decoder only works with non-wrapping data.
|
||||
* Accepts either 0 or 1 argument. Argument is a string (cookie name), other
|
||||
* types will lead to undefined behaviour.
|
||||
*/
|
||||
int
|
||||
acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
struct acl_expr *expr, struct sample *smp)
|
||||
{
|
||||
int bleft;
|
||||
const unsigned char *data;
|
||||
|
||||
if (!l4 || !l4->req)
|
||||
return 0;
|
||||
|
||||
smp->flags = 0;
|
||||
smp->type = SMP_T_CSTR;
|
||||
|
||||
bleft = l4->req->i;
|
||||
if (bleft <= 11)
|
||||
goto too_short;
|
||||
|
||||
data = (const unsigned char *)l4->req->p + 11;
|
||||
bleft -= 11;
|
||||
|
||||
if (bleft <= 7)
|
||||
goto too_short;
|
||||
|
||||
if (strncasecmp((const char *)data, "Cookie:", 7) != 0)
|
||||
goto not_cookie;
|
||||
|
||||
data += 7;
|
||||
bleft -= 7;
|
||||
|
||||
while (bleft > 0 && *data == ' ') {
|
||||
data++;
|
||||
bleft--;
|
||||
}
|
||||
|
||||
if (expr->args) {
|
||||
|
||||
if (bleft <= expr->args->data.str.len)
|
||||
goto too_short;
|
||||
|
||||
if ((data[expr->args->data.str.len] != '=') ||
|
||||
strncasecmp(expr->args->data.str.str, (const char *)data, expr->args->data.str.len) != 0)
|
||||
goto not_cookie;
|
||||
|
||||
data += expr->args->data.str.len + 1;
|
||||
bleft -= expr->args->data.str.len + 1;
|
||||
} else {
|
||||
while (bleft > 0 && *data != '=') {
|
||||
if (*data == '\r' || *data == '\n')
|
||||
goto not_cookie;
|
||||
data++;
|
||||
bleft--;
|
||||
}
|
||||
|
||||
if (bleft < 1)
|
||||
goto too_short;
|
||||
|
||||
if (*data != '=')
|
||||
goto not_cookie;
|
||||
|
||||
data++;
|
||||
bleft--;
|
||||
}
|
||||
|
||||
/* data points to cookie value */
|
||||
smp->data.str.str = (char *)data;
|
||||
smp->data.str.len = 0;
|
||||
|
||||
while (bleft > 0 && *data != '\r') {
|
||||
data++;
|
||||
bleft--;
|
||||
}
|
||||
|
||||
if (bleft < 2)
|
||||
goto too_short;
|
||||
|
||||
if (data[0] != '\r' || data[1] != '\n')
|
||||
goto not_cookie;
|
||||
|
||||
smp->data.str.len = (char *)data - smp->data.str.str;
|
||||
smp->flags = SMP_F_VOLATILE;
|
||||
return 1;
|
||||
|
||||
too_short:
|
||||
smp->flags = SMP_F_MAY_CHANGE;
|
||||
not_cookie:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
acl_fetch_rdp_cookie_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
struct acl_expr *expr, struct sample *smp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = acl_fetch_rdp_cookie(px, l4, l7, dir, expr, smp);
|
||||
|
||||
if (smp->flags & SMP_F_MAY_CHANGE)
|
||||
return 0;
|
||||
|
||||
smp->flags = SMP_F_VOLATILE;
|
||||
smp->type = SMP_T_UINT;
|
||||
smp->data.uint = ret;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These functions are exported and may be used by any other component.
|
||||
*/
|
||||
@ -2159,8 +2047,6 @@ static struct acl_kw_list acl_kws = {{ },{
|
||||
{ "always_true", acl_parse_nothing, acl_fetch_true, acl_match_nothing, ACL_USE_NOTHING, 0 },
|
||||
{ "rep_ssl_hello_type", acl_parse_int, acl_fetch_ssl_hello_type, acl_match_int, ACL_USE_L6RTR_VOLATILE, 0 },
|
||||
{ "req_len", acl_parse_int, acl_fetch_req_len, acl_match_int, ACL_USE_L6REQ_VOLATILE, 0 },
|
||||
{ "req_rdp_cookie", acl_parse_str, acl_fetch_rdp_cookie, acl_match_str, ACL_USE_L6REQ_VOLATILE|ACL_MAY_LOOKUP, ARG1(0,STR) },
|
||||
{ "req_rdp_cookie_cnt", acl_parse_int, acl_fetch_rdp_cookie_cnt, acl_match_int, ACL_USE_L6REQ_VOLATILE, ARG1(0,STR) },
|
||||
{ "req_ssl_hello_type", acl_parse_int, acl_fetch_ssl_hello_type, acl_match_int, ACL_USE_L6REQ_VOLATILE, 0 },
|
||||
{ "req_ssl_sni", acl_parse_str, acl_fetch_ssl_hello_sni, acl_match_str, ACL_USE_L6REQ_VOLATILE|ACL_MAY_LOOKUP, 0 },
|
||||
{ "req_ssl_ver", acl_parse_dotted_ver, acl_fetch_req_ssl_ver, acl_match_int, ACL_USE_L6REQ_VOLATILE, 0 },
|
||||
|
@ -402,7 +402,6 @@ struct server *get_server_rch(struct session *s)
|
||||
unsigned long len;
|
||||
const char *p;
|
||||
int ret;
|
||||
struct acl_expr expr;
|
||||
struct sample smp;
|
||||
struct arg args[2];
|
||||
|
||||
@ -410,7 +409,6 @@ struct server *get_server_rch(struct session *s)
|
||||
if (px->lbprm.tot_weight == 0)
|
||||
return NULL;
|
||||
|
||||
memset(&expr, 0, sizeof(expr));
|
||||
memset(&smp, 0, sizeof(smp));
|
||||
|
||||
args[0].type = ARGT_STR;
|
||||
@ -418,9 +416,7 @@ struct server *get_server_rch(struct session *s)
|
||||
args[0].data.str.len = px->hh_len;
|
||||
args[1].type = ARGT_STOP;
|
||||
|
||||
expr.args = args;
|
||||
|
||||
ret = acl_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, &expr, &smp);
|
||||
ret = smp_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, args, &smp);
|
||||
len = smp.data.str.len;
|
||||
|
||||
if (ret == 0 || (smp.flags & SMP_F_MAY_CHANGE) || len == 0)
|
||||
@ -1113,7 +1109,6 @@ int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit)
|
||||
{
|
||||
struct proxy *px = s->be;
|
||||
int ret;
|
||||
struct acl_expr expr;
|
||||
struct sample smp;
|
||||
struct server *srv = px->srv;
|
||||
struct sockaddr_in addr;
|
||||
@ -1132,7 +1127,6 @@ int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit)
|
||||
if (s->flags & SN_ASSIGNED)
|
||||
goto no_cookie;
|
||||
|
||||
memset(&expr, 0, sizeof(expr));
|
||||
memset(&smp, 0, sizeof(smp));
|
||||
|
||||
args[0].type = ARGT_STR;
|
||||
@ -1140,9 +1134,7 @@ int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit)
|
||||
args[0].data.str.len = s->be->rdp_cookie_len;
|
||||
args[1].type = ARGT_STOP;
|
||||
|
||||
expr.args = args;
|
||||
|
||||
ret = acl_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, &expr, &smp);
|
||||
ret = smp_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, args, &smp);
|
||||
if (ret == 0 || (smp.flags & SMP_F_MAY_CHANGE) || smp.data.str.len == 0)
|
||||
goto no_cookie;
|
||||
|
||||
|
166
src/proto_tcp.c
166
src/proto_tcp.c
@ -1247,10 +1247,146 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* All supported sample fetch functios must be declared here */
|
||||
/************************************************************************/
|
||||
|
||||
/* Fetch the request RDP cookie identified in the args, or any cookie if no arg
|
||||
* is passed. It is usable both for ACL and for patterns. Note: this decoder
|
||||
* only works with non-wrapping data. Accepts either 0 or 1 argument. Argument
|
||||
* is a string (cookie name), other types will lead to undefined behaviour.
|
||||
*/
|
||||
int
|
||||
smp_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
const struct arg *args, struct sample *smp)
|
||||
{
|
||||
int bleft;
|
||||
const unsigned char *data;
|
||||
|
||||
if (!l4 || !l4->req)
|
||||
return 0;
|
||||
|
||||
smp->flags = 0;
|
||||
smp->type = SMP_T_CSTR;
|
||||
|
||||
bleft = l4->req->i;
|
||||
if (bleft <= 11)
|
||||
goto too_short;
|
||||
|
||||
data = (const unsigned char *)l4->req->p + 11;
|
||||
bleft -= 11;
|
||||
|
||||
if (bleft <= 7)
|
||||
goto too_short;
|
||||
|
||||
if (strncasecmp((const char *)data, "Cookie:", 7) != 0)
|
||||
goto not_cookie;
|
||||
|
||||
data += 7;
|
||||
bleft -= 7;
|
||||
|
||||
while (bleft > 0 && *data == ' ') {
|
||||
data++;
|
||||
bleft--;
|
||||
}
|
||||
|
||||
if (args) {
|
||||
|
||||
if (bleft <= args->data.str.len)
|
||||
goto too_short;
|
||||
|
||||
if ((data[args->data.str.len] != '=') ||
|
||||
strncasecmp(args->data.str.str, (const char *)data, args->data.str.len) != 0)
|
||||
goto not_cookie;
|
||||
|
||||
data += args->data.str.len + 1;
|
||||
bleft -= args->data.str.len + 1;
|
||||
} else {
|
||||
while (bleft > 0 && *data != '=') {
|
||||
if (*data == '\r' || *data == '\n')
|
||||
goto not_cookie;
|
||||
data++;
|
||||
bleft--;
|
||||
}
|
||||
|
||||
if (bleft < 1)
|
||||
goto too_short;
|
||||
|
||||
if (*data != '=')
|
||||
goto not_cookie;
|
||||
|
||||
data++;
|
||||
bleft--;
|
||||
}
|
||||
|
||||
/* data points to cookie value */
|
||||
smp->data.str.str = (char *)data;
|
||||
smp->data.str.len = 0;
|
||||
|
||||
while (bleft > 0 && *data != '\r') {
|
||||
data++;
|
||||
bleft--;
|
||||
}
|
||||
|
||||
if (bleft < 2)
|
||||
goto too_short;
|
||||
|
||||
if (data[0] != '\r' || data[1] != '\n')
|
||||
goto not_cookie;
|
||||
|
||||
smp->data.str.len = (char *)data - smp->data.str.str;
|
||||
smp->flags = SMP_F_VOLATILE;
|
||||
return 1;
|
||||
|
||||
too_short:
|
||||
smp->flags = SMP_F_MAY_CHANGE;
|
||||
not_cookie:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pattern_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* sample type set by smp_fetch_rdp_cookie() */
|
||||
ret = smp_fetch_rdp_cookie(px, l4, NULL, ACL_DIR_REQ, arg_p, smp);
|
||||
if (ret == 0 || (smp->flags & SMP_F_MAY_CHANGE) || smp->data.str.len == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* All supported ACL keywords must be declared here. */
|
||||
/************************************************************************/
|
||||
|
||||
static int
|
||||
acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
struct acl_expr *expr, struct sample *smp)
|
||||
{
|
||||
return smp_fetch_rdp_cookie(px, l4, l7, dir, expr->args, smp);
|
||||
}
|
||||
|
||||
/* returns either 1 or 0 depending on whether an RDP cookie is found or not */
|
||||
static int
|
||||
acl_fetch_rdp_cookie_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
struct acl_expr *expr, struct sample *smp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = smp_fetch_rdp_cookie(px, l4, l7, dir, expr->args, smp);
|
||||
|
||||
if (smp->flags & SMP_F_MAY_CHANGE)
|
||||
return 0;
|
||||
|
||||
smp->flags = SMP_F_VOLATILE;
|
||||
smp->type = SMP_T_UINT;
|
||||
smp->data.uint = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* copy the source IPv4/v6 address into temp_pattern */
|
||||
static int
|
||||
acl_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
@ -1472,34 +1608,6 @@ pattern_fetch_payload(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
pattern_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
|
||||
const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
int ret;
|
||||
struct acl_expr expr;
|
||||
struct arg args[2];
|
||||
|
||||
if (!l4)
|
||||
return 0;
|
||||
|
||||
memset(&expr, 0, sizeof(expr));
|
||||
memset(smp, 0, sizeof(*smp));
|
||||
|
||||
args[0].type = ARGT_STR;
|
||||
args[0].data.str.str = arg_p[0].data.str.str;
|
||||
args[0].data.str.len = arg_p[0].data.str.len;
|
||||
args[1].type = ARGT_STOP;
|
||||
|
||||
expr.args = args;
|
||||
|
||||
/* type set by acl_fetch_rdp_cookie */
|
||||
ret = acl_fetch_rdp_cookie(px, l4, NULL, ACL_DIR_REQ, &expr, smp);
|
||||
if (ret == 0 || (smp->flags & SMP_F_MAY_CHANGE) || smp->data.str.len == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function is used to validate the arguments passed to a "payload" fetch
|
||||
* keyword. This keyword expects two positive integers, with the second one
|
||||
* being strictly positive. It is assumed that the types are already the correct
|
||||
@ -1556,6 +1664,8 @@ static struct cfg_kw_list cfg_kws = {{ },{
|
||||
static struct acl_kw_list acl_kws = {{ },{
|
||||
{ "dst", acl_parse_ip, acl_fetch_dst, acl_match_ip, ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP, 0 },
|
||||
{ "dst_port", acl_parse_int, acl_fetch_dport, acl_match_int, ACL_USE_TCP_PERMANENT, 0 },
|
||||
{ "req_rdp_cookie", acl_parse_str, acl_fetch_rdp_cookie, acl_match_str, ACL_USE_L6REQ_VOLATILE|ACL_MAY_LOOKUP, ARG1(0,STR) },
|
||||
{ "req_rdp_cookie_cnt", acl_parse_int, acl_fetch_rdp_cookie_cnt, acl_match_int, ACL_USE_L6REQ_VOLATILE, ARG1(0,STR) },
|
||||
{ "src", acl_parse_ip, acl_fetch_src, acl_match_ip, ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP, 0 },
|
||||
{ "src_port", acl_parse_int, acl_fetch_sport, acl_match_int, ACL_USE_TCP_PERMANENT, 0 },
|
||||
{ NULL, NULL, NULL, NULL },
|
||||
|
Loading…
Reference in New Issue
Block a user