]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] added the 'block' keyword to the config language
authorWilly Tarreau <w@1wt.eu>
Sun, 6 May 2007 22:58:25 +0000 (00:58 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2007 21:24:51 +0000 (23:24 +0200)
The new 'block' keyword makes it possible to block a request based on
ACL test results. Block accepts two optional arguments : 'if' <cond>
and 'unless' <cond>.

The request will be blocked with a 403 response if the condition is validated
(if) or if it is not (unless). Do not rely on this one too much, as it's more
of a proof of concept helping in developing other matches.

include/types/proxy.h
src/cfgparse.c
src/proto_http.c

index 6a96f94b9c354084eac60ec3ac26b585f4556d7a..c403e59f4c0591b74da293337d7f7ce5825bbddb 100644 (file)
@@ -84,6 +84,7 @@ struct proxy {
                char *name;                     /* default backend name during config parse */
        } defbe;
        struct list acl;                        /* ACL declared on this proxy */
+       struct list block_cond;                 /* early blocking conditions (chained) */
        struct server *srv;                     /* known servers */
        int srv_act, srv_bck;                   /* # of running servers */
        int tot_wact, tot_wbck;                 /* total weights of active and backup servers */
index c4c6c8c273aff786f4b4ac85edf764bdf892a9b9..41d706611865085e51d6dbf6eb66c5958d6b036a 100644 (file)
@@ -494,6 +494,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                proxy = curproxy;
                LIST_INIT(&curproxy->pendconns);
                LIST_INIT(&curproxy->acl);
+               LIST_INIT(&curproxy->block_cond);
 
                curproxy->id = strdup(args[1]);
                curproxy->cap = rc;
@@ -912,6 +913,28 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                }
                curproxy->conn_retries = atol(args[1]);
        }
+       else if (!strcmp(args[0], "block")) {  /* early blocking based on ACLs */
+               int pol = ACL_COND_NONE;
+               struct acl_cond *cond;
+
+               if (!strcmp(args[1], "if"))
+                       pol = ACL_COND_IF;
+               else if (!strcmp(args[1], "unless"))
+                       pol = ACL_COND_UNLESS;
+
+               if (pol == ACL_COND_NONE) {
+                       Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
+                             file, linenum, args[0]);
+                       return -1;
+               }
+
+               if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
+                       Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
+                             file, linenum);
+                       return -1;
+               }
+               LIST_ADDQ(&curproxy->block_cond, &cond->list);
+       }
        else if (!strcmp(args[0], "stats")) {
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
                        return 0;
index 706ef464078c96ddab966ff59cf1b705824e9afa..6d4c152801c063c5af2d109f11a88f621a548093 100644 (file)
@@ -1674,9 +1674,25 @@ int process_cli(struct session *t)
                 */
 
                do {
+                       struct acl_cond *cond;
                        struct proxy *rule_set = t->be;
                        cur_proxy = t->be;
 
+                       /* first check whether we have some ACLs set to block this request */
+                       list_for_each_entry(cond, &cur_proxy->block_cond, list) {
+                               int ret = acl_exec_cond(cond, cur_proxy, t, txn);
+                               if (cond->pol == ACL_COND_UNLESS)
+                                       ret = !ret;
+
+                               if (ret) {
+                                       txn->status = 403;
+                                       /* let's log the request time */
+                                       t->logs.t_request = tv_ms_elapsed(&t->logs.tv_accept, &now);
+                                       client_retnclose(t, error_message(t, HTTP_ERR_403));
+                                       goto return_prx_cond;
+                               }
+                       }
+
                        /* try headers filters */
                        if (rule_set->req_exp != NULL) {
                                if (apply_filters_to_request(t, req, rule_set->req_exp) < 0)