mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-24 23:31:40 +02:00
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.
This commit is contained in:
parent
d28c353fc5
commit
fc2c1fd449
84
src/acl.c
84
src/acl.c
@ -1396,6 +1396,26 @@ struct acl_expr *parse_acl_expr(const char **args)
|
|||||||
if (nbargs < 0)
|
if (nbargs < 0)
|
||||||
goto out_free_expr;
|
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)) {
|
else if (ARGM(aclkw->arg_mask)) {
|
||||||
/* there were some mandatory arguments */
|
/* there were some mandatory arguments */
|
||||||
goto out_free_expr;
|
goto out_free_expr;
|
||||||
@ -2013,20 +2033,23 @@ acl_find_targets(struct proxy *p)
|
|||||||
expr->args->data.srv = srv;
|
expr->args->data.srv = srv;
|
||||||
}
|
}
|
||||||
else if (arg->type == ARGT_FE) {
|
else if (arg->type == ARGT_FE) {
|
||||||
struct proxy *prx;
|
struct proxy *prx = p;
|
||||||
char *pname;
|
char *pname = p->id;
|
||||||
|
|
||||||
if (!expr->args->data.str.len) {
|
if (expr->args->data.str.len) {
|
||||||
Alert("proxy %s: acl '%s' %s(): missing frontend name.\n",
|
pname = expr->args->data.str.str;
|
||||||
p->id, acl->name, expr->kw->kw);
|
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++;
|
cfgerr++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pname = expr->args->data.str.str;
|
if (!(prx->cap & PR_CAP_FE)) {
|
||||||
prx = findproxy(pname, PR_CAP_FE);
|
Alert("proxy %s: acl '%s' %s(): proxy '%s' has no frontend capability.\n",
|
||||||
if (!prx) {
|
|
||||||
Alert("proxy %s: acl '%s' %s(): unable to find frontend '%s'.\n",
|
|
||||||
p->id, acl->name, expr->kw->kw, pname);
|
p->id, acl->name, expr->kw->kw, pname);
|
||||||
cfgerr++;
|
cfgerr++;
|
||||||
continue;
|
continue;
|
||||||
@ -2036,20 +2059,23 @@ acl_find_targets(struct proxy *p)
|
|||||||
expr->args->data.prx = prx;
|
expr->args->data.prx = prx;
|
||||||
}
|
}
|
||||||
else if (arg->type == ARGT_BE) {
|
else if (arg->type == ARGT_BE) {
|
||||||
struct proxy *prx;
|
struct proxy *prx = p;
|
||||||
char *pname;
|
char *pname = p->id;
|
||||||
|
|
||||||
if (!expr->args->data.str.len) {
|
if (expr->args->data.str.len) {
|
||||||
Alert("proxy %s: acl '%s' %s(): missing backend name.\n",
|
pname = expr->args->data.str.str;
|
||||||
p->id, acl->name, expr->kw->kw);
|
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++;
|
cfgerr++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pname = expr->args->data.str.str;
|
if (!(prx->cap & PR_CAP_BE)) {
|
||||||
prx = findproxy(pname, PR_CAP_BE);
|
Alert("proxy %s: acl '%s' %s(): proxy '%s' has no backend capability.\n",
|
||||||
if (!prx) {
|
|
||||||
Alert("proxy %s: acl '%s' %s(): unable to find backend '%s'.\n",
|
|
||||||
p->id, acl->name, expr->kw->kw, pname);
|
p->id, acl->name, expr->kw->kw, pname);
|
||||||
cfgerr++;
|
cfgerr++;
|
||||||
continue;
|
continue;
|
||||||
@ -2059,20 +2085,24 @@ acl_find_targets(struct proxy *p)
|
|||||||
expr->args->data.prx = prx;
|
expr->args->data.prx = prx;
|
||||||
}
|
}
|
||||||
else if (arg->type == ARGT_TAB) {
|
else if (arg->type == ARGT_TAB) {
|
||||||
struct proxy *prx;
|
struct proxy *prx = p;
|
||||||
char *pname;
|
char *pname = p->id;
|
||||||
|
|
||||||
if (!expr->args->data.str.len) {
|
if (expr->args->data.str.len) {
|
||||||
Alert("proxy %s: acl '%s' %s(): missing table name.\n",
|
pname = expr->args->data.str.str;
|
||||||
p->id, acl->name, expr->kw->kw);
|
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++;
|
cfgerr++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pname = expr->args->data.str.str;
|
|
||||||
prx = find_stktable(pname);
|
if (!prx->table.size) {
|
||||||
if (!prx) {
|
Alert("proxy %s: acl '%s' %s(): no table in proxy '%s'.\n",
|
||||||
Alert("proxy %s: acl '%s' %s(): unable to find table '%s'.\n",
|
|
||||||
p->id, acl->name, expr->kw->kw, pname);
|
p->id, acl->name, expr->kw->kw, pname);
|
||||||
cfgerr++;
|
cfgerr++;
|
||||||
continue;
|
continue;
|
||||||
|
@ -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.
|
* Please take care of keeping this list alphabetically sorted.
|
||||||
*/
|
*/
|
||||||
static struct acl_kw_list acl_kws = {{ },{
|
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) },
|
{ "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(0,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_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) },
|
{ "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(0,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(0,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(0,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_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_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) },
|
{ "srv_is_up", acl_parse_nothing, acl_fetch_srv_is_up, acl_match_nothing, ACL_USE_NOTHING, ARG1(1,SRV) },
|
||||||
|
@ -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.
|
* Please take care of keeping this list alphabetically sorted.
|
||||||
*/
|
*/
|
||||||
static struct acl_kw_list acl_kws = {{ },{
|
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_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 },
|
{ NULL, NULL, NULL, NULL },
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
@ -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_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_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 },
|
{ "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_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(0,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(0,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(0,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(0,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(0,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(0,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(0,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(0,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(0,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(0,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(0,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(0,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(0,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(0,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(0,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(0,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(0,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(0,TAB) },
|
{ "table_cnt", acl_parse_int, acl_fetch_table_cnt, acl_match_int, ACL_USE_NOTHING, ARG1(1,TAB) },
|
||||||
{ NULL, NULL, NULL, NULL },
|
{ NULL, NULL, NULL, NULL },
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user