2003-12-23 02:29:11 +00:00
|
|
|
/* req_resp_hdrs.c
|
|
|
|
* Routines handling protocols with a request/response line, headers,
|
2003-12-22 00:57:34 +00:00
|
|
|
* a blank line, and an optional body.
|
|
|
|
*
|
2006-05-21 05:12:17 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
2003-12-22 00:57:34 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2018-02-08 16:59:17 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2003-12-22 00:57:34 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <glib.h>
|
2009-08-26 19:27:49 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2003-12-22 00:57:34 +00:00
|
|
|
#include <epan/packet.h>
|
|
|
|
#include <epan/strutil.h>
|
2018-08-12 11:17:29 +00:00
|
|
|
#include <wsutil/strtoi.h>
|
2003-12-22 00:57:34 +00:00
|
|
|
|
2004-09-29 00:25:05 +00:00
|
|
|
#include <epan/req_resp_hdrs.h>
|
2003-12-22 00:57:34 +00:00
|
|
|
|
|
|
|
/*
|
2003-12-23 02:29:11 +00:00
|
|
|
* Optionally do reassembly of the request/response line, headers, and body.
|
2003-12-22 00:57:34 +00:00
|
|
|
*/
|
|
|
|
gboolean
|
2007-11-19 21:28:08 +00:00
|
|
|
req_resp_hdrs_do_reassembly(tvbuff_t *tvb, const int offset, packet_info *pinfo,
|
2019-05-01 00:58:14 +00:00
|
|
|
const gboolean desegment_headers, const gboolean desegment_body,
|
2023-04-17 16:10:08 +00:00
|
|
|
gboolean desegment_until_fin, int *last_chunk_offset,
|
|
|
|
dissector_table_t streaming_subdissector_table, dissector_handle_t *streaming_chunk_handle)
|
2003-12-22 00:57:34 +00:00
|
|
|
{
|
2019-05-10 16:45:13 +00:00
|
|
|
gint next_offset = offset;
|
2003-12-22 00:57:34 +00:00
|
|
|
gint next_offset_sav;
|
2003-12-24 09:50:54 +00:00
|
|
|
gint length_remaining, reported_length_remaining;
|
2012-12-26 05:57:06 +00:00
|
|
|
int linelen;
|
2004-05-04 06:53:47 +00:00
|
|
|
gchar *header_val;
|
2012-12-26 05:57:06 +00:00
|
|
|
int content_length;
|
2003-12-22 00:57:34 +00:00
|
|
|
gboolean content_length_found = FALSE;
|
2006-09-10 14:03:08 +00:00
|
|
|
gboolean content_type_found = FALSE;
|
2004-04-26 17:10:40 +00:00
|
|
|
gboolean chunked_encoding = FALSE;
|
2010-05-26 11:51:41 +00:00
|
|
|
gchar *line;
|
2012-05-22 06:23:36 +00:00
|
|
|
gchar *content_type = NULL;
|
2023-04-17 16:10:08 +00:00
|
|
|
dissector_handle_t streaming_handle = NULL;
|
|
|
|
gboolean streaming_chunk_mode = FALSE;
|
|
|
|
|
|
|
|
DISSECTOR_ASSERT_HINT((streaming_subdissector_table && streaming_chunk_handle)
|
|
|
|
|| (streaming_subdissector_table == NULL && streaming_chunk_handle == NULL),
|
|
|
|
"The streaming_subdissector_table and streaming_chunk_handle arguments must "
|
|
|
|
"be both given or both NULL.");
|
|
|
|
|
|
|
|
/* Check whether the first line is the beginning of a chunk.
|
|
|
|
* If it is the beginning of a chunk, we assume we are working
|
|
|
|
* in streaming chunk mode. The headers of HTTP request or response
|
|
|
|
* and at least one chunk should have been dissected in the previous
|
|
|
|
* packets and now we are processing subsequent chunks.
|
|
|
|
*/
|
|
|
|
if (desegment_body && streaming_subdissector_table
|
|
|
|
&& starts_with_chunk_size(tvb, offset, pinfo)) {
|
|
|
|
streaming_chunk_mode = TRUE;
|
|
|
|
}
|
2003-12-22 00:57:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do header desegmentation if we've been told to.
|
|
|
|
*
|
|
|
|
* RFC 2616 defines HTTP messages as being either of the
|
|
|
|
* Request or the Response type
|
|
|
|
* (HTTP-message = Request | Response).
|
|
|
|
* Request and Response are defined as:
|
|
|
|
* Request = Request-Line
|
|
|
|
* *(( general-header
|
|
|
|
* | request-header
|
|
|
|
* | entity-header ) CRLF)
|
|
|
|
* CRLF
|
|
|
|
* [ message-body ]
|
|
|
|
* Response = Status-Line
|
|
|
|
* *(( general-header
|
|
|
|
* | response-header
|
|
|
|
* | entity-header ) CRLF)
|
|
|
|
* CRLF
|
|
|
|
* [ message-body ]
|
|
|
|
* that's why we can always assume two consecutive line
|
|
|
|
* endings (we allow CR, LF, or CRLF, as some clients
|
|
|
|
* or servers might not use a full CRLF) to mark the end
|
|
|
|
* of the headers. The worst thing that would happen
|
|
|
|
* otherwise would be the packet not being desegmented
|
|
|
|
* or being interpreted as only headers.
|
|
|
|
*
|
|
|
|
* RFC 2326 says RTSP works the same way; RFC 3261 says SIP
|
|
|
|
* works the same way.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If header desegmentation is activated, check that all
|
|
|
|
* headers are in this tvbuff (search for an empty line
|
|
|
|
* marking end of headers) or request one more byte (we
|
|
|
|
* don't know how many bytes we'll need, so we just ask
|
|
|
|
* for one).
|
2023-04-17 16:10:08 +00:00
|
|
|
*
|
|
|
|
* If tvb starts with chunk size, then we just ignore headers parsing.
|
2003-12-22 00:57:34 +00:00
|
|
|
*/
|
2023-04-17 16:10:08 +00:00
|
|
|
if (!streaming_chunk_mode
|
|
|
|
&& desegment_headers && pinfo->can_desegment) {
|
2003-12-22 00:57:34 +00:00
|
|
|
for (;;) {
|
|
|
|
next_offset_sav = next_offset;
|
|
|
|
|
2003-12-24 09:50:54 +00:00
|
|
|
reported_length_remaining =
|
|
|
|
tvb_reported_length_remaining(tvb, next_offset);
|
|
|
|
|
2003-12-22 00:57:34 +00:00
|
|
|
/*
|
|
|
|
* Request one more byte if there're no
|
2003-12-24 09:50:54 +00:00
|
|
|
* bytes left in the reported data (if there're
|
|
|
|
* bytes left in the reported data, but not in
|
|
|
|
* the available data, requesting more bytes
|
|
|
|
* won't help, as those bytes weren't captured).
|
2003-12-22 00:57:34 +00:00
|
|
|
*/
|
2003-12-24 09:50:54 +00:00
|
|
|
if (reported_length_remaining < 1) {
|
2003-12-22 00:57:34 +00:00
|
|
|
pinfo->desegment_offset = offset;
|
2006-11-07 13:19:31 +00:00
|
|
|
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
|
2003-12-22 00:57:34 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2014-05-14 10:35:30 +00:00
|
|
|
length_remaining = tvb_captured_length_remaining(tvb,
|
2007-11-19 21:28:08 +00:00
|
|
|
next_offset);
|
|
|
|
|
2003-12-22 00:57:34 +00:00
|
|
|
/*
|
|
|
|
* Request one more byte if we cannot find a
|
|
|
|
* header (i.e. a line end).
|
|
|
|
*/
|
|
|
|
linelen = tvb_find_line_end(tvb, next_offset,
|
2014-05-14 10:35:30 +00:00
|
|
|
length_remaining, &next_offset, TRUE);
|
2003-12-24 09:50:54 +00:00
|
|
|
if (linelen == -1 &&
|
|
|
|
length_remaining >= reported_length_remaining) {
|
2003-12-22 00:57:34 +00:00
|
|
|
/*
|
|
|
|
* Not enough data; ask for one more
|
|
|
|
* byte.
|
|
|
|
*/
|
|
|
|
pinfo->desegment_offset = offset;
|
2006-11-07 13:19:31 +00:00
|
|
|
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
|
2003-12-22 00:57:34 +00:00
|
|
|
return FALSE;
|
2009-10-03 03:09:53 +00:00
|
|
|
}
|
|
|
|
|
2007-11-19 21:28:08 +00:00
|
|
|
if (linelen == 0) {
|
2003-12-22 00:57:34 +00:00
|
|
|
/*
|
|
|
|
* We found the end of the headers.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-04-26 17:10:40 +00:00
|
|
|
* Is this a Content-Length or Transfer-Encoding
|
|
|
|
* header? If not, it either means that we are in
|
2003-12-22 00:57:34 +00:00
|
|
|
* a different header line, or that we are
|
|
|
|
* at the end of the headers, or that there
|
|
|
|
* isn't enough data; the two latter cases
|
|
|
|
* have already been handled above.
|
|
|
|
*/
|
|
|
|
if (desegment_body) {
|
2013-05-24 02:31:26 +00:00
|
|
|
/* Optimization to avoid fetching the whole (potentially very long)
|
|
|
|
* line and doing expensive string comparisons if the first
|
|
|
|
* character doesn't match. Shaves about 20% off the load time of
|
|
|
|
* one of my sample files that's HTTP-alike. */
|
|
|
|
guchar first_byte = tvb_get_guint8(tvb, next_offset_sav);
|
|
|
|
if (! (first_byte == 'c' || first_byte == 'C' ||
|
|
|
|
first_byte == 't' || first_byte == 'T')) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2003-12-22 00:57:34 +00:00
|
|
|
/*
|
|
|
|
* Check if we've found Content-Length.
|
|
|
|
*/
|
2021-07-16 15:36:34 +00:00
|
|
|
line = tvb_get_string_enc(pinfo->pool, tvb, next_offset_sav, linelen, ENC_UTF_8|ENC_NA);
|
2010-05-26 11:51:41 +00:00
|
|
|
if (g_ascii_strncasecmp(line, "Content-Length:", 15) == 0) {
|
2018-08-12 11:17:29 +00:00
|
|
|
/* SSTP sets 2^64 as length, but does not really have such a
|
|
|
|
* large payload. Since the current tvb APIs are limited to
|
|
|
|
* 2^31-1 bytes, ignore large values we cannot handle. */
|
|
|
|
header_val = g_strstrip(line + 15);
|
|
|
|
if (ws_strtoi32(header_val, NULL, &content_length) && content_length >= 0)
|
2003-12-22 00:57:34 +00:00
|
|
|
content_length_found = TRUE;
|
2010-05-26 11:51:41 +00:00
|
|
|
} else if (g_ascii_strncasecmp(line, "Content-Type:", 13) == 0) {
|
2006-09-10 14:03:08 +00:00
|
|
|
content_type_found = TRUE;
|
2012-05-22 06:23:36 +00:00
|
|
|
content_type = line+13;
|
|
|
|
while (*content_type == ' ') {
|
|
|
|
content_type++;
|
|
|
|
}
|
2023-04-17 16:10:08 +00:00
|
|
|
g_strchomp(content_type);
|
|
|
|
if (streaming_subdissector_table) {
|
|
|
|
streaming_handle = dissector_get_string_handle(streaming_subdissector_table, content_type);
|
|
|
|
}
|
2010-05-26 11:51:41 +00:00
|
|
|
} else if (g_ascii_strncasecmp( line, "Transfer-Encoding:", 18) == 0) {
|
2004-04-26 17:10:40 +00:00
|
|
|
/*
|
|
|
|
* Find out if this Transfer-Encoding is
|
2022-07-17 21:10:43 +00:00
|
|
|
* chunked. It should be, since the
|
|
|
|
* other types aren't really used, but
|
|
|
|
* RFC 7230 defines some.
|
|
|
|
* (RFC 3261 says "chunked" MUST NOT be
|
|
|
|
* used for SIP, and RFCs 2326 and 7826
|
|
|
|
* say the same for RTSP, but handle it
|
|
|
|
* anyway.)
|
2004-04-26 17:10:40 +00:00
|
|
|
*/
|
2004-05-04 06:53:47 +00:00
|
|
|
gchar *p;
|
2007-11-19 21:28:08 +00:00
|
|
|
guint len;
|
2004-04-26 17:10:40 +00:00
|
|
|
|
2010-05-26 11:51:41 +00:00
|
|
|
header_val = line+18;
|
2004-05-04 06:53:47 +00:00
|
|
|
p = header_val;
|
2009-04-08 16:50:20 +00:00
|
|
|
len = (guint) strlen(header_val);
|
2004-05-04 06:53:47 +00:00
|
|
|
/* Skip white space */
|
|
|
|
while (p < header_val + len &&
|
|
|
|
(*p == ' ' || *p == '\t'))
|
|
|
|
p++;
|
|
|
|
if (p <= header_val + len) {
|
strcasecmp(), strncasecmp(), g_strcasecmp(), and g_strncasecmp() delenda
est. Use g_ascii_strcasecmp() and g_ascii_strncasecmp(), and supply our
own versions if they're missing from GLib (as is the case with GLib
1.x).
In the code to build the list of named fields for Diameter, don't use
g_strdown(); do our own g_ascii_-style upper-case to lower-case mapping
in the hash function and use g_ascii_strcasecmp() in the compare
function.
We do this because there is no guarantee that toupper(), tolower(), and
functions that use them will, for example, map between "I" and "i" in
all locales; in Turkish locales, for example, there are, in both
upper case and lower case, versions of "i" with and without a dot, and
the upper-case version of "i" is "I"-with-a-dot and the lower-case
version of "I" is "i"-without-a-dot. This causes strings that should
match not to match.
This finishes fixing bug 2010 - an earlier checkin prevented the crash
(as there are other ways to produce the same crash, e.g. a bogus
dictionary.xml file), but didn't fix the case-insensitive string matching.
svn path=/trunk/; revision=23623
2007-11-27 18:52:51 +00:00
|
|
|
if (g_ascii_strncasecmp(p, "chunked", 7)
|
2004-05-04 06:53:47 +00:00
|
|
|
== 0) {
|
|
|
|
/*
|
|
|
|
* Don't bother looking
|
|
|
|
* for extensions;
|
|
|
|
* since we don't
|
|
|
|
* understand them,
|
|
|
|
* they should be
|
|
|
|
* ignored.
|
|
|
|
*/
|
|
|
|
chunked_encoding = TRUE;
|
2004-04-26 17:10:40 +00:00
|
|
|
}
|
|
|
|
}
|
2003-12-22 00:57:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-17 16:10:08 +00:00
|
|
|
if (streaming_chunk_mode) {
|
|
|
|
/* the tvb starts with chunk size without HTTP headers */
|
|
|
|
chunked_encoding = TRUE;
|
|
|
|
} else if (desegment_body && chunked_encoding && streaming_handle && streaming_chunk_handle) {
|
|
|
|
streaming_chunk_mode = TRUE;
|
|
|
|
*streaming_chunk_handle = streaming_handle;
|
|
|
|
}
|
|
|
|
|
2003-12-22 00:57:34 +00:00
|
|
|
/*
|
|
|
|
* The above loop ends when we reached the end of the headers, so
|
2004-04-26 17:10:40 +00:00
|
|
|
* there should be content_length bytes after the 4 terminating bytes
|
2003-12-22 00:57:34 +00:00
|
|
|
* and next_offset points to after the end of the headers.
|
2022-07-17 21:10:43 +00:00
|
|
|
*
|
|
|
|
* XXX: If desegment_headers is FALSE but desegment_body is TRUE,
|
|
|
|
* then for HTTP Responses we will always set to DESEGMENT_UNTIL_FIN,
|
|
|
|
* which is probably not what we want.
|
2003-12-22 00:57:34 +00:00
|
|
|
*/
|
2004-04-26 17:10:40 +00:00
|
|
|
if (desegment_body) {
|
2013-09-05 15:48:50 +00:00
|
|
|
if (chunked_encoding) {
|
2004-04-26 17:10:40 +00:00
|
|
|
/*
|
|
|
|
* This data is chunked, so we need to keep pulling
|
|
|
|
* data until we reach the end of the stream, or a
|
|
|
|
* zero sized chunk.
|
|
|
|
*
|
2023-04-17 16:10:08 +00:00
|
|
|
* But if streaming_chunk_mode is TRUE,
|
|
|
|
* we will just pull one more chunk if the end of
|
|
|
|
* this tvb is in middle of a chunk. Because we want
|
|
|
|
* to dissect chunks with subdissector as soon as
|
|
|
|
* possible.
|
|
|
|
*
|
2004-04-26 17:10:40 +00:00
|
|
|
* XXX
|
|
|
|
* This doesn't bother with trailing headers; I don't
|
|
|
|
* think they are really used, and we'd have to use
|
|
|
|
* is_http_request_or_reply() to determine if it was
|
|
|
|
* a trailing header, or the start of a new response.
|
|
|
|
*/
|
|
|
|
gboolean done_chunking = FALSE;
|
2022-07-17 21:10:43 +00:00
|
|
|
if (last_chunk_offset != NULL && *last_chunk_offset) {
|
|
|
|
next_offset = offset + *last_chunk_offset;
|
|
|
|
}
|
2004-04-26 17:10:40 +00:00
|
|
|
|
|
|
|
while (!done_chunking) {
|
2009-10-01 14:38:37 +00:00
|
|
|
guint chunk_size = 0;
|
|
|
|
gint chunk_offset = 0;
|
2004-04-26 17:10:40 +00:00
|
|
|
gchar *chunk_string = NULL;
|
|
|
|
gchar *c = NULL;
|
|
|
|
|
|
|
|
reported_length_remaining =
|
|
|
|
tvb_reported_length_remaining(tvb,
|
|
|
|
next_offset);
|
|
|
|
|
2023-04-17 16:10:08 +00:00
|
|
|
if (reported_length_remaining == 0 && streaming_chunk_mode) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2004-04-26 17:10:40 +00:00
|
|
|
if (reported_length_remaining < 1) {
|
|
|
|
pinfo->desegment_offset = offset;
|
2007-08-21 20:57:52 +00:00
|
|
|
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
|
2004-04-26 17:10:40 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2014-05-14 10:35:30 +00:00
|
|
|
length_remaining = tvb_captured_length_remaining(tvb,
|
2007-11-19 21:28:08 +00:00
|
|
|
next_offset);
|
|
|
|
|
2004-04-26 17:10:40 +00:00
|
|
|
linelen = tvb_find_line_end(tvb, next_offset,
|
2014-05-14 10:35:30 +00:00
|
|
|
length_remaining, &chunk_offset, TRUE);
|
2004-04-26 17:10:40 +00:00
|
|
|
|
|
|
|
if (linelen == -1 &&
|
|
|
|
length_remaining >=
|
|
|
|
reported_length_remaining) {
|
|
|
|
pinfo->desegment_offset = offset;
|
2007-08-21 20:57:52 +00:00
|
|
|
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
|
2004-04-26 17:10:40 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2009-10-03 03:09:53 +00:00
|
|
|
|
2004-04-26 17:10:40 +00:00
|
|
|
/* We have a line with the chunk size in it.*/
|
2022-07-17 21:10:43 +00:00
|
|
|
|
|
|
|
/* Save off the offset so we can skip this work next time.
|
|
|
|
* Use a relative offset, because we might call this
|
|
|
|
* with a different offset with a reassembled tvb.
|
|
|
|
*/
|
|
|
|
if (last_chunk_offset != NULL) {
|
|
|
|
*last_chunk_offset = next_offset - offset;
|
|
|
|
}
|
|
|
|
|
2021-07-16 15:36:34 +00:00
|
|
|
chunk_string = tvb_get_string_enc(pinfo->pool, tvb, next_offset,
|
2015-11-26 20:10:06 +00:00
|
|
|
linelen, ENC_ASCII);
|
2004-04-26 17:10:40 +00:00
|
|
|
c = chunk_string;
|
|
|
|
|
2003-12-24 09:50:54 +00:00
|
|
|
/*
|
HTTP: Fix chunking detection for certain request methods
Prior to commit 9a4c503eec4067096ecee30c6554319ef50793c6, we
only looked at a line to find the chunk size when we had definitively
seen a "Transfer-Encoding: chunked" header at the beginning.
Now, the dissection looks for chunk sizes at the start of any
line it is initially fed, which may, among other things, be
quite likely to be a request method.
That means that we cannot simply use sscanf and look for a "%x"
conversion specifier, which returns a positive result for any
string that happens to start with a what looks like a hexadecimal
number, notably Microsoft System Center Configuration Manager's
CCM_POST, also BCOPY from WebDAV, maybe others.
Instead, strip off the extensions (both ';' and any bad whitespace)
and use ws_hexstrtou32 in strict mode instead.
2023-11-03 03:20:46 +00:00
|
|
|
* We don't care about the extensions (including optional
|
|
|
|
* BWS, see RFC 9112 7.1.1)
|
2003-12-24 09:50:54 +00:00
|
|
|
*/
|
HTTP: Fix chunking detection for certain request methods
Prior to commit 9a4c503eec4067096ecee30c6554319ef50793c6, we
only looked at a line to find the chunk size when we had definitively
seen a "Transfer-Encoding: chunked" header at the beginning.
Now, the dissection looks for chunk sizes at the start of any
line it is initially fed, which may, among other things, be
quite likely to be a request method.
That means that we cannot simply use sscanf and look for a "%x"
conversion specifier, which returns a positive result for any
string that happens to start with a what looks like a hexadecimal
number, notably Microsoft System Center Configuration Manager's
CCM_POST, also BCOPY from WebDAV, maybe others.
Instead, strip off the extensions (both ';' and any bad whitespace)
and use ws_hexstrtou32 in strict mode instead.
2023-11-03 03:20:46 +00:00
|
|
|
if ((c = strpbrk(c, "; \t"))) {
|
2004-04-26 17:10:40 +00:00
|
|
|
*c = '\0';
|
|
|
|
}
|
|
|
|
|
HTTP: Fix chunking detection for certain request methods
Prior to commit 9a4c503eec4067096ecee30c6554319ef50793c6, we
only looked at a line to find the chunk size when we had definitively
seen a "Transfer-Encoding: chunked" header at the beginning.
Now, the dissection looks for chunk sizes at the start of any
line it is initially fed, which may, among other things, be
quite likely to be a request method.
That means that we cannot simply use sscanf and look for a "%x"
conversion specifier, which returns a positive result for any
string that happens to start with a what looks like a hexadecimal
number, notably Microsoft System Center Configuration Manager's
CCM_POST, also BCOPY from WebDAV, maybe others.
Instead, strip off the extensions (both ';' and any bad whitespace)
and use ws_hexstrtou32 in strict mode instead.
2023-11-03 03:20:46 +00:00
|
|
|
if (!ws_hexstrtou32(chunk_string, NULL, &chunk_size)) {
|
2004-04-26 17:10:40 +00:00
|
|
|
/* We couldn't get the chunk size,
|
|
|
|
* so stop trying.
|
|
|
|
*/
|
|
|
|
return TRUE;
|
|
|
|
}
|
2015-04-30 22:21:00 +00:00
|
|
|
if (chunk_size > 1U<<31) {
|
2009-10-03 03:09:53 +00:00
|
|
|
/* Chunk size is unreasonable. */
|
|
|
|
/* XXX What /is/ reasonable? */
|
|
|
|
return TRUE;
|
|
|
|
}
|
2004-04-26 17:10:40 +00:00
|
|
|
|
|
|
|
if (chunk_size == 0) {
|
|
|
|
/*
|
|
|
|
* This is the last chunk. Let's pull in the
|
|
|
|
* trailing CRLF.
|
|
|
|
*/
|
|
|
|
linelen = tvb_find_line_end(tvb,
|
2014-05-14 10:35:30 +00:00
|
|
|
chunk_offset, length_remaining, &chunk_offset, TRUE);
|
2009-10-03 03:09:53 +00:00
|
|
|
|
2004-04-26 17:10:40 +00:00
|
|
|
if (linelen == -1 &&
|
|
|
|
length_remaining >=
|
|
|
|
reported_length_remaining) {
|
|
|
|
pinfo->desegment_offset = offset;
|
2007-08-21 20:57:52 +00:00
|
|
|
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
|
2004-04-26 17:10:40 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pinfo->desegment_offset = chunk_offset;
|
|
|
|
pinfo->desegment_len = 0;
|
|
|
|
done_chunking = TRUE;
|
|
|
|
} else {
|
2009-10-03 03:09:53 +00:00
|
|
|
/*
|
2004-04-26 17:10:40 +00:00
|
|
|
* Skip to the next chunk if we
|
2009-10-03 03:09:53 +00:00
|
|
|
* already have it
|
2004-04-26 17:10:40 +00:00
|
|
|
*/
|
|
|
|
if (reported_length_remaining >
|
2009-10-01 15:03:02 +00:00
|
|
|
(gint) chunk_size) {
|
2009-10-03 03:09:53 +00:00
|
|
|
|
|
|
|
next_offset = chunk_offset
|
2004-04-26 17:10:40 +00:00
|
|
|
+ chunk_size + 2;
|
|
|
|
} else {
|
2009-10-03 03:09:53 +00:00
|
|
|
/*
|
2004-04-26 17:10:40 +00:00
|
|
|
* Fetch this chunk, plus the
|
|
|
|
* trailing CRLF.
|
2009-10-03 03:09:53 +00:00
|
|
|
*/
|
2023-04-17 16:10:08 +00:00
|
|
|
if (streaming_chunk_mode) {
|
|
|
|
gint size_remaining = chunk_size + linelen + 4 - reported_length_remaining;
|
|
|
|
if (size_remaining == 0) {
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
pinfo->desegment_offset = offset;
|
|
|
|
pinfo->desegment_len = size_remaining;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
pinfo->desegment_offset = offset;
|
|
|
|
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-04-26 17:10:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-12-24 09:50:54 +00:00
|
|
|
}
|
2013-09-05 15:48:50 +00:00
|
|
|
} else if (content_length_found) {
|
|
|
|
if (content_length >= 128*1024) { /* MS-RPCH stipulate that the content-length must be between 128K and 2G */
|
|
|
|
gchar *tmp;
|
|
|
|
if (content_type_found &&
|
|
|
|
strncmp(content_type, "application/rpc", 15) == 0) {
|
|
|
|
/* It looks like a RPC_IN_DATA request or a RPC_OUT_DATA response
|
|
|
|
* in which the content-length is meaningless
|
|
|
|
*/
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/* Following sizeof will return the length of the string + \0 we need to not count it*/
|
2021-07-16 15:36:34 +00:00
|
|
|
tmp = tvb_get_string_enc(pinfo->pool, tvb, 0, sizeof("RPC_OUT_DATA") - 1, ENC_ASCII);
|
2013-09-05 15:48:50 +00:00
|
|
|
if ((strncmp(tmp, "RPC_IN_DATA", sizeof("RPC_IN_DATA") - 1) == 0) ||
|
|
|
|
(strncmp(tmp, "RPC_OUT_DATA", sizeof("RPC_OUT_DATA") - 1) == 0)) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* next_offset has been set to the end of the headers */
|
|
|
|
if (!tvb_bytes_exist(tvb, next_offset, content_length)) {
|
2014-05-14 10:35:30 +00:00
|
|
|
length_remaining = tvb_captured_length_remaining(tvb,
|
2013-09-05 15:48:50 +00:00
|
|
|
next_offset);
|
|
|
|
reported_length_remaining =
|
|
|
|
tvb_reported_length_remaining(tvb, next_offset);
|
|
|
|
if (length_remaining < reported_length_remaining) {
|
|
|
|
/*
|
|
|
|
* It's a waste of time asking for more
|
|
|
|
* data, because that data wasn't captured.
|
|
|
|
*/
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
if (length_remaining == -1)
|
|
|
|
length_remaining = 0;
|
|
|
|
pinfo->desegment_offset = offset;
|
|
|
|
pinfo->desegment_len =
|
|
|
|
content_length - length_remaining;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2019-05-01 00:58:14 +00:00
|
|
|
} else if (desegment_until_fin && pinfo->can_desegment) {
|
|
|
|
/*
|
|
|
|
* No Content-Length nor Transfer-Encoding headers are
|
|
|
|
* found. For HTTP requests, there is definitely no
|
|
|
|
* body (case 6 of RFC 7230, Section 3.3.3.). For HTTP
|
|
|
|
* responses, the message body length runs until the end
|
|
|
|
* of the connection (case 7).
|
|
|
|
*
|
|
|
|
* Protocols like RTSP treat absence of Content-Length
|
|
|
|
* as 0, so do not request more segments either.
|
2006-09-10 14:03:08 +00:00
|
|
|
*/
|
2014-05-14 10:35:30 +00:00
|
|
|
length_remaining = tvb_captured_length_remaining(tvb, next_offset);
|
2006-09-10 14:03:08 +00:00
|
|
|
reported_length_remaining = tvb_reported_length_remaining(tvb, next_offset);
|
|
|
|
if (length_remaining < reported_length_remaining) {
|
|
|
|
/*
|
|
|
|
* It's a waste of time asking for more
|
|
|
|
* data, because that data wasn't captured.
|
|
|
|
*/
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pinfo->desegment_offset = offset;
|
|
|
|
pinfo->desegment_len = DESEGMENT_UNTIL_FIN;
|
|
|
|
|
|
|
|
return FALSE;
|
2003-12-22 00:57:34 +00:00
|
|
|
}
|
2004-04-26 17:10:40 +00:00
|
|
|
|
2003-12-22 00:57:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No further desegmentation needed.
|
|
|
|
*/
|
|
|
|
return TRUE;
|
|
|
|
}
|
2013-05-24 02:31:26 +00:00
|
|
|
|
|
|
|
/*
|
2019-07-26 18:43:17 +00:00
|
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
2013-05-24 02:31:26 +00:00
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 8
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: t
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
|
|
|
* :indentSize=8:tabSize=8:noTabs=false:
|
|
|
|
*/
|