From 06b917c7abcd7313263d551eaecda1b31b9c03b1 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 6 Jul 2009 16:34:52 +0200 Subject: [PATCH] [BUG] http: redirect rules were processed too early redirect rules are documented as being processed last before use_backend but were mistakenly processed before block rules. Fortunately very few people use a mix of block and redirect rules, so this bug has never been reported yet. --- src/proto_http.c | 212 +++++++++++++++++++++++------------------------ 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/src/proto_http.c b/src/proto_http.c index a8612a4f10..86af03dfd6 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -1837,112 +1837,6 @@ int http_process_request(struct session *s, struct buffer *req) struct proxy *rule_set = s->be; cur_proxy = s->be; - /* first check whether we have some ACLs set to redirect this request */ - list_for_each_entry(rule, &cur_proxy->redirect_rules, list) { - int ret = acl_exec_cond(rule->cond, cur_proxy, s, txn, ACL_DIR_REQ); - - ret = acl_pass(ret); - if (rule->cond->pol == ACL_COND_UNLESS) - ret = !ret; - - if (ret) { - struct chunk rdr = { trash, 0 }; - const char *msg_fmt; - - /* build redirect message */ - switch(rule->code) { - case 303: - rdr.len = strlen(HTTP_303); - msg_fmt = HTTP_303; - break; - case 301: - rdr.len = strlen(HTTP_301); - msg_fmt = HTTP_301; - break; - case 302: - default: - rdr.len = strlen(HTTP_302); - msg_fmt = HTTP_302; - break; - } - - if (unlikely(rdr.len > sizeof(trash))) - goto return_bad_req; - memcpy(rdr.str, msg_fmt, rdr.len); - - switch(rule->type) { - case REDIRECT_TYPE_PREFIX: { - const char *path; - int pathlen; - - path = http_get_path(txn); - /* build message using path */ - if (path) { - pathlen = txn->req.sl.rq.u_l + (txn->req.sol+txn->req.sl.rq.u) - path; - if (rule->flags & REDIRECT_FLAG_DROP_QS) { - int qs = 0; - while (qs < pathlen) { - if (path[qs] == '?') { - pathlen = qs; - break; - } - qs++; - } - } - } else { - path = "/"; - pathlen = 1; - } - - if (rdr.len + rule->rdr_len + pathlen > sizeof(trash) - 4) - goto return_bad_req; - - /* add prefix. Note that if prefix == "/", we don't want to - * add anything, otherwise it makes it hard for the user to - * configure a self-redirection. - */ - if (rule->rdr_len != 1 || *rule->rdr_str != '/') { - memcpy(rdr.str + rdr.len, rule->rdr_str, rule->rdr_len); - rdr.len += rule->rdr_len; - } - - /* add path */ - memcpy(rdr.str + rdr.len, path, pathlen); - rdr.len += pathlen; - break; - } - case REDIRECT_TYPE_LOCATION: - default: - if (rdr.len + rule->rdr_len > sizeof(trash) - 4) - goto return_bad_req; - - /* add location */ - memcpy(rdr.str + rdr.len, rule->rdr_str, rule->rdr_len); - rdr.len += rule->rdr_len; - break; - } - - if (rule->cookie_len) { - memcpy(rdr.str + rdr.len, "\r\nSet-Cookie: ", 14); - rdr.len += 14; - memcpy(rdr.str + rdr.len, rule->cookie_str, rule->cookie_len); - rdr.len += rule->cookie_len; - memcpy(rdr.str + rdr.len, "\r\n", 2); - rdr.len += 2; - } - - /* add end of headers */ - memcpy(rdr.str + rdr.len, "\r\n\r\n", 4); - rdr.len += 4; - - txn->status = rule->code; - /* let's log the request time */ - s->logs.tv_request = now; - stream_int_retnclose(req->prod, &rdr); - goto return_prx_cond; - } - } - /* 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, s, txn, ACL_DIR_REQ); @@ -2059,6 +1953,112 @@ int http_process_request(struct session *s, struct buffer *req) } } + /* first check whether we have some ACLs set to redirect this request */ + list_for_each_entry(rule, &cur_proxy->redirect_rules, list) { + int ret = acl_exec_cond(rule->cond, cur_proxy, s, txn, ACL_DIR_REQ); + + ret = acl_pass(ret); + if (rule->cond->pol == ACL_COND_UNLESS) + ret = !ret; + + if (ret) { + struct chunk rdr = { trash, 0 }; + const char *msg_fmt; + + /* build redirect message */ + switch(rule->code) { + case 303: + rdr.len = strlen(HTTP_303); + msg_fmt = HTTP_303; + break; + case 301: + rdr.len = strlen(HTTP_301); + msg_fmt = HTTP_301; + break; + case 302: + default: + rdr.len = strlen(HTTP_302); + msg_fmt = HTTP_302; + break; + } + + if (unlikely(rdr.len > sizeof(trash))) + goto return_bad_req; + memcpy(rdr.str, msg_fmt, rdr.len); + + switch(rule->type) { + case REDIRECT_TYPE_PREFIX: { + const char *path; + int pathlen; + + path = http_get_path(txn); + /* build message using path */ + if (path) { + pathlen = txn->req.sl.rq.u_l + (txn->req.sol+txn->req.sl.rq.u) - path; + if (rule->flags & REDIRECT_FLAG_DROP_QS) { + int qs = 0; + while (qs < pathlen) { + if (path[qs] == '?') { + pathlen = qs; + break; + } + qs++; + } + } + } else { + path = "/"; + pathlen = 1; + } + + if (rdr.len + rule->rdr_len + pathlen > sizeof(trash) - 4) + goto return_bad_req; + + /* add prefix. Note that if prefix == "/", we don't want to + * add anything, otherwise it makes it hard for the user to + * configure a self-redirection. + */ + if (rule->rdr_len != 1 || *rule->rdr_str != '/') { + memcpy(rdr.str + rdr.len, rule->rdr_str, rule->rdr_len); + rdr.len += rule->rdr_len; + } + + /* add path */ + memcpy(rdr.str + rdr.len, path, pathlen); + rdr.len += pathlen; + break; + } + case REDIRECT_TYPE_LOCATION: + default: + if (rdr.len + rule->rdr_len > sizeof(trash) - 4) + goto return_bad_req; + + /* add location */ + memcpy(rdr.str + rdr.len, rule->rdr_str, rule->rdr_len); + rdr.len += rule->rdr_len; + break; + } + + if (rule->cookie_len) { + memcpy(rdr.str + rdr.len, "\r\nSet-Cookie: ", 14); + rdr.len += 14; + memcpy(rdr.str + rdr.len, rule->cookie_str, rule->cookie_len); + rdr.len += rule->cookie_len; + memcpy(rdr.str + rdr.len, "\r\n", 2); + rdr.len += 2; + } + + /* add end of headers */ + memcpy(rdr.str + rdr.len, "\r\n\r\n", 4); + rdr.len += 4; + + txn->status = rule->code; + /* let's log the request time */ + s->logs.tv_request = now; + stream_int_retnclose(req->prod, &rdr); + goto return_prx_cond; + } + } + /* now check whether we have some switching rules for this request */ if (!(s->flags & SN_BE_ASSIGNED)) { struct switching_rule *rule;