]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] http: add options to ignore invalid header names
authorWilly Tarreau <w@1wt.eu>
Thu, 2 Apr 2009 09:35:18 +0000 (11:35 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 2 Apr 2009 19:36:34 +0000 (21:36 +0200)
Sometimes it is required to let invalid requests pass because
applications sometimes take time to be fixed and other servers
do not care. Thus we provide two new options :

     option accept-invalid-http-request  (for the frontend)
     option accept-invalid-http-response (for the backend)

When those options are set, invalid requests or responses do
not cause a 403/502 error to be generated.

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

index 7313e25c79ef3ebc6f43829702e899c04cfdc00f..c0350d2458f23fb16be8071705d1e031259cd45f 100644 (file)
@@ -231,6 +231,7 @@ struct http_msg {
                } st;                          /* status line : field, length */
        } sl;                                  /* start line */
        unsigned long long hdr_content_len;    /* cache for parsed header value */
+       int err_pos;                           /* err handling: -2=block, -1=pass, 0+=detected */
 };
 
 /* This is an HTTP transaction. It contains both a request message and a
index 432b27bb3e5b9477ca029a12d6f4b839384fad5f..b10fc1034539f3cb2142ca875a312a1a2d3d0840 100644 (file)
 #define PR_O2_SPLIC_RTR        0x00000002      /* transfer responses using linux kernel's splice() */
 #define PR_O2_SPLIC_AUT        0x00000004      /* automatically use linux kernel's splice() */
 #define PR_O2_SPLIC_ANY        (PR_O2_SPLIC_REQ|PR_O2_SPLIC_RTR|PR_O2_SPLIC_AUT)
+#define PR_O2_REQBUG_OK        0x00000008      /* let buggy requests pass through */
+#define PR_O2_RSPBUG_OK        0x00000010      /* let buggy responses pass through */
 
 /* This structure is used to apply fast weighted round robin on a server group */
 struct fwrr_group {
index a0b8d6355495dc934dee5381570af9db02761ba9..3f86ce4def33633bd3c37f0c336216fd7a960263 100644 (file)
@@ -123,6 +123,8 @@ static const struct cfg_opt cfg_opts2[] =
        { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
        { "splice-auto",     PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
 #endif
+       { "accept-invalid-http-request",  PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
+       { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
        { NULL, 0, 0, 0 }
 };
 
index 02c7c02daa5c6490f335200d6fa428a24146c1d9..b3e19804d5264a213c00dc275a29cd8fe3668c9a 100644 (file)
@@ -266,6 +266,9 @@ int event_accept(int fd) {
                        txn->rsp.msg_state = HTTP_MSG_RPBEFORE; /* at the very beginning of the response */
                        txn->req.sol = txn->req.eol = NULL;
                        txn->req.som = txn->req.eoh = 0; /* relative to the buffer */
+                       txn->req.err_pos = txn->rsp.err_pos = -2; /* block buggy requests/responses */
+                       if (p->options2 & PR_O2_REQBUG_OK)
+                               txn->req.err_pos = -1; /* let buggy requests pass */
                        txn->auth_hdr.len = -1;
 
                        if (p->nb_req_cap > 0) {
index 359488bea56bcb9fae243132ba7d56639718463e..a77ab79bda986caab67aadeef6d82caa205e3300 100644 (file)
@@ -1375,7 +1375,14 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx
                        EAT_AND_JUMP_OR_RETURN(http_msg_hdr_l1_sp, HTTP_MSG_HDR_L1_SP);
                }
 
-               goto http_msg_invalid;
+               if (likely(msg->err_pos < -1) || *ptr == '\n')
+                       goto http_msg_invalid;
+
+               if (msg->err_pos == -1) /* capture error pointer */
+                       msg->err_pos = ptr - buf->data; /* >= 0 now */
+
+               /* and we still accept this non-token character */
+               EAT_AND_JUMP_OR_RETURN(http_msg_hdr_name, HTTP_MSG_HDR_NAME);
 
        http_msg_hdr_l1_sp:
        case HTTP_MSG_HDR_L1_SP:
@@ -2055,6 +2062,8 @@ int http_process_request(struct session *s, struct buffer *req)
                                        s->rep->rto = s->req->wto = s->be->timeout.server;
                                        s->req->cto = s->be->timeout.connect;
                                        s->conn_retries = s->be->conn_retries;
+                                       if (s->be->options2 & PR_O2_RSPBUG_OK)
+                                               s->txn.rsp.err_pos = -1; /* let buggy responses pass */
                                        s->flags |= SN_BE_ASSIGNED;
                                        break;
                                }
@@ -2076,6 +2085,8 @@ int http_process_request(struct session *s, struct buffer *req)
                        s->rep->rto = s->req->wto = s->be->timeout.server;
                        s->req->cto = s->be->timeout.connect;
                        s->conn_retries = s->be->conn_retries;
+                       if (s->be->options2 & PR_O2_RSPBUG_OK)
+                               s->txn.rsp.err_pos = -1; /* let buggy responses pass */
                        s->flags |= SN_BE_ASSIGNED;
                }
        } while (s->be != cur_proxy);  /* we loop only if s->be has changed */
@@ -3054,6 +3065,8 @@ int apply_filter_to_req_headers(struct session *t, struct buffer *req, struct hd
                                t->rep->rto = t->req->wto = t->be->timeout.server;
                                t->req->cto = t->be->timeout.connect;
                                t->conn_retries = t->be->conn_retries;
+                               if (t->be->options2 & PR_O2_RSPBUG_OK)
+                                       t->txn.rsp.err_pos = -1; /* let buggy responses pass */
                                last_hdr = 1;
                                break;
 
@@ -3175,6 +3188,8 @@ int apply_filter_to_req_line(struct session *t, struct buffer *req, struct hdr_e
                        t->rep->rto = t->req->wto = t->be->timeout.server;
                        t->req->cto = t->be->timeout.connect;
                        t->conn_retries = t->be->conn_retries;
+                       if (t->be->options2 & PR_O2_RSPBUG_OK)
+                               t->txn.rsp.err_pos = -1; /* let buggy responses pass */
                        done = 1;
                        break;