aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Thacker <johnthacker@gmail.com>2022-08-19 21:15:21 -0400
committerA Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org>2022-08-25 01:08:54 +0000
commitd8e877f6104111cec878908065c6b04c4f1e49a5 (patch)
tree7b9656f487044edf55634c3ca1a6961f56a32182
parent4915b646d074221f287ca27fb14ca07a2fde6a37 (diff)
HTTP: Test the first header line in a PDU more
For a PDU where we haven't seen a request, response, or header line yet, check to see if the header name is valid before deciding that it is a header. Prevents many false positives on continuation data that happens to have a line end and a colon, where we couldn't do desegmentation for some reason.
-rw-r--r--epan/dissectors/packet-http.c59
1 files changed, 34 insertions, 25 deletions
diff --git a/epan/dissectors/packet-http.c b/epan/dissectors/packet-http.c
index e8d46c0601..491a2040ed 100644
--- a/epan/dissectors/packet-http.c
+++ b/epan/dissectors/packet-http.c
@@ -327,6 +327,7 @@ static int is_http_request_or_reply(const gchar *data, int linelen,
*reqresp_dissector, http_conv_t *conv_data);
static guint chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
proto_tree *tree, int offset);
+static gboolean valid_header_name(const guchar *line, int header_len);
static void process_header(tvbuff_t *tvb, int offset, int next_offset,
const guchar *line, int linelen, int colon_offset,
packet_info *pinfo, proto_tree *tree,
@@ -1390,10 +1391,13 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
linep = (const guchar *)memchr(line, ':', linelen);
if (linep) {
/*
- * Colon found, assume it is a header.
+ * Colon found, assume it is a header if we've seen a
+ * valid line before. Check a little more if not.
*/
- colon_offset += (int)(linep - line);
- goto is_http;
+ if (saw_req_resp_or_header || valid_header_name(line, (int)(linep - line))) {
+ colon_offset += (int)(linep - line);
+ goto is_http;
+ }
}
/*
@@ -3066,6 +3070,32 @@ is_token_char(char c)
return strchr("!#$%&\\:*+-.^_`|~", c) || g_ascii_isalnum(c);
}
+static gboolean
+valid_header_name(const guchar *line, int header_len)
+{
+
+ /*
+ * Validate the header name. This allows no space between the field name
+ * and colon (RFC 7230, Section. 3.2.4).
+ */
+ if (header_len == 0) {
+ return FALSE;
+ }
+ for (int i = 0; i < header_len; i++) {
+ /*
+ * NUL is not a valid character; treat it specially
+ * due to C's notion that strings are NUL-terminated.
+ */
+ if (line[i] == '\0') {
+ return FALSE;
+ }
+ if (!is_token_char(line[i])) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
static void
process_header(tvbuff_t *tvb, int offset, int next_offset,
const guchar *line, int linelen, int colon_offset,
@@ -3092,31 +3122,10 @@ process_header(tvbuff_t *tvb, int offset, int next_offset,
line_end_offset = offset + linelen;
header_len = colon_offset - offset;
- /*
- * Validate the header name. This allows no space between the field name
- * and colon (RFC 7230, Section. 3.2.4).
- */
- gboolean valid_header_name = header_len != 0;
- if (valid_header_name) {
- for (i = 0; i < header_len; i++) {
- /*
- * NUL is not a valid character; treat it specially
- * due to C's notion that strings are NUL-terminated.
- */
- if (line[i] == '\0') {
- valid_header_name = FALSE;
- break;
- }
- if (!is_token_char(line[i])) {
- valid_header_name = FALSE;
- break;
- }
- }
- }
/**
* Not a valid header name? Just add a line plus expert info.
*/
- if (!valid_header_name) {
+ if (!valid_header_name(line, header_len)) {
if (http_type == HTTP_REQUEST) {
hf_index = hf_http_request_line;
} else if (http_type == HTTP_RESPONSE) {