From: Willy Tarreau Date: Sun, 4 Mar 2007 17:13:58 +0000 (+0100) Subject: [MINOR] implement http_is_ver_token to fix response parsing X-Git-Tag: v1.3.8~28 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4b89ad4358d70d46805f86b2b7e93bf65b405549;p=thirdparty%2Fhaproxy.git [MINOR] implement http_is_ver_token to fix response parsing This new character map improves accuracy when parsing HTTP version, which helps inspecting requests, and fixes response handling. --- diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h index 4863fe80c9..324a5776fa 100644 --- a/include/proto/proto_http.h +++ b/include/proto/proto_http.h @@ -36,6 +36,9 @@ * SPHT = SP or HT. Use this macro and not a boolean expression for best speed. * CRLF = CR or LF. Use this macro and not a boolean expression for best speed. * token = any CHAR except CTL or SEP. Use this macro and not a boolean expression for best speed. + * + * added for ease of use: + * ver_token = 'H', 'P', 'T', '/', '.', and digits. */ extern const char http_is_ctl[256]; @@ -44,6 +47,7 @@ extern const char http_is_lws[256]; extern const char http_is_spht[256]; extern const char http_is_crlf[256]; extern const char http_is_token[256]; +extern const char http_is_ver_token[256]; #define HTTP_IS_CTL(x) (http_is_ctl[(unsigned char)(x)]) #define HTTP_IS_SEP(x) (http_is_sep[(unsigned char)(x)]) @@ -51,6 +55,7 @@ extern const char http_is_token[256]; #define HTTP_IS_SPHT(x) (http_is_spht[(unsigned char)(x)]) #define HTTP_IS_CRLF(x) (http_is_crlf[(unsigned char)(x)]) #define HTTP_IS_TOKEN(x) (http_is_token[(unsigned char)(x)]) +#define HTTP_IS_VER_TOKEN(x) (http_is_ver_token[(unsigned char)(x)]) int event_accept(int fd); int process_session(struct task *t); diff --git a/src/proto_http.c b/src/proto_http.c index 289ece6c22..0eea5fdfb5 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -294,6 +294,18 @@ const char http_is_token[256] = { }; +/* + * An http ver_token is any ASCII which can be found in an HTTP version, + * which includes 'H', 'T', 'P', '/', '.' and any digit. + */ +const char http_is_ver_token[256] = { + ['.'] = 1, ['/'] = 1, + ['0'] = 1, ['1'] = 1, ['2'] = 1, ['3'] = 1, ['4'] = 1, + ['5'] = 1, ['6'] = 1, ['7'] = 1, ['8'] = 1, ['9'] = 1, + ['H'] = 1, ['P'] = 1, ['T'] = 1, +}; + + #ifdef DEBUG_FULL static char *cli_stnames[5] = {"HDR", "DAT", "SHR", "SHW", "CLS" }; static char *srv_stnames[7] = {"IDL", "CON", "HDR", "DAT", "SHR", "SHW", "CLS" }; @@ -540,7 +552,7 @@ const char *http_parse_rspline(struct http_msg *msg, const char *msg_buf, int st switch (state) { http_msg_rpver: case HTTP_MSG_RPVER: - if (likely(HTTP_IS_TOKEN(*ptr))) + if (likely(HTTP_IS_VER_TOKEN(*ptr))) EAT_AND_JUMP_OR_RETURN(http_msg_rpver, HTTP_MSG_RPVER); if (likely(HTTP_IS_SPHT(*ptr))) { @@ -722,18 +734,24 @@ const char *http_parse_reqline(struct http_msg *msg, const char *msg_buf, int st http_msg_rqver: case HTTP_MSG_RQVER: - if (likely(!HTTP_IS_CRLF(*ptr))) + if (likely(HTTP_IS_VER_TOKEN(*ptr))) EAT_AND_JUMP_OR_RETURN(http_msg_rqver, HTTP_MSG_RQVER); - msg->sl.rq.v_l = (ptr - msg_buf) - msg->sl.rq.v; - http_msg_rqline_eol: - /* We have seen the end of line. Note that we do not - * necessarily have the \n yet, but at least we know that we - * have EITHER \r OR \n, otherwise the request would not be - * complete. We can then record the request length and return - * to the caller which will be able to register it. - */ - msg->sl.rq.l = ptr - msg->sol; - return ptr; + + if (likely(HTTP_IS_CRLF(*ptr))) { + msg->sl.rq.v_l = (ptr - msg_buf) - msg->sl.rq.v; + http_msg_rqline_eol: + /* We have seen the end of line. Note that we do not + * necessarily have the \n yet, but at least we know that we + * have EITHER \r OR \n, otherwise the request would not be + * complete. We can then record the request length and return + * to the caller which will be able to register it. + */ + msg->sl.rq.l = ptr - msg->sol; + return ptr; + } + + /* neither an HTTP_VER token nor a CRLF */ + goto http_msg_invalid; #ifdef DEBUG_FULL default: