]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
htp: keep track of header line terminators so http_raw_header can reconstruct exact...
authorVictor Julien <victor@inliniac.net>
Thu, 31 May 2012 09:00:34 +0000 (11:00 +0200)
committerVictor Julien <victor@inliniac.net>
Fri, 29 Jun 2012 12:39:14 +0000 (14:39 +0200)
libhtp/htp/htp.h
libhtp/htp/htp_request.c
libhtp/htp/htp_response.c
libhtp/htp/htp_util.c

index 38c47518853df287218df1aeb1b20212840de563..22f8a1169c7e1bf21c17bec7b9c03bba46d7bcfe 100644 (file)
@@ -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;
 };
index 57f747de34ba177ea24026af5bd859e5fd3b9b37..aed300f56992487dc649bf9e240d1bad9838970b 100644 (file)
@@ -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;
 
index 118b259438159635ab886dc882929f281be69ee5..da591f340400525e13bd904e45a8e280927a239b 100644 (file)
@@ -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;
index a5d6dc66426ce1a63e4bae902851a6b45cae13ab..09775a7000f505b5c040b1c13a87015f09577aa1 100644 (file)
@@ -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;