]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: acl: ensure that implicit table and proxies are valid
authorWilly Tarreau <w@1wt.eu>
Thu, 19 Apr 2012 21:35:54 +0000 (23:35 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 18:57:12 +0000 (20:57 +0200)
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
src/backend.c
src/frontend.c
src/session.c

index dc9925d519dc00e0dfe9eed3a84c486079606f15..025e4780a857b3149848e0bd7240429f507af5e6 100644 (file)
--- 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,18 +2033,14 @@ 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);
-                                               cfgerr++;
-                                               continue;
+                                       if (expr->args->data.str.len) {
+                                               pname = expr->args->data.str.str;
+                                               prx = findproxy(pname, PR_CAP_FE);
                                        }
 
-                                       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);
@@ -2032,22 +2048,25 @@ acl_find_targets(struct proxy *p)
                                                continue;
                                        }
 
+                                       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;
+                                       }
+
                                        free(expr->args->data.str.str);
                                        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);
-                                               cfgerr++;
-                                               continue;
+                                       if (expr->args->data.str.len) {
+                                               pname = expr->args->data.str.str;
+                                               prx = findproxy(pname, PR_CAP_BE);
                                        }
 
-                                       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);
@@ -2055,22 +2074,25 @@ acl_find_targets(struct proxy *p)
                                                continue;
                                        }
 
+                                       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;
+                                       }
+
                                        free(expr->args->data.str.str);
                                        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);
-                                               cfgerr++;
-                                               continue;
+                                       if (expr->args->data.str.len) {
+                                               pname = expr->args->data.str.str;
+                                               prx = find_stktable(pname);
                                        }
 
-                                       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);
@@ -2078,6 +2100,14 @@ acl_find_targets(struct proxy *p)
                                                continue;
                                        }
 
+
+                                       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;
+                                       }
+
                                        free(expr->args->data.str.str);
                                        expr->args->data.prx = prx;
                                }
index fd2528f4a7aff40aac9cc40fb63dc92470bbee45..b0d7c39b1be8ea0e4bdb5cfc2b4cf09d0cfb79eb 100644 (file)
@@ -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) },
index ebe864bb9813a05ec322d1e7e5aa9a0b37d2e07e..9f8c3232f85f418ccc5453408c84f8821336186b 100644 (file)
@@ -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 },
 }};
 
index 4c5671a751749785fbe00d73ae9773d6f3f4d779..999701479c2bbec9a81619cc261f243b07660922 100644 (file)
@@ -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 },
 }};