/builds/wireshark/wireshark/epan/dissectors/packet-http.c (2024)

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-http.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-18/lib/clang/18 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/epan -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-error=stringop-overflow= -Wno-error=deprecated-declarations -Wno-format-truncation -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -analyzer-output=html -dwarf-debug-flags /usr/lib/llvm-18/bin/clang -### --analyze -x c -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/epan -fvisibility=hidden -fno-strict-overflow -fexcess-precision=fast -Wno-error=stringop-overflow= -Wno-error=deprecated-declarations -Wno-format-truncation -fdiagnostics-color=always -Wno-pointer-sign -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=gnu11 -fPIC /builds/wireshark/wireshark/epan/dissectors/packet-http.c -o /builds/wireshark/wireshark/sbout/2024-08-11-100246-3329-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2024-08-11-100246-3329-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-http.c

1/* packet-http.c2 * Routines for HTTP packet disassembly3 * RFC 1945 (HTTP/1.0)4 * RFC 2616 (HTTP/1.1)5 *6 * Guy Harris <[emailprotected]>7 *8 * Copyright 2017, Eugene Adell <[emailprotected]>9 * Copyright 2004, Jerry Talkington <[emailprotected]>10 * Copyright 2002, Tim Potter <[emailprotected]>11 * Copyright 1999, Andrew Tridgell <[emailprotected]>12 *13 * Wireshark - Network traffic analyzer14 * By Gerald Combs <[emailprotected]>15 * Copyright 1998 Gerald Combs16 *17 * SPDX-License-Identifier: GPL-2.0-or-later18 */19 20#include "config.h"21 22#include <errno(*__errno_location ()).h>23 24#include <epan/packet.h>25#include <epan/prefs.h>26#include <epan/expert.h>27#include <epan/follow.h>28#include <epan/addr_resolv.h>29#include <epan/uat.h>30#include <epan/charsets.h>31#include <epan/strutil.h>32#include <epan/stats_tree.h>33#include <epan/to_str.h>34#include <epan/req_resp_hdrs.h>35#include <epan/proto_data.h>36#include <epan/export_object.h>37#include <epan/exceptions.h>38#include <epan/show_exception.h>39#include <epan/unit_strings.h>40#include <glib.h>41#include "packet-http.h"42#include "packet-http2.h"43#include "packet-tcp.h"44#include "packet-tls.h"45#include "packet-acdr.h"46#include "packet-media-type.h"47 48#include <ui/tap-credentials.h>49 50void proto_register_http(void);51void proto_reg_handoff_http(void);52void proto_register_message_http(void);53void proto_reg_handoff_message_http(void);54 55static int http_tap;56static int http_eo_tap;57static int http_follow_tap;58static int credentials_tap;59 60static int proto_http;61static int proto_http2;62static int proto_ssdp;63static int hf_http_notification;64static int hf_http_response;65static int hf_http_request;66static int hf_http_response_line;67static int hf_http_request_line;68static int hf_http_basic;69static int hf_http_citrix;70static int hf_http_citrix_user;71static int hf_http_citrix_domain;72static int hf_http_citrix_passwd;73static int hf_http_citrix_session;74static int hf_http_request_method;75static int hf_http_request_uri;76static int hf_http_request_full_uri;77static int hf_http_request_path;78static int hf_http_request_path_segment;79static int hf_http_request_query;80static int hf_http_request_query_parameter;81static int hf_http_request_version;82static int hf_http_response_version;83static int hf_http_response_code;84static int hf_http_response_code_desc;85static int hf_http_response_phrase;86static int hf_http_authorization;87static int hf_http_proxy_authenticate;88static int hf_http_proxy_authorization;89static int hf_http_proxy_connect_host;90static int hf_http_proxy_connect_port;91static int hf_http_www_authenticate;92static int hf_http_content_type;93static int hf_http_content_length_header;94static int hf_http_content_length;95static int hf_http_content_encoding;96static int hf_http_transfer_encoding;97static int hf_http_upgrade;98static int hf_http_user_agent;99static int hf_http_host;100static int hf_http_range;101static int hf_http_content_range;102static int hf_http_connection;103static int hf_http_cookie;104static int hf_http_cookie_pair;105static int hf_http_accept;106static int hf_http_referer;107static int hf_http_accept_language;108static int hf_http_accept_encoding;109static int hf_http_date;110static int hf_http_cache_control;111static int hf_http_server;112static int hf_http_location;113static int hf_http_sec_websocket_accept;114static int hf_http_sec_websocket_extensions;115static int hf_http_sec_websocket_key;116static int hf_http_sec_websocket_protocol;117static int hf_http_sec_websocket_version;118static int hf_http_set_cookie;119static int hf_http_last_modified;120static int hf_http_x_forwarded_for;121static int hf_http_http2_settings;122static int hf_http_request_in;123static int hf_http_response_in;124/*static int hf_http_next_request_in;125static int hf_http_next_response_in;126static int hf_http_prev_request_in;127static int hf_http_prev_response_in; */128static int hf_http_time;129static int hf_http_chunk_size;130static int hf_http_chunk_data;131static int hf_http_chunk_boundary;132static int hf_http_chunked_trailer_part;133static int hf_http_file_data;134static int hf_http_unknown_header;135static int hf_http_http2_settings_uri;136 137static int ett_http;138static int ett_http_ntlmssp;139static int ett_http_kerberos;140static int ett_http_request;141static int ett_http_request_uri;142static int ett_http_request_path;143static int ett_http_request_query;144static int ett_http_chunked_response;145static int ett_http_chunk_data;146static int ett_http_encoded_entity;147static int ett_http_header_item;148static int ett_http_http2_settings_item;149 150static expert_field ei_http_te_and_length;151static expert_field ei_http_te_unknown;152static expert_field ei_http_subdissector_failed;153static expert_field ei_http_tls_port;154static expert_field ei_http_leading_crlf;155static expert_field ei_http_excess_data;156static expert_field ei_http_bad_header_name;157static expert_field ei_http_decompression_failed;158static expert_field ei_http_decompression_disabled;159 160static dissector_handle_t http_handle;161static dissector_handle_t http_tcp_handle;162static dissector_handle_t http_tls_handle;163static dissector_handle_t http_sctp_handle;164 165static dissector_handle_t media_handle;166static dissector_handle_t http2_handle;167static dissector_handle_t sstp_handle;168static dissector_handle_t ntlmssp_handle;169static dissector_handle_t gssapi_handle;170 171/* RFC 3986 Ch 2.2 Reserved characters*/172/* patterns used for tvb_ws_mempbrk_pattern_uint8 */173static ws_mempbrk_pattern pbrk_gen_delims;174static ws_mempbrk_pattern pbrk_sub_delims;175 176/* reassembly table for streaming chunk mode */177static reassembly_table http_streaming_reassembly_table;178 179REASSEMBLE_ITEMS_DEFINE(http_body, "HTTP Chunked Body")static int ett_http_body_fragment; static int ett_http_body_fragments
; static int hf_http_body_fragments; static int hf_http_body_fragment
; static int hf_http_body_fragment_overlap; static int hf_http_body_fragment_overlap_conflicts
; static int hf_http_body_fragment_multiple_tails; static int
hf_http_body_fragment_too_long_fragment; static int hf_http_body_fragment_error
; static int hf_http_body_fragment_count; static int hf_http_body_reassembled_in
; static int hf_http_body_reassembled_length; static int hf_http_body_reassembled_data
; static int hf_http_body_segment; static const fragment_items
http_body_fragment_items = { &ett_http_body_fragment, &
ett_http_body_fragments, &hf_http_body_fragments, &hf_http_body_fragment
, &hf_http_body_fragment_overlap, &hf_http_body_fragment_overlap_conflicts
, &hf_http_body_fragment_multiple_tails, &hf_http_body_fragment_too_long_fragment
, &hf_http_body_fragment_error, &hf_http_body_fragment_count
, &hf_http_body_reassembled_in, &hf_http_body_reassembled_length
, &hf_http_body_reassembled_data, "HTTP Chunked Body" " fragments"
}
;180 181/* HTTP chunk virtual frame number (similar to HTTP2 frame num) */182#define get_http_chunk_frame_numget_virtual_frame_num64 get_virtual_frame_num64183 184/* Stuff for generation/handling of fields for custom HTTP headers */185typedef struct _header_field_t {186char* header_name;187char* header_desc;188} header_field_t;189 190static header_field_t* header_fields;191static unsigned num_header_fields;192 193static GHashTable* header_fields_hash;194static hf_register_info* dynamic_hf;195static unsigned dynamic_hf_size;196 197static bool_Bool198header_fields_update_cb(void *r, char **err)199{200header_field_t *rec = (header_field_t *)r;201char c;202 203if (rec->header_name == NULL((void*)0)) {204*err = g_strdup("Header name can't be empty")g_strdup_inline ("Header name can't be empty");205return false0;206}207 208g_strstrip(rec->header_name)g_strchomp (g_strchug (rec->header_name));209if (rec->header_name[0] == 0) {210*err = g_strdup("Header name can't be empty")g_strdup_inline ("Header name can't be empty");211return false0;212}213 214/* Check for invalid characters (to avoid asserting out when215 * registering the field).216 */217c = proto_check_field_name(rec->header_name);218if (c) {219*err = ws_strdup_printf("Header name can't contain '%c'", c)wmem_strdup_printf(((void*)0), "Header name can't contain '%c'"
, c)
;220return false0;221}222 223*err = NULL((void*)0);224return true1;225}226 227static void *228header_fields_copy_cb(void* n, const void* o, size_t siz _U___attribute__((unused)))229{230header_field_t* new_rec = (header_field_t*)n;231const header_field_t* old_rec = (const header_field_t*)o;232 233new_rec->header_name = g_strdup(old_rec->header_name)g_strdup_inline (old_rec->header_name);234new_rec->header_desc = g_strdup(old_rec->header_desc)g_strdup_inline (old_rec->header_desc);235 236return new_rec;237}238 239static void240header_fields_free_cb(void*r)241{242header_field_t* rec = (header_field_t*)r;243 244g_free(rec->header_name);245g_free(rec->header_desc);246}247 248UAT_CSTRING_CB_DEF(header_fields, header_name, header_field_t)static void header_fields_header_name_set_cb(void* rec, const
char* buf, unsigned len, const void* u1 __attribute__((unused
)), const void* u2 __attribute__((unused))) { char* new_buf =
g_strndup(buf,len); g_free((((header_field_t*)rec)->header_name
)); (((header_field_t*)rec)->header_name) = new_buf; } static
void header_fields_header_name_tostr_cb(void* rec, char** out_ptr
, unsigned* out_len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { if (((header_field_t*)rec
)->header_name ) { *out_ptr = g_strdup_inline ((((header_field_t
*)rec)->header_name)); *out_len = (unsigned)strlen((((header_field_t
*)rec)->header_name)); } else { *out_ptr = g_strdup_inline
(""); *out_len = 0; } }
249UAT_CSTRING_CB_DEF(header_fields, header_desc, header_field_t)static void header_fields_header_desc_set_cb(void* rec, const
char* buf, unsigned len, const void* u1 __attribute__((unused
)), const void* u2 __attribute__((unused))) { char* new_buf =
g_strndup(buf,len); g_free((((header_field_t*)rec)->header_desc
)); (((header_field_t*)rec)->header_desc) = new_buf; } static
void header_fields_header_desc_tostr_cb(void* rec, char** out_ptr
, unsigned* out_len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { if (((header_field_t*)rec
)->header_desc ) { *out_ptr = g_strdup_inline ((((header_field_t
*)rec)->header_desc)); *out_len = (unsigned)strlen((((header_field_t
*)rec)->header_desc)); } else { *out_ptr = g_strdup_inline
(""); *out_len = 0; } }
250 251/*252 * desegmentation of HTTP headers253 * (when we are over TCP or another protocol providing the desegmentation API)254 */255static bool_Bool http_desegment_headers = true1;256 257/*258 * desegmentation of HTTP bodies259 * (when we are over TCP or another protocol providing the desegmentation API)260 * TODO let the user filter on content-type the bodies he wants desegmented261 */262static bool_Bool http_desegment_body = true1;263 264/*265 * De-chunking of content-encoding: chunk entity bodies.266 */267static bool_Bool http_dechunk_body = true1;268 269/*270 * Decompression of zlib or brotli encoded entities.271 */272#if defined(HAVE_ZLIB1)|| defined(HAVE_ZLIBNG) || defined(HAVE_BROTLI1)273static bool_Bool http_decompress_body = true1;274#endif275 276/*277 * Extra checks for valid ASCII data in HTTP headers.278 */279static bool_Bool http_check_ascii_headers = false0;280 281/* Simple Service Discovery Protocol282 * SSDP is implemented atop HTTP (yes, it really *does* run over UDP).283 * SSDP is the discovery protocol of Universal Plug and Play284 * UPnP http://www.upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf285 */286#define TCP_PORT_SSDP19001900287#define UDP_PORT_SSDP19001900288 289/*290 * TCP and TLS ports291 *292 * 2710 is the XBT BitTorrent tracker293 */294 295#define TCP_DEFAULT_RANGE"80,3128,3132,5985,8080,8088,11371,1900,2869,2710" "80,3128,3132,5985,8080,8088,11371,1900,2869,2710"296#define SCTP_DEFAULT_RANGE"80" "80"297#define TLS_DEFAULT_RANGE"443" "443"298 299static range_t *global_http_tls_range;300 301static range_t *http_tcp_range;302static range_t *http_sctp_range;303static range_t *http_tls_range;304 305typedef void (*ReqRespDissector)(packet_info*, tvbuff_t*, proto_tree*, int, const unsigned char*,306 const unsigned char*, http_conv_t *, http_req_res_t *);307 308/**309 * Transfer codings from310 * https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#transfer-coding311 * Note: chunked encoding is handled separately.312 */313typedef enum _http_transfer_coding {314HTTP_TE_NONE, /* Dummy value for header which is not set */315/* HTTP_TE_CHUNKED, */316HTTP_TE_COMPRESS,317HTTP_TE_DEFLATE,318HTTP_TE_GZIP,319HTTP_TE_IDENTITY,320HTTP_TE_UNKNOWN, /* Header was set, but no valid name was found */321} http_transfer_coding;322 323/*324 * Structure holding information from headers needed by main325 * HTTP dissector code.326 */327typedef struct {328char*content_type;329char*content_type_parameters;330bool_Bool have_content_length;331int64_t content_length;332char *content_encoding;333bool_Bool transfer_encoding_chunked;334http_transfer_coding transfer_encoding;335char *upgrade;336} headers_t;337 338/* request or response streaming reassembly data */339typedef struct {340/* reassembly information only for request or response with chunked and streaming data */341streaming_reassembly_info_t* streaming_reassembly_info;342/* subdissector handler for request or response with chunked and streaming data */343dissector_handle_t streaming_handle;344/* message being passed to subdissector if the request or response has chunked and streaming data */345media_content_info_t* content_info;346headers_t* main_headers;347} http_streaming_reassembly_data_t;348 349/* http request or response private data */350typedef struct {351/* direction of request message */352int req_fwd_flow;353/* request or response streaming reassembly data */354http_streaming_reassembly_data_t* req_streaming_reassembly_data;355http_streaming_reassembly_data_t* res_streaming_reassembly_data;356} http_req_res_private_data_t;357 358 typedef struct _request_trans_t {359uint64_t first_range_num;360uint32_t req_frame;361nstime_t abs_time;362char *request_uri;363} request_trans_t;364 365 typedef struct _match_trans_t {366uint32_t req_frame;367uint32_t resp_frame;368nstime_t delta_time;369char *request_uri;370char *http_host;371} match_trans_t;372 373static int parse_http_status_code(const unsigned char *line, const unsigned char *lineend);374static int is_http_request_or_reply(packet_info *pinfo, const char *data, int linelen,375 media_container_type_t *type, ReqRespDissector376 *reqresp_dissector, http_conv_t *conv_data);377static unsigned chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,378proto_tree *tree, int offset);379static bool_Bool valid_header_name(const unsigned char *line, int header_len);380static bool_Bool process_header(tvbuff_t *tvb, int offset, int next_offset,381 const unsigned char *line, int linelen, int colon_offset,382 packet_info *pinfo, proto_tree *tree,383 headers_t *eh_ptr, http_conv_t *conv_data,384 media_container_type_t http_type, wmem_map_t *header_value_map, bool_Bool streaming_chunk_mode);385static int find_header_hf_value(tvbuff_t *tvb, int offset, unsigned header_len);386static bool_Bool check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb,387 packet_info *pinfo, char *value);388static bool_Bool check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb,389 packet_info *pinfo, char *value);390static bool_Bool check_auth_digest(proto_item* hdr_item, tvbuff_t* tvb, packet_info* pinfo _U___attribute__((unused)), char* value, int offset, int len);391static bool_Bool check_auth_citrixbasic(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo,392 char *value, int offset);393static bool_Bool check_auth_kerberos(proto_item *hdr_item, tvbuff_t *tvb,394 packet_info *pinfo, const char *value);395 396static dissector_table_t port_subdissector_table;397static dissector_table_t media_type_subdissector_table;398static dissector_table_t streaming_content_type_dissector_table;399static dissector_table_t upgrade_subdissector_table;400static heur_dissector_list_t heur_subdissector_list;401 402static tap_packet_status403http_eo_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *data, tap_flags_t flags _U___attribute__((unused)))404{405export_object_list_t *object_list = (export_object_list_t *)tapdata;406const http_eo_t *eo_info = (const http_eo_t *)data;407export_object_entry_t *entry;408 409if(eo_info) { /* We have data waiting for us */410/* These values will be freed when the Export Object window411 * is closed. */412entry = g_new(export_object_entry_t, 1)((export_object_entry_t *) g_malloc_n ((1), sizeof (export_object_entry_t
)))
;413 414entry->pkt_num = pinfo->num;415/* XXX: Should this remove the port, if any? It's only416 * for display, so probably not. */417entry->hostname = g_strdup(eo_info->hostname)g_strdup_inline (eo_info->hostname);418entry->content_type = g_strdup(eo_info->content_type)g_strdup_inline (eo_info->content_type);419/* XXX: Should this remove the query portion, if any, from420 * the path? (Or should that be done in the dissector?) */421entry->filename = eo_info->filename ? g_path_get_basename(eo_info->filename) : NULL((void*)0);422entry->payload_len = tvb_captured_length(eo_info->payload);423entry->payload_data = (uint8_t *)tvb_memdup(NULL((void*)0), eo_info->payload, 0, entry->payload_len);424 425object_list->add_entry(object_list->gui_data, entry);426 427return TAP_PACKET_REDRAW; /* State changed - window should be redrawn */428} else {429return TAP_PACKET_DONT_REDRAW; /* State unchanged - no window updates needed */430}431}432 433/* --- HTTP Status Codes */434/* Note: The reference for uncommented entries is RFC 2616 */435const value_string vals_http_status_code[] = {436{ 100, "Continue" },437{ 101, "Switching Protocols" },438{ 102, "Processing" }, /* RFC 2518 */439{ 103, "Early Hints" }, /* RFC-ietf-httpbis-early-hints-05 */440{ 199, "Informational - Others" },441 442{ 200, "OK"},443{ 201, "Created"},444{ 202, "Accepted"},445{ 203, "Non-authoritative Information"},446{ 204, "No Content"},447{ 205, "Reset Content"},448{ 206, "Partial Content"},449{ 207, "Multi-Status"}, /* RFC 4918 */450{ 208, "Already Reported"}, /* RFC 5842 */451{ 226, "IM Used"}, /* RFC 3229 */452{ 299, "Success - Others"},453 454{ 300, "Multiple Choices"},455{ 301, "Moved Permanently"},456{ 302, "Found"},457{ 303, "See Other"},458{ 304, "Not Modified"},459{ 305, "Use Proxy"},460{ 307, "Temporary Redirect"},461{ 308, "Permanent Redirect"}, /* RFC 7538 */462{ 399, "Redirection - Others"},463 464{ 400, "Bad Request"},465{ 401, "Unauthorized"},466{ 402, "Payment Required"},467{ 403, "Forbidden"},468{ 404, "Not Found"},469{ 405, "Method Not Allowed"},470{ 406, "Not Acceptable"},471{ 407, "Proxy Authentication Required"},472{ 408, "Request Time-out"},473{ 409, "Conflict"},474{ 410, "Gone"},475{ 411, "Length Required"},476{ 412, "Precondition Failed"},477{ 413, "Request Entity Too Large"},478{ 414, "Request-URI Too Long"},479{ 415, "Unsupported Media Type"},480{ 416, "Requested Range Not Satisfiable"},481{ 417, "Expectation Failed"},482{ 418, "I'm a teapot"}, /* RFC 2324 */483{ 421, "Misdirected Request"}, /* RFC 7540 */484{ 422, "Unprocessable Entity"}, /* RFC 4918 */485{ 423, "Locked"}, /* RFC 4918 */486{ 424, "Failed Dependency"}, /* RFC 4918 */487{ 425, "Too Early"}, /* RFC 8470 */488{ 426, "Upgrade Required"}, /* RFC 2817 */489{ 428, "Precondition Required"}, /* RFC 6585 */490{ 429, "Too Many Requests"}, /* RFC 6585 */491{ 431, "Request Header Fields Too Large"}, /* RFC 6585 */492{ 451, "Unavailable For Legal Reasons"}, /* RFC 7725 */493{ 499, "Client Error - Others"},494 495{ 500, "Internal Server Error"},496{ 501, "Not Implemented"},497{ 502, "Bad Gateway"},498{ 503, "Service Unavailable"},499{ 504, "Gateway Time-out"},500{ 505, "HTTP Version not supported"},501{ 506, "Variant Also Negotiates"}, /* RFC 2295 */502{ 507, "Insufficient Storage"}, /* RFC 4918 */503{ 508, "Loop Detected"}, /* RFC 5842 */504{ 510, "Not Extended"}, /* RFC 2774 */505{ 511, "Network Authentication Required"}, /* RFC 6585 */506{ 599, "Server Error - Others"},507 508{ 0, NULL((void*)0)}509};510 511static const char* st_str_reqs = "HTTP Requests by Server";512static const char* st_str_reqs_by_srv_addr = "HTTP Requests by Server Address";513static const char* st_str_reqs_by_http_host = "HTTP Requests by HTTP Host";514static const char* st_str_resps_by_srv_addr = "HTTP Responses by Server Address";515 516static int st_node_reqs = -1;517static int st_node_reqs_by_srv_addr = -1;518static int st_node_reqs_by_http_host = -1;519static int st_node_resps_by_srv_addr = -1;520 521/* Parse HTTP path sub components RFC3986 Ch 3.3, 3.4 */522void523http_add_path_components_to_tree(tvbuff_t* tvb, packet_info* pinfo _U___attribute__((unused)), proto_item* item, int offset, int length)524{525proto_item* ti;526proto_tree* uri_tree;527int end_offset, end_path_offset, query_offset, path_len, query_len, parameter_offset;528end_offset = offset + length;529/* The Content-Location (and Referer) headers in HTTP 1.1, and the530 * :path header in HTTP/2 can be an absolute-URI or a partial-URI;531 * i.e. that they can include a path and a query, but not a fragment.532 * RFC 7230 2.7 Uniform Request Identifiers, RFC 7231 Appendices C and D,533 * RFC 7540 8.1.2.3. Request Pseudo-Header Fields534 * Look for a ? to mark a query.535 */536query_offset = tvb_find_uint8(tvb, offset, length, '?');537end_path_offset = (query_offset == -1) ? end_offset : query_offset;538parameter_offset = tvb_ws_mempbrk_pattern_uint8(tvb, offset + 1, end_path_offset - offset - 1, &pbrk_sub_delims, NULL((void*)0));539if (query_offset == -1 && parameter_offset == -1) {540/* Nothing interesting, no need to split. */541return;542}543uri_tree = proto_item_add_subtree(item, ett_http_request_uri);544path_len = end_path_offset - offset;545proto_tree_add_item(uri_tree, hf_http_request_path, tvb, offset, path_len, ENC_ASCII0x00000000);546parameter_offset = tvb_ws_mempbrk_pattern_uint8(tvb, offset + 1, end_path_offset - offset - 1, &pbrk_sub_delims, NULL((void*)0));547if (parameter_offset != -1) {548proto_tree* path_tree = proto_item_add_subtree(item, ett_http_request_path);549while (offset < end_path_offset) {550parameter_offset = tvb_ws_mempbrk_pattern_uint8(tvb, offset + 1, end_path_offset - offset - 1, &pbrk_sub_delims, NULL((void*)0));551if (parameter_offset == -1) {552parameter_offset = end_path_offset;553}554proto_tree_add_item(path_tree, hf_http_request_path_segment, tvb, offset, parameter_offset - offset, ENC_ASCII0x00000000);555offset = parameter_offset + 1;556}557}558if (query_offset == -1) {559return;560}561/* Skip past the delimiter. */562query_offset++;563query_len = end_offset - query_offset;564offset = query_offset;565ti = proto_tree_add_item(uri_tree, hf_http_request_query, tvb, query_offset, query_len, ENC_ASCII0x00000000);566proto_tree *query_tree = proto_item_add_subtree(ti, ett_http_request_query);567while (offset < end_offset) {568parameter_offset = tvb_ws_mempbrk_pattern_uint8(tvb, offset + 1, end_offset - offset - 1, &pbrk_sub_delims, NULL((void*)0));569if (parameter_offset == -1) {570parameter_offset = end_offset;571}572proto_tree_add_item(query_tree, hf_http_request_query_parameter, tvb, offset, parameter_offset - offset, ENC_ASCII0x00000000);573offset = parameter_offset + 1;574}575}576 577/* HTTP/Load Distribution stats init function */578static void579http_reqs_stats_tree_init(stats_tree* st)580{581st_node_reqs = stats_tree_create_node(st, st_str_reqs, 0, STAT_DT_INT, true1);582st_node_reqs_by_srv_addr = stats_tree_create_node(st, st_str_reqs_by_srv_addr, st_node_reqs, STAT_DT_INT, true1);583st_node_reqs_by_http_host = stats_tree_create_node(st, st_str_reqs_by_http_host, st_node_reqs, STAT_DT_INT, true1);584st_node_resps_by_srv_addr = stats_tree_create_node(st, st_str_resps_by_srv_addr, 0, STAT_DT_INT, true1);585}586 587/* HTTP/Load Distribution stats packet function */588static tap_packet_status589http_reqs_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U___attribute__((unused)), const void* p, tap_flags_t flags _U___attribute__((unused)))590{591const http_info_value_t* v = (const http_info_value_t*)p;592int reqs_by_this_host;593int reqs_by_this_addr;594int resps_by_this_addr;595int i = v->response_code;596char *ip_str;597 598 599if (v->request_method) {600ip_str = address_to_str(NULL((void*)0), &pinfo->dst);601 602tick_stat_node(st, st_str_reqs, 0, false)(stats_tree_manip_node_int(MN_INCREASE,(st),(st_str_reqs),(0)
,(0),1))
;603tick_stat_node(st, st_str_reqs_by_srv_addr, st_node_reqs, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(st_str_reqs_by_srv_addr
),(st_node_reqs),(1),1))
;604tick_stat_node(st, st_str_reqs_by_http_host, st_node_reqs, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(st_str_reqs_by_http_host
),(st_node_reqs),(1),1))
;605reqs_by_this_addr = tick_stat_node(st, ip_str, st_node_reqs_by_srv_addr, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(ip_str),(st_node_reqs_by_srv_addr
),(1),1))
;606 607if (v->http_host) {608reqs_by_this_host = tick_stat_node(st, v->http_host, st_node_reqs_by_http_host, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(v->http_host)
,(st_node_reqs_by_http_host),(1),1))
;609tick_stat_node(st, ip_str, reqs_by_this_host, false)(stats_tree_manip_node_int(MN_INCREASE,(st),(ip_str),(reqs_by_this_host
),(0),1))
;610 611tick_stat_node(st, v->http_host, reqs_by_this_addr, false)(stats_tree_manip_node_int(MN_INCREASE,(st),(v->http_host)
,(reqs_by_this_addr),(0),1))
;612}613 614wmem_free(NULL((void*)0), ip_str);615 616return TAP_PACKET_REDRAW;617 618} else if (i != 0) {619ip_str = address_to_str(NULL((void*)0), &pinfo->src);620 621tick_stat_node(st, st_str_resps_by_srv_addr, 0, false)(stats_tree_manip_node_int(MN_INCREASE,(st),(st_str_resps_by_srv_addr
),(0),(0),1))
;622resps_by_this_addr = tick_stat_node(st, ip_str, st_node_resps_by_srv_addr, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(ip_str),(st_node_resps_by_srv_addr
),(1),1))
;623 624if ( (i>=100)&&(i<400) ) {625tick_stat_node(st, "OK", resps_by_this_addr, false)(stats_tree_manip_node_int(MN_INCREASE,(st),("OK"),(resps_by_this_addr
),(0),1))
;626} else {627tick_stat_node(st, "Error", resps_by_this_addr, false)(stats_tree_manip_node_int(MN_INCREASE,(st),("Error"),(resps_by_this_addr
),(0),1))
;628}629 630wmem_free(NULL((void*)0), ip_str);631 632return TAP_PACKET_REDRAW;633}634 635return TAP_PACKET_DONT_REDRAW;636}637 638 639static int st_node_requests_by_host = -1;640static const char *st_str_requests_by_host = "HTTP Requests by HTTP Host";641 642/* HTTP/Requests stats init function */643static void644http_req_stats_tree_init(stats_tree* st)645{646st_node_requests_by_host = stats_tree_create_node(st, st_str_requests_by_host, 0, STAT_DT_INT, true1);647}648 649/* HTTP/Requests stats packet function */650static tap_packet_status651http_req_stats_tree_packet(stats_tree* st, packet_info* pinfo _U___attribute__((unused)), epan_dissect_t* edt _U___attribute__((unused)), const void* p, tap_flags_t flags _U___attribute__((unused)))652{653const http_info_value_t* v = (const http_info_value_t*)p;654int reqs_by_this_host;655 656if (v->request_method) {657tick_stat_node(st, st_str_requests_by_host, 0, false)(stats_tree_manip_node_int(MN_INCREASE,(st),(st_str_requests_by_host
),(0),(0),1))
;658 659if (v->http_host) {660reqs_by_this_host = tick_stat_node(st, v->http_host, st_node_requests_by_host, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(v->http_host)
,(st_node_requests_by_host),(1),1))
;661 662if (v->request_uri) {663tick_stat_node(st, v->request_uri, reqs_by_this_host, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(v->request_uri
),(reqs_by_this_host),(1),1))
;664}665}666 667return TAP_PACKET_REDRAW;668}669 670return TAP_PACKET_DONT_REDRAW;671}672 673static const char *st_str_packets = "Total HTTP Packets";674static const char *st_str_requests = "HTTP Request Packets";675static const char *st_str_responses = "HTTP Response Packets";676static const char *st_str_resp_broken = "???: broken";677static const char *st_str_resp_100 = "1xx: Informational";678static const char *st_str_resp_200 = "2xx: Success";679static const char *st_str_resp_300 = "3xx: Redirection";680static const char *st_str_resp_400 = "4xx: Client Error";681static const char *st_str_resp_500 = "5xx: Server Error";682static const char *st_str_other = "Other HTTP Packets";683 684static int st_node_packets = -1;685static int st_node_requests = -1;686static int st_node_responses = -1;687static int st_node_resp_broken = -1;688static int st_node_resp_100 = -1;689static int st_node_resp_200 = -1;690static int st_node_resp_300 = -1;691static int st_node_resp_400 = -1;692static int st_node_resp_500 = -1;693static int st_node_other = -1;694 695 696/* HTTP/Packet Counter stats init function */697static void698http_stats_tree_init(stats_tree* st)699{700st_node_packets = stats_tree_create_node(st, st_str_packets, 0, STAT_DT_INT, true1);701st_node_requests = stats_tree_create_pivot(st, st_str_requests, st_node_packets);702st_node_responses = stats_tree_create_node(st, st_str_responses, st_node_packets, STAT_DT_INT, true1);703st_node_resp_broken = stats_tree_create_node(st, st_str_resp_broken, st_node_responses, STAT_DT_INT, true1);704st_node_resp_100 = stats_tree_create_node(st, st_str_resp_100, st_node_responses, STAT_DT_INT, true1);705st_node_resp_200 = stats_tree_create_node(st, st_str_resp_200, st_node_responses, STAT_DT_INT, true1);706st_node_resp_300 = stats_tree_create_node(st, st_str_resp_300, st_node_responses, STAT_DT_INT, true1);707st_node_resp_400 = stats_tree_create_node(st, st_str_resp_400, st_node_responses, STAT_DT_INT, true1);708st_node_resp_500 = stats_tree_create_node(st, st_str_resp_500, st_node_responses, STAT_DT_INT, true1);709st_node_other = stats_tree_create_node(st, st_str_other, st_node_packets, STAT_DT_INT, false0);710}711 712/* HTTP/Packet Counter stats packet function */713static tap_packet_status714http_stats_tree_packet(stats_tree* st, packet_info* pinfo _U___attribute__((unused)), epan_dissect_t* edt _U___attribute__((unused)), const void* p, tap_flags_t flags _U___attribute__((unused)))715{716const http_info_value_t* v = (const http_info_value_t*)p;717unsigned i = v->response_code;718int resp_grp;719const char *resp_str;720char str[64];721 722tick_stat_node(st, st_str_packets, 0, false)(stats_tree_manip_node_int(MN_INCREASE,(st),(st_str_packets),
(0),(0),1))
;723 724if (i) {725tick_stat_node(st, st_str_responses, st_node_packets, false)(stats_tree_manip_node_int(MN_INCREASE,(st),(st_str_responses
),(st_node_packets),(0),1))
;726 727if ( (i<100)||(i>=600) ) {728resp_grp = st_node_resp_broken;729resp_str = st_str_resp_broken;730} else if (i<200) {731resp_grp = st_node_resp_100;732resp_str = st_str_resp_100;733} else if (i<300) {734resp_grp = st_node_resp_200;735resp_str = st_str_resp_200;736} else if (i<400) {737resp_grp = st_node_resp_300;738resp_str = st_str_resp_300;739} else if (i<500) {740resp_grp = st_node_resp_400;741resp_str = st_str_resp_400;742} else {743resp_grp = st_node_resp_500;744resp_str = st_str_resp_500;745}746 747tick_stat_node(st, resp_str, st_node_responses, false)(stats_tree_manip_node_int(MN_INCREASE,(st),(resp_str),(st_node_responses
),(0),1))
;748 749snprintf(str, sizeof(str), "%u %s", i,750 val_to_str(i, vals_http_status_code, "Unknown (%d)"));751tick_stat_node(st, str, resp_grp, false)(stats_tree_manip_node_int(MN_INCREASE,(st),(str),(resp_grp),
(0),1))
;752} else if (v->request_method) {753stats_tree_tick_pivot(st,st_node_requests,v->request_method);754} else {755tick_stat_node(st, st_str_other, st_node_packets, false)(stats_tree_manip_node_int(MN_INCREASE,(st),(st_str_other),(st_node_packets
),(0),1))
;756}757 758return TAP_PACKET_REDRAW;759}760 761/*762Generates a referer tree - a best-effort representation of which web request led to which.763 764Some challenges:765A user can be forwarded to a single sites from multiple sources. For example,766google.com -> foo.com and bing.com -> foo.com. A URI alone is not unique.767 768Additionally, if a user has a subsequent request to foo.com -> bar.com, the769full chain could either be:770google.com -> foo.com -> bar.com, or771bing.com -> foo.com -> bar.com,772 773This indicates that a URI and its referer are not unique. Only a URI and its774full referer chain are unique. However, HTTP requests only contain the URI775and the immediate referer. This means that any attempt at generating a776referer tree is inherently going to be a best-effort approach.777 778This code assumes that the referer in a request is from the most-recent request779to that referer.780 781* To maintain readability of the statistics, whenever a site is visited, all782prior referers are 'ticked' as well, so that one can easily see the breakdown.783*/784 785/* Root node for all referer statistics */786static int st_node_requests_by_referer = -1;787/* Referer statistics root node's text */788static const char *st_str_request_sequences = "HTTP Request Sequences";789 790/* Mapping of URIs to the most-recently seen node id */791static wmem_map_t* refstats_uri_to_node_id_hash;792/* Mapping of node ids to the node's URI ('name' value) */793static wmem_map_t* refstats_node_id_to_uri_hash;794/* Mapping of node ids to the parent node id */795static wmem_map_t* refstats_node_id_to_parent_node_id_hash;796 797 798/* HTTP/Request Sequences stats init function */799static void800http_seq_stats_tree_init(stats_tree* st)801{802int root_node_id = 0;803void *root_node_id_p = GINT_TO_POINTER(root_node_id)((gpointer) (glong) (root_node_id));804void *node_id_p = NULL((void*)0);805char *uri = NULL((void*)0);806 807refstats_node_id_to_parent_node_id_hash = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);808refstats_node_id_to_uri_hash = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);809refstats_uri_to_node_id_hash = wmem_map_new(wmem_file_scope(), wmem_str_hash, g_str_equal);810 811/* Add the root node and its mappings */812st_node_requests_by_referer = stats_tree_create_node(st, st_str_request_sequences, root_node_id, STAT_DT_INT, true1);813node_id_p = GINT_TO_POINTER(st_node_requests_by_referer)((gpointer) (glong) (st_node_requests_by_referer));814uri = wmem_strdup(wmem_file_scope(), st_str_request_sequences);815 816wmem_map_insert(refstats_uri_to_node_id_hash, uri, node_id_p);817wmem_map_insert(refstats_node_id_to_uri_hash, node_id_p, uri);818wmem_map_insert(refstats_node_id_to_parent_node_id_hash, node_id_p, root_node_id_p);819}820 821static int822http_seq_stats_tick_referer(stats_tree* st, const char* arg_referer_uri)823{824int root_node_id = st_node_requests_by_referer;825void *root_node_id_p = GINT_TO_POINTER(st_node_requests_by_referer)((gpointer) (glong) (st_node_requests_by_referer));826int referer_node_id;827void *referer_node_id_p;828int referer_parent_node_id;829void *referer_parent_node_id_p;830char *referer_uri;831 832/* Tick the referer's URI */833/* Does the node exist? */834if (!wmem_map_lookup_extended(refstats_uri_to_node_id_hash, arg_referer_uri, NULL((void*)0), &referer_node_id_p)) {835/* The node for the referer didn't already exist, create the mappings */836referer_node_id = tick_stat_node(st, arg_referer_uri, root_node_id, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(arg_referer_uri)
,(root_node_id),(1),1))
;837referer_node_id_p = GINT_TO_POINTER(referer_node_id)((gpointer) (glong) (referer_node_id));838referer_parent_node_id_p = root_node_id_p;839 840referer_uri = wmem_strdup(wmem_file_scope(), arg_referer_uri);841wmem_map_insert(refstats_uri_to_node_id_hash, referer_uri, referer_node_id_p);842wmem_map_insert(refstats_node_id_to_uri_hash, referer_node_id_p, referer_uri);843wmem_map_insert(refstats_node_id_to_parent_node_id_hash, referer_node_id_p, referer_parent_node_id_p);844} else {845/* The node for the referer already exists, tick it */846referer_parent_node_id_p = wmem_map_lookup(refstats_node_id_to_parent_node_id_hash, referer_node_id_p);847referer_parent_node_id = GPOINTER_TO_INT(referer_parent_node_id_p)((gint) (glong) (referer_parent_node_id_p));848referer_node_id = tick_stat_node(st, arg_referer_uri, referer_parent_node_id, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(arg_referer_uri)
,(referer_parent_node_id),(1),1))
;849}850return referer_node_id;851}852 853static void854http_seq_stats_tick_request(stats_tree* st, const char* arg_full_uri, int referer_node_id)855{856void *referer_node_id_p = GINT_TO_POINTER(referer_node_id)((gpointer) (glong) (referer_node_id));857int node_id;858void *node_id_p;859char *uri;860 861node_id = tick_stat_node(st, arg_full_uri, referer_node_id, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(arg_full_uri),(referer_node_id
),(1),1))
;862node_id_p = GINT_TO_POINTER(node_id)((gpointer) (glong) (node_id));863 864/* Update the mappings. Even if the URI was already seen, the URI->node mapping may need to be updated */865 866/* Is this a new node? */867uri = (char *) wmem_map_lookup(refstats_node_id_to_uri_hash, node_id_p);868if (!uri) {869/* node not found, add mappings for the node and uri */870uri = wmem_strdup(wmem_file_scope(), arg_full_uri);871 872wmem_map_insert(refstats_uri_to_node_id_hash, uri, node_id_p);873wmem_map_insert(refstats_node_id_to_uri_hash, node_id_p, uri);874wmem_map_insert(refstats_node_id_to_parent_node_id_hash, node_id_p, referer_node_id_p);875} else {876/* We've seen the node id before. Update the URI mapping refer to this node id*/877wmem_map_insert(refstats_uri_to_node_id_hash, uri, node_id_p);878}879}880 881static char*882determine_http_location_target(wmem_allocator_t *scope, const char *base_url, const char * location_url)883{884/* Resolving a base URI + relative URI to an absolute URI ("Relative Resolution")885is complicated. Because of that, we take shortcuts that may result in886inaccurate results, but is also significantly simpler.887It would be best to use an external library to do this for us.888For reference, the RFC is located at https://tools.ietf.org/html/rfc3986#section-5.4889 890Returns NULL if the resolution fails891*/892char *final_target;893 894/* base_url must be an absolute URL.*/895if (strstr(base_url, "://") == NULL((void*)0)){896return NULL((void*)0);897}898 899/* Empty Location */900if (location_url[0] == '\0') {901final_target = wmem_strdup(scope, base_url);902return final_target;903}904/* Protocol Relative */905else if (g_str_has_prefix(location_url, "//")(__builtin_constant_p ("//")? __extension__ ({ const char * const
__str = (location_url); const char * const __prefix = ("//")
; gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (location_url, "//") )
) {906char *base_scheme = g_uri_parse_scheme(base_url);907if (base_scheme == NULL((void*)0)) {908return NULL((void*)0);909}910final_target = wmem_strdup_printf(scope, "%s:%s", base_scheme, location_url);911g_free(base_scheme);912return final_target;913}914/* Absolute URL*/915else if (strstr(location_url, "://") != NULL((void*)0)) {916final_target = wmem_strdup(scope, location_url);917return final_target;918}919/* Relative */920else {921char *start_fragment = strstr(base_url, "#");922char *start_query = NULL((void*)0);923char *base_url_no_fragment = NULL((void*)0);924char *base_url_no_query = NULL((void*)0);925 926/* Strip off the fragment (which should never be present)*/927if (start_fragment == NULL((void*)0)) {928base_url_no_fragment = wmem_strdup(scope, base_url);929}930else {931base_url_no_fragment = wmem_strndup(scope, base_url, start_fragment - base_url);932}933 934/* Strip off the query (Queries are stripped from all relative URIs) */935start_query = strstr(base_url_no_fragment, "?");936if (start_query == NULL((void*)0)) {937base_url_no_query = wmem_strdup(scope, base_url_no_fragment);938}939else {940base_url_no_query = wmem_strndup(scope, base_url_no_fragment, start_query - base_url_no_fragment);941}942 943/* A leading question mark (?) means to replace the old query with the new*/944if (g_str_has_prefix(location_url, "?")(__builtin_constant_p ("?")? __extension__ ({ const char * const
__str = (location_url); const char * const __prefix = ("?");
gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (location_url, "?") )
) {945final_target = wmem_strdup_printf(scope, "%s%s", base_url_no_query, location_url);946return final_target;947}948/* A leading slash means to put the location after the netloc */949else if (g_str_has_prefix(location_url, "/")(__builtin_constant_p ("/")? __extension__ ({ const char * const
__str = (location_url); const char * const __prefix = ("/");
gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (location_url, "/") )
) {950/* We have already tested strstr(base_url) above */951char *scheme_end;952char *netloc_end;953int netloc_length;954 955scheme_end = strstr(base_url_no_query, "://") + 3;956/* The following code was the only way to stop VS dereferencing errors. */957if (!(*scheme_end)) {958return NULL((void*)0);959}960netloc_end = strstr(scheme_end, "/");961if (!(*netloc_end)) {962return NULL((void*)0);963}964netloc_length = (int) (netloc_end - base_url_no_query);965final_target = wmem_strdup_printf(scope, "%.*s%s", netloc_length, base_url_no_query, location_url);966return final_target;967}968/* Otherwise, it replaces the last element in the URI */969else {970char *scheme_end = strstr(base_url_no_query, "://") + 3;971char *end_of_path = g_strrstr(scheme_end, "/");972 973if (end_of_path != NULL((void*)0)) {974int base_through_path = (int) (end_of_path - base_url_no_query);975final_target = wmem_strdup_printf(scope, "%.*s/%s", base_through_path, base_url_no_query, location_url);976}977else {978final_target = wmem_strdup_printf(scope, "%s/%s", base_url_no_query, location_url);979}980 981return final_target;982}983}984return NULL((void*)0);985}986 987/* HTTP/Request Sequences stats packet function */988static tap_packet_status989http_seq_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U___attribute__((unused)), const void* p, tap_flags_t flags _U___attribute__((unused)))990{991const http_info_value_t* v = (const http_info_value_t*)p;992 993/* Track HTTP Redirects */994if (v->location_target && v->location_base_uri) {995int referer_node_id;996int parent_node_id;997void *parent_node_id_p;998void *current_node_id_p;999char *uri = NULL((void*)0);1000 1001char *absolute_target = determine_http_location_target(pinfo->pool, v->location_base_uri, v->location_target);1002/* absolute_target is NULL if the resolution fails */1003if (absolute_target != NULL((void*)0)) {1004/* We assume the user makes the request to the absolute_target */1005/* Tick the base URI */1006referer_node_id = http_seq_stats_tick_referer(st, v->location_base_uri);1007 1008/* Tick the location header's resolved URI */1009http_seq_stats_tick_request(st, absolute_target, referer_node_id);1010 1011/* Tick all stats nodes above the location */1012current_node_id_p = GINT_TO_POINTER(referer_node_id)((gpointer) (glong) (referer_node_id));1013while (wmem_map_lookup_extended(refstats_node_id_to_parent_node_id_hash, current_node_id_p, NULL((void*)0), &parent_node_id_p)) {1014parent_node_id = GPOINTER_TO_INT(parent_node_id_p)((gint) (glong) (parent_node_id_p));1015uri = (char *) wmem_map_lookup(refstats_node_id_to_uri_hash, current_node_id_p);1016tick_stat_node(st, uri, parent_node_id, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(uri),(parent_node_id
),(1),1))
;1017current_node_id_p = parent_node_id_p;1018}1019}1020}1021 1022/* Track HTTP Requests/Referers */1023if (v->request_method && v->referer_uri && v->full_uri) {1024int referer_node_id;1025int parent_node_id;1026void *parent_node_id_p;1027void *current_node_id_p;1028char *uri = NULL((void*)0);1029/* Tick the referer's URI */1030referer_node_id = http_seq_stats_tick_referer(st, v->referer_uri);1031 1032/* Tick the request's URI */1033http_seq_stats_tick_request(st, v->full_uri, referer_node_id);1034 1035/* Tick all stats nodes above the referer */1036current_node_id_p = GINT_TO_POINTER(referer_node_id)((gpointer) (glong) (referer_node_id));1037while (wmem_map_lookup_extended(refstats_node_id_to_parent_node_id_hash, current_node_id_p, NULL((void*)0), &parent_node_id_p)) {1038parent_node_id = GPOINTER_TO_INT(parent_node_id_p)((gint) (glong) (parent_node_id_p));1039uri = (char *) wmem_map_lookup(refstats_node_id_to_uri_hash, current_node_id_p);1040tick_stat_node(st, uri, parent_node_id, true)(stats_tree_manip_node_int(MN_INCREASE,(st),(uri),(parent_node_id
),(1),1))
;1041current_node_id_p = parent_node_id_p;1042}1043}1044return TAP_PACKET_DONT_REDRAW;1045}1046 1047 1048static void1049dissect_http_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,1050 const char *line)1051{1052tvbuff_t *ntlmssp_tvb;1053 1054ntlmssp_tvb = base64_to_tvb(tvb, line);1055add_new_data_source(pinfo, ntlmssp_tvb, "NTLMSSP / GSSAPI Data");1056if (tvb_strneql(ntlmssp_tvb, 0, "NTLMSSP", 7) == 0)1057call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo, tree);1058else1059call_dissector(gssapi_handle, ntlmssp_tvb, pinfo, tree);1060}1061 1062static void1063dissect_http_kerberos(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,1064 const char *line)1065{1066tvbuff_t *kerberos_tvb;1067 1068kerberos_tvb = base64_to_tvb(tvb, line + 9); /* skip 'Kerberos ' which is 9 chars */1069add_new_data_source(pinfo, kerberos_tvb, "Kerberos Data");1070call_dissector(gssapi_handle, kerberos_tvb, pinfo, tree);1071 1072}1073 1074 1075static http_conv_t *1076get_http_conversation_data(packet_info *pinfo, conversation_t **conversation)1077{1078http_conv_t*conv_data;1079 1080*conversation = find_or_create_conversation(pinfo);1081 1082/* Retrieve information from conversation1083 * or add it if it isn't there yet1084 */1085conv_data = (http_conv_t *)conversation_get_proto_data(*conversation, proto_http);1086if(!conv_data) {1087/* Setup the conversation structure itself */1088conv_data = wmem_new0(wmem_file_scope(), http_conv_t)((http_conv_t*)wmem_alloc0((wmem_file_scope()), sizeof(http_conv_t
)))
;1089conv_data->chunk_offsets_fwd = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);1090conv_data->chunk_offsets_rev = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);1091conv_data->req_list = NULL((void*)0);1092conv_data->matches_table = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);1093 1094conversation_add_proto_data(*conversation, proto_http,1095 conv_data);1096}1097 1098return conv_data;1099}1100 1101/**1102 * create a new http_req_res_t and add it to the conversation.1103 * @return the new allocated object which is already added to the linked list1104 */1105static http_req_res_t*1106push_req_res(http_conv_t *conv_data)1107{1108http_req_res_t *req_res = wmem_new0(wmem_file_scope(), http_req_res_t)((http_req_res_t*)wmem_alloc0((wmem_file_scope()), sizeof(http_req_res_t
)))
;1109 1110nstime_set_unset(&(req_res->req_ts));1111conv_data->req_res_tail = req_res;1112req_res->private_data = wmem_new0(wmem_file_scope(), http_req_res_private_data_t)((http_req_res_private_data_t*)wmem_alloc0((wmem_file_scope()
), sizeof(http_req_res_private_data_t)))
;1113 1114return req_res;1115}1116 1117/**1118 * push a request frame number and its time stamp to the conversation data.1119 */1120static http_req_res_t*1121push_req(http_conv_t *conv_data, packet_info *pinfo)1122{1123/* a request will always create a new http_req_res_t object */1124http_req_res_t *req_res = push_req_res(conv_data);1125 1126req_res->req_framenum = pinfo->num;1127req_res->req_ts = pinfo->abs_ts;1128 1129/* XXX: Using the same proto key for the frame doesn't work well1130 * with HTTP 1.1 pipelining, or other situations where more1131 * than one request can appear in a frame.1132 */1133p_add_proto_data(wmem_file_scope(), pinfo, proto_http, HTTP_PROTO_DATA_REQRES0, req_res);1134 1135return req_res;1136}1137 1138/**1139 * push a response frame number to the conversation data.1140 */1141static http_req_res_t*1142push_res(http_conv_t *conv_data, packet_info *pinfo)1143{1144/* a response will create a new http_req_res_t object: if no1145 object exists, or if the most recent one is already for1146 a different response. (Exception: If the previous response1147 code was in the Informational 1xx category, then it was1148 an interim response, and this response could be for the same1149 request.) In both cases the corresponding request was not1150 detected/included in the conversation. In all other cases1151 the http_req_res_t object created by the request is1152 used. */1153/* XXX: This finds the only most recent request and doesn't support1154 * HTTP 1.1 pipelining. This limitation has been addressed for1155 * HTTP GETS if Range Requests are supported.1156 */1157http_req_res_t *req_res = conv_data->req_res_tail;1158if (!req_res || (req_res->res_framenum > 0 && req_res->response_code >= 200)) {1159req_res = push_req_res(conv_data);1160}1161req_res->res_framenum = pinfo->num;1162/* XXX: Using the same proto key for the frame doesn't work well1163 * with HTTP 1.1 pipelining, or other situations where more1164 * than one request can appear in a frame and multiple outstanding1165 * GET requests. The latter has been addressed with matches_table."1166 */1167p_add_proto_data(wmem_file_scope(), pinfo, proto_http, HTTP_PROTO_DATA_REQRES0, req_res);1168 1169return req_res;1170}1171 1172static int1173dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,1174 proto_tree *tree, http_conv_t *conv_data,1175 const char* proto_tag, int proto, bool_Bool end_of_stream,1176 const uint32_t* const seq)1177{1178proto_tree*http_tree = NULL((void*)0);1179proto_item*ti = NULL((void*)0);1180proto_item*hidden_item;1181const unsigned char*line, *firstline;1182intnext_offset;1183const unsigned char*linep, *lineend;1184intorig_offset = offset;1185intfirst_linelen, linelen;1186bool_Boolis_request_or_reply, is_tls = false0;1187bool_Boolsaw_req_resp_or_header;1188media_container_type_t http_type;1189proto_item*hdr_item = NULL((void*)0);1190ReqRespDissector reqresp_dissector;1191proto_tree*req_tree;1192intcolon_offset;1193headers_t*headers = NULL((void*)0);

1

'headers' initialized to a null pointer value

1194intdatalen;1195intreported_datalen = -1;1196dissector_handle_t handle = NULL((void*)0);1197bool_Booldissected = false0;1198bool_Boolfirst_loop = true1;1199bool_Boolhave_seen_http = false0;1200/*unsignedi;*/1201/*http_info_value_t *si;*/1202http_eo_t *eo_info;1203heur_dtbl_entry_t *hdtbl_entry;1204int reported_length;1205uint16_t word;1206bool_Boolleading_crlf = false0;1207bool_Boolexcess_data = false0;1208media_content_info_t* content_info = NULL((void*)0);1209wmem_map_t* header_value_map = NULL((void*)0);1210int chunk_offset = 0;1211wmem_map_t*chunk_map = NULL((void*)0);1212/*1213 * For supporting dissecting chunked data in streaming reassembly mode.1214 *1215 * If a HTTP request or response is chunked encoding (the transfer-encoding1216 * header is 'chunked') and its content-type matching a subdissector in1217 * "streaming_content_type" dissector table, then we switch to dissect in1218 * streaming chunk mode. In streaming chunk mode, we dissect the data as soon1219 * as possible, unlike normal mode, we don't start reassembling until the end1220 * of the request or response message or at the end of the TCP stream. In1221 * streaming chunk mode, the first reassembled PDU contains HTTP headers1222 * and at least one completed chunk of this request or response message. And1223 * subsequent PDUs consist of one or more chunks:1224 *1225 * ----- +-- Reassembled Streaming Content PDU(s) --+-- Reassembled Streaming Content PDU(s) --+--- Reassembled ...1226 * HLProtos | 1*high-proto-pdu | 1*high-proto-pdu | 1*high-proto-pdu1227 * ----- +-------------------------------------+----+--------------------------------+---------+-------------------1228 * | de-chunked-data | de-chunked-data | de-chunked-data1229 * HTTP +-------- First Reassembled HTTP PDU -----------+--- Second Reassembled HTTP PDU -----+- Third PDU -+ +- Fourth ---1230 * | headers and 1*chunk | 1*chunk | 1*chunk | | 1*chunk ...1231 * ----- +--------- TCP segment ---------+ +-----------TCP segment -----------+ +---- TCP segment ---------+ +------------1232 * TCP | headers | *chunk | part-chunk | | part-chunk | *chunk | part-chunk | | part-chunk | 1*chunk | | 1*chunk ...1233 * ----- +---------+--------+------------+ +------------+--------+------------+ +------------+-------------+ +------------1234 *1235 * Notation:1236 * - headers HTTP headers of a request or response message.1237 * - part-chunk The front or rear part of a HTTP chunk.1238 * - *chunk Zero or more completed HTTP chunks of a HTTP message.1239 * - 1*chunk One or more completed HTTP chunks of a HTTP message.1240 * - de-chunked-data De-chunked HTTP body data based on one or more completed chunks.1241 * - 1*high-proto-pdu One or more high level protocol (on top of HTTP) PDUs.1242 * - HLProtos High Level Protocols like GRPC-Web.1243 *1244 * The headers and content_info of the req_res are allocated in file scope that1245 * helps to provide information for dissecting subsequent PDUs which only1246 * contains chunks without headers.1247 */1248bool_Bool streaming_chunk_mode = false0;1249bool_Bool begin_with_chunk = false0;1250http_streaming_reassembly_data_t* streaming_reassembly_data = NULL((void*)0);1251 1252http_req_res_t *curr = (http_req_res_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_http, HTTP_PROTO_DATA_REQRES0);1253http_info_value_t *stat_info = NULL((void*)0);1254http_req_res_private_data_t* prv_data = curr ? (http_req_res_private_data_t*)curr->private_data : NULL((void*)0);

2

Assuming 'curr' is null

3

'?' condition is false

1255http_req_res_private_data_t* tail_prv_data = NULL((void*)0);1256 1257/* Determine the direction as in the TCP dissector, but don't call1258 * get_tcp_conversation_data because we don't want to create a new1259 * TCP stream if it doesn't exist (e.g., SSDP over UDP.)1260 */1261int direction = cmp_address(&pinfo->src, &pinfo->dst);1262/* if the addresses are equal, match the ports instead */1263if (direction == 0) {

4

Assuming 'direction' is not equal to 0

5

Taking false branch

1264direction = (pinfo->srcport > pinfo->destport) ? 1 : -1;1265}1266if (direction >= 0) {

6

Assuming 'direction' is < 0

7

Taking false branch

1267chunk_map = conv_data->chunk_offsets_fwd;1268} else {1269chunk_map = conv_data->chunk_offsets_rev;1270}1271 1272if (seq && chunk_map) {

8

Assuming 'seq' is null

1273chunk_offset = GPOINTER_TO_INT(wmem_map_lookup(chunk_map, GUINT_TO_POINTER(*seq)))((gint) (glong) (wmem_map_lookup(chunk_map, ((gpointer) (gulong
) (*seq)))))
;1274/* Returns 0 when there is no entry in the map, as we want. */1275}1276 1277reported_length = tvb_reported_length_remaining(tvb, offset);1278if (reported_length < 1) {

9

Assuming 'reported_length' is >= 1

10

Taking false branch

1279return -1;1280}1281 1282/* RFC 26161283 * In the interest of robustness, servers SHOULD ignore any empty1284 * line(s) received where a Request-Line is expected. In other words, if1285 * the server is reading the protocol stream at the beginning of a1286 * message and receives a CRLF first, it should ignore the CRLF.1287 */1288if (reported_length > 3) {

11

Assuming 'reported_length' is <= 3

1289word = tvb_get_ntohs(tvb,offset);1290if (word == 0x0d0a) {1291leading_crlf = true1;1292offset += 2;1293}1294}1295 1296/*1297 * If we previously dissected an HTTP request in this conversation then1298 * we should be pretty sure that whatever we got in this TVB is1299 * actually HTTP (even if what we have here is part of a file being1300 * transferred over HTTP).1301 */1302if (conv_data->req_res_tail)

13

Assuming field 'req_res_tail' is null

14

Taking false branch

1303have_seen_http = true1;1304 1305/*1306 * If this is binary data then there's no point in doing all the string1307 * operations below: they'll just be slow on this data.1308 */1309if (!g_ascii_isprint(tvb_get_uint8(tvb, offset))((g_ascii_table[(guchar) (tvb_get_uint8(tvb, offset))] & G_ASCII_PRINT
) != 0)
) {

15

Assuming the condition is false

16

Taking false branch

1310/*1311 * But, if we've seen some real HTTP then we're sure this is1312 * an HTTP conversation, and this is binary file data.1313 * Mark it as such.1314 */1315if (have_seen_http) {1316tvbuff_t *next_tvb;1317int data_len;1318 1319col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);1320col_set_str(pinfo->cinfo, COL_INFO, "Continuation");1321ti = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA0x00000000);1322http_tree = proto_item_add_subtree(ti, ett_http);1323 1324next_tvb = tvb_new_subset_remaining(tvb, orig_offset);1325/* If orig_offset > 0, this isn't the first message1326 * dissected in this TCP segment, which means we had1327 * a Content-Length, but more data after that body.1328 */1329if (orig_offset > 0) {1330proto_tree_add_expert(http_tree, pinfo, &ei_http_excess_data, next_tvb, 0, tvb_captured_length(next_tvb));1331}1332/* Send it to Follow HTTP Stream and mark as file data */1333if(have_tap_listener(http_follow_tap)) {1334tap_queue_packet(http_follow_tap, pinfo, next_tvb);1335}1336data_len = tvb_captured_length(next_tvb);1337proto_tree_add_bytes_format_value(http_tree, hf_http_file_data,1338next_tvb, 0, data_len, NULL((void*)0), "%u byte%s", data_len, plurality(data_len, "", "s")((data_len) == 1 ? ("") : ("s")));1339call_data_dissector(next_tvb, pinfo, http_tree);1340}1341return -1;1342}1343 1344/*1345 * Is this a request or response?1346 *1347 * Note that "tvb_find_line_end()" will return a value that1348 * is not longer than what's in the buffer, so the1349 * "tvb_get_ptr()" call won't throw an exception.1350 */1351first_linelen = tvb_find_line_end(tvb, offset,1352 tvb_ensure_captured_length_remaining(tvb, offset), &next_offset,1353 true1);1354 1355if (first_linelen == -1) {

17

Assuming the condition is false

1356/* No complete line was found in this segment, do1357 * desegmentation if we're told to.1358 */1359if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,1360 http_desegment_headers, http_desegment_body, false0, &chunk_offset,1361streaming_content_type_dissector_table, &handle)) {1362/*1363 * More data needed for desegmentation.1364 */1365return -1;1366}1367}1368 1369if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && conv_data->req_res_tail && conv_data->req_res_tail->private_data) {

18

Assuming field 'visited' is not equal to 0

1370tail_prv_data = (http_req_res_private_data_t*) conv_data->req_res_tail->private_data;1371}1372 1373/* Check whether the first line is the beginning of a chunk. If it is the beginning1374 * of a chunk, the headers and at least one chunk of HTTP request or response should1375 * be dissected in the previous packets, and now we are processing subsequent chunks.1376 */1377if (http_desegment_body && http_dechunk_body) {

19

Assuming 'http_desegment_body' is true

20

Assuming 'http_dechunk_body' is true

21

Taking true branch

1378begin_with_chunk = starts_with_chunk_size(tvb, offset, pinfo);

22

Calling 'starts_with_chunk_size'

32

Returning from 'starts_with_chunk_size'

1379 1380if (begin_with_chunk

32.1

'begin_with_chunk' is true

32.1

'begin_with_chunk' is true
&&1381((prv_data

32.2

'prv_data' is null

32.2

'prv_data' is null
&& ( /* This packet has been parsed */1382/* and now we are in a HTTP request chunk stream */1383(prv_data->req_fwd_flow == direction && prv_data->req_streaming_reassembly_data) ||1384/* and now we are in a HTTP response chunk stream */1385(prv_data->req_fwd_flow != direction && prv_data->res_streaming_reassembly_data)))1386||1387(tail_prv_data

32.3

'tail_prv_data' is null

32.3

'tail_prv_data' is null
&& ( /* This packet has not been parsed and headers info in conv_data->req_res_tail */1388/* and now we are in a HTTP request chunk stream */1389(tail_prv_data->req_fwd_flow == direction && tail_prv_data->req_streaming_reassembly_data) ||1390/* and now we are in a HTTP response chunk stream */1391(tail_prv_data->req_fwd_flow != direction && tail_prv_data->res_streaming_reassembly_data)))))1392{1393streaming_chunk_mode = true1;1394}1395}1396 1397/*1398 * Is the first line a request or response?1399 *1400 * Note that "tvb_find_line_end()" will return a value that1401 * is not longer than what's in the buffer, so the1402 * "tvb_get_ptr()" call won't throw an exception.1403 */1404firstline = tvb_get_ptr(tvb, offset, first_linelen);1405http_type = MEDIA_CONTAINER_HTTP_OTHERS;/* type not known yet */1406is_request_or_reply = is_http_request_or_reply(pinfo, (const char *)firstline,

33

Calling 'is_http_request_or_reply'

39

Returning from 'is_http_request_or_reply'

1407 first_linelen, &http_type, NULL((void*)0), conv_data);1408if (is_request_or_reply

39.1

'is_request_or_reply' is true

39.1

'is_request_or_reply' is true
|| streaming_chunk_mode) {1409bool_Bool try_desegment_body;1410 1411if (streaming_chunk_mode

39.2

'streaming_chunk_mode' is false

39.2

'streaming_chunk_mode' is false
&& begin_with_chunk) {1412col_set_str(pinfo->cinfo, COL_INFO, "Chunk Stream ");1413} else {1414/*1415 * Yes, it's a request or response.1416 * Put the first line from the buffer into the summary1417 * (but leave out the line terminator).1418 */1419col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", format_text(pinfo->pool, firstline, first_linelen));1420}1421 1422/*1423 * Do header desegmentation if we've been told to,1424 * and do body desegmentation if we've been told to and1425 * we find a Content-Length header in requests.1426 *1427 * The following cases (from RFC 7230, Section 3.3) never have a1428 * response body, so do not attempt to desegment the body for:1429 * * Responses to HEAD requests.1430 * * 2xx responses to CONNECT requests.1431 * * 1xx, 204 No Content, 304 Not Modified responses.1432 *1433 * Additionally if we are at the end of stream, no more segments1434 * will be added so disable body segmentation too in that case.1435 */1436try_desegment_body = (http_desegment_body && !end_of_stream);

40

Assuming 'http_desegment_body' is false

1437if (try_desegment_body

40.1

'try_desegment_body' is false

40.1

'try_desegment_body' is false
&& http_type == MEDIA_CONTAINER_HTTP_RESPONSE && !streaming_chunk_mode) {1438/*1439 * The response_code is not yet set, so extract1440 * the response code from the current line.1441 */1442int response_code = parse_http_status_code(firstline, firstline + first_linelen);1443/*1444 * On a second pass, we should have already associated1445 * the response with the request. On a first sequential1446 * pass, we haven't done so yet (as we don't know if we1447 * need more data), so get the request method from the1448 * most recent request, if it exists.1449 */1450char* request_method = NULL((void*)0);1451if (curr) {1452request_method = curr->request_method;1453} else if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && conv_data->req_res_tail) {1454request_method = conv_data->req_res_tail->request_method;1455}1456if ((g_strcmp0(request_method, "HEAD") == 0 ||1457(response_code / 100 == 2 &&1458(g_strcmp0(request_method, "CONNECT") == 0 ||1459 g_strcmp0(request_method, "SSTP_DUPLEX_POST") == 0)) ||1460response_code / 100 == 1 ||1461response_code == 204 ||1462response_code == 304)) {1463/* No response body is present. */1464try_desegment_body = false0;1465}1466}1467if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,

41

Assuming the condition is false

1468 http_desegment_headers, try_desegment_body, http_type == MEDIA_CONTAINER_HTTP_RESPONSE, &chunk_offset,1469streaming_content_type_dissector_table, &handle)) {1470/*1471 * More data needed for desegmentation.1472 */1473if (seq && chunk_map && chunk_offset) {1474wmem_map_insert(chunk_map, GUINT_TO_POINTER(*seq)((gpointer) (gulong) (*seq)), GINT_TO_POINTER(chunk_offset)((gpointer) (glong) (chunk_offset)));1475}1476return -1;1477}1478 1479if (handle && http_desegment_body && http_dechunk_body) {

42

Assuming 'handle' is non-null

43

Assuming 'http_desegment_body' is true

44

Assuming 'http_dechunk_body' is true

45

Taking true branch

1480/* This handle is set because there is a header 'Transfer-Encoding: chunked', and1481 * a streaming mode reassembly supported subdissector is found according to the1482 * header of Content-Type.1483 */1484streaming_chunk_mode = true1;1485}1486} else if (have_seen_http) {1487/*1488 * If we know this is HTTP then call it continuation.1489 */1490/* If orig_offset > 0, this isn't the first message dissected1491 * in this segment, which means we had a Content-Length, but1492 * more data after the body. If this isn't a request or reply,1493 * that's bogus, and probably means the Content-Length was1494 * wrong.1495 */1496if (orig_offset > 0) {1497excess_data = true1;1498}1499col_set_str(pinfo->cinfo, COL_INFO, "Continuation");1500}1501 1502if (is_request_or_reply

45.1

'is_request_or_reply' is true

45.1

'is_request_or_reply' is true
|| have_seen_http || streaming_chunk_mode) {1503/*1504 * Now set COL_PROTOCOL and create the http tree for the1505 * cases where we set COL_INFO above.1506 */1507col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);1508ti = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA0x00000000);1509http_tree = proto_item_add_subtree(ti, ett_http);1510 1511if (leading_crlf

45.2

'leading_crlf' is false

45.2

'leading_crlf' is false
) {

46

Taking false branch

1512proto_tree_add_expert(http_tree, pinfo, &ei_http_leading_crlf, tvb, offset-2, 2);1513}1514if (excess_data

46.1

'excess_data' is false

46.1

'excess_data' is false
) {

47

Taking false branch

1515proto_tree_add_expert(http_tree, pinfo, &ei_http_excess_data, tvb, offset, tvb_captured_length_remaining(tvb, offset));1516}1517}1518 1519is_tls = proto_is_frame_protocol(pinfo->layers, "tls");1520 1521if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && begin_with_chunk

