From: Willy Tarreau Date: Thu, 28 Jan 2010 19:22:06 +0000 (+0100) Subject: [MEDIUM] http: make the request filter loop check for optional conditions X-Git-Tag: v1.4-rc1~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6c123b15cba5096ecf77b20cd111b3f658cef9ce;p=thirdparty%2Fhaproxy.git [MEDIUM] http: make the request filter loop check for optional conditions From now on, if request filters have ACLs defined, these ACLs will be evaluated to condition the filter. This will be used to conditionally remove/rewrite headers based on ACLs. --- diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h index cfaf9859a3..6a424c0f06 100644 --- a/include/proto/proto_http.h +++ b/include/proto/proto_http.h @@ -75,7 +75,7 @@ void debug_hdr(const char *dir, struct session *t, const char *start, const char void get_srv_from_appsession(struct session *t, const char *begin, int len); int apply_filter_to_req_headers(struct session *t, struct buffer *req, struct hdr_exp *exp); int apply_filter_to_req_line(struct session *t, struct buffer *req, struct hdr_exp *exp); -int apply_filters_to_request(struct session *t, struct buffer *req, struct hdr_exp *exp); +int apply_filters_to_request(struct session *s, struct buffer *req, struct proxy *px); int apply_filters_to_response(struct session *t, struct buffer *rtr, struct hdr_exp *exp); void manage_client_side_appsession(struct session *t, const char *buf, int len); void manage_client_side_cookies(struct session *t, struct buffer *req); diff --git a/src/proto_http.c b/src/proto_http.c index 94022c8766..975963504b 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2764,7 +2764,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s /* try headers filters */ if (px->req_exp != NULL) { - if (apply_filters_to_request(s, req, px->req_exp) < 0) + if (apply_filters_to_request(s, req, px) < 0) goto return_bad_req; /* has the request been denied ? */ @@ -5176,16 +5176,17 @@ int apply_filter_to_req_line(struct session *t, struct buffer *req, struct hdr_e /* - * Apply all the req filters to all headers in buffer of session . + * Apply all the req filters of proxy to all headers in buffer of session . * Returns 0 if everything is alright, or -1 in case a replacement lead to an * unparsable request. Since it can manage the switch to another backend, it * updates the per-proxy DENY stats. */ -int apply_filters_to_request(struct session *t, struct buffer *req, struct hdr_exp *exp) +int apply_filters_to_request(struct session *s, struct buffer *req, struct proxy *px) { - struct http_txn *txn = &t->txn; - /* iterate through the filters in the outer loop */ - while (exp && !(txn->flags & (TX_CLDENY|TX_CLTARPIT))) { + struct http_txn *txn = &s->txn; + struct hdr_exp *exp; + + for (exp = px->req_exp; exp; exp = exp->next) { int ret; /* @@ -5194,15 +5195,29 @@ int apply_filters_to_request(struct session *t, struct buffer *req, struct hdr_e * the evaluation. */ + if (txn->flags & (TX_CLDENY|TX_CLTARPIT)) + break; + if ((txn->flags & TX_CLALLOW) && (exp->action == ACT_ALLOW || exp->action == ACT_DENY || - exp->action == ACT_TARPIT || exp->action == ACT_PASS)) { - exp = exp->next; + exp->action == ACT_TARPIT || exp->action == ACT_PASS)) continue; + + /* if this filter had a condition, evaluate it now and skip to + * next filter if the condition does not match. + */ + if (exp->cond) { + ret = acl_exec_cond(exp->cond, px, s, txn, ACL_DIR_REQ); + ret = acl_pass(ret); + if (((struct acl_cond *)exp->cond)->pol == ACL_COND_UNLESS) + ret = !ret; + + if (!ret) + continue; } /* Apply the filter to the request line. */ - ret = apply_filter_to_req_line(t, req, exp); + ret = apply_filter_to_req_line(s, req, exp); if (unlikely(ret < 0)) return -1; @@ -5210,9 +5225,8 @@ int apply_filters_to_request(struct session *t, struct buffer *req, struct hdr_e /* The filter did not match the request, it can be * iterated through all headers. */ - apply_filter_to_req_headers(t, req, exp); + apply_filter_to_req_headers(s, req, exp); } - exp = exp->next; } return 0; }