diff --git a/src/proto_http.c b/src/proto_http.c index 2c33a84ce..8ca39c124 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2085,13 +2085,13 @@ int http_parse_chunk_size(struct buffer *buf, struct http_msg *msg) if (++ptr >= end) ptr = buf->data; if (chunk & 0xF000000) /* overflow will occur */ - return -1; + goto error; chunk = (chunk << 4) + c; } /* empty size not allowed */ if (ptr == buf->lr) - return -1; + goto error; while (http_is_spht[(unsigned char)*ptr]) { if (++ptr >= end) @@ -2114,7 +2114,7 @@ int http_parse_chunk_size(struct buffer *buf, struct http_msg *msg) } if (*ptr != '\n') - return -1; + goto error; if (++ptr >= end) ptr = buf->data; /* done */ @@ -2137,7 +2137,7 @@ int http_parse_chunk_size(struct buffer *buf, struct http_msg *msg) continue; } else - return -1; + goto error; } /* OK we found our CRLF and now points to the next byte, @@ -2149,6 +2149,9 @@ int http_parse_chunk_size(struct buffer *buf, struct http_msg *msg) msg->hdr_content_len = chunk; msg->msg_state = chunk ? HTTP_MSG_DATA : HTTP_MSG_TRAILERS; return 1; + error: + msg->err_pos = ptr - buf->data; + return -1; } /* This function skips trailers in the buffer associated with HTTP @@ -2187,8 +2190,10 @@ int http_forward_trailers(struct buffer *buf, struct http_msg *msg) } if (*ptr == '\r') { - if (p1) + if (p1) { + msg->err_pos = ptr - buf->data; return -1; + } p1 = ptr; } @@ -2255,8 +2260,10 @@ int http_skip_chunk_crlf(struct buffer *buf, struct http_msg *msg) if (bytes > buf->l - buf->send_max) return 0; - if (*ptr != '\n') + if (*ptr != '\n') { + msg->err_pos = ptr - buf->data; return -1; + } ptr++; if (ptr >= buf->data + buf->size) @@ -4361,6 +4368,8 @@ int http_request_forward_body(struct session *s, struct buffer *req, int an_bit) goto missing_data; else if (ret < 0) { session_inc_http_err_ctr(s); + if (msg->err_pos >= 0) + http_capture_bad_message(&s->fe->invalid_req, s, req, msg, HTTP_MSG_CHUNK_SIZE, s->be); goto return_bad_req; } /* otherwise we're in HTTP_MSG_DATA or HTTP_MSG_TRAILERS state */ @@ -4382,6 +4391,8 @@ int http_request_forward_body(struct session *s, struct buffer *req, int an_bit) goto missing_data; else if (ret < 0) { session_inc_http_err_ctr(s); + if (msg->err_pos >= 0) + http_capture_bad_message(&s->fe->invalid_req, s, req, msg, HTTP_MSG_DATA_CRLF, s->be); goto return_bad_req; } /* we're in MSG_CHUNK_SIZE now */ @@ -4393,11 +4404,15 @@ int http_request_forward_body(struct session *s, struct buffer *req, int an_bit) goto missing_data; else if (ret < 0) { session_inc_http_err_ctr(s); + if (msg->err_pos >= 0) + http_capture_bad_message(&s->fe->invalid_req, s, req, msg, HTTP_MSG_TRAILERS, s->be); goto return_bad_req; } /* we're in HTTP_MSG_DONE now */ } else { + int old_state = msg->msg_state; + /* other states, DONE...TUNNEL */ /* for keep-alive we don't want to forward closes on DONE */ if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL || @@ -4417,6 +4432,8 @@ int http_request_forward_body(struct session *s, struct buffer *req, int an_bit) if (!(s->flags & SN_FINST_MASK)) s->flags |= SN_FINST_D; } + if (msg->err_pos >= 0) + http_capture_bad_message(&s->fe->invalid_req, s, req, msg, old_state, s->be); goto return_bad_req; } return 1; @@ -5352,8 +5369,11 @@ int http_response_forward_body(struct session *s, struct buffer *res, int an_bit if (!ret) goto missing_data; - else if (ret < 0) + else if (ret < 0) { + if (msg->err_pos >= 0) + http_capture_bad_message(&s->be->invalid_rep, s, res, msg, HTTP_MSG_CHUNK_SIZE, s->fe); goto return_bad_res; + } /* otherwise we're in HTTP_MSG_DATA or HTTP_MSG_TRAILERS state */ /* Don't set a PUSH at the end of that chunk if it's not the last one */ if (msg->msg_state == HTTP_MSG_DATA) @@ -5371,8 +5391,11 @@ int http_response_forward_body(struct session *s, struct buffer *res, int an_bit if (!ret) goto missing_data; - else if (ret < 0) + else if (ret < 0) { + if (msg->err_pos >= 0) + http_capture_bad_message(&s->be->invalid_rep, s, res, msg, HTTP_MSG_DATA_CRLF, s->fe); goto return_bad_res; + } /* we're in MSG_CHUNK_SIZE now */ } else if (msg->msg_state == HTTP_MSG_TRAILERS) { @@ -5380,11 +5403,16 @@ int http_response_forward_body(struct session *s, struct buffer *res, int an_bit if (ret == 0) goto missing_data; - else if (ret < 0) + else if (ret < 0) { + if (msg->err_pos >= 0) + http_capture_bad_message(&s->be->invalid_rep, s, res, msg, HTTP_MSG_TRAILERS, s->fe); goto return_bad_res; + } /* we're in HTTP_MSG_DONE now */ } else { + int old_state = msg->msg_state; + /* other states, DONE...TUNNEL */ /* for keep-alive we don't want to forward closes on DONE */ if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL || @@ -5405,6 +5433,8 @@ int http_response_forward_body(struct session *s, struct buffer *res, int an_bit if (!(s->flags & SN_FINST_MASK)) s->flags |= SN_FINST_D; } + if (msg->err_pos >= 0) + http_capture_bad_message(&s->be->invalid_rep, s, res, msg, old_state, s->fe); goto return_bad_res; } return 1;