From dc008c57a4445564e2added7c60a3f644b7001ec Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 1 Feb 2010 16:20:08 +0100 Subject: [PATCH] [MEDIUM] http: stricter processing of the CONNECT method Now we establish the tunnel only once the status 200 reponse is received. That way we can still support an authentication request in response to a CONNECT, then a client's authentication response. --- src/proto_http.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/proto_http.c b/src/proto_http.c index 8a0345a50..821bf8912 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2723,10 +2723,6 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) * to the message-body. */ - /* CONNECT sets a tunnel and ignores everything else */ - if (txn->meth == HTTP_METH_CONNECT) - goto skip_xfer_len; - use_close_only = 0; ctx.idx = 0; /* set TE_CHNK and XFER_LEN only if "chunked" is seen last */ @@ -2767,7 +2763,6 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) if (!use_close_only) txn->flags |= TX_REQ_XFER_LEN; - skip_xfer_len: /* end of job, return OK */ req->analysers &= ~an_bit; req->analyse_exp = TICK_ETERNITY; @@ -2931,11 +2926,10 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s del_cl = del_ka = 0; - if ((txn->meth != HTTP_METH_CONNECT) && - ((!(txn->flags & TX_HDR_CONN_PRS) && - (s->fe->options & (PR_O_KEEPALIVE|PR_O_SERVER_CLO|PR_O_HTTP_CLOSE|PR_O_FORCE_CLO))) || - ((s->fe->options & (PR_O_KEEPALIVE|PR_O_SERVER_CLO|PR_O_HTTP_CLOSE|PR_O_FORCE_CLO)) != - (s->be->options & (PR_O_KEEPALIVE|PR_O_SERVER_CLO|PR_O_HTTP_CLOSE|PR_O_FORCE_CLO))))) { + if ((!(txn->flags & TX_HDR_CONN_PRS) && + (s->fe->options & (PR_O_KEEPALIVE|PR_O_SERVER_CLO|PR_O_HTTP_CLOSE|PR_O_FORCE_CLO))) || + ((s->fe->options & (PR_O_KEEPALIVE|PR_O_SERVER_CLO|PR_O_HTTP_CLOSE|PR_O_FORCE_CLO)) != + (s->be->options & (PR_O_KEEPALIVE|PR_O_SERVER_CLO|PR_O_HTTP_CLOSE|PR_O_FORCE_CLO)))) { int tmp = TX_CON_WANT_TUN; if ((s->fe->options|s->be->options) & PR_O_KEEPALIVE) @@ -4574,9 +4568,6 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit) goto skip_content_length; } - if (txn->meth == HTTP_METH_CONNECT) - goto skip_content_length; - use_close_only = 0; ctx.idx = 0; while ((txn->flags & TX_RES_VER_11) && @@ -4669,21 +4660,22 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s * See doc/internals/connection-header.txt for the complete matrix. */ - if (unlikely(txn->status == 101)) { - /* this is a "switching protocol" response, we're very unlikely + if (unlikely((txn->meth == HTTP_METH_CONNECT && txn->status == 200) || + txn->status == 101)) { + /* Either we've established an explicit tunnel, or we're + * switching the protocol. In both cases, we're very unlikely * to understand the next protocols. We have to switch to tunnel * mode, so that we transfer the request and responses then let * this protocol pass unmodified. When we later implement specific * parsers for such protocols, we'll want to check the Upgrade - * header which contains information about that protocol (eg: see - * RFC2817 about TLS). + * header which contains information about that protocol for + * responses with status 101 (eg: see RFC2817 about TLS). */ txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_TUN; } - else if ((txn->meth != HTTP_METH_CONNECT) && - (txn->status >= 200) && !(txn->flags & TX_HDR_CONN_PRS) && - ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN || - ((t->fe->options|t->be->options) & PR_O_HTTP_CLOSE))) { + else if ((txn->status >= 200) && !(txn->flags & TX_HDR_CONN_PRS) && + ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN || + ((t->fe->options|t->be->options) & PR_O_HTTP_CLOSE))) { int to_del = 0; /* on unknown transfer length, we must close */ @@ -4916,7 +4908,8 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s } skip_header_mangling: - if (txn->flags & TX_RES_XFER_LEN) + if ((txn->flags & TX_RES_XFER_LEN) || + (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_TUN) rep->analysers |= AN_RES_HTTP_XFER_BODY; /*************************************************************