From fc2c1fd44907b2977c82bc71275bc484824f9a0b Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 19 Apr 2012 23:35:54 +0200 Subject: [PATCH] MAJOR: acl: ensure that implicit table and proxies are valid A large number of ACLs make use of frontend, backend or table names in their arguments, and fall back to the current proxy when no argument is passed. If the expected capability is not available, the ACL silently fails at runtime. Now we make all those names mandatory in the parser and we rely on acl_find_targets() to replace the missing names with the holding proxy, then to perform the appropriate tests, and to reject errors at parsing time. It is possible that some faulty configurations will get rejected from now on, while they used to silently fail till now. This is the reason why this change is marked as MAJOR. --- src/acl.c | 84 ++++++++++++++++++++++++++++++++++---------------- src/backend.c | 12 ++++---- src/frontend.c | 4 +-- src/session.c | 38 +++++++++++------------ 4 files changed, 84 insertions(+), 54 deletions(-) diff --git a/src/acl.c b/src/acl.c index dc9925d51..025e4780a 100644 --- a/src/acl.c +++ b/src/acl.c @@ -1396,6 +1396,26 @@ struct acl_expr *parse_acl_expr(const char **args) if (nbargs < 0) goto out_free_expr; } + else if (ARGM(aclkw->arg_mask) == 1) { + int type = (aclkw->arg_mask >> 4) & 15; + + /* If a proxy is noted as a mandatory argument, we'll fake + * an empty one so that acl_find_targets() resolves it as + * the current one later. + */ + if (type != ARGT_FE && type != ARGT_BE && type != ARGT_TAB) + goto out_free_expr; + + /* Build an arg list containing the type as an empty string + * and the usual STOP. + */ + expr->args = calloc(2, sizeof(*expr->args)); + expr->args[0].type = type; + expr->args[0].data.str.str = strdup(""); + expr->args[0].data.str.len = 1; + expr->args[0].data.str.len = 0; + expr->args[1].type = ARGT_STOP; + } else if (ARGM(aclkw->arg_mask)) { /* there were some mandatory arguments */ goto out_free_expr; @@ -2013,20 +2033,23 @@ acl_find_targets(struct proxy *p) expr->args->data.srv = srv; } else if (arg->type == ARGT_FE) { - struct proxy *prx; - char *pname; + struct proxy *prx = p; + char *pname = p->id; - if (!expr->args->data.str.len) { - Alert("proxy %s: acl '%s' %s(): missing frontend name.\n", - p->id, acl->name, expr->kw->kw); + if (expr->args->data.str.len) { + pname = expr->args->data.str.str; + prx = findproxy(pname, PR_CAP_FE); + } + + if (!prx) { + Alert("proxy %s: acl '%s' %s(): unable to find frontend '%s'.\n", + p->id, acl->name, expr->kw->kw, pname); cfgerr++; continue; } - pname = expr->args->data.str.str; - prx = findproxy(pname, PR_CAP_FE); - if (!prx) { - Alert("proxy %s: acl '%s' %s(): unable to find frontend '%s'.\n", + if (!(prx->cap & PR_CAP_FE)) { + Alert("proxy %s: acl '%s' %s(): proxy '%s' has no frontend capability.\n", p->id, acl->name, expr->kw->kw, pname); cfgerr++; continue; @@ -2036,20 +2059,23 @@ acl_find_targets(struct proxy *p) expr->args->data.prx = prx; } else if (arg->type == ARGT_BE) { - struct proxy *prx; - char *pname; + struct proxy *prx = p; + char *pname = p->id; - if (!expr->args->data.str.len) { - Alert("proxy %s: acl '%s' %s(): missing backend name.\n", - p->id, acl->name, expr->kw->kw); + if (expr->args->data.str.len) { + pname = expr->args->data.str.str; + prx = findproxy(pname, PR_CAP_BE); + } + + if (!prx) { + Alert("proxy %s: acl '%s' %s(): unable to find backend '%s'.\n", + p->id, acl->name, expr->kw->kw, pname); cfgerr++; continue; } - pname = expr->args->data.str.str; - prx = findproxy(pname, PR_CAP_BE); - if (!prx) { - Alert("proxy %s: acl '%s' %s(): unable to find backend '%s'.\n", + if (!(prx->cap & PR_CAP_BE)) { + Alert("proxy %s: acl '%s' %s(): proxy '%s' has no backend capability.\n", p->id, acl->name, expr->kw->kw, pname); cfgerr++; continue; @@ -2059,20 +2085,24 @@ acl_find_targets(struct proxy *p) expr->args->data.prx = prx; } else if (arg->type == ARGT_TAB) { - struct proxy *prx; - char *pname; + struct proxy *prx = p; + char *pname = p->id; - if (!expr->args->data.str.len) { - Alert("proxy %s: acl '%s' %s(): missing table name.\n", - p->id, acl->name, expr->kw->kw); + if (expr->args->data.str.len) { + pname = expr->args->data.str.str; + prx = find_stktable(pname); + } + + if (!prx) { + Alert("proxy %s: acl '%s' %s(): unable to find table '%s'.\n", + p->id, acl->name, expr->kw->kw, pname); cfgerr++; continue; } - pname = expr->args->data.str.str; - prx = find_stktable(pname); - if (!prx) { - Alert("proxy %s: acl '%s' %s(): unable to find table '%s'.\n", + + if (!prx->table.size) { + Alert("proxy %s: acl '%s' %s(): no table in proxy '%s'.\n", p->id, acl->name, expr->kw->kw, pname); cfgerr++; continue; diff --git a/src/backend.c b/src/backend.c index fd2528f4a..b0d7c39b1 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1578,13 +1578,13 @@ acl_fetch_srv_conn(struct proxy *px, struct session *l4, void *l7, int dir, * Please take care of keeping this list alphabetically sorted. */ static struct acl_kw_list acl_kws = {{ },{ - { "avg_queue", acl_parse_int, acl_fetch_avg_queue_size, acl_match_int, ACL_USE_NOTHING, ARG1(0,BE) }, - { "be_conn", acl_parse_int, acl_fetch_be_conn, acl_match_int, ACL_USE_NOTHING, ARG1(0,BE) }, + { "avg_queue", acl_parse_int, acl_fetch_avg_queue_size, acl_match_int, ACL_USE_NOTHING, ARG1(1,BE) }, + { "be_conn", acl_parse_int, acl_fetch_be_conn, acl_match_int, ACL_USE_NOTHING, ARG1(1,BE) }, { "be_id", acl_parse_int, acl_fetch_be_id, acl_match_int, ACL_USE_NOTHING, 0 }, - { "be_sess_rate", acl_parse_int, acl_fetch_be_sess_rate, acl_match_int, ACL_USE_NOTHING, ARG1(0,BE) }, - { "connslots", acl_parse_int, acl_fetch_connslots, acl_match_int, ACL_USE_NOTHING, ARG1(0,BE) }, - { "nbsrv", acl_parse_int, acl_fetch_nbsrv, acl_match_int, ACL_USE_NOTHING, ARG1(0,BE) }, - { "queue", acl_parse_int, acl_fetch_queue_size, acl_match_int, ACL_USE_NOTHING, ARG1(0,BE) }, + { "be_sess_rate", acl_parse_int, acl_fetch_be_sess_rate, acl_match_int, ACL_USE_NOTHING, ARG1(1,BE) }, + { "connslots", acl_parse_int, acl_fetch_connslots, acl_match_int, ACL_USE_NOTHING, ARG1(1,BE) }, + { "nbsrv", acl_parse_int, acl_fetch_nbsrv, acl_match_int, ACL_USE_NOTHING, ARG1(1,BE) }, + { "queue", acl_parse_int, acl_fetch_queue_size, acl_match_int, ACL_USE_NOTHING, ARG1(1,BE) }, { "srv_conn", acl_parse_int, acl_fetch_srv_conn, acl_match_int, ACL_USE_NOTHING, ARG1(1,SRV) }, { "srv_id", acl_parse_int, acl_fetch_srv_id, acl_match_int, ACL_USE_RTR_INTERNAL, 0 }, { "srv_is_up", acl_parse_nothing, acl_fetch_srv_is_up, acl_match_nothing, ACL_USE_NOTHING, ARG1(1,SRV) }, diff --git a/src/frontend.c b/src/frontend.c index ebe864bb9..9f8c3232f 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -544,9 +544,9 @@ acl_fetch_fe_conn(struct proxy *px, struct session *l4, void *l7, int dir, * Please take care of keeping this list alphabetically sorted. */ static struct acl_kw_list acl_kws = {{ },{ - { "fe_conn", acl_parse_int, acl_fetch_fe_conn, acl_match_int, ACL_USE_NOTHING, ARG1(0,FE) }, + { "fe_conn", acl_parse_int, acl_fetch_fe_conn, acl_match_int, ACL_USE_NOTHING, ARG1(1,FE) }, { "fe_id", acl_parse_int, acl_fetch_fe_id, acl_match_int, ACL_USE_NOTHING, 0 }, - { "fe_sess_rate", acl_parse_int, acl_fetch_fe_sess_rate, acl_match_int, ACL_USE_NOTHING, ARG1(0,FE) }, + { "fe_sess_rate", acl_parse_int, acl_fetch_fe_sess_rate, acl_match_int, ACL_USE_NOTHING, ARG1(1,FE) }, { NULL, NULL, NULL, NULL }, }}; diff --git a/src/session.c b/src/session.c index 4c5671a75..999701479 100644 --- a/src/session.c +++ b/src/session.c @@ -3372,25 +3372,25 @@ static struct acl_kw_list acl_kws = {{ },{ { "sc2_kbytes_out", acl_parse_int, acl_fetch_sc2_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 }, { "sc2_sess_cnt", acl_parse_int, acl_fetch_sc2_sess_cnt, acl_match_int, ACL_USE_NOTHING, 0 }, { "sc2_sess_rate", acl_parse_int, acl_fetch_sc2_sess_rate, acl_match_int, ACL_USE_NOTHING, 0 }, - { "src_bytes_in_rate", acl_parse_int, acl_fetch_src_bytes_in_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_bytes_out_rate", acl_parse_int, acl_fetch_src_bytes_out_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_clr_gpc0", acl_parse_int, acl_fetch_src_clr_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_conn_cnt", acl_parse_int, acl_fetch_src_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_conn_cur", acl_parse_int, acl_fetch_src_conn_cur, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_conn_rate", acl_parse_int, acl_fetch_src_conn_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_get_gpc0", acl_parse_int, acl_fetch_src_get_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_http_err_cnt", acl_parse_int, acl_fetch_src_http_err_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_http_err_rate", acl_parse_int, acl_fetch_src_http_err_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_http_req_cnt", acl_parse_int, acl_fetch_src_http_req_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_http_req_rate", acl_parse_int, acl_fetch_src_http_req_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_inc_gpc0", acl_parse_int, acl_fetch_src_inc_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_kbytes_in", acl_parse_int, acl_fetch_src_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_kbytes_out", acl_parse_int, acl_fetch_src_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_sess_cnt", acl_parse_int, acl_fetch_src_sess_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_sess_rate", acl_parse_int, acl_fetch_src_sess_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "src_updt_conn_cnt", acl_parse_int, acl_fetch_src_updt_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(0,TAB) }, - { "table_avl", acl_parse_int, acl_fetch_table_avl, acl_match_int, ACL_USE_NOTHING, ARG1(0,TAB) }, - { "table_cnt", acl_parse_int, acl_fetch_table_cnt, acl_match_int, ACL_USE_NOTHING, ARG1(0,TAB) }, + { "src_bytes_in_rate", acl_parse_int, acl_fetch_src_bytes_in_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_bytes_out_rate", acl_parse_int, acl_fetch_src_bytes_out_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_clr_gpc0", acl_parse_int, acl_fetch_src_clr_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_conn_cnt", acl_parse_int, acl_fetch_src_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_conn_cur", acl_parse_int, acl_fetch_src_conn_cur, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_conn_rate", acl_parse_int, acl_fetch_src_conn_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_get_gpc0", acl_parse_int, acl_fetch_src_get_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_http_err_cnt", acl_parse_int, acl_fetch_src_http_err_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_http_err_rate", acl_parse_int, acl_fetch_src_http_err_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_http_req_cnt", acl_parse_int, acl_fetch_src_http_req_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_http_req_rate", acl_parse_int, acl_fetch_src_http_req_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_inc_gpc0", acl_parse_int, acl_fetch_src_inc_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_kbytes_in", acl_parse_int, acl_fetch_src_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_kbytes_out", acl_parse_int, acl_fetch_src_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_sess_cnt", acl_parse_int, acl_fetch_src_sess_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_sess_rate", acl_parse_int, acl_fetch_src_sess_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "src_updt_conn_cnt", acl_parse_int, acl_fetch_src_updt_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) }, + { "table_avl", acl_parse_int, acl_fetch_table_avl, acl_match_int, ACL_USE_NOTHING, ARG1(1,TAB) }, + { "table_cnt", acl_parse_int, acl_fetch_table_cnt, acl_match_int, ACL_USE_NOTHING, ARG1(1,TAB) }, { NULL, NULL, NULL, NULL }, }};