]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] http-request: allow/deny/auth support for frontend/backend/listen
authorKrzysztof Piotr Oledzki <ole@ans.pl>
Fri, 29 Jan 2010 16:58:21 +0000 (17:58 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 31 Jan 2010 18:14:08 +0000 (19:14 +0100)
Use the generic auth framework to control access to frontends/backends/listens

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

index bdb42b90431e6c08cc811544a890bd355c636fd6..fabc93640817cbcc389208433f0c94592a425b0f 100644 (file)
@@ -170,6 +170,7 @@ struct proxy {
                char *name;                     /* default backend name during config parse */
        } defbe;
        struct list acl;                        /* ACL declared on this proxy */
+       struct list req_acl;                    /* request ACL: allow/deny/http-auth */
        struct list block_cond;                 /* early blocking conditions (chained) */
        struct list redirect_rules;             /* content redirecting rules (chained) */
        struct list switching_rules;            /* content switching rules (chained) */
index 5c181f16c4ffff9af06a657a327c57f8d9063f43..ef34760fd9dabf3e4811dcee4fb7e9d564ad6717 100644 (file)
@@ -882,6 +882,7 @@ static void init_new_proxy(struct proxy *p)
        memset(p, 0, sizeof(struct proxy));
        LIST_INIT(&p->pendconns);
        LIST_INIT(&p->acl);
+       LIST_INIT(&p->req_acl);
        LIST_INIT(&p->block_cond);
        LIST_INIT(&p->redirect_rules);
        LIST_INIT(&p->mon_fail_cond);
@@ -1927,6 +1928,31 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                }
                curproxy->conn_retries = atol(args[1]);
        }
+       else if (!strcmp(args[0], "http-request")) {    /* request access control: allow/deny/auth */
+               struct req_acl_rule *req_acl;
+
+               if (curproxy == &defproxy) {
+                       Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
+
+
+               if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
+                       Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
+                               file, linenum, args[0]);
+                       err_code |= ERR_WARN;
+               }
+
+               req_acl = parse_auth_cond((const char **)args + 1, file, linenum, &curproxy->acl, &curproxy->acl_requires);
+
+               if (!req_acl) {
+                       err_code |= ERR_ALERT | ERR_ABORT;
+                       goto out;
+               }
+
+               LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
+       }
        else if (!strcmp(args[0], "block")) {  /* early blocking based on ACLs */
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
index 0393ebfee13c2a06d11998fae7132e2c6d1527dd..905febfaede5d8f0599a9fc278dbda0f3dc85cc3 100644 (file)
@@ -859,6 +859,8 @@ void deinit(void)
                        l = l_next;
                }/* end while(l) */
 
+               req_acl_free(&p->req_acl);
+
                pool_destroy2(p->req_cap_pool);
                pool_destroy2(p->rsp_cap_pool);
                pool_destroy2(p->hdr_idx_pool);
index b2dd232ceef7415a343538bc17ac16a8297e94ab..59952a43586f4de82cad706fb8a4e72d3583b5d9 100644 (file)
@@ -1351,7 +1351,6 @@ const char *http_parse_stsline(struct http_msg *msg, const char *msg_buf,
        return NULL;
 }
 
-
 /*
  * This function parses a request line between <ptr> and <end>, starting with
  * parser state <state>. Only states HTTP_MSG_RQMETH, HTTP_MSG_RQMETH_SP,
@@ -2723,6 +2722,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
        struct http_txn *txn = &s->txn;
        struct http_msg *msg = &txn->req;
        struct acl_cond *cond;
+       struct req_acl_rule *req_acl, *req_acl_final = NULL;
        struct redirect_rule *rule;
        struct cond_wordlist *wl;
        int del_ka, del_cl;
@@ -2762,6 +2762,29 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
                }
        }
 
+       list_for_each_entry(req_acl, &px->req_acl, list) {
+               int ret = 1;
+
+               if (req_acl->action >= PR_REQ_ACL_ACT_MAX)
+                       continue;
+
+               /* check condition, but only if attached */
+               if (req_acl->cond)
+                       ret = acl_exec_cond(req_acl->cond, px, s, txn, ACL_DIR_REQ);
+
+               if (ret) {
+                       req_acl_final = req_acl;
+                       break;
+               }
+       }
+
+       if (req_acl_final && req_acl_final->action == PR_REQ_ACL_ACT_DENY) {
+                       txn->status = 403;
+                       s->logs.tv_request = now;
+                       stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_403));
+                       goto return_prx_cond;
+       }
+
        /* try headers filters */
        if (px->req_exp != NULL) {
                if (apply_filters_to_request(s, req, px) < 0)
@@ -2864,6 +2887,16 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
                        goto return_bad_req;
        }
 
+       if (req_acl_final && req_acl_final->action == PR_REQ_ACL_ACT_HTTP_AUTH) {
+               struct chunk msg;
+
+               sprintf(trash, HTTP_401_fmt, req_acl->http_auth.realm?req_acl->http_auth.realm:px->id);
+               chunk_initlen(&msg, trash, sizeof(trash), strlen(trash));
+               txn->status = 401;
+               stream_int_retnclose(req->prod, &msg);
+               goto return_prx_cond;
+       }
+
        /* check if stats URI was requested, and if an auth is needed */
        if (px->uri_auth != NULL &&
            (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)) {