From: Victor Julien Date: Thu, 31 May 2012 09:00:34 +0000 (+0200) Subject: htp: keep track of header line terminators so http_raw_header can reconstruct exact... X-Git-Tag: suricata-1.3rc1~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d236e68b62a91c155602207a6747ceada8995d5b;p=thirdparty%2Fsuricata.git htp: keep track of header line terminators so http_raw_header can reconstruct exact headers. --- diff --git a/libhtp/htp/htp.h b/libhtp/htp/htp.h index 38c4751885..22f8a1169c 100644 --- a/libhtp/htp/htp.h +++ b/libhtp/htp/htp.h @@ -704,7 +704,10 @@ struct htp_header_line_t { /** Parsing flags: HTP_FIELD_INVALID_NOT_FATAL, HTP_FIELD_INVALID_FATAL, HTP_FIELD_LONG */ unsigned int flags; - + + /** terminator characters, if NULL assume RFC compliant 0d 0a */ + bstr *terminators; + /** Header that uses this line. */ htp_header_t *header; }; diff --git a/libhtp/htp/htp_request.c b/libhtp/htp/htp_request.c index 57f747de34..aed300f569 100644 --- a/libhtp/htp/htp_request.c +++ b/libhtp/htp/htp_request.c @@ -460,7 +460,8 @@ int htp_connp_REQ_HEADERS(htp_connp_t *connp) { } // Prepare line for consumption - int chomp_result = htp_chomp(connp->in_line, &connp->in_line_len); + size_t raw_in_line_len = connp->in_line_len; + htp_chomp(connp->in_line, &connp->in_line_len); // Check for header folding if (htp_connp_is_line_folded(connp->in_line, connp->in_line_len) == 0) { @@ -491,11 +492,27 @@ int htp_connp_REQ_HEADERS(htp_connp_t *connp) { } // Add the raw header line to the list - connp->in_header_line->line = bstr_memdup((char *) connp->in_line, connp->in_line_len + chomp_result); + if (raw_in_line_len > connp->in_line_len) { + if (raw_in_line_len - connp->in_line_len == 2 && + connp->in_line[connp->in_line_len] == 0x0d && + connp->in_line[connp->in_line_len + 1] == 0x0a) { + connp->in_header_line->terminators = NULL; + } else { + connp->in_header_line->terminators = + bstr_memdup((char *) connp->in_line + connp->in_line_len, + raw_in_line_len - connp->in_line_len); + if (connp->in_header_line->terminators == NULL) { + return HTP_ERROR; + } + } + } else { + connp->in_header_line->terminators = NULL; + } + + connp->in_header_line->line = bstr_memdup((char *) connp->in_line, connp->in_line_len); if (connp->in_header_line->line == NULL) { return HTP_ERROR; } - list_add(connp->in_tx->request_header_lines, connp->in_header_line); connp->in_header_line = NULL; diff --git a/libhtp/htp/htp_response.c b/libhtp/htp/htp_response.c index 118b259438..da591f3404 100644 --- a/libhtp/htp/htp_response.c +++ b/libhtp/htp/htp_response.c @@ -487,6 +487,7 @@ int htp_connp_RES_HEADERS(htp_connp_t *connp) { } // Prepare line for consumption + size_t raw_out_line_len = connp->out_line_len; htp_chomp(connp->out_line, &connp->out_line_len); // Check for header folding @@ -517,6 +518,24 @@ int htp_connp_RES_HEADERS(htp_connp_t *connp) { } // Add the raw header line to the list + + if (raw_out_line_len > connp->out_line_len) { + if (raw_out_line_len - connp->out_line_len == 2 && + connp->out_line[connp->out_line_len] == 0x0d && + connp->out_line[connp->out_line_len + 1] == 0x0a) { + connp->out_header_line->terminators = NULL; + } else { + connp->out_header_line->terminators = + bstr_memdup((char *) connp->out_line + connp->out_line_len, + raw_out_line_len - connp->out_line_len); + if (connp->out_header_line->terminators == NULL) { + return HTP_ERROR; + } + } + } else { + connp->out_header_line->terminators = NULL; + } + connp->out_header_line->line = bstr_memdup((char *) connp->out_line, connp->out_line_len); if (connp->out_header_line->line == NULL) { return HTP_ERROR; diff --git a/libhtp/htp/htp_util.c b/libhtp/htp/htp_util.c index a5d6dc6642..09775a7000 100644 --- a/libhtp/htp/htp_util.c +++ b/libhtp/htp/htp_util.c @@ -1830,6 +1830,10 @@ bstr *htp_tx_generate_request_headers_raw(htp_tx_t *tx) { for (i = 0; i < list_size(tx->request_header_lines); i++) { htp_header_line_t *hl = list_get(tx->request_header_lines, i); len += bstr_len(hl->line); + if (hl->terminators) + len += bstr_len(hl->terminators); + else + len += 2; // 0d 0a } request_headers_raw = bstr_alloc(len); @@ -1841,6 +1845,10 @@ bstr *htp_tx_generate_request_headers_raw(htp_tx_t *tx) { for (i = 0; i < list_size(tx->request_header_lines); i++) { htp_header_line_t *hl = list_get(tx->request_header_lines, i); bstr_add_str_noex(request_headers_raw, hl->line); + if (hl->terminators) + bstr_add_str_noex(request_headers_raw, hl->terminators); + else + bstr_add_cstr_noex(request_headers_raw, "\r\n"); } return request_headers_raw; @@ -1892,6 +1900,10 @@ bstr *htp_tx_generate_response_headers_raw(htp_tx_t *tx) { for (i = 0; i < list_size(tx->response_header_lines); i++) { htp_header_line_t *hl = list_get(tx->response_header_lines, i); len += bstr_len(hl->line); + if (hl->terminators) + len += bstr_len(hl->terminators); + else + len += 2; // 0d 0a } response_headers_raw = bstr_alloc(len); @@ -1903,6 +1915,10 @@ bstr *htp_tx_generate_response_headers_raw(htp_tx_t *tx) { for (i = 0; i < list_size(tx->response_header_lines); i++) { htp_header_line_t *hl = list_get(tx->response_header_lines, i); bstr_add_str_noex(response_headers_raw, hl->line); + if (hl->terminators) + bstr_add_str_noex(response_headers_raw, hl->terminators); + else + bstr_add_cstr_noex(response_headers_raw, "\r\n"); } return response_headers_raw;