48

Assuming field 'visited' is not equal to 0

1522&& streaming_chunk_mode && conv_data->req_res_tail) {1523/* point this packet beginning with a chunk to req_res info created in previous packet. */1524curr = conv_data->req_res_tail;1525prv_data = (http_req_res_private_data_t*)curr->private_data;1526p_set_proto_data(wmem_file_scope(), pinfo, proto_http, HTTP_PROTO_DATA_REQRES0, curr);1527}1528 1529if (prv_data

48.1

'prv_data' is null

48.1

'prv_data' is null
) {1530if (prv_data->req_fwd_flow == direction && prv_data->req_streaming_reassembly_data) {1531/* in request flow */1532streaming_reassembly_data = prv_data->req_streaming_reassembly_data;1533} else if (prv_data->req_fwd_flow != direction && prv_data->res_streaming_reassembly_data) {1534/* in response flow */1535streaming_reassembly_data = prv_data->res_streaming_reassembly_data;1536}1537 1538if (streaming_reassembly_data) {1539streaming_chunk_mode = true1;1540headers = streaming_reassembly_data->main_headers;1541handle = streaming_reassembly_data->streaming_handle;1542content_info = streaming_reassembly_data->content_info;1543header_value_map = (wmem_map_t*) content_info->data;1544}1545}1546 1547if (streaming_chunk_mode

48.2

'streaming_chunk_mode' is true

48.2

'streaming_chunk_mode' is true
&& begin_with_chunk

48.3

'begin_with_chunk' is true

48.3

'begin_with_chunk' is true
) {

49

Taking true branch

1548datalen = reported_length;1549goto dissecting_body;

50

Control jumps to line 2045

1550}1551 1552stat_info = wmem_new(pinfo->pool, http_info_value_t)((http_info_value_t*)wmem_alloc((pinfo->pool), sizeof(http_info_value_t
)))
;1553stat_info->framenum = pinfo->num;1554stat_info->response_code = 0;1555stat_info->request_method = NULL((void*)0);1556stat_info->request_uri = NULL((void*)0);1557stat_info->referer_uri = NULL((void*)0);1558stat_info->http_host = NULL((void*)0);1559stat_info->full_uri = NULL((void*)0);1560stat_info->location_target = NULL((void*)0);1561stat_info->location_base_uri = NULL((void*)0);1562p_set_proto_data(pinfo->pool, pinfo, proto_http, HTTP_PROTO_DATA_INFO1, (void *)stat_info);1563 1564/*1565 * Process the packet data, a line at a time.1566 */1567http_type = MEDIA_CONTAINER_HTTP_OTHERS;/* type not known yet */1568if (headers == NULL((void*)0)) {1569DISSECTOR_ASSERT_HINT(!PINFO_FD_VISITED(pinfo) || (PINFO_FD_VISITED(pinfo) && !streaming_chunk_mode),((void) ((!((pinfo)->fd->visited) || (((pinfo)->fd->
visited) && !streaming_chunk_mode)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/dissectors/packet-http.c"
, 1570, "!((pinfo)->fd->visited) || (((pinfo)->fd->visited) && !streaming_chunk_mode)"
, "The headers variable should not be NULL if it is in streaming mode during a non first scan."
))))
1570"The headers variable should not be NULL if it is in streaming mode during a non first scan.")((void) ((!((pinfo)->fd->visited) || (((pinfo)->fd->
visited) && !streaming_chunk_mode)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/dissectors/packet-http.c"
, 1570, "!((pinfo)->fd->visited) || (((pinfo)->fd->visited) && !streaming_chunk_mode)"
, "The headers variable should not be NULL if it is in streaming mode during a non first scan."
))))
;1571DISSECTOR_ASSERT_HINT(header_value_map == NULL, "The header_value_map variable should be NULL while headers is NULL.")((void) ((header_value_map == ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/dissectors/packet-http.c"
, 1571, "header_value_map == ((void*)0)", "The header_value_map variable should be NULL while headers is NULL."
))))
;1572 1573headers = wmem_new0((streaming_chunk_mode ? wmem_file_scope() : pinfo->pool), headers_t)((headers_t*)wmem_alloc0(((streaming_chunk_mode ? wmem_file_scope
() : pinfo->pool)), sizeof(headers_t)))
;1574header_value_map = wmem_map_new((streaming_chunk_mode ? wmem_file_scope() : pinfo->pool), g_str_hash, g_str_equal);1575}1576 1577saw_req_resp_or_header = false0;/* haven't seen anything yet */1578while (tvb_offset_exists(tvb, offset)) {1579/*1580 * Find the end of the line.1581 * XXX - what if we don't find it because the packet1582 * is cut short by a snapshot length or the header is1583 * split across TCP segments? How much dissection should1584 * we do on it?1585 */1586linelen = tvb_find_line_end(tvb, offset,1587 tvb_ensure_captured_length_remaining(tvb, offset), &next_offset,1588 false0);1589if (linelen < 0)1590return -1;1591 1592/*1593 * Get a buffer that refers to the line.1594 *1595 * Note that "tvb_find_line_end()" will return a value that1596 * is not longer than what's in the buffer, so the1597 * "tvb_get_ptr()" call won't throw an exception.1598 */1599line = tvb_get_ptr(tvb, offset, linelen);1600lineend = line + linelen;1601colon_offset = -1;1602 1603/*1604 * OK, does it look like an HTTP request or response?1605 */1606reqresp_dissector = NULL((void*)0);1607is_request_or_reply =1608 is_http_request_or_reply(pinfo, (const char *)line,1609 linelen, &http_type, &reqresp_dissector, conv_data);1610if (is_request_or_reply)1611goto is_http;1612 1613/*1614 * No. Does it look like a blank line (as would appear1615 * at the end of an HTTP request)?1616 */1617if (linelen == 0)1618goto is_http;/* Yes. */1619 1620/*1621 * No. Does it look like a header?1622 */1623colon_offset = offset;1624 1625linep = (const unsigned char *)memchr(line, ':', linelen);1626if (linep) {1627/*1628 * Colon found, assume it is a header if we've seen a1629 * valid line before. Check a little more if not.1630 */1631if (saw_req_resp_or_header || valid_header_name(line, (int)(linep - line))) {1632colon_offset += (int)(linep - line);1633if (http_check_ascii_headers) {1634int i;1635for (i = 0; i < linelen; i++) {1636if (line[i] & 0x80) {1637/*1638 * Non-ASCII! Return -2 for invalid1639 * HTTP, distinct from -1 for possible1640 * reassembly required.1641 */1642return -2;1643}1644}1645}1646goto is_http;1647}1648}1649 1650/*1651 * We haven't seen the colon yet.1652 *1653 * If we've already seen an HTTP request or response1654 * line, or a header line, and we're at the end of1655 * the tvbuff, we assume this is an incomplete header1656 * line. (We quit this loop after seeing a blank line,1657 * so if we've seen a request or response line, or a1658 * header line, this is probably more of the request1659 * or response we're presumably seeing. There is some1660 * risk of false positives, but the same applies for1661 * full request or response lines or header lines,1662 * although that's less likely.)1663 *1664 * We throw an exception in that case, by checking for1665 * the existence of the next byte after the last one1666 * in the line. If it exists, "tvb_ensure_bytes_exist()"1667 * throws no exception, and we fall through to the1668 * "not HTTP" case. If it doesn't exist,1669 * "tvb_ensure_bytes_exist()" will throw the appropriate1670 * exception.1671 */1672if (saw_req_resp_or_header)1673tvb_ensure_bytes_exist(tvb, offset, linelen + 1);1674 1675/*1676 * We don't consider this part of an HTTP request or1677 * reply, so we don't display it.1678 * (Yeah, that means we don't display, say, a text/http1679 * page, but you can get that from the data pane.)1680 */1681break;1682 1683is_http:1684if ((tree) && (http_tree == NULL((void*)0))) {1685ti = proto_tree_add_item(tree, proto, tvb, orig_offset, -1, ENC_NA0x00000000);1686http_tree = proto_item_add_subtree(ti, ett_http);1687if (leading_crlf) {1688proto_tree_add_expert(http_tree, pinfo, &ei_http_leading_crlf, tvb, orig_offset-2, 2);1689}1690}1691 1692if (first_loop && !is_tls && pinfo->ptype == PT_TCP &&1693(pinfo->srcport == 443 || pinfo->destport == 443)) {1694expert_add_info(pinfo, ti, &ei_http_tls_port);1695}1696 1697first_loop = false0;1698 1699/*1700 * Process this line.1701 */1702 1703if (linelen == 0) {1704/*1705 * This is a blank line, which means that1706 * whatever follows it isn't part of this1707 * request or reply.1708 */1709proto_tree_add_format_text(http_tree, tvb, offset, next_offset - offset);1710offset = next_offset;1711break;1712}1713 1714/*1715 * Not a blank line - either a request, a reply, or a header1716 * line.1717 */1718saw_req_resp_or_header = true1;1719if (is_request_or_reply) {1720char *text = tvb_format_text(pinfo->pool, tvb, offset, next_offset - offset);1721 1722req_tree = proto_tree_add_subtree(http_tree, tvb,1723 offset, next_offset - offset, ett_http_request, &hdr_item, text);1724 1725if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {1726if (http_type == MEDIA_CONTAINER_HTTP_REQUEST) {1727curr = push_req(conv_data, pinfo);1728curr->request_method = wmem_strdup(wmem_file_scope(), stat_info->request_method);1729prv_data = curr->private_data;1730prv_data->req_fwd_flow = direction;1731} else if (http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {1732curr = push_res(conv_data, pinfo);1733prv_data = curr->private_data;1734prv_data->req_fwd_flow = -direction;1735}1736}1737if (reqresp_dissector) {1738reqresp_dissector(pinfo, tvb, req_tree, offset, line,1739 lineend, conv_data, curr);1740}1741} else {1742/*1743 * Header.1744 */1745bool_Bool good_header = process_header(tvb, offset, next_offset, line, linelen,1746 colon_offset, pinfo, http_tree, headers, conv_data,1747 http_type, header_value_map, streaming_chunk_mode);1748if (http_check_ascii_headers && !good_header) {1749/*1750 * Line is not a good HTTP header.1751 * Return -2 to mark as invalid HTTP;1752 * this is distinct from returning -1 when1753 * it may be HTTP but in need of reassembly.1754 */1755return -2;1756}1757}1758offset = next_offset;1759}1760if (stat_info->http_host && stat_info->request_uri) {1761char *uri;1762 1763if ((g_ascii_strncasecmp(stat_info->request_uri, "http://", 7) == 0) ||1764 (g_ascii_strncasecmp(stat_info->request_uri, "https://", 8) == 0) ||1765 (g_ascii_strncasecmp(stat_info->request_method, "CONNECT", 7) == 0)) {1766uri = wmem_strdup(pinfo->pool, stat_info->request_uri);1767}1768else {1769uri = wmem_strdup_printf(pinfo->pool, "%s://%s%s",1770 is_tls ? "https" : "http",1771 g_strstrip(wmem_strdup(pinfo->pool, stat_info->http_host))g_strchomp (g_strchug (wmem_strdup(pinfo->pool, stat_info->
http_host)))
, stat_info->request_uri);1772}1773stat_info->full_uri = wmem_strdup(pinfo->pool, uri);1774if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && curr) {1775 curr->full_uri = wmem_strdup(wmem_file_scope(), uri);1776}1777}1778else {1779/* If the request has a range, this is, or potentially is, asynchronous I/O thus1780* full_uri must be reinitialized because it is set to that of the last request. */1781if (curr && curr->req_has_range)1782curr->full_uri = NULL((void*)0);1783}1784if (tree) {1785proto_item *pi;1786 1787switch (http_type) {1788 1789case MEDIA_CONTAINER_HTTP_NOTIFICATION:1790hidden_item = proto_tree_add_boolean(http_tree,1791 hf_http_notification, tvb, 0, 0, 1);1792proto_item_set_hidden(hidden_item);1793break;1794 1795case MEDIA_CONTAINER_HTTP_RESPONSE:1796hidden_item = proto_tree_add_boolean(http_tree,1797 hf_http_response, tvb, 0, 0, 1);1798proto_item_set_hidden(hidden_item);1799 1800match_trans_t *match_trans = NULL((void*)0);1801 1802if (curr && curr->response_code == 206 && curr->resp_has_range) {1803/* The conv_data->matches_table is only used for GET requests with ranges and1804* response_codes of 206 (Partial Content). (Note: only GETs use ranges.)1805*/1806match_trans = (match_trans_t *)wmem_map_lookup(conv_data->matches_table,1807GUINT_TO_POINTER(pinfo->num)((gpointer) (gulong) (pinfo->num)));1808if (match_trans) {1809pi = proto_tree_add_uint(http_tree, hf_http_request_in, tvb, 0, 0,1810match_trans->req_frame);1811proto_item_set_generated(pi);1812 1813pi = proto_tree_add_time(http_tree, hf_http_time, tvb, 0, 0,1814&match_trans->delta_time);1815proto_item_set_generated(pi);1816 1817pi = proto_tree_add_string(http_tree, hf_http_request_uri, tvb, 0, 0,1818match_trans->request_uri);1819proto_item_set_generated(pi);1820{1821char *uri;1822uri = wmem_strdup_printf(pinfo->pool, "%s://%s%s",1823 is_tls ? "https" : "http",1824g_strstrip(wmem_strdup(pinfo->pool, match_trans->http_host))g_strchomp (g_strchug (wmem_strdup(pinfo->pool, match_trans
->http_host)))
, match_trans->request_uri);1825 1826pi = proto_tree_add_string(http_tree, hf_http_request_full_uri, tvb, 0, 0,1827uri);1828proto_item_set_url(pi);1829proto_item_set_generated(pi);1830}1831}1832}1833 1834/* If responses don't have a range, the I/O is synchronous in which case a request is1835* matched with the following response. If a request or response is missing from the1836* capture file, correct matching resumes at the next request. */1837if(!match_trans1838&& curr1839&& !curr->resp_has_range1840&& curr->req_framenum) {1841pi = proto_tree_add_uint(http_tree, hf_http_request_in, tvb, 0, 0, curr->req_framenum);1842proto_item_set_generated(pi);1843 1844if (! nstime_is_unset(&(curr->req_ts))) {1845nstime_t delta;1846 1847nstime_delta(&delta, &pinfo->abs_ts, &(curr->req_ts));1848pi = proto_tree_add_time(http_tree, hf_http_time, tvb, 0, 0, &delta);1849proto_item_set_generated(pi);1850}1851if (curr->request_uri) {1852pi = proto_tree_add_string(http_tree, hf_http_request_uri, tvb, 0, 0,1853curr->request_uri);1854proto_item_set_generated(pi);1855}1856if (curr->full_uri) {1857pi = proto_tree_add_string(http_tree, hf_http_request_full_uri, tvb, 0, 0,1858curr->full_uri);1859proto_item_set_url(pi);1860proto_item_set_generated(pi);1861}1862}1863break;1864case MEDIA_CONTAINER_HTTP_REQUEST:1865{1866int size = wmem_map_size(conv_data->matches_table);1867 1868hidden_item = proto_tree_add_boolean(http_tree,hf_http_request, tvb, 0, 0, 1);1869proto_item_set_hidden(hidden_item);1870 1871match_trans = NULL((void*)0);1872if (curr) {1873if (size > 0 && curr->req_has_range) {1874match_trans = (match_trans_t *)wmem_map_lookup(conv_data->matches_table,1875GUINT_TO_POINTER(pinfo->num)((gpointer) (gulong) (pinfo->num)));1876if (match_trans) {1877pi = proto_tree_add_uint(http_tree, hf_http_response_in,1878tvb, 0, 0, match_trans->resp_frame);1879proto_item_set_generated(pi);1880}1881}1882else {1883if(!match_trans1884&& !curr->resp_has_range1885&& curr->res_framenum) {1886pi = proto_tree_add_uint(http_tree, hf_http_response_in, tvb, 0, 0, curr->res_framenum);1887proto_item_set_generated(pi);1888 1889}1890}1891 1892if (curr->full_uri) {1893pi = proto_tree_add_string(http_tree, hf_http_request_full_uri, tvb, 0, 0,1894curr->full_uri);1895proto_item_set_url(pi);1896proto_item_set_generated(pi);1897}1898else if (stat_info->full_uri){1899pi = proto_tree_add_string(http_tree, hf_http_request_full_uri, tvb, 0, 0,1900stat_info->full_uri);1901proto_item_set_url(pi);1902proto_item_set_generated(pi);1903}1904}1905}1906break;1907 1908case MEDIA_CONTAINER_HTTP_OTHERS:1909default:1910break;1911}1912}1913 1914/* Give the follow tap what we've currently dissected */1915if(have_tap_listener(http_follow_tap)) {1916tap_queue_packet(http_follow_tap, pinfo, tvb_new_subset_length(tvb, orig_offset, offset-orig_offset));1917}1918 1919reported_datalen = tvb_reported_length_remaining(tvb, offset);1920datalen = tvb_captured_length_remaining(tvb, offset);1921 1922/*1923 * If a content length was supplied, the amount of data to be1924 * processed as HTTP payload is the minimum of the content1925 * length and the amount of data remaining in the frame.1926 *1927 * If a message is received with both a Transfer-Encoding1928 * header field and a Content-Length header field, the latter1929 * MUST be ignored.1930 *1931 * If no content length was supplied (or if a bad content length1932 * was supplied), the amount of data to be processed is the amount1933 * of data remaining in the frame.1934 *1935 * If there was no Content-Length entity header, we should1936 * accumulate all data until the end of the connection.1937 * That'd require that the TCP dissector call subdissectors1938 * for all frames with FIN, even if they contain no data,1939 * which would require subdissectors to deal intelligently1940 * with empty segments.1941 *1942 * According to RFC 2616, however, 1xx responses, 204 responses,1943 * and 304 responses MUST NOT include a message body; if no1944 * content length is specified for them, we don't attempt to1945 * dissect the body.1946 *1947 * XXX - it says the same about responses to HEAD requests;1948 * unless there's a way to determine from the response1949 * whether it's a response to a HEAD request, we have to1950 * keep information about the request and associate that with1951 * the response in order to handle that.1952 */1953if (headers->have_content_length &&1954 headers->transfer_encoding == HTTP_TE_NONE) {1955if (datalen > headers->content_length)1956datalen = (int)headers->content_length;1957 1958/*1959 * XXX - limit the reported length in the tvbuff we'll1960 * hand to a subdissector to be no greater than the1961 * content length.1962 *1963 * We really need both unreassembled and "how long it'd1964 * be if it were reassembled" lengths for tvbuffs, so1965 * that we throw the appropriate exceptions for1966 * "not enough data captured" (running past the length),1967 * "packet needed reassembly" (within the length but1968 * running past the unreassembled length), and1969 * "packet is malformed" (running past the reassembled1970 * length).1971 */1972if (reported_datalen > headers->content_length)1973reported_datalen = (int)headers->content_length;1974} else {1975switch (http_type) {1976 1977case MEDIA_CONTAINER_HTTP_REQUEST:1978/*1979 * Requests have no content if there's no1980 * Content-Length header and no Transfer-Encoding1981 * header.1982 */1983if (headers->transfer_encoding == HTTP_TE_NONE)1984datalen = 0;1985else1986reported_datalen = -1;1987break;1988 1989case MEDIA_CONTAINER_HTTP_RESPONSE:1990if ((stat_info->response_code/100) == 1 ||1991 stat_info->response_code == 204 ||1992 stat_info->response_code == 304)1993datalen = 0;/* no content! */1994else {1995/*1996 * XXX - responses to HEAD requests,1997 * and possibly other responses,1998 * "MUST NOT" include a1999 * message-body.2000 */2001reported_datalen = -1;2002}2003break;2004 2005default:2006/*2007 * XXX - what about MEDIA_CONTAINER_HTTP_NOTIFICATION?2008 */2009reported_datalen = -1;2010break;2011}2012}2013 2014if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && streaming_chunk_mode && streaming_reassembly_data == NULL((void*)0)) {2015DISSECTOR_ASSERT(!begin_with_chunk && handle && http_dechunk_body && http_desegment_body((void) ((!begin_with_chunk && handle && http_dechunk_body
&& http_desegment_body && headers &&
headers->content_type && header_value_map) ? (void
)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-http.c", 2016, "!begin_with_chunk && handle && http_dechunk_body && http_desegment_body && headers && headers->content_type && header_value_map"
))))
2016&& headers && headers->content_type && header_value_map)((void) ((!begin_with_chunk && handle && http_dechunk_body
&& http_desegment_body && headers &&
headers->content_type && header_value_map) ? (void
)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-http.c", 2016, "!begin_with_chunk && handle && http_dechunk_body && http_desegment_body && headers && headers->content_type && header_value_map"
))))
;2017 2018content_info = wmem_new0(wmem_file_scope(), media_content_info_t)((media_content_info_t*)wmem_alloc0((wmem_file_scope()), sizeof
(media_content_info_t)))
;2019content_info->media_str = headers->content_type_parameters;2020content_info->type = http_type;2021content_info->data = header_value_map;2022 2023streaming_reassembly_data = wmem_new0(wmem_file_scope(), http_streaming_reassembly_data_t)((http_streaming_reassembly_data_t*)wmem_alloc0((wmem_file_scope
()), sizeof(http_streaming_reassembly_data_t)))
;2024streaming_reassembly_data->streaming_handle = handle;2025streaming_reassembly_data->streaming_reassembly_info = streaming_reassembly_info_new();2026streaming_reassembly_data->content_info = content_info;2027streaming_reassembly_data->main_headers = headers;2028 2029if (prv_data->req_fwd_flow == direction) {2030prv_data->req_streaming_reassembly_data = streaming_reassembly_data;2031} else {2032prv_data->res_streaming_reassembly_data = streaming_reassembly_data;2033}2034}2035 2036if (content_info == NULL((void*)0)) {2037content_info = wmem_new0(pinfo->pool, media_content_info_t)((media_content_info_t*)wmem_alloc0((pinfo->pool), sizeof(
media_content_info_t)))
;2038content_info->media_str = headers->content_type_parameters;2039content_info->type = http_type;2040content_info->data = header_value_map;2041}2042 2043dissecting_body:2044 2045if (datalen

50.1

'datalen' is > 0

50.1

'datalen' is > 0
> 0) {

51

Taking true branch

2046/*2047 * There's stuff left over; process it.2048 */2049tvbuff_t *next_tvb;2050unsigned chunked_datalen = 0;2051int data_len;2052 2053/*2054 * Create a tvbuff for the payload.2055 *2056 * The amount of data to be processed that's2057 * available in the tvbuff is "datalen", which2058 * is the minimum of the amount of data left in2059 * the tvbuff and any specified content length.2060 *2061 * The amount of data to be processed that's in2062 * this frame, regardless of whether it was2063 * captured or not, is "reported_datalen",2064 * which, if no content length was specified,2065 * is -1, i.e. "to the end of the frame.2066 */2067next_tvb = tvb_new_subset_length_caplen(tvb, offset, datalen,2068 reported_datalen);2069 2070/*2071 * Handle *transfer* encodings.2072 */2073if (headers

51.1

'headers' is null

51.1

'headers' is null
&& headers->transfer_encoding_chunked) {2074if (!http_dechunk_body) {2075/* Chunking disabled, cannot dissect further. */2076/* XXX: Should this be sent to the follow tap? */2077call_data_dissector(next_tvb, pinfo, http_tree);2078goto body_dissected;2079}2080 2081chunked_datalen = chunked_encoding_dissector(2082 &next_tvb, pinfo, http_tree, 0);2083 2084if (chunked_datalen == 0) {2085/*2086 * The chunks weren't reassembled,2087 * or there was a single zero2088 * length chunk.2089 */2090goto body_dissected;2091} else {2092/*2093 * Add a new data source for the2094 * de-chunked data.2095 */2096#if 0 /* Handled in chunked_encoding_dissector() */2097tvb_set_child_real_data_tvbuff(tvb,2098next_tvb);2099#endif2100add_new_data_source(pinfo, next_tvb,2101"De-chunked entity body");2102/* chunked-body might be smaller than2103 * datalen. */2104datalen = chunked_datalen;2105}2106}2107/* Handle other transfer codings after de-chunking. */2108switch (headers->transfer_encoding) {

52

Access to field 'transfer_encoding' results in a dereference of a null pointer (loaded from variable 'headers')
2109case HTTP_TE_COMPRESS:2110case HTTP_TE_DEFLATE:2111case HTTP_TE_GZIP:2112/*2113 * We currently can't handle, for example, "gzip",2114 * "compress", or "deflate" as *transfer* encodings;2115 * just handle them as data for now.2116 * XXX: Should this be sent to the follow tap?2117 */2118call_data_dissector(next_tvb, pinfo, http_tree);2119goto body_dissected;2120default:2121/* Nothing to do for "identity" or when header is2122 * missing or invalid. */2123break;2124}2125/*2126 * At this point, any chunked *transfer* coding has been removed2127 * (the entity body has been dechunked) so it can be presented2128 * for the following operation (*content* encoding), or it has2129 * been handed off to the data dissector.2130 *2131 * Handle *content* encodings other than "identity" (which2132 * shouldn't appear in a Content-Encoding header, but2133 * we handle it in any case).2134 */2135if (headers->content_encoding != NULL((void*)0) &&2136 g_ascii_strcasecmp(headers->content_encoding, "identity") != 0) {2137/*2138 * We currently don't handle, for example, "compress";2139 * just handle them as data for now.2140 *2141 * After July 7, 2004 the LZW patent expired, so2142 * support could be added. However, I don't think2143 * that anybody ever really implemented "compress",2144 * due to the aforementioned patent.2145 */2146tvbuff_t *uncomp_tvb = NULL((void*)0);2147proto_item *e_ti = NULL((void*)0);2148proto_tree *e_tree = NULL((void*)0);2149 2150#if defined(HAVE_ZLIB1) || defined(HAVE_ZLIBNG)2151if (http_decompress_body &&2152 (g_ascii_strcasecmp(headers->content_encoding, "gzip") == 0 ||2153 g_ascii_strcasecmp(headers->content_encoding, "deflate") == 0 ||2154 g_ascii_strcasecmp(headers->content_encoding, "x-gzip") == 0 ||2155 g_ascii_strcasecmp(headers->content_encoding, "x-deflate") == 0))2156{2157uncomp_tvb = tvb_child_uncompress_zlib(tvb, next_tvb, 0,2158 tvb_captured_length(next_tvb));2159}2160#endif2161 2162#ifdef HAVE_BROTLI12163if (http_decompress_body &&2164 g_ascii_strcasecmp(headers->content_encoding, "br") == 0)2165{2166uncomp_tvb = tvb_child_uncompress_brotli(tvb, next_tvb, 0,2167 tvb_captured_length(next_tvb));2168}2169#endif2170 2171#ifdef HAVE_SNAPPY12172if (http_decompress_body &&2173 g_ascii_strcasecmp(headers->content_encoding, "snappy") == 0)2174{2175uncomp_tvb = tvb_child_uncompress_snappy(tvb, next_tvb, 0,2176 tvb_captured_length(next_tvb));2177}2178#endif2179 2180/*2181 * Add the encoded entity to the protocol tree2182 */2183e_tree = proto_tree_add_subtree_format(http_tree, next_tvb,21840, tvb_captured_length(next_tvb), ett_http_encoded_entity, &e_ti,2185"Content-encoded entity body (%s): %u bytes",2186headers->content_encoding,2187tvb_captured_length(next_tvb));2188 2189if (uncomp_tvb != NULL((void*)0)) {2190/*2191 * Decompression worked2192 */2193 2194/* XXX - Don't free this, since it's possible2195 * that the data was only partially2196 * decompressed, such as when desegmentation2197 * isn't enabled.2198 *2199tvb_free(next_tvb);2200*/2201proto_item_append_text(e_ti, " -> %u bytes", tvb_captured_length(uncomp_tvb));2202next_tvb = uncomp_tvb;2203add_new_data_source(pinfo, next_tvb,2204 "Uncompressed entity body");2205} else {2206#if defined(HAVE_ZLIB1) || defined(HAVE_ZLIBNG) || defined(HAVE_BROTLI1)2207if (http_decompress_body) {2208expert_add_info(pinfo, e_ti, &ei_http_decompression_failed);2209}2210else {2211expert_add_info(pinfo, e_ti, &ei_http_decompression_disabled);2212}2213#endif2214/* XXX: Should this be sent to the follow tap? */2215call_data_dissector(next_tvb, pinfo, e_tree);2216 2217goto body_dissected;2218}2219}2220/*2221 * Note that a new data source is added for the entity body2222 * only if it was content-encoded and/or transfer-encoded.2223 */2224 2225/* Save values for the Export Object GUI feature if we have2226 * an active listener to process it (which happens when2227 * the export object window is open). */2228/* XXX: Do we really want to send it to Export Object if we didn't2229 * get the headers, so that this is just a fragment of Continuation2230 * Data and not a complete object?2231 */2232if(have_tap_listener(http_eo_tap)) {2233eo_info = wmem_new0(pinfo->pool, http_eo_t)((http_eo_t*)wmem_alloc0((pinfo->pool), sizeof(http_eo_t))
)
;2234 2235if (curr) {2236eo_info->hostname = curr->http_host;2237eo_info->filename = curr->request_uri;2238}2239eo_info->content_type = headers->content_type;2240eo_info->payload = next_tvb;2241 2242tap_queue_packet(http_eo_tap, pinfo, eo_info);2243}2244 2245/* Send it to Follow HTTP Stream and mark as file data */2246if(have_tap_listener(http_follow_tap)) {2247tap_queue_packet(http_follow_tap, pinfo, next_tvb);2248}2249data_len = tvb_captured_length(next_tvb);2250proto_tree_add_bytes_format_value(http_tree, hf_http_file_data,2251next_tvb, 0, data_len, NULL((void*)0), "%u byte%s", data_len, plurality(data_len, "", "s")((data_len) == 1 ? ("") : ("s")));2252 2253if (tvb_captured_length(next_tvb) == 0)2254goto body_dissected;2255 2256/*2257 * Do subdissector checks.2258 *2259 * First, if we have a Content-Type value, check whether2260 * there's a subdissector for that media type.2261 */2262if (headers->content_type != NULL((void*)0) && handle == NULL((void*)0)) {2263/*2264 * We didn't find any subdissector that2265 * registered for the port, and we have a2266 * Content-Type value. Is there any subdissector2267 * for that content type?2268 */2269 2270/*2271 * Calling the string handle for the media type2272 * dissector table will set pinfo->match_string2273 * to headers->content_type for us.2274 */2275pinfo->match_string = headers->content_type;2276handle = dissector_get_string_handle(2277 media_type_subdissector_table,2278 headers->content_type);2279if (handle == NULL((void*)0) &&2280 strncmp(headers->content_type, "multipart/", sizeof("multipart/")-1) == 0) {2281/* Try to decode the unknown multipart subtype anyway */2282handle = dissector_get_string_handle(2283 media_type_subdissector_table,2284 "multipart/");2285}2286}2287 2288/*2289 * Now, if we didn't find such a subdissector, check2290 * whether some subdissector asked that they be called2291 * if HTTP traffic was on some particular port. This2292 * handles protocols that use HTTP syntax but don't have2293 * a media type and instead use a specified port.2294 */2295if (handle == NULL((void*)0)) {2296/* If the HTTP dissector was called heuristically2297 * (or the HTTP dissector was called from the TLS2298 * dissector, which was called heuristically), then2299 * match_uint doesn't get set (or is likely set to2300 * 6 for IP_PROTO_TCP.) Some protocols (e.g., IPP)2301 * use the same specified port for both HTTP and2302 * HTTP over TLS, and one will be a heuristic match.2303 * In those cases, look at the src or dest port.2304 */2305if (pinfo->match_uint == pinfo->srcport || pinfo->match_uint == pinfo->destport) {2306handle = dissector_get_uint_handle(port_subdissector_table,2307 pinfo->match_uint);2308} else if (http_type == MEDIA_CONTAINER_HTTP_REQUEST) {2309handle = dissector_get_uint_handle(port_subdissector_table,2310 pinfo->destport);2311} else if (http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {2312handle = dissector_get_uint_handle(port_subdissector_table,2313 pinfo->srcport);2314}2315}2316 2317if (handle != NULL((void*)0)) {2318/*2319 * We have a subdissector - call it.2320 */2321if (streaming_chunk_mode) {2322pinfo->match_string = headers->content_type;2323/* reassemble and call subdissector */2324dissected = (bool_Bool)reassemble_streaming_data_and_call_subdissector(next_tvb, pinfo, 0,2325tvb_reported_length_remaining(next_tvb, 0), http_tree, proto_tree_get_parent_tree(tree),2326http_streaming_reassembly_table, streaming_reassembly_data->streaming_reassembly_info,2327get_http_chunk_frame_numget_virtual_frame_num64(tvb, pinfo, offset), handle,2328proto_tree_get_parent_tree(tree), content_info,2329"HTTP", &http_body_fragment_items, hf_http_body_segment);2330} else {2331dissected = (bool_Bool)call_dissector_only(handle, next_tvb, pinfo, tree, content_info);2332}2333if (!dissected)2334expert_add_info(pinfo, http_tree, &ei_http_subdissector_failed);2335}2336 2337if (!dissected) {2338/*2339 * We don't have a subdissector or we have one and it did not2340 * dissect the payload - try the heuristic subdissectors.2341 */2342dissected = dissector_try_heuristic(heur_subdissector_list,2343 next_tvb, pinfo, tree, &hdtbl_entry, content_info);2344}2345 2346if (dissected) {2347/*2348 * The subdissector dissected the body.2349 * Fix up the top-level item so that it doesn't2350 * include the stuff for that protocol.2351 */2352if (ti != NULL((void*)0))2353proto_item_set_len(ti, offset);2354} else {2355if (headers->content_type != NULL((void*)0)) {2356/*2357 * Calling the default media handle if there is a content-type that2358 * wasn't handled above.2359 */2360call_dissector_with_data(media_handle, next_tvb, pinfo, tree, content_info);2361} else {2362/* Call the default data dissector */2363call_data_dissector(next_tvb, pinfo, http_tree);2364}2365}2366 2367body_dissected:2368/*2369 * We've processed "datalen" bytes worth of data2370 * (which may be no data at all); advance the2371 * offset past whatever data we've processed.2372 */2373offset += datalen;2374}2375 2376/* Detect protocol changes after receiving full response headers. */2377if (http_type == MEDIA_CONTAINER_HTTP_RESPONSE && curr && pinfo->desegment_offset <= 0 && pinfo->desegment_len <= 0) {2378dissector_handle_t next_handle = NULL((void*)0);2379bool_Bool server_acked = false0;2380 2381/*2382 * SSTP uses a special request method (instead of the Upgrade2383 * header) and expects a 200 response to set up the session.2384 */2385if (g_strcmp0(curr->request_method, "SSTP_DUPLEX_POST") == 0 && curr->response_code == 200) {2386next_handle = sstp_handle;2387server_acked = true1;2388}2389 2390/*2391 * An HTTP/1.1 upgrade only proceeds if the server responds2392 * with 101 Switching Protocols. See RFC 7230 Section 6.7.2393 */2394if (headers->upgrade && curr->response_code == 101) {2395next_handle = dissector_get_string_handle(upgrade_subdissector_table, headers->upgrade);2396if (!next_handle) {2397char *slash_pos = strchr(headers->upgrade, '/');2398if (slash_pos) {2399/* Try again without version suffix. */2400next_handle = dissector_get_string_handle(upgrade_subdissector_table,2401wmem_strndup(pinfo->pool, headers->upgrade, slash_pos - headers->upgrade));2402}2403}2404server_acked = true1;2405}2406 2407if (server_acked && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {2408conv_data->startframe = pinfo->num;2409conv_data->startoffset = offset;2410conv_data->next_handle = next_handle;2411copy_address_wmem(wmem_file_scope(), &conv_data->server_addr, &pinfo->src);2412conv_data->server_port = pinfo->srcport;2413}2414}2415 2416if (stat_info)2417tap_queue_packet(http_tap, pinfo, stat_info);2418 2419return offset - orig_offset;2420}2421 2422/* This can be used to dissect an HTTP request until such time2423 * that a more complete dissector is written for that HTTP request.2424 * This simple dissector only puts the request method, URI, and2425 * protocol version into a sub-tree.2426 */2427static void2428basic_request_dissector(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,2429int offset, const unsigned char *line, const unsigned char *lineend,2430http_conv_t *conv_data _U___attribute__((unused)), http_req_res_t *curr)2431{2432const unsigned char *next_token;2433const char *request_uri;2434int tokenlen;2435proto_item* ti;2436http_info_value_t *stat_info = p_get_proto_data(pinfo->pool, pinfo, proto_http, HTTP_PROTO_DATA_INFO1);2437 2438/* The first token is the method. */2439tokenlen = get_token_len(line, lineend, &next_token);2440if (tokenlen == 0)2441return;2442proto_tree_add_item(tree, hf_http_request_method, tvb, offset, tokenlen,2443 ENC_ASCII0x00000000);2444if ((next_token - line) > 2 && next_token[-1] == ' ' && next_token[-2] == ' ') {2445 /* Two spaces in a now indicates empty URI, so roll back one here */2446 next_token--;2447}2448offset += (int) (next_token - line);2449line = next_token;2450 2451/* The next token is the URI. */2452tokenlen = get_token_len(line, lineend, &next_token);2453 2454/* Save the request URI for various later uses */2455request_uri = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII0x00000000);2456 2457if (request_uri == NULL((void*)0) && curr)2458 request_uri = curr->request_uri;2459 2460stat_info->request_uri = wmem_strdup(pinfo->pool, request_uri);2461if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && curr) {2462curr->request_uri = wmem_strdup(wmem_file_scope(), request_uri);2463}2464ti = proto_tree_add_string(tree, hf_http_request_uri, tvb, offset, tokenlen, request_uri);2465http_add_path_components_to_tree(tvb, pinfo, ti, offset, tokenlen);2466offset += (int) (next_token - line);2467line = next_token;2468 2469/* Everything to the end of the line is the version. */2470tokenlen = (int) (lineend - line);2471proto_tree_add_item(tree, hf_http_request_version, tvb, offset, tokenlen,2472 ENC_ASCII0x00000000);2473}2474 2475static int2476parse_http_status_code(const unsigned char *line, const unsigned char *lineend)2477{2478const unsigned char *next_token;2479int tokenlen;2480char response_code_chars[4];2481int32_t status_code = 0;2482 2483/*2484 * The first token is the HTTP Version.2485 */2486tokenlen = get_token_len(line, lineend, &next_token);2487if (tokenlen == 0)2488return 0;2489line = next_token;2490 2491/*2492 * The second token is the Status Code.2493 */2494tokenlen = get_token_len(line, lineend, &next_token);2495if (tokenlen != 3)2496return 0;2497 2498memcpy(response_code_chars, line, 3);2499response_code_chars[3] = '\0';2500if (!ws_strtoi32(response_code_chars, NULL((void*)0), &status_code))2501return 0;2502 2503return status_code;2504}2505 2506static void2507basic_response_dissector(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,2508int offset, const unsigned char *line, const unsigned char *lineend,2509 http_conv_t *conv_data _U___attribute__((unused)), http_req_res_t *curr)2510{2511const unsigned char *next_token;2512int tokenlen;2513char response_code_chars[4];2514proto_item *r_ti;2515http_info_value_t *stat_info = p_get_proto_data(pinfo->pool, pinfo, proto_http, HTTP_PROTO_DATA_INFO1);2516 2517/*2518 * The first token is the HTTP Version.2519 */2520tokenlen = get_token_len(line, lineend, &next_token);2521if (tokenlen == 0)2522return;2523proto_tree_add_item(tree, hf_http_response_version, tvb, offset, tokenlen,2524 ENC_ASCII0x00000000);2525/* Advance to the start of the next token. */2526offset += (int) (next_token - line);2527line = next_token;2528 2529/*2530 * The second token is the Status Code.2531 */2532tokenlen = get_token_len(line, lineend, &next_token);2533if (tokenlen < 3)2534return;2535 2536/* The Status Code characters must be copied into a null-terminated2537 * buffer for strtoul() to parse them into an unsigned integer value.2538 */2539memcpy(response_code_chars, line, 3);2540response_code_chars[3] = '\0';2541 2542stat_info->response_code =2543(unsigned)strtoul(response_code_chars, NULL((void*)0), 10);2544if (curr) {2545curr->response_code = stat_info->response_code;2546}2547 2548proto_tree_add_uint(tree, hf_http_response_code, tvb, offset, 3,2549 stat_info->response_code);2550 2551r_ti = proto_tree_add_string(tree, hf_http_response_code_desc,2552tvb, offset, 3, val_to_str(stat_info->response_code,2553vals_http_status_code, "Unknown (%d)"));2554 2555proto_item_set_generated(r_ti);2556 2557/* Advance to the start of the next token. */2558offset += (int) (next_token - line);2559line = next_token;2560 2561/*2562 * The remaining tokens in the line comprise the Reason Phrase.2563 */2564tokenlen = (int) (lineend - line);2565if (tokenlen >= 1) {2566proto_tree_add_item(tree, hf_http_response_phrase, tvb, offset,2567tokenlen, ENC_ASCII0x00000000);2568}2569}2570 2571/*2572 * Dissect the http data chunks and add them to the tree.2573 */2574static unsigned2575chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,2576 proto_tree *tree, int offset)2577{2578tvbuff_t*tvb;2579uint32_t datalen;2580uint32_t orig_datalen;2581int chunked_data_size;2582proto_tree*subtree;2583proto_item*pi_chunked = NULL((void*)0);2584uint8_t*raw_data;2585int raw_len;2586int chunk_counter = 0;2587int last_chunk_id = -1;2588 2589if ((tvb_ptr == NULL((void*)0)) || (*tvb_ptr == NULL((void*)0))) {2590return 0;2591}2592 2593tvb = *tvb_ptr;2594 2595datalen = tvb_reported_length_remaining(tvb, offset);2596 2597subtree = proto_tree_add_subtree(tree, tvb, offset, datalen,2598 ett_http_chunked_response, &pi_chunked,2599 "HTTP chunked response");2600 2601/* Dechunk the "chunked response" to a new memory buffer */2602/* XXX: Composite tvbuffers do work now, so we should probably2603 * use that to avoid the memcpys unless necessary.2604 */2605orig_datalen = datalen;2606raw_data = (uint8_t *)wmem_alloc(pinfo->pool, datalen);2607raw_len = 0;2608chunked_data_size = 0;2609 2610while (datalen > 0) {2611uint32_t chunk_size;2612int chunk_offset;2613uint8_t *chunk_string;2614int linelen;2615char *c;2616 2617linelen = tvb_find_line_end(tvb, offset, -1, &chunk_offset, true1);2618 2619if (linelen <= 0) {2620/* Can't get the chunk size line */2621break;2622}2623 2624chunk_string = tvb_get_string_enc(pinfo->pool, tvb, offset, linelen, ENC_ASCII0x00000000);2625 2626if (chunk_string == NULL((void*)0)) {2627/* Can't get the chunk size line */2628break;2629}2630 2631c = (char*)chunk_string;2632 2633/*2634 * We don't care about the extensions.2635 */2636if ((c = strchr(c, ';'))) {2637*c = '\0';2638}2639 2640chunk_size = (uint32_t)strtol((char*)chunk_string, NULL((void*)0), 16);2641 2642if (chunk_size > datalen) {2643/*2644 * The chunk size is more than what's in the tvbuff,2645 * so either the user hasn't enabled decoding, or all2646 * of the segments weren't captured.2647 */2648chunk_size = datalen;2649}2650 2651chunked_data_size += chunk_size;2652 2653DISSECTOR_ASSERT((raw_len+chunk_size) <= orig_datalen)((void) (((raw_len+chunk_size) <= orig_datalen) ? (void)0 :
(proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-http.c", 2653, "(raw_len+chunk_size) <= orig_datalen"
))))
;2654tvb_memcpy(tvb, (uint8_t *)(raw_data + raw_len), chunk_offset, chunk_size);2655raw_len += chunk_size;2656 2657++chunk_counter;2658 2659if (subtree) {2660proto_tree *chunk_subtree;2661proto_item *chunk_size_item;2662 2663if(chunk_size == 0) {2664chunk_subtree = proto_tree_add_subtree(subtree, tvb,2665 offset,2666 chunk_offset - offset + chunk_size + 2,2667 ett_http_chunk_data, NULL((void*)0),2668 "End of chunked encoding");2669last_chunk_id = chunk_counter - 1;2670} else {2671chunk_subtree = proto_tree_add_subtree_format(subtree, tvb,2672 offset,2673 chunk_offset - offset + chunk_size + 2,2674 ett_http_chunk_data, NULL((void*)0),2675 "Data chunk (%u octets)", chunk_size);2676}2677 2678chunk_size_item = proto_tree_add_uint(chunk_subtree, hf_http_chunk_size, tvb, offset,2679 1, chunk_size);2680proto_item_set_len(chunk_size_item, chunk_offset - offset);2681 2682/* last-chunk does not have chunk-data CRLF. */2683if (chunk_size > 0) {2684/*2685 * Adding the chunk as FT_BYTES means that, in2686 * TShark, you get the entire chunk dumped2687 * out in hex, in addition to whatever2688 * dissection is done on the reassembled data.2689 */2690proto_tree_add_item(chunk_subtree, hf_http_chunk_data, tvb, chunk_offset, chunk_size, ENC_NA0x00000000);2691proto_tree_add_item(chunk_subtree, hf_http_chunk_boundary, tvb,2692chunk_offset + chunk_size, 2, ENC_NA0x00000000);2693}2694}2695 2696offset = chunk_offset + chunk_size; /* beginning of next chunk */2697if (chunk_size > 0) offset += 2; /* CRLF of chunk */2698datalen = tvb_reported_length_remaining(tvb, offset);2699 2700/* This is the last chunk */2701if (chunk_size == 0) {2702/* Check for: trailer-part CRLF.2703 * trailer-part = *( header-field CRLF ) */2704int trailer_offset = offset, trailer_len;2705int header_field_len;2706/* Skip all header-fields. */2707do {2708trailer_len = trailer_offset - offset;2709header_field_len = tvb_find_line_end(tvb,2710trailer_offset,2711datalen - trailer_len,2712&trailer_offset, true1);2713} while (header_field_len > 0);2714if (trailer_len > 0) {2715proto_tree_add_item(subtree,2716hf_http_chunked_trailer_part,2717tvb, offset, trailer_len, ENC_ASCII0x00000000);2718offset += trailer_len;2719datalen -= trailer_len;2720}2721 2722/* last CRLF of chunked-body is found. */2723if (header_field_len == 0) {2724proto_tree_add_format_text(subtree, tvb, offset,2725trailer_offset - offset);2726datalen -= trailer_offset - offset;2727}2728break;2729}2730}2731 2732/* datalen is the remaining bytes that are available for consumption. If2733 * smaller than orig_datalen, then bytes were consumed. */2734if (datalen < orig_datalen) {2735tvbuff_t *new_tvb;2736proto_item_set_len(pi_chunked, orig_datalen - datalen);2737new_tvb = tvb_new_child_real_data(tvb, raw_data, chunked_data_size, chunked_data_size);2738*tvb_ptr = new_tvb;2739}2740 2741if (chunk_counter > 0) {2742proto_item* ti_http = proto_tree_get_parent(tree);2743proto_item_append_text(ti_http, ", has %d chunk%s%s",2744chunk_counter, plurality(chunk_counter, "", "s")((chunk_counter) == 1 ? ("") : ("s")),2745(last_chunk_id < 0 ? "" : " (including last chunk)"));2746 2747if (last_chunk_id == 0) {2748/* only append text to column while starting with last chunk */2749col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[Last Chunk]");2750}2751}2752 2753/* Size of chunked-body or 0 if none was found. */2754return orig_datalen - datalen;2755}2756 2757static bool_Bool2758conversation_dissector_is_http(conversation_t *conv, uint32_t frame_num)2759{2760dissector_handle_t conv_handle;2761 2762if (conv == NULL((void*)0))2763return false0;2764conv_handle = conversation_get_dissector(conv, frame_num);2765return conv_handle == http_handle ||2766 conv_handle == http_tcp_handle ||2767 conv_handle == http_sctp_handle;2768}2769 2770/* Call a subdissector to handle HTTP CONNECT's traffic */2771static void2772http_payload_subdissector(tvbuff_t *tvb, proto_tree *tree,2773 packet_info *pinfo, http_conv_t *conv_data, void* data)2774{2775uint32_t *ptr = NULL((void*)0);2776uint32_t uri_port, saved_port, srcport, destport;2777char **strings; /* An array for splitting the request URI into hostname and port */2778proto_item *item;2779proto_tree *proxy_tree;2780conversation_t *conv;2781bool_Bool from_server = pinfo->srcport == conv_data->server_port &&2782addresses_equal(&conv_data->server_addr, &pinfo->src);2783 2784/* Grab the destination port number from the request URI to find the right subdissector */2785strings = wmem_strsplit(pinfo->pool, conv_data->req_res_tail->request_uri, ":", 2);2786 2787if(strings[0] != NULL((void*)0) && strings[1] != NULL((void*)0)) {2788/*2789 * The string was successfully split in two2790 * Create a proxy-connect subtree2791 */2792if(tree) {2793item = proto_tree_add_item(tree, proto_http, tvb, 0, -1, ENC_NA0x00000000);2794proxy_tree = proto_item_add_subtree(item, ett_http);2795 2796item = proto_tree_add_string(proxy_tree, hf_http_proxy_connect_host,2797 tvb, 0, 0, strings[0]);2798proto_item_set_generated(item);2799 2800item = proto_tree_add_uint(proxy_tree, hf_http_proxy_connect_port,2801 tvb, 0, 0, (uint32_t)strtol(strings[1], NULL((void*)0), 10) );2802proto_item_set_generated(item);2803}2804 2805uri_port = (int)strtol(strings[1], NULL((void*)0), 10); /* Convert string to a base-10 integer */2806 2807if (!from_server) {2808srcport = pinfo->srcport;2809destport = uri_port;2810} else {2811srcport = uri_port;2812destport = pinfo->destport;2813}2814 2815conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, srcport, destport, 0);2816 2817/* We may get stuck in a recursion loop if we let process_tcp_payload() call us.2818 * So, if the port in the URI is one we're registered for or we have set up a2819 * conversation (e.g., one we detected heuristically or via Decode-As) call the data2820 * dissector directly.2821 */2822if (value_is_in_range(http_tcp_range, uri_port) ||2823 conversation_dissector_is_http(conv, pinfo->num)) {2824call_data_dissector(tvb, pinfo, tree);2825} else {2826/* set pinfo->{src/dst port} and call the TCP sub-dissector lookup */2827if (!from_server)2828ptr = &pinfo->destport;2829else2830ptr = &pinfo->srcport;2831 2832/* Increase pinfo->can_desegment because we are traversing2833 * http and want to preserve desegmentation functionality for2834 * the proxied protocol2835 */2836if( pinfo->can_desegment>0 )2837pinfo->can_desegment++;2838 2839saved_port = *ptr;2840*ptr = uri_port;2841decode_tcp_ports(tvb, 0, pinfo, tree,2842pinfo->srcport, pinfo->destport, NULL((void*)0),2843(struct tcpinfo *)data);2844*ptr = saved_port;2845}2846}2847}2848 2849 2850 2851/*2852 * XXX - this won't handle HTTP 0.9 replies, but they're all data2853 * anyway.2854 */2855static int2856is_http_request_or_reply(packet_info *pinfo, const char *data, int linelen, media_container_type_t *type,2857 ReqRespDissector *reqresp_dissector,2858 http_conv_t *conv_data _U___attribute__((unused)))2859{2860http_info_value_t *stat_info = p_get_proto_data(pinfo->pool, pinfo, proto_http, HTTP_PROTO_DATA_INFO1);2861int isHttpRequestOrReply = false0;2862 2863/*2864 * From RFC 2774 - An HTTP Extension Framework2865 *2866 * Support the command prefix that identifies the presence of2867 * a "mandatory" header.2868 */2869if (linelen >= 2 && strncmp(data, "M-", 2) == 0) {

34

Assuming 'linelen' is >= 2

35

Assuming the condition is false

2870data += 2;2871linelen -= 2;2872}2873 2874/*2875 * From draft-cohen-gena-client-01.txt, available from the uPnP forum:2876 *NOTIFY, SUBSCRIBE, UNSUBSCRIBE2877 *2878 * From draft-ietf-dasl-protocol-00.txt, a now vanished Microsoft draft:2879 *SEARCH2880 */2881if ((linelen >= 5 && strncmp(data, "HTTP/", 5) == 0) ||

36

Assuming 'linelen' is >= 5

2882(linelen >= 3 && strncmp(data, "ICY", 3) == 0)) {2883*type = MEDIA_CONTAINER_HTTP_RESPONSE;2884isHttpRequestOrReply = true1;/* response */2885if (reqresp_dissector

36.1

'reqresp_dissector' is null

36.1

'reqresp_dissector' is null
)

37

Taking false branch

2886*reqresp_dissector = basic_response_dissector;2887} else {2888const unsigned char * ptr = (const unsigned char *)data;2889int indx = 0;2890 2891/* Look for the space following the Method */2892while (indx < linelen) {2893if (*ptr == ' ')2894break;2895else {2896ptr++;2897indx++;2898}2899}2900 2901/* Check the methods that have same length */2902switch (indx) {2903 2904case 3:2905if (strncmp(data, "GET", indx) == 0 ||2906 strncmp(data, "PUT", indx) == 0) {2907*type = MEDIA_CONTAINER_HTTP_REQUEST;2908isHttpRequestOrReply = true1;2909}2910break;2911 2912case 4:2913if (strncmp(data, "COPY", indx) == 0 ||2914 strncmp(data, "HEAD", indx) == 0 ||2915 strncmp(data, "LOCK", indx) == 0 ||2916 strncmp(data, "MOVE", indx) == 0 ||2917 strncmp(data, "POLL", indx) == 0 ||2918 strncmp(data, "POST", indx) == 0) {2919*type = MEDIA_CONTAINER_HTTP_REQUEST;2920isHttpRequestOrReply = true1;2921}2922break;2923 2924case 5:2925if (strncmp(data, "BCOPY", indx) == 0 ||2926strncmp(data, "BMOVE", indx) == 0 ||2927strncmp(data, "MKCOL", indx) == 0 ||2928strncmp(data, "TRACE", indx) == 0 ||2929strncmp(data, "PATCH", indx) == 0 || /* RFC 5789 */2930strncmp(data, "LABEL", indx) == 0 || /* RFC 3253 8.2 */2931strncmp(data, "MERGE", indx) == 0) { /* RFC 3253 11.2 */2932*type = MEDIA_CONTAINER_HTTP_REQUEST;2933isHttpRequestOrReply = true1;2934}2935break;2936 2937case 6:2938if (strncmp(data, "DELETE", indx) == 0 ||2939strncmp(data, "SEARCH", indx) == 0 ||2940strncmp(data, "UNLOCK", indx) == 0 ||2941strncmp(data, "REPORT", indx) == 0 || /* RFC 3253 3.6 */2942strncmp(data, "UPDATE", indx) == 0) { /* RFC 3253 7.1 */2943*type = MEDIA_CONTAINER_HTTP_REQUEST;2944isHttpRequestOrReply = true1;2945}2946else if (strncmp(data, "NOTIFY", indx) == 0) {2947*type = MEDIA_CONTAINER_HTTP_NOTIFICATION;2948isHttpRequestOrReply = true1;2949}2950break;2951 2952case 7:2953if (strncmp(data, "BDELETE", indx) == 0 ||2954 strncmp(data, "CONNECT", indx) == 0 ||2955 strncmp(data, "OPTIONS", indx) == 0 ||2956 strncmp(data, "CHECKIN", indx) == 0) { /* RFC 3253 4.4, 9.4 */2957*type = MEDIA_CONTAINER_HTTP_REQUEST;2958isHttpRequestOrReply = true1;2959}2960break;2961 2962case 8:2963if (strncmp(data, "PROPFIND", indx) == 0 ||2964 strncmp(data, "CHECKOUT", indx) == 0 || /* RFC 3253 4.3, 9.3 */2965 strncmp(data, "CCM_POST", indx) == 0) {2966*type = MEDIA_CONTAINER_HTTP_REQUEST;2967isHttpRequestOrReply = true1;2968}2969break;2970 2971case 9:2972if (strncmp(data, "SUBSCRIBE", indx) == 0) {2973*type = MEDIA_CONTAINER_HTTP_NOTIFICATION;2974isHttpRequestOrReply = true1;2975} else if (strncmp(data, "PROPPATCH", indx) == 0 ||2976 strncmp(data, "BPROPFIND", indx) == 0) {2977*type = MEDIA_CONTAINER_HTTP_REQUEST;2978isHttpRequestOrReply = true1;2979}2980break;2981 2982case 10:2983if (strncmp(data, "BPROPPATCH", indx) == 0 ||2984strncmp(data, "UNCHECKOUT", indx) == 0 || /* RFC 3253 4.5 */2985strncmp(data, "MKACTIVITY", indx) == 0) { /* RFC 3253 13.5 */2986*type = MEDIA_CONTAINER_HTTP_REQUEST;2987isHttpRequestOrReply = true1;2988}2989break;2990 2991case 11:2992if (strncmp(data, "MKWORKSPACE", indx) == 0 || /* RFC 3253 6.3 */2993 strncmp(data, "RPC_CONNECT", indx) == 0 || /* [MS-RPCH] 2.1.1.1.1 */2994 strncmp(data, "RPC_IN_DATA", indx) == 0) { /* [MS-RPCH] 2.1.2.1.1 */2995*type = MEDIA_CONTAINER_HTTP_REQUEST;2996isHttpRequestOrReply = true1;2997} else if (strncmp(data, "UNSUBSCRIBE", indx) == 0) {2998*type = MEDIA_CONTAINER_HTTP_NOTIFICATION;2999isHttpRequestOrReply = true1;3000}3001break;3002 3003case 12:3004if (strncmp(data, "RPC_OUT_DATA", indx) == 0) { /* [MS-RPCH] 2.1.2.1.2 */3005*type = MEDIA_CONTAINER_HTTP_REQUEST;3006isHttpRequestOrReply = true1;3007}3008break;3009 3010case 15:3011if (strncmp(data, "VERSION-CONTROL", indx) == 0) { /* RFC 3253 3.5 */3012*type = MEDIA_CONTAINER_HTTP_REQUEST;3013isHttpRequestOrReply = true1;3014}3015break;3016 3017case 16:3018if (strncmp(data, "BASELINE-CONTROL", indx) == 0) { /* RFC 3253 12.6 */3019*type = MEDIA_CONTAINER_HTTP_REQUEST;3020isHttpRequestOrReply = true1;3021} else if (strncmp(data, "SSTP_DUPLEX_POST", indx) == 0) { /* MS SSTP */3022*type = MEDIA_CONTAINER_HTTP_REQUEST;3023isHttpRequestOrReply = true1;3024}3025break;3026 3027default:3028break;3029}3030 3031if (isHttpRequestOrReply && reqresp_dissector) {3032*reqresp_dissector = basic_request_dissector;3033 3034stat_info->request_method = wmem_strndup(pinfo->pool, data, indx);3035}3036 3037 3038 3039}3040 3041return isHttpRequestOrReply;

38

Returning the value 1 (loaded from 'isHttpRequestOrReply'), which participates in a condition later

3042}3043 3044/*3045 * Process headers.3046 */3047typedef struct {3048const char*name;3049int*hf;3050intspecial;3051} header_info;3052 3053#define HDR_NO_SPECIAL003054#define HDR_AUTHORIZATION113055#define HDR_AUTHENTICATE223056#define HDR_CONTENT_TYPE333057#define HDR_CONTENT_LENGTH443058#define HDR_CONTENT_ENCODING553059#define HDR_TRANSFER_ENCODING663060#define HDR_HOST773061#define HDR_UPGRADE883062#define HDR_COOKIE993063#define HDR_WEBSOCKET_PROTOCOL10103064#define HDR_WEBSOCKET_EXTENSIONS11113065#define HDR_REFERER12123066#define HDR_LOCATION13133067#define HDR_HTTP2_SETTINGS14143068#define HDR_RANGE15 153069#define HDR_CONTENT_RANGE16163070 3071static const header_info headers[] = {3072{ "Authorization", &hf_http_authorization, HDR_AUTHORIZATION1 },3073{ "Proxy-Authorization", &hf_http_proxy_authorization, HDR_AUTHORIZATION1 },3074{ "Proxy-Authenticate", &hf_http_proxy_authenticate, HDR_AUTHENTICATE2 },3075{ "WWW-Authenticate", &hf_http_www_authenticate, HDR_AUTHENTICATE2 },3076{ "Content-Type", &hf_http_content_type, HDR_CONTENT_TYPE3 },3077{ "Content-Length", &hf_http_content_length_header, HDR_CONTENT_LENGTH4 },3078{ "Content-Encoding", &hf_http_content_encoding, HDR_CONTENT_ENCODING5 },3079{ "Transfer-Encoding", &hf_http_transfer_encoding, HDR_TRANSFER_ENCODING6 },3080{ "Upgrade", &hf_http_upgrade, HDR_UPGRADE8 },3081{ "User-Agent",&hf_http_user_agent, HDR_NO_SPECIAL0 },3082{ "Host", &hf_http_host, HDR_HOST7 },3083{ "Range", &hf_http_range, HDR_RANGE15 },3084{ "Content-Range", &hf_http_content_range, HDR_CONTENT_RANGE16 },3085{ "Connection", &hf_http_connection, HDR_NO_SPECIAL0 },3086{ "Cookie", &hf_http_cookie, HDR_COOKIE9 },3087{ "Accept", &hf_http_accept, HDR_NO_SPECIAL0 },3088{ "Referer", &hf_http_referer, HDR_REFERER12 },3089{ "Accept-Language", &hf_http_accept_language, HDR_NO_SPECIAL0 },3090{ "Accept-Encoding", &hf_http_accept_encoding, HDR_NO_SPECIAL0 },3091{ "Date", &hf_http_date, HDR_NO_SPECIAL0 },3092{ "Cache-Control", &hf_http_cache_control, HDR_NO_SPECIAL0 },3093{ "Server", &hf_http_server, HDR_NO_SPECIAL0 },3094{ "Location", &hf_http_location, HDR_LOCATION13 },3095{ "Sec-WebSocket-Accept", &hf_http_sec_websocket_accept, HDR_NO_SPECIAL0 },3096{ "Sec-WebSocket-Extensions", &hf_http_sec_websocket_extensions, HDR_WEBSOCKET_EXTENSIONS11 },3097{ "Sec-WebSocket-Key", &hf_http_sec_websocket_key, HDR_NO_SPECIAL0 },3098{ "Sec-WebSocket-Protocol", &hf_http_sec_websocket_protocol, HDR_WEBSOCKET_PROTOCOL10 },3099{ "Sec-WebSocket-Version", &hf_http_sec_websocket_version, HDR_NO_SPECIAL0 },3100{ "Set-Cookie", &hf_http_set_cookie, HDR_NO_SPECIAL0 },3101{ "Last-Modified", &hf_http_last_modified, HDR_NO_SPECIAL0 },3102{ "X-Forwarded-For", &hf_http_x_forwarded_for, HDR_NO_SPECIAL0 },3103{ "HTTP2-Settings", &hf_http_http2_settings, HDR_HTTP2_SETTINGS14 },3104};3105 3106/*3107 * Look up a header name (assume lower-case header_name).3108 */3109static int*3110get_hf_for_header(char* header_name)3111{3112int* hf_id = NULL((void*)0);3113 3114if (header_fields_hash) {3115hf_id = (int*) g_hash_table_lookup(header_fields_hash, header_name);3116} else {3117hf_id = NULL((void*)0);3118}3119 3120return hf_id;3121}3122 3123/*3124 *3125 */3126static void3127deregister_header_fields(void)3128{3129if (dynamic_hf) {3130/* Deregister all fields */3131for (unsigned i = 0; i < dynamic_hf_size; i++) {3132proto_deregister_field (proto_http, *(dynamic_hf[i].p_id));3133g_free (dynamic_hf[i].p_id);3134}3135 3136proto_add_deregistered_data (dynamic_hf);3137dynamic_hf = NULL((void*)0);3138dynamic_hf_size = 0;3139}3140 3141if (header_fields_hash) {3142g_hash_table_destroy (header_fields_hash);3143header_fields_hash = NULL((void*)0);3144}3145}3146 3147static void3148header_fields_post_update_cb(void)3149{3150int* hf_id;3151char* header_name;3152char* header_name_key;3153 3154deregister_header_fields();3155 3156if (num_header_fields) {3157header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL((void*)0));3158dynamic_hf = g_new0(hf_register_info, num_header_fields)((hf_register_info *) g_malloc0_n ((num_header_fields), sizeof
(hf_register_info)))
;3159dynamic_hf_size = num_header_fields;3160 3161for (unsigned i = 0; i < dynamic_hf_size; i++) {3162hf_id = g_new(int,1)((int *) g_malloc_n ((1), sizeof (int)));3163*hf_id = -1;3164header_name = g_strdup(header_fields[i].header_name)g_strdup_inline (header_fields[i].header_name);3165header_name_key = g_ascii_strdown(header_name, -1);3166 3167dynamic_hf[i].p_id = hf_id;3168dynamic_hf[i].hfinfo.name = header_name;3169dynamic_hf[i].hfinfo.abbrev = ws_strdup_printf("http.header.%s", header_name)wmem_strdup_printf(((void*)0), "http.header.%s", header_name);3170dynamic_hf[i].hfinfo.type = FT_STRING;3171dynamic_hf[i].hfinfo.display = BASE_NONE;3172dynamic_hf[i].hfinfo.strings = NULL((void*)0);3173dynamic_hf[i].hfinfo.bitmask = 0;3174dynamic_hf[i].hfinfo.blurb = g_strdup(header_fields[i].header_desc)g_strdup_inline (header_fields[i].header_desc);3175HFILL_INIT(dynamic_hf[i])(dynamic_hf[i]).hfinfo.id = -1; (dynamic_hf[i]).hfinfo.parent
= 0; (dynamic_hf[i]).hfinfo.ref_type = HF_REF_TYPE_NONE; (dynamic_hf
[i]).hfinfo.same_name_prev_id = -1; (dynamic_hf[i]).hfinfo.same_name_next
= ((void*)0);
;3176 3177g_hash_table_insert(header_fields_hash, header_name_key, hf_id);3178}3179 3180proto_register_field_array(proto_http, dynamic_hf, dynamic_hf_size);3181}3182}3183 3184static void3185header_fields_reset_cb(void)3186{3187deregister_header_fields();3188}3189 3190/**3191 * Parses the transfer-coding, returning true if everything was fully understood3192 * or false when unknown names were encountered.3193 */3194static bool_Bool3195http_parse_transfer_coding(const char *value, headers_t *eh_ptr)3196{3197bool_Bool is_fully_parsed = true1;3198 3199/* Mark header as set, but with unknown encoding. */3200eh_ptr->transfer_encoding = HTTP_TE_UNKNOWN;3201 3202while (*value) {3203/* skip OWS (SP / HTAB) and commas; stop at the end. */3204while (*value == ' ' || *value == '\t' || *value == ',')3205value++;3206if (!*value)3207break;3208 3209if (g_str_has_prefix(value, "chunked")(__builtin_constant_p ("chunked")? __extension__ ({ const char
* const __str = (value); const char * const __prefix = ("chunked"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (value, "chunked") )
) {3210eh_ptr->transfer_encoding_chunked = true1;3211value += sizeof("chunked") - 1;3212continue;3213}3214 3215/* For now assume that chunked can only combined with exactly3216 * one other (compression) encoding. Anything else is3217 * unsupported. */3218if (eh_ptr->transfer_encoding != HTTP_TE_UNKNOWN) {3219/* No more transfer codings are expected. */3220is_fully_parsed = false0;3221break;3222}3223 3224if (g_str_has_prefix(value, "compress")(__builtin_constant_p ("compress")? __extension__ ({ const char
* const __str = (value); const char * const __prefix = ("compress"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (value, "compress") )
) {3225eh_ptr->transfer_encoding = HTTP_TE_COMPRESS;3226value += sizeof("compress") - 1;3227} else if (g_str_has_prefix(value, "deflate")(__builtin_constant_p ("deflate")? __extension__ ({ const char
* const __str = (value); const char * const __prefix = ("deflate"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (value, "deflate") )
) {3228eh_ptr->transfer_encoding = HTTP_TE_DEFLATE;3229value += sizeof("deflate") - 1;3230} else if (g_str_has_prefix(value, "gzip")(__builtin_constant_p ("gzip")? __extension__ ({ const char *
const __str = (value); const char * const __prefix = ("gzip"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (value, "gzip") )
) {3231eh_ptr->transfer_encoding = HTTP_TE_GZIP;3232value += sizeof("gzip") - 1;3233} else if (g_str_has_prefix(value, "identity")(__builtin_constant_p ("identity")? __extension__ ({ const char
* const __str = (value); const char * const __prefix = ("identity"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (value, "identity") )
) {3234eh_ptr->transfer_encoding = HTTP_TE_IDENTITY;3235value += sizeof("identity") - 1;3236} else if (g_str_has_prefix(value, "x-compress")(__builtin_constant_p ("x-compress")? __extension__ ({ const char
* const __str = (value); const char * const __prefix = ("x-compress"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (value, "x-compress") )
) {3237eh_ptr->transfer_encoding = HTTP_TE_COMPRESS;3238value += sizeof("x-compress") - 1;3239} else if (g_str_has_prefix(value, "x-gzip")(__builtin_constant_p ("x-gzip")? __extension__ ({ const char
* const __str = (value); const char * const __prefix = ("x-gzip"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (value, "x-gzip") )
) {3240eh_ptr->transfer_encoding = HTTP_TE_GZIP;3241value += sizeof("x-gzip") - 1;3242} else {3243/* Unknown transfer encoding, skip until next comma.3244 * Stop when no more names are found. */3245is_fully_parsed = false0;3246value = strchr(value, ',');3247if (!value)3248break;3249}3250}3251 3252return is_fully_parsed;3253}3254 3255static bool_Bool3256is_token_char(char c)3257{3258/* tchar according to https://tools.ietf.org/html/rfc7230#section-3.2.6 */3259return strchr("!#$%&\\:*+-.^_`|~", c) || g_ascii_isalnum(c)((g_ascii_table[(guchar) (c)] & G_ASCII_ALNUM) != 0);3260}3261 3262static bool_Bool3263valid_header_name(const unsigned char *line, int header_len)3264{3265 3266/*3267 * Validate the header name. This allows no space between the field name3268 * and colon (RFC 7230, Section. 3.2.4).3269 */3270if (header_len == 0) {3271return false0;3272}3273for (int i = 0; i < header_len; i++) {3274/*3275 * NUL is not a valid character; treat it specially3276 * due to C's notion that strings are NUL-terminated.3277 */3278if (line[i] == '\0') {3279return false0;3280}3281if (!is_token_char(line[i])) {3282return false0;3283}3284}3285return true1;3286}3287 3288static bool_Bool3289process_header(tvbuff_t *tvb, int offset, int next_offset,3290 const unsigned char *line, int linelen, int colon_offset,3291 packet_info *pinfo, proto_tree *tree, headers_t *eh_ptr,3292 http_conv_t *conv_data, media_container_type_t http_type, wmem_map_t *header_value_map,3293 bool_Bool streaming_chunk_mode)3294{3295int len;3296int line_end_offset;3297int header_len;3298int hf_index;3299unsigned char c;3300int value_offset;3301int value_len, value_bytes_len;3302uint8_t *value_bytes;3303char *value;3304char *header_name;3305char *p;3306unsigned char *up;3307proto_item *hdr_item, *it;3308int f;3309int* hf_id;3310tap_credential_t* auth;3311http_req_res_t *curr_req_res = (http_req_res_t *)p_get_proto_data(wmem_file_scope(), pinfo,3312proto_http, HTTP_PROTO_DATA_REQRES0);3313http_info_value_t *stat_info = p_get_proto_data(pinfo->pool, pinfo, proto_http, HTTP_PROTO_DATA_INFO1);3314wmem_allocator_t *scope = (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && streaming_chunk_mode) ? wmem_file_scope() :3315 ((PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && streaming_chunk_mode) ? NULL((void*)0) : pinfo->pool);3316 3317len = next_offset - offset;3318line_end_offset = offset + linelen;3319header_len = colon_offset - offset;3320 3321/**3322 * Not a valid header name? Just add a line plus expert info.3323 */3324if (!valid_header_name(line, header_len)) {3325if (http_check_ascii_headers) {3326/* If we're offering the chance for other dissectors to parse,3327 * we shouldn't add any tree items ourselves.3328 */3329return false0;3330}3331if (http_type == MEDIA_CONTAINER_HTTP_REQUEST) {3332hf_index = hf_http_request_line;3333} else if (http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3334hf_index = hf_http_response_line;3335} else {3336hf_index = hf_http_unknown_header;3337}3338it = proto_tree_add_item(tree, hf_index, tvb, offset, len, ENC_NA0x00000000|ENC_ASCII0x00000000);3339proto_item_set_text(it, "%s", format_text(pinfo->pool, line, len));3340expert_add_info(pinfo, it, &ei_http_bad_header_name);3341return false0;3342}3343 3344/*3345 * Make a null-terminated, all-lower-case version of the header3346 * name.3347 */3348header_name = wmem_ascii_strdown(pinfo->pool, &line[0], header_len);3349 3350hf_index = find_header_hf_value(tvb, offset, header_len);3351 3352/*3353 * Skip whitespace after the colon.3354 */3355value_offset = colon_offset + 1;3356while (value_offset < line_end_offset3357&& ((c = line[value_offset - offset]) == ' ' || c == '\t'))3358value_offset++;3359 3360/*3361 * Fetch the value.3362 *3363 * XXX - RFC 9110 5.5 "Specification for newly defined fields3364 * SHOULD limit their values to visible US-ASCII octets (VCHAR),3365 * SP, and HTAB. A recipient SHOULD treat other allowed octets in3366 * field content (i.e., obs-text [%x80-FF]) as opaque data...3367 * Field values containing CR, LF, or NUL characters are invalid3368 * and dangerous." (Up to RFC 7230, an obsolete "line-folding"3369 * mechanism that included CRLF was allowed.)3370 *3371 * So NUL is not allowed, and we should have one or more3372 * expert infos if the field value has anything other than3373 * ASCII printable + TAB. (Possibly different severities3374 * depending on whether it contains obsolete characters3375 * like \x80-\xFF vs characters never allowed like NUL.)3376 * All known field types respect this (using Base64, etc.)3377 * Unknown field types (possibly including those registered3378 * through the UAT) should be treated like FT_BYTES with3379 * BASE_SHOW_ASCII_PRINTABLE instead of FT_STRING, but it's3380 * more difficult to do that with the custom formatting3381 * that uses the header name.3382 *3383 * Instead, for now for display purposes we will treat strings3384 * as ASCII and pass the raw value to subdissectors via the3385 * header_value_map. For the latter, we allocate a buffer that's3386 * value_bytes_len+1 bytes long, copy value_bytes_len bytes, and3387 * stick in a NUL terminator, so that the buffer for value actually3388 * has value_bytes_len bytes in it.3389 */3390value_bytes_len = line_end_offset - value_offset;3391value_bytes = (char *)wmem_alloc((scope ? scope : pinfo->pool), value_bytes_len+1);3392memcpy(value_bytes, &line[value_offset - offset], value_bytes_len);3393value_bytes[value_bytes_len] = '\0';3394value = tvb_get_string_enc(pinfo->pool, tvb, value_offset, value_bytes_len, ENC_ASCII0x00000000);3395/* The length of the value might change after UTF-8 sanitization */3396value_len = (int)strlen(value);3397 3398if (scope == pinfo->pool) {3399wmem_map_insert(header_value_map, header_name, value_bytes);3400} else if (scope) { /* (!PINFO_FD_VISITED(pinfo) && streaming_chunk_mode) */3401wmem_map_insert(header_value_map, wmem_strdup(scope, header_name), value_bytes);3402} /* else skip while (PINFO_FD_VISITED(pinfo) && streaming_chunk_mode) */3403 3404if (hf_index == -1) {3405/*3406 * Not a header we know anything about.3407 * Check if a HF generated from UAT information exists.3408 */3409hf_id = get_hf_for_header(header_name);3410 3411if (tree) {3412if (!hf_id) {3413if (http_type == MEDIA_CONTAINER_HTTP_REQUEST ||3414http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3415it = proto_tree_add_item(tree,3416http_type == MEDIA_CONTAINER_HTTP_RESPONSE ?3417hf_http_response_line :3418hf_http_request_line,3419tvb, offset, len,3420ENC_NA0x00000000|ENC_ASCII0x00000000);3421proto_item_set_text(it, "%s",3422format_text(pinfo->pool, line, len));3423} else {3424char* str = format_text(pinfo->pool, line, len);3425proto_tree_add_string_format(tree, hf_http_unknown_header, tvb, offset,3426len, str, "%s", str);3427}3428 3429} else {3430proto_tree_add_string_format(tree,3431*hf_id, tvb, offset, len, value,3432"%s", format_text(pinfo->pool, line, len));3433if (http_type == MEDIA_CONTAINER_HTTP_REQUEST ||3434http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3435it = proto_tree_add_item(tree,3436http_type == MEDIA_CONTAINER_HTTP_RESPONSE ?3437hf_http_response_line :3438hf_http_request_line,3439tvb, offset, len,3440ENC_NA0x00000000|ENC_ASCII0x00000000);3441proto_item_set_text(it, "%s",3442format_text(pinfo->pool, line, len));3443proto_item_set_hidden(it);3444}3445}3446}3447} else {3448/*3449 * Add it to the protocol tree as a particular field,3450 * but display the line as is.3451 */3452if (tree) {3453header_field_info *hfinfo;3454uint32_t tmp;3455 3456hfinfo = proto_registrar_get_nth(*headers[hf_index].hf);3457switch(hfinfo->type){3458case FT_UINT8:3459case FT_UINT16:3460case FT_UINT24:3461case FT_UINT32:3462case FT_INT8:3463case FT_INT16:3464case FT_INT24:3465case FT_INT32:3466tmp=(uint32_t)strtol(value, NULL((void*)0), 10);3467hdr_item = proto_tree_add_uint(tree, *headers[hf_index].hf, tvb, offset, len, tmp);3468if (http_type == MEDIA_CONTAINER_HTTP_REQUEST ||3469http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3470it = proto_tree_add_item(tree,3471http_type == MEDIA_CONTAINER_HTTP_RESPONSE ?3472hf_http_response_line :3473hf_http_request_line,3474tvb, offset, len,3475ENC_NA0x00000000|ENC_ASCII0x00000000);3476proto_item_set_text(it, "%d", tmp);3477proto_item_set_hidden(it);3478}3479break;3480default:3481hdr_item = proto_tree_add_string_format(tree,3482 *headers[hf_index].hf, tvb, offset, len,3483 value,3484 "%s", format_text(pinfo->pool, line, len));3485if (http_type == MEDIA_CONTAINER_HTTP_REQUEST ||3486http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3487it = proto_tree_add_item(tree,3488http_type == MEDIA_CONTAINER_HTTP_RESPONSE ?3489hf_http_response_line :3490hf_http_request_line,3491tvb, offset, len,3492ENC_NA0x00000000|ENC_ASCII0x00000000);3493proto_item_set_text(it, "%s",3494format_text(pinfo->pool, line, len));3495proto_item_set_hidden(it);3496}3497}3498} else3499hdr_item = NULL((void*)0);3500 3501/*3502 * Do any special processing that particular headers3503 * require.3504 */3505switch (headers[hf_index].special) {3506 3507case HDR_AUTHORIZATION1:3508if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))3509break;/* dissected NTLMSSP */3510if (check_auth_basic(hdr_item, tvb, pinfo, value))3511break; /* dissected basic auth */3512if (check_auth_citrixbasic(hdr_item, tvb, pinfo, value, offset))3513break; /* dissected citrix basic auth */3514if (check_auth_kerberos(hdr_item, tvb, pinfo, value))3515break;3516if (check_auth_digest(hdr_item, tvb, pinfo, value, offset, value_len))3517break;/* dissected digest basic auth */3518auth = wmem_new0(pinfo->pool, tap_credential_t)((tap_credential_t*)wmem_alloc0((pinfo->pool), sizeof(tap_credential_t
)))
;3519auth->num = pinfo->num;3520auth->password_hf_id = *headers[hf_index].hf;3521auth->proto = "HTTP header auth";3522auth->username = wmem_strdup(pinfo->pool, TAP_CREDENTIALS_PLACEHOLDER"n.a.");3523tap_queue_packet(credentials_tap, pinfo, auth);3524break;3525 3526case HDR_AUTHENTICATE2:3527if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))3528break; /* dissected NTLMSSP */3529check_auth_kerberos(hdr_item, tvb, pinfo, value);3530break;3531 3532case HDR_CONTENT_TYPE3:3533if (scope == NULL((void*)0)) { /* identical to (PINFO_FD_VISITED(pinfo) && streaming_chunk_mode) */3534break; /* eh_ptr->content_type[_parameters] must have been set during first scan */3535}3536eh_ptr->content_type = wmem_strdup(scope, value);3537 3538for (f = 0; f < value_len; f++) {3539c = value[f];3540if (c == ';' || g_ascii_isspace(c)((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0)) {3541/*3542 * End of subtype - either3543 * white space or a ";"3544 * separating the subtype from3545 * a parameter.3546 */3547break;3548}3549 3550/*3551 * Map the character to lower case;3552 * content types are case-insensitive.3553 */3554eh_ptr->content_type[f] = g_ascii_tolower(eh_ptr->content_type[f]);3555}3556eh_ptr->content_type[f] = '\0';3557/*3558 * Now find the start of the optional parameters;3559 * skip the optional white space and the semicolon3560 * if this has not been done before.3561 */3562f++;3563while (f < value_len) {3564c = eh_ptr->content_type[f];3565if (c == ';' || g_ascii_isspace(c)((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0))3566/* Skip till start of parameters */3567f++;3568else3569break;3570}3571if (f < value_len)3572eh_ptr->content_type_parameters = eh_ptr->content_type + f;3573else3574eh_ptr->content_type_parameters = NULL((void*)0);3575break;3576 3577case HDR_CONTENT_LENGTH4:3578DISSECTOR_ASSERT_HINT(!streaming_chunk_mode, "In streaming chunk mode, there will never be content-length header.")((void) ((!streaming_chunk_mode) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/dissectors/packet-http.c"
, 3578, "!streaming_chunk_mode", "In streaming chunk mode, there will never be content-length header."
))))
;3579errno(*__errno_location ()) = 0;3580eh_ptr->content_length = g_ascii_strtoll(value, &p, 10);3581up = (unsigned char *)p;3582if (eh_ptr->content_length < 0 ||3583 p == value ||3584 errno(*__errno_location ()) == ERANGE34 ||3585 (*up != '\0' && !g_ascii_isspace(*up)((g_ascii_table[(guchar) (*up)] & G_ASCII_SPACE) != 0))) {3586/*3587 * Content length not valid; pretend3588 * we don't have it.3589 */3590eh_ptr->have_content_length = false0;3591} else {3592proto_tree *header_tree;3593proto_item *tree_item;3594/*3595 * We do have a valid content length.3596 */3597eh_ptr->have_content_length = true1;3598header_tree = proto_item_add_subtree(hdr_item, ett_http_header_item);3599tree_item = proto_tree_add_uint64(header_tree, hf_http_content_length,3600tvb, offset, len, eh_ptr->content_length);3601proto_item_set_generated(tree_item);3602if (eh_ptr->transfer_encoding != HTTP_TE_NONE) {3603expert_add_info(pinfo, hdr_item, &ei_http_te_and_length);3604}3605}3606break;3607 3608case HDR_CONTENT_ENCODING5:3609if (scope == NULL((void*)0)) { /* identical to (PINFO_FD_VISITED(pinfo) && streaming_chunk_mode) */3610break; /* eh_ptr->content_encoding must have been set during first scan */3611}3612eh_ptr->content_encoding = wmem_strndup(scope, value, value_len);3613break;3614 3615case HDR_TRANSFER_ENCODING6:3616if (eh_ptr->have_content_length) {3617expert_add_info(pinfo, hdr_item, &ei_http_te_and_length);3618}3619if (!http_parse_transfer_coding(value, eh_ptr)) {3620expert_add_info(pinfo, hdr_item, &ei_http_te_unknown);3621}3622break;3623 3624case HDR_HOST7:3625stat_info->http_host = wmem_strndup(pinfo->pool, value, value_len);3626if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && curr_req_res) {3627curr_req_res->http_host = wmem_strndup(wmem_file_scope(), value, value_len);3628}3629break;3630 3631case HDR_UPGRADE8:3632if (scope == NULL((void*)0)) { /* identical to (PINFO_FD_VISITED(pinfo) && streaming_chunk_mode) */3633break;3634}3635eh_ptr->upgrade = wmem_ascii_strdown(scope, value, value_len);3636break;3637 3638case HDR_COOKIE9:3639if (hdr_item) {3640proto_tree *cookie_tree;3641char *part, *part_end;3642int part_len;3643 3644cookie_tree = proto_item_add_subtree(hdr_item, ett_http_header_item);3645for (f = 0; f < value_len; ) {3646/* skip whitespace and ';' (terminates at '\0' or earlier) */3647c = value[f];3648while (c == ';' || g_ascii_isspace(c)((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0))3649c = value[++f];3650 3651if (f >= value_len)3652break;3653 3654/* find "cookie=foo " in "cookie=foo ; bar" */3655part = value + f;3656part_end = (char *)memchr(part, ';', value_len - f);3657if (part_end)3658part_len =(int)(part_end - part);3659else3660part_len = value_len - f;3661 3662/* finally add cookie to tree */3663proto_tree_add_item(cookie_tree, hf_http_cookie_pair,3664tvb, value_offset + f, part_len, ENC_NA0x00000000|ENC_ASCII0x00000000);3665f += part_len;3666}3667}3668break;3669 3670case HDR_WEBSOCKET_PROTOCOL10:3671if (http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3672conv_data->websocket_protocol = wmem_strndup(wmem_file_scope(), value, value_len);3673}3674break;3675 3676case HDR_WEBSOCKET_EXTENSIONS11:3677if (http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3678conv_data->websocket_extensions = wmem_strndup(wmem_file_scope(), value, value_len);3679}3680break;3681 3682case HDR_REFERER12:3683stat_info->referer_uri = wmem_strndup(pinfo->pool, value, value_len);3684break;3685 3686case HDR_LOCATION13:3687if (curr_req_res && curr_req_res->request_uri){3688stat_info->location_target = wmem_strndup(pinfo->pool, value, value_len);3689stat_info->location_base_uri = wmem_strdup(pinfo->pool, curr_req_res->full_uri);3690}3691break;3692case HDR_HTTP2_SETTINGS14:3693{3694proto_tree* settings_tree = proto_item_add_subtree(hdr_item, ett_http_http2_settings_item);3695tvbuff_t* new_tvb = base64uri_tvb_to_new_tvb(tvb, value_offset, value_bytes_len);3696add_new_data_source(pinfo, new_tvb, "Base64uri decoded");3697TRY{ except_t *volatile exc; volatile int except_state = 0; static
const except_id_t catch_spec[] = { { 1, 0 } }; { struct except_stacknode
except_sn; struct except_catch except_ch; except_setup_try(&
except_sn, &except_ch, catch_spec, 1); if (_setjmp (except_ch
.except_jmp)) *(&exc) = &except_ch.except_obj; else *
(&exc) = 0; if(except_state & 1) except_state |= 2; except_state
&= ~1; if (except_state == 0 && exc == 0)
{3698dissect_http2_settings_ext(new_tvb, pinfo, settings_tree, 0);3699} CATCH_ALLif (except_state == 0 && exc != 0 && (except_state
|=1))
{3700show_exception(tvb, pinfo, settings_tree, EXCEPT_CODE((exc)->except_id.except_code), GET_MESSAGE((exc)->except_message));3701}3702ENDTRYif(!(except_state&1) && exc != 0) except_rethrow(
exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}
;3703 3704break;3705}3706case HDR_RANGE15:3707{3708/* THIS IS A GET REQUEST3709 * Note: GET is the only method that employs ranges.3710 * (Unless the data has errors or is noncompliant.)3711 */3712if (curr_req_res && !pinfo->fd->visited) {3713 /*3714 * Unlike protocols such as NFS and SMB, the HTTP protocol (RFC 9110) does not3715 * provide an identifier with which to match requests and responses. Instead,3716 * matching is solely based upon the order in which responses are received.3717 * HTTP I/O is 'asynchronously ordered' such that, for example, the first of four3718 * GET responses are matched with the first outstanding request, the next3719 * response with the second oldest outstanding request and so on (FIFO).3720 * The previous method instead matched responses with the last of several3721 * async requests rather than the first (LIFO), and did not handle requests3722 * with no responses such as the case where one or more HTTP packets were3723 * not captured. Whenever there were multiple outstanding requests, the SRT3724 * (RTT) stats were incorrect, in some cases massively so.3725 *3726 * While RFC 9110 expressly prohibits matching via byte ranges because, among3727 * other things, the server may return fewer bytes than requested,3728 * the first number of the range does not change. Unlike HTTP implementations,3729 * Wireshark has the problem of requests/responses missing from the capture3730 * file. In such cases resumption of correct matching was virtually impossible.3731 * In addition, all matching was incorrect from that point on.3732 *3733 * The method of matching used herein is able to recover from packet loss,3734 * any number of missing frames, and duplicate range requests. The3735 * method used is explained within the comments.3736 */3737/* https://www.rfc-editor.org/rfc/rfc9110.html#name-range-requests3738 * Note that RFC 9110 16.5 defines a registry for3739 * range units, but only bytes are registered.3740 * ABNF:3741 * Range = ranges-specifier3742 * ranges-specifier = range-unit "=" range-set3743 * range-set = 1#range-spec3744 * range-spec = int-range / suffix-range / other-range3745 * 1# is an ABNF extension defined in RFC 9110 5.6.13746 * which covers comma separated list with optional3747 * white space:3748 * 1#element => element *( OWS "," OWS element )3749 * We don't care about other-range, but will try to3750 * handle int-range and suffix-range.3751 * This ignores any entries past the first in a list,3752 * though responses to such would be multipart.3753 * As mentioned above, this breaks down if the3754 * response does not include all requested ranges3755 * fully in one response.3756 */3757const char *pos = strchr(value, '=');3758if (pos == NULL((void*)0)) {3759break;3760}3761pos++;3762uint64_t first_range_num = 0;3763/* Get the first range number */3764ws_strtou64(pos, &pos, &first_range_num);3765/* If the first number of the range is missing or '0',3766 * use the second number in the range instead if we can.3767 * XXX - Unlike strtoul, we can check the return value3768 * of ws_strtou64() to distinguish between "converted3769 * successfully as 0" and "failed conversion."3770 * Note that strtoul allows an unsigned integer to3771 * begin with a negative sign and applies unsigned3772 * integer wraparound rules.3773 * ws_strtouXX rejects an initial hyphen-minus, which3774 * is good, as we want to properly handle:3775 * suffix-range = "-" suffix-length3776 */3777if (first_range_num == 0 && *pos == '-') {3778pos++;3779/* Pass in an end pointer to convert3780 * a list of ranges, the first of which is3781 * a suffix-range.3782 */3783ws_strtou64(pos, &pos, &first_range_num);3784}3785/* req_list is used for req/resp matching and the deletion (and freeing) of matching3786* requests and any orphans that preceed them. A GSList is used instead of a wmem map3787* because there are rarely more than 10 requests in the list."3788*/3789if (first_range_num > 0) {3790request_trans_t* req_trans = wmem_new(wmem_file_scope(), request_trans_t)((request_trans_t*)wmem_alloc((wmem_file_scope()), sizeof(request_trans_t
)))
;3791req_trans->first_range_num = first_range_num;3792req_trans->req_frame = pinfo->num;3793req_trans->abs_time = pinfo->fd->abs_ts;3794req_trans->request_uri = curr_req_res->request_uri;3795 3796/* XXX - This leaks if matching responses aren't3797 * found (the data does not, but the list node3798 * does.) A wmem_list would prevent that.3799 */3800conv_data->req_list = g_slist_append(conv_data->req_list, GUINT_TO_POINTER(req_trans)((gpointer) (gulong) (req_trans)));3801curr_req_res->req_has_range = true1;3802}3803}3804 3805break;3806}3807case HDR_CONTENT_RANGE16:3808/*3809 * THIS IS A GET RESPONSE3810 * GET is the only method that employs ranges.3811 * XXX - Except that RFC 9110 14.4 & 14.5 note that by3812 * private agreement it can be included in a request3813 * to request a partial PUT.3814 * ABNF:3815 * Content-Range = range-unit SP ( range-resp / unsatisfied-range )3816 * range-resp = incl-range "/" ( complete-length / "*" )3817 * We do not attempt to handle unsatisfied-range.3818 * Note that only one range can be included; multiple3819 * ranges are transmitted with the media type of3820 * "multipart/byteranges" and each body part contains3821 * its own Content-Type and Content-Range fields.3822 * The multipart dissector does not handle this nor3823 * access the request list.3824 */3825if (curr_req_res && !pinfo->fd->visited) {3826request_trans_t *req_trans;3827match_trans_t *match_trans = NULL((void*)0);3828nstime_t ns;3829GSList *iter = NULL((void*)0);3830 3831/* Note SP instead of '=' in ABNF. */3832const char *pos = strchr(value, ' ');3833if (pos == NULL((void*)0)) {3834break;3835}3836pos++;3837uint64_t first_crange_num = 0;3838/* Get the first content range number */3839ws_strtou64(pos, &pos, &first_crange_num);3840 3841if (first_crange_num == 0 && *pos == '-') {3842pos++;3843ws_strtou64(pos, &pos, &first_crange_num);3844}3845 3846/* Get the position of the matching request if any in the reqs_table.3847* This is used to remove and free the matching request, and the unmatched3848* requests (orphans) that preceed it.3849* XXX - There is *NO* guarantee that there is3850* a perfectly matching request, see 15.3.7:3851* "However, a server might want to send only a3852* subset of the data requested for reasons of3853* its own... A client MUST inspect a 2063854* response's Content-Type and Content-Range3855* field(s) to determine what parts are enclosed3856* and whether additional requests are needed."3857* Also 15.3.7.2 Multiple Parts, noting that3858* the response may be sent in a Content-Type3859* multipart/byteranges, also "When multiple3860* ranges are requested, a server MAY coalesce3861* any of the ranges that overlap, or that are3862* separated by a gap that is smaller than the3863* overhead of sending multiple parts, regardless3864* of the order in which the corresponding range-3865* spec appeared in the received Range header3866* field." and 15.3.7.3 Combining Parts.3867* However, as mentioned above, the LIFO method3868* had issues with that as well. Truly proper3869* handling of such edge cases is more difficult.3870*/3871req_trans = NULL((void*)0);3872if (conv_data->req_list && conv_data->req_list->data) {3873for (iter = conv_data->req_list; iter; iter = iter->next) {3874if (((request_trans_t*)iter->data)->first_range_num == first_crange_num) {3875req_trans = iter->data;3876break;3877}3878}3879}3880 3881if (first_crange_num != 0 && req_trans) {3882match_trans = wmem_new(wmem_file_scope(), match_trans_t)((match_trans_t*)wmem_alloc((wmem_file_scope()), sizeof(match_trans_t
)))
;3883match_trans->req_frame = req_trans->req_frame;3884match_trans->resp_frame = pinfo->num;3885nstime_delta(&ns, &pinfo->fd->abs_ts, &req_trans->abs_time);3886match_trans->delta_time = ns;3887match_trans->request_uri = req_trans->request_uri;3888match_trans->http_host = curr_req_res->http_host;3889 3890wmem_map_insert(conv_data->matches_table,3891GUINT_TO_POINTER(match_trans->req_frame)((gpointer) (gulong) (match_trans->req_frame)), (void *)match_trans);3892wmem_map_insert(conv_data->matches_table,3893GUINT_TO_POINTER(match_trans->resp_frame)((gpointer) (gulong) (match_trans->resp_frame)), (void *)match_trans);3894 3895/* Remove and free all of the list entries up to and including the3896* matching one from req_list. */3897if (conv_data->req_list) {3898GSList *top_of_list = NULL((void*)0);3899 3900top_of_list = conv_data->req_list;3901while (top_of_list && top_of_list->data != req_trans) {3902 3903 top_of_list = g_slist_delete_link(top_of_list, top_of_list);3904}3905if (top_of_list && top_of_list->data == req_trans) {3906 3907 top_of_list = g_slist_delete_link(top_of_list, top_of_list);3908}3909conv_data->req_list = top_of_list;3910}3911}3912}3913if (curr_req_res)3914curr_req_res->resp_has_range = true1;3915break;3916}3917}3918return true1;3919}3920 3921/* Returns index of header tag in headers */3922static int3923find_header_hf_value(tvbuff_t *tvb, int offset, unsigned header_len)3924{3925unsigned i;3926 3927for (i = 0; i < array_length(headers)(sizeof (headers) / sizeof (headers)[0]); i++) {3928if (header_len == strlen(headers[i].name) &&3929tvb_strncaseeql(tvb, offset,3930 headers[i].name, header_len) == 0)3931return i;3932}3933 3934return -1;3935}3936 3937/*3938 * Dissect Microsoft's abomination called NTLMSSP over HTTP.3939 */3940static bool_Bool3941check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo, char *value)3942{3943static const char *ntlm_headers[] = {3944"NTLM ",3945"Negotiate ",3946NULL((void*)0)3947};3948const char **header;3949size_t hdrlen;3950proto_tree *hdr_tree;3951 3952/*3953 * Check for NTLM credentials and challenge; those can3954 * occur with WWW-Authenticate.3955 */3956for (header = &ntlm_headers[0]; *header != NULL((void*)0); header++) {3957hdrlen = strlen(*header);3958if (strncmp(value, *header, hdrlen) == 0) {3959if (hdr_item != NULL((void*)0)) {3960hdr_tree = proto_item_add_subtree(hdr_item,3961 ett_http_ntlmssp);3962} else3963hdr_tree = NULL((void*)0);3964value += hdrlen;3965dissect_http_ntlmssp(tvb, pinfo, hdr_tree, value);3966return true1;3967}3968}3969return false0;3970}3971 3972static tap_credential_t*3973basic_auth_credentials(wmem_allocator_t *scope, const char* str)3974{3975char **tokens = g_strsplit(str, ":", -1);3976 3977if (!tokens || !tokens[0] || !tokens[1]) {3978g_strfreev(tokens);3979return NULL((void*)0);3980}3981 3982tap_credential_t* auth = wmem_new0(scope, tap_credential_t)((tap_credential_t*)wmem_alloc0((scope), sizeof(tap_credential_t
)))
;3983 3984auth->username = wmem_strdup(scope, tokens[0]);3985auth->proto = "HTTP basic auth";3986 3987g_strfreev(tokens);3988 3989return auth;3990}3991 3992/*3993 * Dissect HTTP Basic authorization.3994 */3995static bool_Bool3996check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo, char *value)3997{3998static const char *basic_headers[] = {3999"Basic ",4000NULL((void*)0)4001};4002const char **header;4003size_t hdrlen;4004const uint8_t *decoded_value;4005proto_tree *hdr_tree;4006tvbuff_t *auth_tvb;4007 4008for (header = &basic_headers[0]; *header != NULL((void*)0); header++) {4009hdrlen = strlen(*header);4010if (strncmp(value, *header, hdrlen) == 0) {4011if (hdr_item != NULL((void*)0)) {4012hdr_tree = proto_item_add_subtree(hdr_item,4013 ett_http_ntlmssp);4014} else4015hdr_tree = NULL((void*)0);4016value += hdrlen;4017 4018auth_tvb = base64_to_tvb(tvb, value);4019add_new_data_source(pinfo, auth_tvb, "Basic Credentials");4020/* RFC 7617 says that the character encoding is only4021 * known to be UTF-8 if the 'charset' parameter was4022 * used. Otherwise, after Base64 decoding it could be4023 * any character encoding.4024 * XXX: Perhaps the field should be a FT_BYTES with4025 * BASE_SHOW_UTF_8_PRINTABLE?4026 */4027proto_tree_add_item_ret_string(hdr_tree, hf_http_basic, auth_tvb, 0, tvb_reported_length(auth_tvb), ENC_UTF_80x00000002, pinfo->pool, &decoded_value);4028tap_credential_t* auth = basic_auth_credentials(pinfo->pool, decoded_value);4029if (auth) {4030auth->num = auth->username_num = pinfo->num;4031auth->password_hf_id = hf_http_basic;4032tap_queue_packet(credentials_tap, pinfo, auth);4033}4034 4035return true1;4036}4037}4038return false0;4039}4040 4041/*4042 * Dissect HTTP Digest authorization.4043 */4044static bool_Bool4045check_auth_digest(proto_item* hdr_item, tvbuff_t* tvb, packet_info* pinfo _U___attribute__((unused)), char* value, int offset, int len)4046{4047proto_tree* hdr_tree;4048int queried_offset;4049 4050if (strncmp(value, "Digest", 6) == 0) {4051if (hdr_item != NULL((void*)0)) {4052hdr_tree = proto_item_add_subtree(hdr_item, ett_http_ntlmssp);4053} else {4054hdr_tree = NULL((void*)0);4055}4056offset += 21;4057len -= 21;4058while (len > 0) {4059/* Find comma/end of line */4060queried_offset = tvb_find_uint8(tvb, offset, len, ',');4061if (queried_offset > 0) {4062proto_tree_add_format_text(hdr_tree, tvb, offset, queried_offset - offset);4063len -= (queried_offset - offset);4064offset = queried_offset + 1;4065} else {4066len = 0;4067}4068}4069return true1;4070} else {4071return false0;4072}4073}4074/*4075 * Dissect HTTP CitrixAGBasic authorization.4076 */4077static bool_Bool4078check_auth_citrixbasic(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo, char *value, int offset)4079{4080static const char *basic_headers[] = {4081"CitrixAGBasic ",4082NULL((void*)0)4083};4084const char **header;4085size_t hdrlen;4086proto_tree *hdr_tree;4087char *ch_ptr;4088int data_len;4089tvbuff_t *data_tvb;4090proto_item *hidden_item;4091proto_item *pi;4092const uint8_t *user = NULL((void*)0), *passwd = NULL((void*)0);4093 4094for (header = &basic_headers[0]; *header != NULL((void*)0); header++) {4095hdrlen = strlen(*header);4096if (strncmp(value, *header, hdrlen) == 0) {4097if (hdr_item != NULL((void*)0)) {4098hdr_tree = proto_item_add_subtree(hdr_item,4099 ett_http_ntlmssp);4100} else4101hdr_tree = NULL((void*)0);4102value += hdrlen;4103offset += (int)hdrlen + 15;4104hidden_item = proto_tree_add_boolean(hdr_tree,4105 hf_http_citrix, tvb, 0, 0, 1);4106proto_item_set_hidden(hidden_item);4107 4108if(strncmp(value, "username=\"", 10) == 0) {4109value += 10;4110offset += 10;4111ch_ptr = strchr(value, '"');4112if ( ch_ptr != NULL((void*)0) ) {4113data_len = (int)(ch_ptr - value);4114if (data_len) {4115data_tvb = base64_tvb_to_new_tvb(tvb, offset, data_len);4116add_new_data_source(pinfo, data_tvb, "Username");4117/* XXX: We don't know for certain the string encoding here. */4118pi = proto_tree_add_item_ret_string(hdr_tree, hf_http_citrix_user, data_tvb, 0, tvb_reported_length(data_tvb), ENC_UTF_80x00000002, pinfo->pool, &user);4119} else {4120pi = proto_tree_add_string(hdr_tree, hf_http_citrix_user, tvb, offset, 0, "");4121}4122proto_item_set_generated(pi);4123value += data_len + 1;4124offset += data_len + 1;4125}4126}4127if(strncmp(value, "; domain=\"", 10) == 0) {4128value += 10;4129offset += 10;4130ch_ptr = strchr(value, '"');4131if ( ch_ptr != NULL((void*)0) ) {4132data_len = (int)(ch_ptr - value);4133if (data_len) {4134data_tvb = base64_tvb_to_new_tvb(tvb, offset, data_len);4135add_new_data_source(pinfo, data_tvb, "Domain");4136pi = proto_tree_add_item(hdr_tree, hf_http_citrix_domain, data_tvb, 0, tvb_reported_length(data_tvb), ENC_UTF_80x00000002);4137} else {4138pi = proto_tree_add_string(hdr_tree, hf_http_citrix_domain, tvb, offset, 0, "");4139}4140proto_item_set_generated(pi);4141value += data_len + 1;4142offset += data_len + 1;4143}4144}4145if(strncmp(value, "; password=\"", 12) == 0) {4146value += 12;4147offset += 12;4148ch_ptr = strchr(value, '"');4149if ( ch_ptr != NULL((void*)0) ) {4150data_len = (int)(ch_ptr - value);4151if (data_len) {4152data_tvb = base64_tvb_to_new_tvb(tvb, offset, data_len);4153add_new_data_source(pinfo, data_tvb, "Password");4154pi = proto_tree_add_item_ret_string(hdr_tree, hf_http_citrix_passwd, data_tvb, 0, tvb_reported_length(data_tvb), ENC_UTF_80x00000002, pinfo->pool, &passwd);4155} else {4156pi = proto_tree_add_string(hdr_tree, hf_http_citrix_passwd, tvb, offset, 0, "");4157}4158proto_item_set_generated(pi);4159value += data_len + 1;4160offset += data_len + 1;4161}4162}4163if(strncmp(value, "; AGESessionId=\"", 16) == 0) {4164value += 16;4165offset += 16;4166ch_ptr = strchr(value, '"');4167if ( ch_ptr != NULL((void*)0) ) {4168data_len = (int)(ch_ptr - value);4169if (data_len) {4170data_tvb = base64_tvb_to_new_tvb(tvb, offset, data_len);4171add_new_data_source(pinfo, data_tvb, "Session ID");4172pi = proto_tree_add_item(hdr_tree, hf_http_citrix_session, data_tvb, 0, tvb_reported_length(data_tvb), ENC_UTF_80x00000002);4173} else {4174pi = proto_tree_add_string(hdr_tree, hf_http_citrix_session, tvb,4175 offset, 0, "");4176}4177proto_item_set_generated(pi);4178}4179}4180if (user != NULL((void*)0) && passwd != NULL((void*)0)) {4181 4182tap_credential_t* auth = wmem_new0(pinfo->pool, tap_credential_t)((tap_credential_t*)wmem_alloc0((pinfo->pool), sizeof(tap_credential_t
)))
;4183 4184auth->username = wmem_strdup(pinfo->pool, user);4185auth->proto = "HTTP CitrixAGBasic auth";4186auth->num = auth->username_num = pinfo->num;4187auth->password_hf_id = hf_http_citrix_passwd;4188tap_queue_packet(credentials_tap, pinfo, auth);4189}4190return true1;4191}4192}4193return false0;4194}4195 4196static bool_Bool4197check_auth_kerberos(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo, const char *value)4198{4199proto_tree *hdr_tree;4200 4201if (strncmp(value, "Kerberos ", 9) == 0) {4202if (hdr_item != NULL((void*)0)) {4203hdr_tree = proto_item_add_subtree(hdr_item, ett_http_kerberos);4204} else4205hdr_tree = NULL((void*)0);4206 4207dissect_http_kerberos(tvb, pinfo, hdr_tree, value);4208return true1;4209}4210return false0;4211}4212 4213static int4214dissect_http_on_stream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,4215 http_conv_t *conv_data, bool_Bool end_of_stream, const uint32_t *seq)4216{4217intoffset = 0;4218intlen = 0;4219 4220while (tvb_reported_length_remaining(tvb, offset) > 0) {4221/* Switch protocol if the data starts after response headers. */4222if (conv_data->startframe &&4223(pinfo->num > conv_data->startframe ||4224(pinfo->num == conv_data->startframe && offset >= conv_data->startoffset))) {4225/* Increase pinfo->can_desegment because we are traversing4226 * http and want to preserve desegmentation functionality for4227 * the proxied protocol4228 */4229if (pinfo->can_desegment > 0)4230pinfo->can_desegment++;4231if (conv_data->next_handle) {4232call_dissector_only(conv_data->next_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree, NULL((void*)0));4233} else {4234call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);4235}4236/*4237 * If a subdissector requests reassembly, be sure not to4238 * include the preceding HTTP headers.4239 */4240if (pinfo->desegment_len) {4241pinfo->desegment_offset += offset;4242}4243break;4244}4245len = dissect_http_message(tvb, offset, pinfo, tree, conv_data, "HTTP", proto_http, end_of_stream, seq);4246if (len < 0)4247break;4248offset += len;4249 4250/*4251 * OK, we've set the Protocol and Info columns for the4252 * first HTTP message; set a fence so that subsequent4253 * HTTP messages don't overwrite the Info column.4254 */4255col_set_fence(pinfo->cinfo, COL_INFO);4256}4257/* dissect_http_message() returns -2 if message is not valid HTTP */4258return (len == -2)4259? 04260: (int)tvb_captured_length(tvb);4261}4262 4263static int4264dissect_http_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)4265{4266struct tcpinfo *tcpinfo = (struct tcpinfo *)data;4267conversation_t *conversation;4268http_conv_t *conv_data;4269bool_Bool end_of_stream;4270 4271conv_data = get_http_conversation_data(pinfo, &conversation);4272 4273/* Call HTTP2 dissector directly when detected via heuristics, but not4274 * when it was upgraded (the conversation started with HTTP). */4275if (conversation_get_proto_data(conversation, proto_http2) &&4276 !conv_data->startframe) {4277if (pinfo->can_desegment > 0)4278pinfo->can_desegment++;4279return call_dissector_only(http2_handle, tvb, pinfo, tree, data);4280}4281 4282/*4283 * Check if this is proxied connection and if so, hand of dissection to the4284 * payload-dissector.4285 * Response code 200 means "OK" and strncmp() == 0 means the strings match exactly */4286http_req_res_t *curr_req_res = conv_data->req_res_tail;4287if(pinfo->num >= conv_data->startframe &&4288 curr_req_res &&4289 curr_req_res->response_code == 200 &&4290 curr_req_res->request_method &&4291 strncmp(curr_req_res->request_method, "CONNECT", 7) == 0 &&4292 curr_req_res->request_uri) {4293if (conv_data->startframe == 0 && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4294conv_data->startframe = pinfo->num;4295conv_data->startoffset = 0;4296copy_address_wmem(wmem_file_scope(), &conv_data->server_addr, &pinfo->dst);4297conv_data->server_port = pinfo->destport;4298}4299http_payload_subdissector(tvb, tree, pinfo, conv_data, data);4300 4301return tvb_captured_length(tvb);4302}4303 4304/* XXX - how to detect end-of-stream without tcpinfo */4305end_of_stream = (tcpinfo && IS_TH_FIN(tcpinfo->flags)(tcpinfo->flags & 0x0001));4306return dissect_http_on_stream(tvb, pinfo, tree, conv_data, end_of_stream, tcpinfo ? &tcpinfo->seq : NULL((void*)0));4307}4308 4309static bool_Bool4310dissect_http_heur_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)4311{4312int offset = 0, next_offset, linelen;4313conversation_t *conversation;4314 4315 4316/* Check if we have a line terminated by CRLF4317 * Return the length of the line (not counting the line terminator at4318 * the end), or, if we don't find a line terminator:4319 *4320 *if "deseg" is true, return -1;4321 */4322linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, true1);4323if((linelen == -1)||(linelen == 8)){4324return false0;4325}4326 4327/* Check if the line start or ends with the HTTP token */4328if((tvb_strncaseeql(tvb, linelen-8, "HTTP/1.", 7) == 0)||(tvb_strncaseeql(tvb, 0, "HTTP/1.", 7) == 0)){4329conversation = find_or_create_conversation(pinfo);4330conversation_set_dissector_from_frame_number(conversation, pinfo->num, http_tcp_handle);4331dissect_http_tcp(tvb, pinfo, tree, data);4332return true1;4333}4334 4335return false0;4336}4337 4338static int4339dissect_http_tls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))4340{4341conversation_t *conversation;4342http_conv_t *conv_data;4343bool_Bool end_of_stream;4344 4345conv_data = get_http_conversation_data(pinfo, &conversation);4346 4347struct tlsinfo *tlsinfo = (struct tlsinfo *)data;4348end_of_stream = (tlsinfo && tlsinfo->end_of_stream);4349return dissect_http_on_stream(tvb, pinfo, tree, conv_data, end_of_stream, tlsinfo ? &tlsinfo->seq : NULL((void*)0));4350}4351 4352static bool_Bool4353dissect_http_heur_tls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)4354{4355int offset = 0, next_offset, linelen;4356conversation_t *conversation;4357http_conv_t*conv_data;4358 4359conversation = find_or_create_conversation(pinfo);4360conv_data = (http_conv_t *)conversation_get_proto_data(conversation, proto_http);4361/* A http conversation was previously started, assume it is still active */4362if (conv_data) {4363dissect_http_tls(tvb, pinfo, tree, data);4364return true1;4365}4366 4367/* Check if we have a line terminated by CRLF4368 * Return the length of the line (not counting the line terminator at4369 * the end), or, if we don't find a line terminator:4370 *4371 *if "deseg" is true, return -1;4372 */4373linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, true1);4374if((linelen == -1)||(linelen == 8)){4375return false0;4376}4377 4378/* Check if the line start or ends with the HTTP token */4379if((tvb_strncaseeql(tvb, linelen-8, "HTTP/1.", 7) != 0) && (tvb_strncaseeql(tvb, 0, "HTTP/1.", 7) != 0)) {4380 /* we couldn't find the Magic Hello HTTP/1.X. */4381return false0;4382}4383 4384dissect_http_tls(tvb, pinfo, tree, data);4385return true1;4386}4387 4388static int4389dissect_http_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))4390{4391conversation_t *conversation;4392http_conv_t *conv_data;4393 4394conv_data = get_http_conversation_data(pinfo, &conversation);4395 4396/*4397 * XXX - we need to provide an end-of-stream indication.4398 */4399return dissect_http_on_stream(tvb, pinfo, tree, conv_data, false0, NULL((void*)0));4400}4401 4402static int4403dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))4404{4405conversation_t *conversation;4406http_conv_t *conv_data;4407 4408conv_data = get_http_conversation_data(pinfo, &conversation);4409 4410/*4411 * XXX - what should be done about reassembly, pipelining, etc.4412 * here?4413 */4414return dissect_http_on_stream(tvb, pinfo, tree, conv_data, false0, NULL((void*)0));4415}4416 4417static int4418dissect_ssdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))4419{4420conversation_t *conversation;4421http_conv_t*conv_data;4422 4423conv_data = get_http_conversation_data(pinfo, &conversation);4424dissect_http_message(tvb, 0, pinfo, tree, conv_data, "SSDP", proto_ssdp, false0, NULL((void*)0));4425return tvb_captured_length(tvb);4426}4427 4428static void4429range_delete_http_tls_callback(uint32_t port, void *ptr _U___attribute__((unused))) {4430ssl_dissector_delete(port, http_tls_handle);4431}4432 4433static void4434range_add_http_tls_callback(uint32_t port, void *ptr _U___attribute__((unused))) {4435ssl_dissector_add(port, http_tls_handle);4436}4437 4438static void reinit_http(void) {4439http_tcp_range = prefs_get_range_value("http", "tcp.port");4440 4441http_sctp_range = prefs_get_range_value("http", "sctp.port");4442 4443range_foreach(http_tls_range, range_delete_http_tls_callback, NULL((void*)0));4444wmem_free(wmem_epan_scope(), http_tls_range);4445http_tls_range = range_copy(wmem_epan_scope(), global_http_tls_range);4446range_foreach(http_tls_range, range_add_http_tls_callback, NULL((void*)0));4447}4448 4449void4450proto_register_http(void)4451{4452static hf_register_info hf[] = {4453 { &hf_http_notification,4454 { "Notification", "http.notification",4455FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,4456"true if HTTP notification", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4457 { &hf_http_response,4458 { "Response", "http.response",4459FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,4460"true if HTTP response", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4461 { &hf_http_request,4462 { "Request", "http.request",4463FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,4464"true if HTTP request", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4465 { &hf_http_basic,4466 { "Credentials", "http.authbasic",4467FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4468 { &hf_http_citrix,4469 { "Citrix AG Auth", "http.authcitrix",4470FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,4471"true if CitrixAGBasic Auth", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4472 { &hf_http_citrix_user,4473 { "Citrix AG Username", "http.authcitrix.user",4474FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4475 { &hf_http_citrix_domain,4476 { "Citrix AG Domain", "http.authcitrix.domain",4477FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4478 { &hf_http_citrix_passwd,4479 { "Citrix AG Password", "http.authcitrix.password",4480FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4481 { &hf_http_citrix_session,4482 { "Citrix AG Session ID", "http.authcitrix.session",4483FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4484 { &hf_http_response_line,4485 { "Response line", "http.response.line",4486FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4487 { &hf_http_request_line,4488 { "Request line", "http.request.line",4489FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4490 { &hf_http_request_method,4491 { "Request Method", "http.request.method",4492FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4493"HTTP Request Method", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4494 { &hf_http_request_uri,4495 { "Request URI", "http.request.uri",4496FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4497"HTTP Request-URI", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4498 { &hf_http_request_path,4499 { "Request URI Path", "http.request.uri.path",4500FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4501"HTTP Request-URI Path", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4502 { &hf_http_request_path_segment,4503 { "Request URI Path Segment", "http.request.uri.path.segment",4504FT_STRING, BASE_NONE, NULL((void*)0), 0,4505NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },4506 { &hf_http_request_query,4507 { "Request URI Query", "http.request.uri.query",4508FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4509"HTTP Request-URI Query", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4510 { &hf_http_request_query_parameter,4511 { "Request URI Query Parameter", "http.request.uri.query.parameter",4512FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4513"HTTP Request-URI Query Parameter", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4514 { &hf_http_request_version,4515 { "Request Version", "http.request.version",4516FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4517"HTTP Request HTTP-Version", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4518 { &hf_http_response_version,4519 { "Response Version", "http.response.version",4520FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4521"HTTP Response HTTP-Version", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4522 { &hf_http_request_full_uri,4523 { "Full request URI", "http.request.full_uri",4524FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4525"The full requested URI (including host name)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4526 { &hf_http_response_code,4527 { "Status Code", "http.response.code",4528FT_UINT24, BASE_DEC, NULL((void*)0), 0x0,4529"HTTP Response Status Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4530 { &hf_http_response_code_desc,4531 { "Status Code Description", "http.response.code.desc",4532FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4533"HTTP Response Status Code Description", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4534 { &hf_http_response_phrase,4535 { "Response Phrase", "http.response.phrase",4536 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4537"HTTP Response Reason Phrase", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4538 { &hf_http_authorization,4539 { "Authorization", "http.authorization",4540FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4541"HTTP Authorization header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4542 { &hf_http_proxy_authenticate,4543 { "Proxy-Authenticate", "http.proxy_authenticate",4544FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4545"HTTP Proxy-Authenticate header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4546 { &hf_http_proxy_authorization,4547 { "Proxy-Authorization", "http.proxy_authorization",4548FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4549"HTTP Proxy-Authorization header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4550 { &hf_http_proxy_connect_host,4551 { "Proxy-Connect-Hostname", "http.proxy_connect_host",4552FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4553"HTTP Proxy Connect Hostname", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4554 { &hf_http_proxy_connect_port,4555 { "Proxy-Connect-Port", "http.proxy_connect_port",4556FT_UINT16, BASE_DEC, NULL((void*)0), 0x0,4557"HTTP Proxy Connect Port", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4558 { &hf_http_www_authenticate,4559 { "WWW-Authenticate", "http.www_authenticate",4560FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4561"HTTP WWW-Authenticate header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4562 { &hf_http_content_type,4563 { "Content-Type", "http.content_type",4564FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4565"HTTP Content-Type header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4566 { &hf_http_content_length_header,4567 { "Content-Length", "http.content_length_header",4568FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4569"HTTP Content-Length header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4570 { &hf_http_content_length,4571 { "Content length", "http.content_length",4572FT_UINT64, BASE_DEC, NULL((void*)0), 0x0,4573NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4574 { &hf_http_content_encoding,4575 { "Content-Encoding", "http.content_encoding",4576FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4577"HTTP Content-Encoding header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4578 { &hf_http_transfer_encoding,4579 { "Transfer-Encoding", "http.transfer_encoding",4580FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4581"HTTP Transfer-Encoding header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4582 { &hf_http_upgrade,4583 { "Upgrade", "http.upgrade",4584FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4585"HTTP Upgrade header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4586 { &hf_http_user_agent,4587 { "User-Agent", "http.user_agent",4588FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4589"HTTP User-Agent header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4590 { &hf_http_host,4591 { "Host", "http.host",4592FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4593"HTTP Host", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4594 { &hf_http_range,4595 { "Range", "http.range",4596FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4597"HTTP Range", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4598 { &hf_http_content_range,4599 { "Content-Range", "http.content_range",4600FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4601"HTTP Content-Range", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4602 { &hf_http_connection,4603 { "Connection", "http.connection",4604FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4605"HTTP Connection", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4606 { &hf_http_cookie,4607 { "Cookie", "http.cookie",4608FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4609"HTTP Cookie", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4610 { &hf_http_cookie_pair,4611 { "Cookie pair", "http.cookie_pair",4612FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4613"A name/value HTTP cookie pair", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4614 { &hf_http_accept,4615 { "Accept", "http.accept",4616FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4617"HTTP Accept", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4618 { &hf_http_referer,4619 { "Referer", "http.referer",4620FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4621"HTTP Referer", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4622 { &hf_http_accept_language,4623 { "Accept-Language", "http.accept_language",4624FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4625"HTTP Accept Language", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4626 { &hf_http_accept_encoding,4627 { "Accept Encoding", "http.accept_encoding",4628FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4629"HTTP Accept Encoding", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4630 { &hf_http_date,4631 { "Date", "http.date",4632FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4633"HTTP Date", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4634 { &hf_http_cache_control,4635 { "Cache-Control", "http.cache_control",4636FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4637"HTTP Cache Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4638 { &hf_http_server,4639 { "Server", "http.server",4640FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4641"HTTP Server", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4642 { &hf_http_location,4643 { "Location", "http.location",4644FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4645"HTTP Location", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4646 { &hf_http_sec_websocket_accept,4647 { "Sec-WebSocket-Accept", "http.sec_websocket_accept",4648FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4649NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4650 { &hf_http_sec_websocket_extensions,4651 { "Sec-WebSocket-Extensions", "http.sec_websocket_extensions",4652FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4653NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4654 { &hf_http_sec_websocket_key,4655 { "Sec-WebSocket-Key", "http.sec_websocket_key",4656FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4657NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4658 { &hf_http_sec_websocket_protocol,4659 { "Sec-WebSocket-Protocol", "http.sec_websocket_protocol",4660FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4661NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4662 { &hf_http_sec_websocket_version,4663 { "Sec-WebSocket-Version", "http.sec_websocket_version",4664FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4665NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4666 { &hf_http_set_cookie,4667 { "Set-Cookie", "http.set_cookie",4668FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4669"HTTP Set Cookie", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4670 { &hf_http_last_modified,4671 { "Last-Modified", "http.last_modified",4672FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4673"HTTP Last Modified", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4674 { &hf_http_x_forwarded_for,4675 { "X-Forwarded-For", "http.x_forwarded_for",4676FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4677"HTTP X-Forwarded-For", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4678 { &hf_http_http2_settings,4679 { "HTTP2-Settings", "http.http2_settings",4680FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4681NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4682 { &hf_http_request_in,4683 { "Request in frame", "http.request_in",4684FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST)((gpointer) (glong) (FT_FRAMENUM_REQUEST)), 0,4685"This packet is a response to the packet with this number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4686 { &hf_http_response_in,4687 { "Response in frame", "http.response_in",4688FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE)((gpointer) (glong) (FT_FRAMENUM_RESPONSE)), 0,4689"This packet will be responded in the packet with this number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4690 { &hf_http_time,4691 { "Time since request", "http.time",4692FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0,4693"Time since the request was sent", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4694 { &hf_http_chunked_trailer_part,4695 { "trailer-part", "http.chunked_trailer_part",4696FT_STRING, BASE_NONE, NULL((void*)0), 0,4697"Optional trailer in a chunked body", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4698 { &hf_http_chunk_boundary,4699 { "Chunk boundary", "http.chunk_boundary",4700FT_BYTES, BASE_NONE, NULL((void*)0), 0,4701NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4702 { &hf_http_chunk_size,4703 { "Chunk size", "http.chunk_size",4704FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_octet_octets)((0 ? (const struct unit_name_string*)0 : ((&units_octet_octets
))))
, 0,4705NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4706 { &hf_http_chunk_data,4707 { "Chunk data", "http.chunk_data",4708FT_BYTES, BASE_NONE, NULL((void*)0), 0,4709NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4710 { &hf_http_file_data,4711 { "File Data", "http.file_data",4712FT_BYTES, BASE_NONE, NULL((void*)0), 0,4713NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4714 { &hf_http_unknown_header,4715 { "Unknown header", "http.unknown_header",4716FT_STRING, BASE_NONE, NULL((void*)0), 0,4717NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4718 { &hf_http_http2_settings_uri,4719 { "HTTP2 Settings URI", "http.http2_settings_uri",4720FT_BYTES, BASE_NONE, NULL((void*)0), 0,4721NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4722 4723/* Body fragments */4724 REASSEMBLE_INIT_HF_ITEMS(http_body, "HTTP Chunked Body", "http.body"){ &hf_http_body_fragments, { "Reassembled " "HTTP Chunked Body"
" fragments", "http.body" ".fragments", FT_NONE, BASE_NONE, (
(void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0) } }, { &hf_http_body_fragment, { "HTTP Chunked Body"
" fragment", "http.body" ".fragment", FT_FRAMENUM, BASE_NONE
, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, (
(void*)0) } }, { &hf_http_body_fragment_overlap, { "HTTP Chunked Body"
" fragment overlap", "http.body" ".fragment.overlap", FT_BOOLEAN
, BASE_NONE, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { &hf_http_body_fragment_overlap_conflicts
, { "HTTP Chunked Body" " fragment overlapping with conflicting data"
, "http.body" ".fragment.overlap.conflicts", FT_BOOLEAN, BASE_NONE
, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, (
(void*)0) } }, { &hf_http_body_fragment_multiple_tails, {
"HTTP Chunked Body" " has multiple tail fragments", "http.body"
".fragment.multiple_tails", FT_BOOLEAN, BASE_NONE, ((void*)0
), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
}, { &hf_http_body_fragment_too_long_fragment, { "HTTP Chunked Body"
" fragment too long", "http.body" ".fragment.too_long_fragment"
, FT_BOOLEAN, BASE_NONE, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { &hf_http_body_fragment_error, { "HTTP Chunked Body"
" defragment error", "http.body" ".fragment.error", FT_FRAMENUM
, BASE_NONE, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { &hf_http_body_fragment_count, { "HTTP Chunked Body"
" fragment count", "http.body" ".fragment.count", FT_UINT32,
BASE_DEC, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { &hf_http_body_reassembled_in, { "Reassembled in"
, "http.body" ".reassembled.in", FT_FRAMENUM, BASE_NONE, ((void
*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0
) } }, { &hf_http_body_reassembled_length, { "Reassembled length"
, "http.body" ".reassembled.length", FT_UINT32, BASE_DEC, ((void
*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0
) } }, { &hf_http_body_reassembled_data, { "Reassembled data"
, "http.body" ".reassembled.data", FT_BYTES, BASE_NONE, ((void
*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0
) } }, { &hf_http_body_segment, { "HTTP Chunked Body" " segment"
, "http.body" ".segment", FT_BYTES, BASE_NONE, ((void*)0), 0x0
, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} }
,4725};4726static int *ett[] = {4727&ett_http,4728&ett_http_ntlmssp,4729&ett_http_kerberos,4730&ett_http_request,4731&ett_http_request_uri,4732&ett_http_request_path,4733&ett_http_request_query,4734&ett_http_chunked_response,4735&ett_http_chunk_data,4736&ett_http_encoded_entity,4737&ett_http_header_item,4738&ett_http_http2_settings_item,4739REASSEMBLE_INIT_ETT_ITEMS(http_body)&ett_http_body_fragment, &ett_http_body_fragments,4740};4741 4742static ei_register_info ei[] = {4743{ &ei_http_te_and_length, { "http.te_and_length", PI_MALFORMED0x07000000, PI_WARN0x00600000, "The Content-Length and Transfer-Encoding header must not be set together", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},4744{ &ei_http_te_unknown, { "http.te_unknown", PI_UNDECODED0x05000000, PI_WARN0x00600000, "Unknown transfer coding name in Transfer-Encoding header", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},4745{ &ei_http_subdissector_failed, { "http.subdissector_failed", PI_MALFORMED0x07000000, PI_NOTE0x00400000, "HTTP body subdissector failed, trying heuristic subdissector", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},4746{ &ei_http_tls_port, { "http.tls_port", PI_SECURITY0x0a000000, PI_WARN0x00600000, "Unencrypted HTTP protocol detected over encrypted port, could indicate a dangerous misconfiguration.", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},4747{ &ei_http_excess_data, { "http.excess_data", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Excess data after a body (not a new request/response), previous Content-Length bogus?", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},4748{ &ei_http_leading_crlf, { "http.leading_crlf", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Leading CRLF previous message in the stream may have extra CRLF", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},4749{ &ei_http_bad_header_name, { "http.bad_header_name", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Illegal characters found in header name", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},4750{ &ei_http_decompression_failed, { "http.decompression_failed", PI_UNDECODED0x05000000, PI_WARN0x00600000, "Decompression failed", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},4751{ &ei_http_decompression_disabled, { "http.decompression_disabled", PI_UNDECODED0x05000000, PI_CHAT0x00200000, "Decompression disabled", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}}4752 4753};4754 4755/* UAT for header fields */4756static uat_field_t custom_header_uat_fields[] = {4757UAT_FLD_CSTRING(header_fields, header_name, "Header name", "HTTP header name"){"header_name", "Header name", PT_TXTMOD_STRING,{uat_fld_chk_str
,header_fields_header_name_set_cb,header_fields_header_name_tostr_cb
},{0,0,0},0,"HTTP header name",((void*)0)}
,4758UAT_FLD_CSTRING(header_fields, header_desc, "Field desc", "Description of the value contained in the header"){"header_desc", "Field desc", PT_TXTMOD_STRING,{uat_fld_chk_str
,header_fields_header_desc_set_cb,header_fields_header_desc_tostr_cb
},{0,0,0},0,"Description of the value contained in the header"
,((void*)0)}
,4759UAT_END_FIELDS{((void*)0),((void*)0),PT_TXTMOD_NONE,{0,0,0},{0,0,0},0,0,((void
*)0)}
4760};4761 4762module_t *http_module;4763expert_module_t* expert_http;4764uat_t* headers_uat;4765 4766proto_http = proto_register_protocol("Hypertext Transfer Protocol", "HTTP", "http");4767proto_ssdp = proto_register_protocol("Simple Service Discovery Protocol", "SSDP", "ssdp");4768 4769proto_register_field_array(proto_http, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));4770proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));4771expert_http = expert_register_protocol(proto_http);4772expert_register_field_array(expert_http, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));4773 4774http_handle = register_dissector("http", dissect_http, proto_http);4775http_tcp_handle = register_dissector("http-over-tcp", dissect_http_tcp, proto_http);4776http_tls_handle = register_dissector("http-over-tls", dissect_http_tls, proto_http); /* RFC 2818 */4777http_sctp_handle = register_dissector("http-over-sctp", dissect_http_sctp, proto_http);4778 4779reassembly_table_register(&http_streaming_reassembly_table, &addresses_ports_reassembly_table_functions);4780 4781http_module = prefs_register_protocol(proto_http, reinit_http);4782prefs_register_bool_preference(http_module, "desegment_headers",4783 "Reassemble HTTP headers spanning multiple TCP segments",4784 "Whether the HTTP dissector should reassemble headers "4785 "of a request spanning multiple TCP segments. "4786"To use this option, you must also enable "4787"\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",4788 &http_desegment_headers);4789prefs_register_bool_preference(http_module, "desegment_body",4790 "Reassemble HTTP bodies spanning multiple TCP segments",4791 "Whether the HTTP dissector should use the "4792 "\"Content-length:\" value, if present, to reassemble "4793 "the body of a request spanning multiple TCP segments, "4794 "and reassemble chunked data spanning multiple TCP segments. "4795"To use this option, you must also enable "4796"\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",4797 &http_desegment_body);4798prefs_register_bool_preference(http_module, "dechunk_body",4799 "Reassemble chunked transfer-coded bodies",4800 "Whether to reassemble bodies of entities that are transferred "4801 "using the \"Transfer-Encoding: chunked\" method",4802 &http_dechunk_body);4803#if defined(HAVE_ZLIB1) || defined(HAVE_ZLIBNG) || defined(HAVE_BROTLI1)4804prefs_register_bool_preference(http_module, "decompress_body",4805 "Uncompress entity bodies",4806 "Whether to uncompress entity bodies that are compressed "4807 "using \"Content-Encoding: \"",4808 &http_decompress_body);4809#endif4810prefs_register_bool_preference(http_module, "check_ascii_headers",4811 "Reject non-ASCII headers as invalid HTTP",4812 "Whether to treat non-ASCII in headers as non-HTTP data "4813 "and allow other dissectors to process it",4814 &http_check_ascii_headers);4815prefs_register_obsolete_preference(http_module, "tcp_alternate_port");4816 4817range_convert_str(wmem_epan_scope(), &global_http_tls_range, TLS_DEFAULT_RANGE"443", 65535);4818prefs_register_range_preference(http_module, "tls.port", "SSL/TLS Ports",4819"SSL/TLS Ports range",4820&global_http_tls_range, 65535);4821prefs_register_obsolete_preference(http_module, "ssl.port");4822/* UAT */4823headers_uat = uat_new("Custom HTTP Header Fields",4824 sizeof(header_field_t),4825 "custom_http_header_fields",4826 true1,4827 &header_fields,4828 &num_header_fields,4829 /* specifies named fields, so affects dissection4830 and the set of named fields */4831 UAT_AFFECTS_DISSECTION0x00000001|UAT_AFFECTS_FIELDS0x00000002,4832 NULL((void*)0),4833 header_fields_copy_cb,4834 header_fields_update_cb,4835 header_fields_free_cb,4836 header_fields_post_update_cb,4837 header_fields_reset_cb,4838 custom_header_uat_fields4839);4840 4841prefs_register_uat_preference(http_module, "custom_http_header_fields", "Custom HTTP header fields",4842 "A table to define custom HTTP header for which fields can be setup and used for filtering/data extraction etc.",4843 headers_uat);4844 4845/*4846 * Dissectors shouldn't register themselves in this table;4847 * instead, they should call "http_tcp_dissector_add()", and4848 * we'll register the port number they specify as a port4849 * for HTTP, and register them in our subdissector table.4850 *4851 * This only works for protocols such as IPP that run over4852 * HTTP on a specific non-HTTP port.4853 */4854port_subdissector_table = register_dissector_table("http.port",4855 "TCP port for protocols using HTTP", proto_http, FT_UINT16, BASE_DEC);4856 4857/*4858 * Maps the lowercase Upgrade header value.4859 * https://tools.ietf.org/html/rfc7230#section-8.64860 */4861upgrade_subdissector_table = register_dissector_table("http.upgrade", "HTTP Upgrade", proto_http, FT_STRING, STRING_CASE_SENSITIVE0);4862 4863/*4864 * Heuristic dissectors SHOULD register themselves in4865 * this table using the standard heur_dissector_add()4866 * function.4867 */4868heur_subdissector_list = register_heur_dissector_list_with_description("http", "HTTP payload fallback", proto_http);4869 4870/*4871 * Register for tapping4872 */4873http_tap = register_tap("http"); /* HTTP statistics tap */4874http_follow_tap = register_tap("http_follow"); /* HTTP Follow tap */4875credentials_tap = register_tap("credentials"); /* credentials tap */4876 4877register_follow_stream(proto_http, "http_follow", tcp_follow_conv_filter, tcp_follow_index_filter, tcp_follow_address_filter,4878tcp_port_to_display, follow_tvb_tap_listener,4879get_tcp_stream_count, NULL((void*)0));4880http_eo_tap = register_export_object(proto_http, http_eo_packet, NULL((void*)0));4881 4882/* compile patterns, excluding "/" */4883ws_mempbrk_compile(&pbrk_gen_delims, ":?#[]@");4884/* exclude "=", separating key and value should be done separately */4885ws_mempbrk_compile(&pbrk_sub_delims, "!$&'()*+,;");4886 4887}4888 4889/*4890 * Called by dissectors for protocols that run atop HTTP/TCP.4891 */4892void4893http_tcp_dissector_add(uint32_t port, dissector_handle_t handle)4894{4895/*4896 * Register ourselves as the handler for that port number4897 * over TCP. "Auto-preference" not needed4898 */4899dissector_add_uint("tcp.port", port, http_tcp_handle);4900 4901/*4902 * And register them in *our* table for that port.4903 */4904dissector_add_uint("http.port", port, handle);4905}4906 4907WS_DLL_PUBLIC__attribute__ ((visibility ("default"))) extern4908void http_tcp_dissector_delete(uint32_t port)4909{4910/*4911 * Unregister ourselves as the handler for that port number4912 * over TCP. "Auto-preference" not needed4913 */4914dissector_delete_uint("tcp.port", port, NULL((void*)0));4915 4916/*4917 * And unregister them in *our* table for that port.4918 */4919dissector_delete_uint("http.port", port, NULL((void*)0));4920}4921 4922void4923http_tcp_port_add(uint32_t port)4924{4925/*4926 * Register ourselves as the handler for that port number4927 * over TCP. We rely on our caller having registered4928 * themselves for the appropriate media type.4929 * No "auto-preference" used.4930 */4931dissector_add_uint("tcp.port", port, http_tcp_handle);4932}4933 4934void4935proto_reg_handoff_http(void)4936{4937dissector_handle_t ssdp_handle;4938 4939media_handle = find_dissector_add_dependency("media", proto_http);4940http2_handle = find_dissector("http2");4941/*4942 * XXX - is there anything to dissect in the body of an SSDP4943 * request or reply? I.e., should there be an SSDP dissector?4944 */4945ssdp_handle = create_dissector_handle(dissect_ssdp, proto_ssdp);4946dissector_add_uint_with_preference("udp.port", UDP_PORT_SSDP1900, ssdp_handle);4947 4948/*4949 * TLS Application-Layer Protocol Negotiation (ALPN) protocol ID.4950 */4951dissector_add_string("tls.alpn", "http/1.1", http_tls_handle);4952 4953ntlmssp_handle = find_dissector_add_dependency("ntlmssp", proto_http);4954gssapi_handle = find_dissector_add_dependency("gssapi", proto_http);4955sstp_handle = find_dissector_add_dependency("sstp", proto_http);4956 4957stats_tree_cfg *st_config;4958st_config = stats_tree_register("http", "http", "HTTP" STATS_TREE_MENU_SEPARATOR"//" "Packet Counter", 0, http_stats_tree_packet, http_stats_tree_init, NULL((void*)0) );4959stats_tree_set_first_column_name(st_config, "Packet Type");4960st_config = stats_tree_register("http", "http_req", "HTTP" STATS_TREE_MENU_SEPARATOR"//" "Requests", 0, http_req_stats_tree_packet, http_req_stats_tree_init, NULL((void*)0) );4961stats_tree_set_first_column_name(st_config, "Request Type");4962st_config = stats_tree_register("http", "http_srv", "HTTP" STATS_TREE_MENU_SEPARATOR"//" "Load Distribution",0, http_reqs_stats_tree_packet, http_reqs_stats_tree_init, NULL((void*)0) );4963stats_tree_set_first_column_name(st_config, "Packet Type");4964st_config = stats_tree_register("http", "http_seq", "HTTP" STATS_TREE_MENU_SEPARATOR"//" "Request Sequences",0, http_seq_stats_tree_packet, http_seq_stats_tree_init, NULL((void*)0) );4965stats_tree_set_first_column_name(st_config, "Sequence Type");4966 4967dissector_add_uint("acdr.tls_application_port", 443, http_handle);4968dissector_add_uint("acdr.tls_application", TLS_APP_HTTP, http_handle);4969dissector_add_uint("acdr.tls_application", TLS_APP_TR069, http_handle);4970dissector_add_uint("ippusb", 0, http_tcp_handle);4971}4972 4973/*4974 * Content-Type: message/http4975 */4976 4977static int proto_message_http;4978static int ett_message_http;4979 4980static int4981dissect_message_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))4982{4983proto_tree*subtree;4984proto_item*ti;4985intoffset = 0, next_offset;4986intlen;4987 4988col_append_str(pinfo->cinfo, COL_INFO, " (message/http)");4989if (tree) {4990ti = proto_tree_add_item(tree, proto_message_http,4991tvb, 0, -1, ENC_NA0x00000000);4992subtree = proto_item_add_subtree(ti, ett_message_http);4993while (tvb_offset_exists(tvb, offset)) {4994len = tvb_find_line_end(tvb, offset,4995tvb_ensure_captured_length_remaining(tvb, offset),4996&next_offset, false0);4997if (len == -1)4998break;4999proto_tree_add_format_text(subtree, tvb, offset, len);5000offset = next_offset;5001}5002}5003return tvb_captured_length(tvb);5004}5005 5006void5007proto_register_message_http(void)5008{5009static int *ett[] = {5010&ett_message_http,5011};5012 5013proto_message_http = proto_register_protocol("Media Type: message/http", "message/http", "message-http");5014proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));5015}5016 5017void5018proto_reg_handoff_message_http(void)5019{5020dissector_handle_t message_http_handle;5021 5022message_http_handle = create_dissector_handle(dissect_message_http,5023proto_message_http);5024 5025dissector_add_string("media_type", "message/http", message_http_handle);5026 5027heur_dissector_add("tcp", dissect_http_heur_tcp, "HTTP over TCP", "http_tcp", proto_http, HEURISTIC_ENABLE);5028heur_dissector_add("tls", dissect_http_heur_tls, "HTTP over TLS", "http_tls", proto_http, HEURISTIC_ENABLE);5029 5030proto_http2 = proto_get_id_by_filter_name("http2");5031 5032dissector_add_uint_range_with_preference("tcp.port", TCP_DEFAULT_RANGE"80,3128,3132,5985,8080,8088,11371,1900,2869,2710", http_tcp_handle);5033dissector_add_uint_range_with_preference("sctp.port", SCTP_DEFAULT_RANGE"80", http_sctp_handle);5034 5035/*5036 * Get the content type and Internet media type table5037 */5038media_type_subdissector_table = find_dissector_table("media_type");5039 5040streaming_content_type_dissector_table = find_dissector_table("streaming_content_type");5041 5042reinit_http();5043}5044 5045/*5046 * Editor modelines - https://www.wireshark.org/tools/modelines.html5047 *5048 * Local variables:5049 * c-basic-offset: 85050 * tab-width: 85051 * indent-tabs-mode: t5052 * End:5053 *5054 * vi: set shiftwidth=8 tabstop=8 noexpandtab:5055 * :indentSize=8:tabSize=8:noTabs=false:5056 */
1/** @file2 * Declarations of routines handling protocols with a request/response line,3 * headers, a blank line, and an optional body.4 *5 * Wireshark - Network traffic analyzer6 * By Gerald Combs <[emailprotected]>7 * Copyright 1998 Gerald Combs8 *9 * SPDX-License-Identifier: GPL-2.0-or-later10 */11 12#ifndef __REQ_RESP_HDRS_H__13#define __REQ_RESP_HDRS_H__14 15#include "ws_symbol_export.h"16#include "wsutil/strtoi.h"17 18/**19 * Optionally do reassembly of the request/response line, headers, and body.20 *21 * @param tvb The buffer.22 * @param offset The offset in the buffer to begin inspection.23 * @param pinfo Packet info from the parent protocol.24 * @param desegment_headers Do desegmentation on headers.25 * @param desegment_body Do desegmentation on body.26 * @param desegment_until_fin When desegment_body is enabled and no27 * Content-Length header is found, assume that all data following the headers28 * are part of the body.29 * @param[in,out] last_chunk_offset For the chunked Transfer-Encoding,30 * the offset (relative to the initial tvb offset) of the last chunk size31 * found. The result can be fed back into a future call in order to skip32 * to a later chunk and reduce processing from O(N^2) to O(N). Use 0 for33 * the initial call. Only set when chunked TE is found. May be NULL.34 * @param streaming_subdissector_table For searching a streaming reassembly35 * mode supported subdissector on it by the content-type header value.36 * @param[out] streaming_chunk_handle Only set when this is the beginning of37 * a chunk stream. (There is 'Transfer-Encoding: chunked' header and a38 * streaming reassembly mode supported subdissector is found according to39 * Content-Type header)40 * @return true if desegmentation is complete otherwise false41 */42WS_DLL_PUBLIC__attribute__ ((visibility ("default"))) extern bool_Bool43req_resp_hdrs_do_reassembly(tvbuff_t *tvb, const int offset, packet_info *pinfo,44 const bool_Bool desegment_headers, const bool_Bool desegment_body,45 bool_Bool desegment_until_fin, int *last_chunk_offset,46dissector_table_t streaming_subdissector_table, dissector_handle_t *streaming_chunk_handle);47 48/** Check whether the first line is the beginning of a chunk. */49static inline bool_Bool50starts_with_chunk_size(tvbuff_t* tvb, const int offset, packet_info* pinfo)51{52unsigned chunk_size = 0;53int linelen = tvb_find_line_end(tvb, offset, tvb_reported_length_remaining(tvb, offset), NULL((void*)0), true1);54 55if (linelen < 0)

23

Assuming 'linelen' is >= 0

24

Taking false branch

56return false0;57 58char* chunk_string = tvb_get_string_enc(pinfo->pool, tvb, offset, linelen, ENC_ASCII0x00000000);59char* c = chunk_string;60 61/* ignore extensions, including optional BWS ("bad whitespace")62 * in the grammar for historical reasons, see RFC 9112 7.1.1.63 */64if ((c = strpbrk(c, "; \t"))) {

25

Assuming 'c' is null

26

Taking false branch

65*c = '\0';66}67 68 if (!ws_hexstrtou32(chunk_string, NULL((void*)0), &chunk_size)) {

27

Assuming the condition is false

28

Taking false branch

69return false0; /* can not get chunk size*/70} else if (chunk_size > (1U << 31)) {

29

Assuming the condition is false

30

Taking false branch

71return false0; /* chunk size is unreasonable */72}73return true1;

31

Returning the value 1, which participates in a condition later

74}75 76#endif
/builds/wireshark/wireshark/epan/dissectors/packet-http.c (2024)
Top Articles
Mets Minors Recap: Brett Baty, Luke Ritter Mash in Syracuse
Futures Skills Showcase to highlight prospects
Design215 Word Pattern Finder
Using GPT for translation: How to get the best outcomes
Chicago Neighborhoods: Lincoln Square & Ravenswood - Chicago Moms
craigslist: kenosha-racine jobs, apartments, for sale, services, community, and events
Obor Guide Osrs
30 Insanely Useful Websites You Probably Don't Know About
Undergraduate Programs | Webster Vienna
Konkurrenz für Kioske: 7-Eleven will Minisupermärkte in Deutschland etablieren
Garrick Joker'' Hastings Sentenced
Azeroth Pilot Reloaded - Addons - World of Warcraft
2021 Lexus IS for sale - Richardson, TX - craigslist
The Connecticut Daily Lottery Hub
How Many Slices Are In A Large Pizza? | Number Of Pizzas To Order For Your Next Party
Shemal Cartoon
Sams Early Hours
National Weather Service Denver Co Forecast
Finger Lakes Ny Craigslist
Simplify: r^4+r^3-7r^2-r+6=0 Tiger Algebra Solver
Napa Autocare Locator
Salem Oregon Costco Gas Prices
360 Tabc Answers
V-Pay: Sicherheit, Kosten und Alternativen - BankingGeek
Huntersville Town Billboards
Persona 5 Royal Fusion Calculator (Fusion list with guide)
Menus - Sea Level Oyster Bar - NBPT
Amelia Chase Bank Murder
Workshops - Canadian Dam Association (CDA-ACB)
Bidrl.com Visalia
When His Eyes Opened Chapter 3123
Pixel Combat Unblocked
Movies - EPIC Theatres
Www.1Tamilmv.con
Davita Salary
Does Circle K Sell Elf Bars
Shiftwizard Login Johnston
Smartfind Express Henrico
Vip Lounge Odu
Heavenly Delusion Gif
Keeper Of The Lost Cities Series - Shannon Messenger
Hisense Ht5021Kp Manual
Babylon 2022 Showtimes Near Cinemark Downey And Xd
Payrollservers.us Webclock
Sofia Franklyn Leaks
60 Days From May 31
Gli italiani buttano sempre più cibo, quasi 7 etti a settimana (a testa)
Phone Store On 91St Brown Deer
Pulpo Yonke Houston Tx
Skybird_06
Www Extramovies Com
What Are Routing Numbers And How Do You Find Them? | MoneyTransfers.com
Latest Posts
Article information

Author: Jonah Leffler

Last Updated:

Views: 6311

Rating: 4.4 / 5 (45 voted)

Reviews: 92% of readers found this page helpful

Author information

Name: Jonah Leffler

Birthday: 1997-10-27

Address: 8987 Kieth Ports, Luettgenland, CT 54657-9808

Phone: +2611128251586

Job: Mining Supervisor

Hobby: Worldbuilding, Electronics, Amateur radio, Skiing, Cycling, Jogging, Taxidermy

Introduction: My name is Jonah Leffler, I am a determined, faithful, outstanding, inexpensive, cheerful, determined, smiling person who loves writing and wants to share my knowledge and understanding with you.