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

1

'headers' initialized to a null pointer value

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

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

4

Assuming 'direction' is not equal to 0

5

Taking false branch

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

6

Assuming 'direction' is < 0

7

Taking false branch

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

8

Assuming 'seq' is null

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

9

Assuming 'reported_length' is >= 1

10

Taking false branch

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

11

Assuming 'reported_length' is <= 3

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

13

Assuming field 'req_res_tail' is null

14

Taking false branch

1302have_seen_http = true1;1303 1304/*1305 * If this is binary data then there's no point in doing all the string1306 * operations below: they'll just be slow on this data.1307 */1308if (!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

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

17

Assuming the condition is false

1355/* No complete line was found in this segment, do1356 * desegmentation if we're told to.1357 */1358if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,1359 http_desegment_headers, http_desegment_body, false0, &chunk_offset,1360streaming_content_type_dissector_table, &handle)) {1361/*1362 * More data needed for desegmentation.1363 */1364return -1;1365}1366}1367 1368if (!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

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

19

Assuming 'http_desegment_body' is true

20

Assuming 'http_dechunk_body' is true

21

Taking true branch

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

22

Calling 'starts_with_chunk_size'

32

Returning from 'starts_with_chunk_size'

1378 1379if (begin_with_chunk

32.1

'begin_with_chunk' is true

32.1

'begin_with_chunk' is true
&&1380((prv_data

32.2

'prv_data' is null

32.2

'prv_data' is null
&& ( /* This packet has been parsed */1381/* and now we are in a HTTP request chunk stream */1382(prv_data->req_fwd_flow == direction && prv_data->req_streaming_reassembly_data) ||1383/* and now we are in a HTTP response chunk stream */1384(prv_data->req_fwd_flow != direction && prv_data->res_streaming_reassembly_data)))1385||1386(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 */1387/* and now we are in a HTTP request chunk stream */1388(tail_prv_data->req_fwd_flow == direction && tail_prv_data->req_streaming_reassembly_data) ||1389/* and now we are in a HTTP response chunk stream */1390(tail_prv_data->req_fwd_flow != direction && tail_prv_data->res_streaming_reassembly_data)))))1391{1392streaming_chunk_mode = true1;1393}1394}1395 1396/*1397 * Is the first line a request or response?1398 *1399 * Note that "tvb_find_line_end()" will return a value that1400 * is not longer than what's in the buffer, so the1401 * "tvb_get_ptr()" call won't throw an exception.1402 */1403firstline = tvb_get_ptr(tvb, offset, first_linelen);1404http_type = MEDIA_CONTAINER_HTTP_OTHERS;/* type not known yet */1405is_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'

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

39.1

'is_request_or_reply' is true

39.1

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

39.2

'streaming_chunk_mode' is false

39.2

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

40

Assuming 'http_desegment_body' is false

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

41

Assuming the condition is false

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

1479/* This handle is set because there is a header 'Transfer-Encoding: chunked', and1480 * a streaming mode reassembly supported subdissector is found according to the1481 * header of Content-Type.1482 */1483streaming_chunk_mode = true1;1484}1485} else if (have_seen_http) {1486/*1487 * If we know this is HTTP then call it continuation.1488 */1489/* If orig_offset > 0, this isn't the first message dissected1490 * in this segment, which means we had a Content-Length, but1491 * more data after the body. If this isn't a request or reply,1492 * that's bogus, and probably means the Content-Length was1493 * wrong.1494 */1495if (orig_offset > 0) {1496excess_data = true1;1497}1498col_set_str(pinfo->cinfo, COL_INFO, "Continuation");1499}1500 1501if (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) {1502/*1503 * Now set COL_PROTOCOL and create the http tree for the1504 * cases where we set COL_INFO above.1505 */1506col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);1507ti = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA0x00000000);1508http_tree = proto_item_add_subtree(ti, ett_http);1509 1510if (leading_crlf

45.2

'leading_crlf' is false

45.2

'leading_crlf' is false
) {

46

Taking false branch

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

46.1

'excess_data' is false

46.1

'excess_data' is false
) {

47

Taking false branch

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

48

Assuming field 'visited' is not equal to 0

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

48.1

'prv_data' is null

48.1

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

1547datalen = reported_length;1548goto dissecting_body;

50

Control jumps to line 2044

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

50.1

'datalen' is > 0

50.1

'datalen' is > 0
> 0) {

51

Taking true branch

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

51.1

'headers' is null

51.1

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

52

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

34

Assuming 'linelen' is >= 2

35

Assuming the condition is false

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

36

Assuming 'linelen' is >= 5

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

36.1

'reqresp_dissector' is null

36.1

'reqresp_dissector' is null
)

37

Taking false branch

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

38

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

3041}3042 3043/*3044 * Process headers.3045 */3046typedef struct {3047const char*name;3048int*hf;3049intspecial;3050} header_info;3051 3052#define HDR_NO_SPECIAL003053#define HDR_AUTHORIZATION113054#define HDR_AUTHENTICATE223055#define HDR_CONTENT_TYPE333056#define HDR_CONTENT_LENGTH443057#define HDR_CONTENT_ENCODING553058#define HDR_TRANSFER_ENCODING663059#define HDR_HOST773060#define HDR_UPGRADE883061#define HDR_COOKIE993062#define HDR_WEBSOCKET_PROTOCOL10103063#define HDR_WEBSOCKET_EXTENSIONS11113064#define HDR_REFERER12123065#define HDR_LOCATION13133066#define HDR_HTTP2_SETTINGS14143067#define HDR_RANGE15 153068#define HDR_CONTENT_RANGE16163069 3070static const header_info headers[] = {3071{ "Authorization", &hf_http_authorization, HDR_AUTHORIZATION1 },3072{ "Proxy-Authorization", &hf_http_proxy_authorization, HDR_AUTHORIZATION1 },3073{ "Proxy-Authenticate", &hf_http_proxy_authenticate, HDR_AUTHENTICATE2 },3074{ "WWW-Authenticate", &hf_http_www_authenticate, HDR_AUTHENTICATE2 },3075{ "Content-Type", &hf_http_content_type, HDR_CONTENT_TYPE3 },3076{ "Content-Length", &hf_http_content_length_header, HDR_CONTENT_LENGTH4 },3077{ "Content-Encoding", &hf_http_content_encoding, HDR_CONTENT_ENCODING5 },3078{ "Transfer-Encoding", &hf_http_transfer_encoding, HDR_TRANSFER_ENCODING6 },3079{ "Upgrade", &hf_http_upgrade, HDR_UPGRADE8 },3080{ "User-Agent",&hf_http_user_agent, HDR_NO_SPECIAL0 },3081{ "Host", &hf_http_host, HDR_HOST7 },3082{ "Range", &hf_http_range, HDR_RANGE15 },3083{ "Content-Range", &hf_http_content_range, HDR_CONTENT_RANGE16 },3084{ "Connection", &hf_http_connection, HDR_NO_SPECIAL0 },3085{ "Cookie", &hf_http_cookie, HDR_COOKIE9 },3086{ "Accept", &hf_http_accept, HDR_NO_SPECIAL0 },3087{ "Referer", &hf_http_referer, HDR_REFERER12 },3088{ "Accept-Language", &hf_http_accept_language, HDR_NO_SPECIAL0 },3089{ "Accept-Encoding", &hf_http_accept_encoding, HDR_NO_SPECIAL0 },3090{ "Date", &hf_http_date, HDR_NO_SPECIAL0 },3091{ "Cache-Control", &hf_http_cache_control, HDR_NO_SPECIAL0 },3092{ "Server", &hf_http_server, HDR_NO_SPECIAL0 },3093{ "Location", &hf_http_location, HDR_LOCATION13 },3094{ "Sec-WebSocket-Accept", &hf_http_sec_websocket_accept, HDR_NO_SPECIAL0 },3095{ "Sec-WebSocket-Extensions", &hf_http_sec_websocket_extensions, HDR_WEBSOCKET_EXTENSIONS11 },3096{ "Sec-WebSocket-Key", &hf_http_sec_websocket_key, HDR_NO_SPECIAL0 },3097{ "Sec-WebSocket-Protocol", &hf_http_sec_websocket_protocol, HDR_WEBSOCKET_PROTOCOL10 },3098{ "Sec-WebSocket-Version", &hf_http_sec_websocket_version, HDR_NO_SPECIAL0 },3099{ "Set-Cookie", &hf_http_set_cookie, HDR_NO_SPECIAL0 },3100{ "Last-Modified", &hf_http_last_modified, HDR_NO_SPECIAL0 },3101{ "X-Forwarded-For", &hf_http_x_forwarded_for, HDR_NO_SPECIAL0 },3102{ "HTTP2-Settings", &hf_http_http2_settings, HDR_HTTP2_SETTINGS14 },3103};3104 3105/*3106 * Look up a header name (assume lower-case header_name).3107 */3108static int*3109get_hf_for_header(char* header_name)3110{3111int* hf_id = NULL((void*)0);3112 3113if (header_fields_hash) {3114hf_id = (int*) g_hash_table_lookup(header_fields_hash, header_name);3115} else {3116hf_id = NULL((void*)0);3117}3118 3119return hf_id;3120}3121 3122/*3123 *3124 */3125static void3126deregister_header_fields(void)3127{3128if (dynamic_hf) {3129/* Deregister all fields */3130for (unsigned i = 0; i < dynamic_hf_size; i++) {3131proto_deregister_field (proto_http, *(dynamic_hf[i].p_id));3132g_free (dynamic_hf[i].p_id);3133}3134 3135proto_add_deregistered_data (dynamic_hf);3136dynamic_hf = NULL((void*)0);3137dynamic_hf_size = 0;3138}3139 3140if (header_fields_hash) {3141g_hash_table_destroy (header_fields_hash);3142header_fields_hash = NULL((void*)0);3143}3144}3145 3146static void3147header_fields_post_update_cb(void)3148{3149int* hf_id;3150char* header_name;3151char* header_name_key;3152 3153deregister_header_fields();3154 3155if (num_header_fields) {3156header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL((void*)0));3157dynamic_hf = g_new0(hf_register_info, num_header_fields)((hf_register_info *) g_malloc0_n ((num_header_fields), sizeof
(hf_register_info)))
;3158dynamic_hf_size = num_header_fields;3159 3160for (unsigned i = 0; i < dynamic_hf_size; i++) {3161hf_id = g_new(int,1)((int *) g_malloc_n ((1), sizeof (int)));3162*hf_id = -1;3163header_name = g_strdup(header_fields[i].header_name)g_strdup_inline (header_fields[i].header_name);3164header_name_key = g_ascii_strdown(header_name, -1);3165 3166dynamic_hf[i].p_id = hf_id;3167dynamic_hf[i].hfinfo.name = header_name;3168dynamic_hf[i].hfinfo.abbrev = ws_strdup_printf("http.header.%s", header_name)wmem_strdup_printf(((void*)0), "http.header.%s", header_name);3169dynamic_hf[i].hfinfo.type = FT_STRING;3170dynamic_hf[i].hfinfo.display = BASE_NONE;3171dynamic_hf[i].hfinfo.strings = NULL((void*)0);3172dynamic_hf[i].hfinfo.bitmask = 0;3173dynamic_hf[i].hfinfo.blurb = g_strdup(header_fields[i].header_desc)g_strdup_inline (header_fields[i].header_desc);3174HFILL_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);
;3175 3176g_hash_table_insert(header_fields_hash, header_name_key, hf_id);3177}3178 3179proto_register_field_array(proto_http, dynamic_hf, dynamic_hf_size);3180}3181}3182 3183static void3184header_fields_reset_cb(void)3185{3186deregister_header_fields();3187}3188 3189/**3190 * Parses the transfer-coding, returning true if everything was fully understood3191 * or false when unknown names were encountered.3192 */3193static bool_Bool3194http_parse_transfer_coding(const char *value, headers_t *eh_ptr)3195{3196bool_Bool is_fully_parsed = true1;3197 3198/* Mark header as set, but with unknown encoding. */3199eh_ptr->transfer_encoding = HTTP_TE_UNKNOWN;3200 3201while (*value) {3202/* skip OWS (SP / HTAB) and commas; stop at the end. */3203while (*value == ' ' || *value == '\t' || *value == ',')3204value++;3205if (!*value)3206break;3207 3208if (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") )
) {3209eh_ptr->transfer_encoding_chunked = true1;3210value += sizeof("chunked") - 1;3211continue;3212}3213 3214/* For now assume that chunked can only combined with exactly3215 * one other (compression) encoding. Anything else is3216 * unsupported. */3217if (eh_ptr->transfer_encoding != HTTP_TE_UNKNOWN) {3218/* No more transfer codings are expected. */3219is_fully_parsed = false0;3220break;3221}3222 3223if (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") )
) {3224eh_ptr->transfer_encoding = HTTP_TE_COMPRESS;3225value += sizeof("compress") - 1;3226} 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") )
) {3227eh_ptr->transfer_encoding = HTTP_TE_DEFLATE;3228value += sizeof("deflate") - 1;3229} 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") )
) {3230eh_ptr->transfer_encoding = HTTP_TE_GZIP;3231value += sizeof("gzip") - 1;3232} 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") )
) {3233eh_ptr->transfer_encoding = HTTP_TE_IDENTITY;3234value += sizeof("identity") - 1;3235} 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") )
) {3236eh_ptr->transfer_encoding = HTTP_TE_COMPRESS;3237value += sizeof("x-compress") - 1;3238} 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") )
) {3239eh_ptr->transfer_encoding = HTTP_TE_GZIP;3240value += sizeof("x-gzip") - 1;3241} else {3242/* Unknown transfer encoding, skip until next comma.3243 * Stop when no more names are found. */3244is_fully_parsed = false0;3245value = strchr(value, ',');3246if (!value)3247break;3248}3249}3250 3251return is_fully_parsed;3252}3253 3254static bool_Bool3255is_token_char(char c)3256{3257/* tchar according to https://tools.ietf.org/html/rfc7230#section-3.2.6 */3258return strchr("!#$%&\\:*+-.^_`|~", c) || g_ascii_isalnum(c)((g_ascii_table[(guchar) (c)] & G_ASCII_ALNUM) != 0);3259}3260 3261static bool_Bool3262valid_header_name(const unsigned char *line, int header_len)3263{3264 3265/*3266 * Validate the header name. This allows no space between the field name3267 * and colon (RFC 7230, Section. 3.2.4).3268 */3269if (header_len == 0) {3270return false0;3271}3272for (int i = 0; i < header_len; i++) {3273/*3274 * NUL is not a valid character; treat it specially3275 * due to C's notion that strings are NUL-terminated.3276 */3277if (line[i] == '\0') {3278return false0;3279}3280if (!is_token_char(line[i])) {3281return false0;3282}3283}3284return true1;3285}3286 3287static bool_Bool3288process_header(tvbuff_t *tvb, int offset, int next_offset,3289 const unsigned char *line, int linelen, int colon_offset,3290 packet_info *pinfo, proto_tree *tree, headers_t *eh_ptr,3291 http_conv_t *conv_data, media_container_type_t http_type, wmem_map_t *header_value_map,3292 bool_Bool streaming_chunk_mode)3293{3294int len;3295int line_end_offset;3296int header_len;3297int hf_index;3298unsigned char c;3299int value_offset;3300int value_len, value_bytes_len;3301uint8_t *value_bytes;3302char *value;3303char *header_name;3304char *p;3305unsigned char *up;3306proto_item *hdr_item, *it;3307int f;3308int* hf_id;3309tap_credential_t* auth;3310http_req_res_t *curr_req_res = (http_req_res_t *)p_get_proto_data(wmem_file_scope(), pinfo,3311proto_http, HTTP_PROTO_DATA_REQRES0);3312http_info_value_t *stat_info = p_get_proto_data(pinfo->pool, pinfo, proto_http, HTTP_PROTO_DATA_INFO1);3313wmem_allocator_t *scope = (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && streaming_chunk_mode) ? wmem_file_scope() :3314 ((PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && streaming_chunk_mode) ? NULL((void*)0) : pinfo->pool);3315 3316len = next_offset - offset;3317line_end_offset = offset + linelen;3318header_len = colon_offset - offset;3319 3320/**3321 * Not a valid header name? Just add a line plus expert info.3322 */3323if (!valid_header_name(line, header_len)) {3324if (http_check_ascii_headers) {3325/* If we're offering the chance for other dissectors to parse,3326 * we shouldn't add any tree items ourselves.3327 */3328return false0;3329}3330if (http_type == MEDIA_CONTAINER_HTTP_REQUEST) {3331hf_index = hf_http_request_line;3332} else if (http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3333hf_index = hf_http_response_line;3334} else {3335hf_index = hf_http_unknown_header;3336}3337it = proto_tree_add_item(tree, hf_index, tvb, offset, len, ENC_NA0x00000000|ENC_ASCII0x00000000);3338proto_item_set_text(it, "%s", format_text(pinfo->pool, line, len));3339expert_add_info(pinfo, it, &ei_http_bad_header_name);3340return false0;3341}3342 3343/*3344 * Make a null-terminated, all-lower-case version of the header3345 * name.3346 */3347header_name = wmem_ascii_strdown(pinfo->pool, &line[0], header_len);3348 3349hf_index = find_header_hf_value(tvb, offset, header_len);3350 3351/*3352 * Skip whitespace after the colon.3353 */3354value_offset = colon_offset + 1;3355while (value_offset < line_end_offset3356&& ((c = line[value_offset - offset]) == ' ' || c == '\t'))3357value_offset++;3358 3359/*3360 * Fetch the value.3361 *3362 * XXX - RFC 9110 5.5 "Specification for newly defined fields3363 * SHOULD limit their values to visible US-ASCII octets (VCHAR),3364 * SP, and HTAB. A recipient SHOULD treat other allowed octets in3365 * field content (i.e., obs-text [%x80-FF]) as opaque data...3366 * Field values containing CR, LF, or NUL characters are invalid3367 * and dangerous." (Up to RFC 7230, an obsolete "line-folding"3368 * mechanism that included CRLF was allowed.)3369 *3370 * So NUL is not allowed, and we should have one or more3371 * expert infos if the field value has anything other than3372 * ASCII printable + TAB. (Possibly different severities3373 * depending on whether it contains obsolete characters3374 * like \x80-\xFF vs characters never allowed like NUL.)3375 * All known field types respect this (using Base64, etc.)3376 * Unknown field types (possibly including those registered3377 * through the UAT) should be treated like FT_BYTES with3378 * BASE_SHOW_ASCII_PRINTABLE instead of FT_STRING, but it's3379 * more difficult to do that with the custom formatting3380 * that uses the header name.3381 *3382 * Instead, for now for display purposes we will treat strings3383 * as ASCII and pass the raw value to subdissectors via the3384 * header_value_map. For the latter, we allocate a buffer that's3385 * value_bytes_len+1 bytes long, copy value_bytes_len bytes, and3386 * stick in a NUL terminator, so that the buffer for value actually3387 * has value_bytes_len bytes in it.3388 */3389value_bytes_len = line_end_offset - value_offset;3390value_bytes = (char *)wmem_alloc((scope ? scope : pinfo->pool), value_bytes_len+1);3391memcpy(value_bytes, &line[value_offset - offset], value_bytes_len);3392value_bytes[value_bytes_len] = '\0';3393value = tvb_get_string_enc(pinfo->pool, tvb, value_offset, value_bytes_len, ENC_ASCII0x00000000);3394/* The length of the value might change after UTF-8 sanitization */3395value_len = (int)strlen(value);3396 3397if (scope == pinfo->pool) {3398wmem_map_insert(header_value_map, header_name, value_bytes);3399} else if (scope) { /* (!PINFO_FD_VISITED(pinfo) && streaming_chunk_mode) */3400wmem_map_insert(header_value_map, wmem_strdup(scope, header_name), value_bytes);3401} /* else skip while (PINFO_FD_VISITED(pinfo) && streaming_chunk_mode) */3402 3403if (hf_index == -1) {3404/*3405 * Not a header we know anything about.3406 * Check if a HF generated from UAT information exists.3407 */3408hf_id = get_hf_for_header(header_name);3409 3410if (tree) {3411if (!hf_id) {3412if (http_type == MEDIA_CONTAINER_HTTP_REQUEST ||3413http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3414it = proto_tree_add_item(tree,3415http_type == MEDIA_CONTAINER_HTTP_RESPONSE ?3416hf_http_response_line :3417hf_http_request_line,3418tvb, offset, len,3419ENC_NA0x00000000|ENC_ASCII0x00000000);3420proto_item_set_text(it, "%s",3421format_text(pinfo->pool, line, len));3422} else {3423char* str = format_text(pinfo->pool, line, len);3424proto_tree_add_string_format(tree, hf_http_unknown_header, tvb, offset,3425len, str, "%s", str);3426}3427 3428} else {3429proto_tree_add_string_format(tree,3430*hf_id, tvb, offset, len, value,3431"%s", format_text(pinfo->pool, line, len));3432if (http_type == MEDIA_CONTAINER_HTTP_REQUEST ||3433http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3434it = proto_tree_add_item(tree,3435http_type == MEDIA_CONTAINER_HTTP_RESPONSE ?3436hf_http_response_line :3437hf_http_request_line,3438tvb, offset, len,3439ENC_NA0x00000000|ENC_ASCII0x00000000);3440proto_item_set_text(it, "%s",3441format_text(pinfo->pool, line, len));3442proto_item_set_hidden(it);3443}3444}3445}3446} else {3447/*3448 * Add it to the protocol tree as a particular field,3449 * but display the line as is.3450 */3451if (tree) {3452header_field_info *hfinfo;3453uint32_t tmp;3454 3455hfinfo = proto_registrar_get_nth(*headers[hf_index].hf);3456switch(hfinfo->type){3457case FT_UINT8:3458case FT_UINT16:3459case FT_UINT24:3460case FT_UINT32:3461case FT_INT8:3462case FT_INT16:3463case FT_INT24:3464case FT_INT32:3465tmp=(uint32_t)strtol(value, NULL((void*)0), 10);3466hdr_item = proto_tree_add_uint(tree, *headers[hf_index].hf, tvb, offset, len, tmp);3467if (http_type == MEDIA_CONTAINER_HTTP_REQUEST ||3468http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3469it = proto_tree_add_item(tree,3470http_type == MEDIA_CONTAINER_HTTP_RESPONSE ?3471hf_http_response_line :3472hf_http_request_line,3473tvb, offset, len,3474ENC_NA0x00000000|ENC_ASCII0x00000000);3475proto_item_set_text(it, "%d", tmp);3476proto_item_set_hidden(it);3477}3478break;3479default:3480hdr_item = proto_tree_add_string_format(tree,3481 *headers[hf_index].hf, tvb, offset, len,3482 value,3483 "%s", format_text(pinfo->pool, line, len));3484if (http_type == MEDIA_CONTAINER_HTTP_REQUEST ||3485http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3486it = proto_tree_add_item(tree,3487http_type == MEDIA_CONTAINER_HTTP_RESPONSE ?3488hf_http_response_line :3489hf_http_request_line,3490tvb, offset, len,3491ENC_NA0x00000000|ENC_ASCII0x00000000);3492proto_item_set_text(it, "%s",3493format_text(pinfo->pool, line, len));3494proto_item_set_hidden(it);3495}3496}3497} else3498hdr_item = NULL((void*)0);3499 3500/*3501 * Do any special processing that particular headers3502 * require.3503 */3504switch (headers[hf_index].special) {3505 3506case HDR_AUTHORIZATION1:3507if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))3508break;/* dissected NTLMSSP */3509if (check_auth_basic(hdr_item, tvb, pinfo, value))3510break; /* dissected basic auth */3511if (check_auth_citrixbasic(hdr_item, tvb, pinfo, value, offset))3512break; /* dissected citrix basic auth */3513if (check_auth_kerberos(hdr_item, tvb, pinfo, value))3514break;3515if (check_auth_digest(hdr_item, tvb, pinfo, value, offset, value_len))3516break;/* dissected digest basic auth */3517auth = wmem_new0(pinfo->pool, tap_credential_t)((tap_credential_t*)wmem_alloc0((pinfo->pool), sizeof(tap_credential_t
)))
;3518auth->num = pinfo->num;3519auth->password_hf_id = *headers[hf_index].hf;3520auth->proto = "HTTP header auth";3521auth->username = wmem_strdup(pinfo->pool, TAP_CREDENTIALS_PLACEHOLDER"n.a.");3522tap_queue_packet(credentials_tap, pinfo, auth);3523break;3524 3525case HDR_AUTHENTICATE2:3526if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))3527break; /* dissected NTLMSSP */3528check_auth_kerberos(hdr_item, tvb, pinfo, value);3529break;3530 3531case HDR_CONTENT_TYPE3:3532if (scope == NULL((void*)0)) { /* identical to (PINFO_FD_VISITED(pinfo) && streaming_chunk_mode) */3533break; /* eh_ptr->content_type[_parameters] must have been set during first scan */3534}3535eh_ptr->content_type = wmem_strdup(scope, value);3536 3537for (f = 0; f < value_len; f++) {3538c = value[f];3539if (c == ';' || g_ascii_isspace(c)((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0)) {3540/*3541 * End of subtype - either3542 * white space or a ";"3543 * separating the subtype from3544 * a parameter.3545 */3546break;3547}3548 3549/*3550 * Map the character to lower case;3551 * content types are case-insensitive.3552 */3553eh_ptr->content_type[f] = g_ascii_tolower(eh_ptr->content_type[f]);3554}3555eh_ptr->content_type[f] = '\0';3556/*3557 * Now find the start of the optional parameters;3558 * skip the optional white space and the semicolon3559 * if this has not been done before.3560 */3561f++;3562while (f < value_len) {3563c = eh_ptr->content_type[f];3564if (c == ';' || g_ascii_isspace(c)((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0))3565/* Skip till start of parameters */3566f++;3567else3568break;3569}3570if (f < value_len)3571eh_ptr->content_type_parameters = eh_ptr->content_type + f;3572else3573eh_ptr->content_type_parameters = NULL((void*)0);3574break;3575 3576case HDR_CONTENT_LENGTH4:3577DISSECTOR_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"
, 3577, "!streaming_chunk_mode", "In streaming chunk mode, there will never be content-length header."
))))
;3578errno(*__errno_location ()) = 0;3579eh_ptr->content_length = g_ascii_strtoll(value, &p, 10);3580up = (unsigned char *)p;3581if (eh_ptr->content_length < 0 ||3582 p == value ||3583 errno(*__errno_location ()) == ERANGE34 ||3584 (*up != '\0' && !g_ascii_isspace(*up)((g_ascii_table[(guchar) (*up)] & G_ASCII_SPACE) != 0))) {3585/*3586 * Content length not valid; pretend3587 * we don't have it.3588 */3589eh_ptr->have_content_length = false0;3590} else {3591proto_tree *header_tree;3592proto_item *tree_item;3593/*3594 * We do have a valid content length.3595 */3596eh_ptr->have_content_length = true1;3597header_tree = proto_item_add_subtree(hdr_item, ett_http_header_item);3598tree_item = proto_tree_add_uint64(header_tree, hf_http_content_length,3599tvb, offset, len, eh_ptr->content_length);3600proto_item_set_generated(tree_item);3601if (eh_ptr->transfer_encoding != HTTP_TE_NONE) {3602expert_add_info(pinfo, hdr_item, &ei_http_te_and_length);3603}3604}3605break;3606 3607case HDR_CONTENT_ENCODING5:3608if (scope == NULL((void*)0)) { /* identical to (PINFO_FD_VISITED(pinfo) && streaming_chunk_mode) */3609break; /* eh_ptr->content_encoding must have been set during first scan */3610}3611eh_ptr->content_encoding = wmem_strndup(scope, value, value_len);3612break;3613 3614case HDR_TRANSFER_ENCODING6:3615if (eh_ptr->have_content_length) {3616expert_add_info(pinfo, hdr_item, &ei_http_te_and_length);3617}3618if (!http_parse_transfer_coding(value, eh_ptr)) {3619expert_add_info(pinfo, hdr_item, &ei_http_te_unknown);3620}3621break;3622 3623case HDR_HOST7:3624stat_info->http_host = wmem_strndup(pinfo->pool, value, value_len);3625if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && curr_req_res) {3626curr_req_res->http_host = wmem_strndup(wmem_file_scope(), value, value_len);3627}3628break;3629 3630case HDR_UPGRADE8:3631if (scope == NULL((void*)0)) { /* identical to (PINFO_FD_VISITED(pinfo) && streaming_chunk_mode) */3632break;3633}3634eh_ptr->upgrade = wmem_ascii_strdown(scope, value, value_len);3635break;3636 3637case HDR_COOKIE9:3638if (hdr_item) {3639proto_tree *cookie_tree;3640char *part, *part_end;3641int part_len;3642 3643cookie_tree = proto_item_add_subtree(hdr_item, ett_http_header_item);3644for (f = 0; f < value_len; ) {3645/* skip whitespace and ';' (terminates at '\0' or earlier) */3646c = value[f];3647while (c == ';' || g_ascii_isspace(c)((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0))3648c = value[++f];3649 3650if (f >= value_len)3651break;3652 3653/* find "cookie=foo " in "cookie=foo ; bar" */3654part = value + f;3655part_end = (char *)memchr(part, ';', value_len - f);3656if (part_end)3657part_len =(int)(part_end - part);3658else3659part_len = value_len - f;3660 3661/* finally add cookie to tree */3662proto_tree_add_item(cookie_tree, hf_http_cookie_pair,3663tvb, value_offset + f, part_len, ENC_NA0x00000000|ENC_ASCII0x00000000);3664f += part_len;3665}3666}3667break;3668 3669case HDR_WEBSOCKET_PROTOCOL10:3670if (http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3671conv_data->websocket_protocol = wmem_strndup(wmem_file_scope(), value, value_len);3672}3673break;3674 3675case HDR_WEBSOCKET_EXTENSIONS11:3676if (http_type == MEDIA_CONTAINER_HTTP_RESPONSE) {3677conv_data->websocket_extensions = wmem_strndup(wmem_file_scope(), value, value_len);3678}3679break;3680 3681case HDR_REFERER12:3682stat_info->referer_uri = wmem_strndup(pinfo->pool, value, value_len);3683break;3684 3685case HDR_LOCATION13:3686if (curr_req_res && curr_req_res->request_uri){3687stat_info->location_target = wmem_strndup(pinfo->pool, value, value_len);3688stat_info->location_base_uri = wmem_strdup(pinfo->pool, curr_req_res->full_uri);3689}3690break;3691case HDR_HTTP2_SETTINGS14:3692{3693proto_tree* settings_tree = proto_item_add_subtree(hdr_item, ett_http_http2_settings_item);3694tvbuff_t* new_tvb = base64uri_tvb_to_new_tvb(tvb, value_offset, value_bytes_len);3695add_new_data_source(pinfo, new_tvb, "Base64uri decoded");3696TRY{ 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)
{3697dissect_http2_settings_ext(new_tvb, pinfo, settings_tree, 0);3698} CATCH_ALLif (except_state == 0 && exc != 0 && (except_state
|=1))
{3699show_exception(tvb, pinfo, settings_tree, EXCEPT_CODE((exc)->except_id.except_code), GET_MESSAGE((exc)->except_message));3700}3701ENDTRYif(!(except_state&1) && exc != 0) except_rethrow(
exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}
;3702 3703break;3704}3705case HDR_RANGE15:3706{3707/* THIS IS A GET REQUEST3708 * Note: GET is the only method that employs ranges.3709 * (Unless the data has errors or is noncompliant.)3710 */3711if (curr_req_res && !pinfo->fd->visited) {3712 /*3713 * Unlike protocols such as NFS and SMB, the HTTP protocol (RFC 9110) does not3714 * provide an identifier with which to match requests and responses. Instead,3715 * matching is solely based upon the order in which responses are received.3716 * HTTP I/O is 'asynchronously ordered' such that, for example, the first of four3717 * GET responses are matched with the first outstanding request, the next3718 * response with the second oldest outstanding request and so on (FIFO).3719 * The previous method instead matched responses with the last of several3720 * async requests rather than the first (LIFO), and did not handle requests3721 * with no responses such as the case where one or more HTTP packets were3722 * not captured. Whenever there were multiple outstanding requests, the SRT3723 * (RTT) stats were incorrect, in some cases massively so.3724 *3725 * While RFC 9110 expressly prohibits matching via byte ranges because, among3726 * other things, the server may return fewer bytes than requested,3727 * the first number of the range does not change. Unlike HTTP implementations,3728 * Wireshark has the problem of requests/responses missing from the capture3729 * file. In such cases resumption of correct matching was virtually impossible.3730 * In addition, all matching was incorrect from that point on.3731 *3732 * The method of matching used herein is able to recover from packet loss,3733 * any number of missing frames, and duplicate range requests. The3734 * method used is explained within the comments.3735 */3736/* https://www.rfc-editor.org/rfc/rfc9110.html#name-range-requests3737 * Note that RFC 9110 16.5 defines a registry for3738 * range units, but only bytes are registered.3739 * ABNF:3740 * Range = ranges-specifier3741 * ranges-specifier = range-unit "=" range-set3742 * range-set = 1#range-spec3743 * range-spec = int-range / suffix-range / other-range3744 * 1# is an ABNF extension defined in RFC 9110 5.6.13745 * which covers comma separated list with optional3746 * white space:3747 * 1#element => element *( OWS "," OWS element )3748 * We don't care about other-range, but will try to3749 * handle int-range and suffix-range.3750 * This ignores any entries past the first in a list,3751 * though responses to such would be multipart.3752 * As mentioned above, this breaks down if the3753 * response does not include all requested ranges3754 * fully in one response.3755 */3756const char *pos = strchr(value, '=');3757if (pos == NULL((void*)0)) {3758break;3759}3760pos++;3761uint64_t first_range_num = 0;3762/* Get the first range number */3763ws_strtou64(pos, &pos, &first_range_num);3764/* If the first number of the range is missing or '0',3765 * use the second number in the range instead if we can.3766 * XXX - Unlike strtoul, we can check the return value3767 * of ws_strtou64() to distinguish between "converted3768 * successfully as 0" and "failed conversion."3769 * Note that strtoul allows an unsigned integer to3770 * begin with a negative sign and applies unsigned3771 * integer wraparound rules.3772 * ws_strtouXX rejects an initial hyphen-minus, which3773 * is good, as we want to properly handle:3774 * suffix-range = "-" suffix-length3775 */3776if (first_range_num == 0 && *pos == '-') {3777pos++;3778/* Pass in an end pointer to convert3779 * a list of ranges, the first of which is3780 * a suffix-range.3781 */3782ws_strtou64(pos, &pos, &first_range_num);3783}3784/* req_list is used for req/resp matching and the deletion (and freeing) of matching3785* requests and any orphans that preceed them. A GSList is used instead of a wmem map3786* because there are rarely more than 10 requests in the list."3787*/3788if (first_range_num > 0) {3789request_trans_t* req_trans = wmem_new(wmem_file_scope(), request_trans_t)((request_trans_t*)wmem_alloc((wmem_file_scope()), sizeof(request_trans_t
)))
;3790req_trans->first_range_num = first_range_num;3791req_trans->req_frame = pinfo->num;3792req_trans->abs_time = pinfo->fd->abs_ts;3793req_trans->request_uri = curr_req_res->request_uri;3794 3795/* XXX - This leaks if matching responses aren't3796 * found (the data does not, but the list node3797 * does.) A wmem_list would prevent that.3798 */3799conv_data->req_list = g_slist_append(conv_data->req_list, GUINT_TO_POINTER(req_trans)((gpointer) (gulong) (req_trans)));3800curr_req_res->req_has_range = true1;3801}3802}3803 3804break;3805}3806case HDR_CONTENT_RANGE16:3807/*3808 * THIS IS A GET RESPONSE3809 * GET is the only method that employs ranges.3810 * XXX - Except that RFC 9110 14.4 & 14.5 note that by3811 * private agreement it can be included in a request3812 * to request a partial PUT.3813 * ABNF:3814 * Content-Range = range-unit SP ( range-resp / unsatisfied-range )3815 * range-resp = incl-range "/" ( complete-length / "*" )3816 * We do not attempt to handle unsatisfied-range.3817 * Note that only one range can be included; multiple3818 * ranges are transmitted with the media type of3819 * "multipart/byteranges" and each body part contains3820 * its own Content-Type and Content-Range fields.3821 * The multipart dissector does not handle this nor3822 * access the request list.3823 */3824if (curr_req_res && !pinfo->fd->visited) {3825request_trans_t *req_trans;3826match_trans_t *match_trans = NULL((void*)0);3827nstime_t ns;3828GSList *iter = NULL((void*)0);3829 3830/* Note SP instead of '=' in ABNF. */3831const char *pos = strchr(value, ' ');3832if (pos == NULL((void*)0)) {3833break;3834}3835pos++;3836uint64_t first_crange_num = 0;3837/* Get the first content range number */3838ws_strtou64(pos, &pos, &first_crange_num);3839 3840if (first_crange_num == 0 && *pos == '-') {3841pos++;3842ws_strtou64(pos, &pos, &first_crange_num);3843}3844 3845/* Get the position of the matching request if any in the reqs_table.3846* This is used to remove and free the matching request, and the unmatched3847* requests (orphans) that preceed it.3848* XXX - There is *NO* guarantee that there is3849* a perfectly matching request, see 15.3.7:3850* "However, a server might want to send only a3851* subset of the data requested for reasons of3852* its own... A client MUST inspect a 2063853* response's Content-Type and Content-Range3854* field(s) to determine what parts are enclosed3855* and whether additional requests are needed."3856* Also 15.3.7.2 Multiple Parts, noting that3857* the response may be sent in a Content-Type3858* multipart/byteranges, also "When multiple3859* ranges are requested, a server MAY coalesce3860* any of the ranges that overlap, or that are3861* separated by a gap that is smaller than the3862* overhead of sending multiple parts, regardless3863* of the order in which the corresponding range-3864* spec appeared in the received Range header3865* field." and 15.3.7.3 Combining Parts.3866* However, as mentioned above, the LIFO method3867* had issues with that as well. Truly proper3868* handling of such edge cases is more difficult.3869*/3870req_trans = NULL((void*)0);3871if (conv_data->req_list && conv_data->req_list->data) {3872for (iter = conv_data->req_list; iter; iter = iter->next) {3873if (((request_trans_t*)iter->data)->first_range_num == first_crange_num) {3874req_trans = iter->data;3875break;3876}3877}3878}3879 3880if (first_crange_num != 0 && req_trans) {3881match_trans = wmem_new(wmem_file_scope(), match_trans_t)((match_trans_t*)wmem_alloc((wmem_file_scope()), sizeof(match_trans_t
)))
;3882match_trans->req_frame = req_trans->req_frame;3883match_trans->resp_frame = pinfo->num;3884nstime_delta(&ns, &pinfo->fd->abs_ts, &req_trans->abs_time);3885match_trans->delta_time = ns;3886match_trans->request_uri = req_trans->request_uri;3887match_trans->http_host = curr_req_res->http_host;3888 3889wmem_map_insert(conv_data->matches_table,3890GUINT_TO_POINTER(match_trans->req_frame)((gpointer) (gulong) (match_trans->req_frame)), (void *)match_trans);3891wmem_map_insert(conv_data->matches_table,3892GUINT_TO_POINTER(match_trans->resp_frame)((gpointer) (gulong) (match_trans->resp_frame)), (void *)match_trans);3893 3894/* Remove and free all of the list entries up to and including the3895* matching one from req_list. */3896if (conv_data->req_list) {3897GSList *top_of_list = NULL((void*)0);3898 3899top_of_list = conv_data->req_list;3900while (top_of_list && top_of_list->data != req_trans) {3901 3902 top_of_list = g_slist_delete_link(top_of_list, top_of_list);3903}3904if (top_of_list && top_of_list->data == req_trans) {3905 3906 top_of_list = g_slist_delete_link(top_of_list, top_of_list);3907}3908conv_data->req_list = top_of_list;3909}3910}3911}3912if (curr_req_res)3913curr_req_res->resp_has_range = true1;3914break;3915}3916}3917return true1;3918}3919 3920/* Returns index of header tag in headers */3921static int3922find_header_hf_value(tvbuff_t *tvb, int offset, unsigned header_len)3923{3924unsigned i;3925 3926for (i = 0; i < array_length(headers)(sizeof (headers) / sizeof (headers)[0]); i++) {3927if (header_len == strlen(headers[i].name) &&3928tvb_strncaseeql(tvb, offset,3929 headers[i].name, header_len) == 0)3930return i;3931}3932 3933return -1;3934}3935 3936/*3937 * Dissect Microsoft's abomination called NTLMSSP over HTTP.3938 */3939static bool_Bool3940check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo, char *value)3941{3942static const char *ntlm_headers[] = {3943"NTLM ",3944"Negotiate ",3945NULL((void*)0)3946};3947const char **header;3948size_t hdrlen;3949proto_tree *hdr_tree;3950 3951/*3952 * Check for NTLM credentials and challenge; those can3953 * occur with WWW-Authenticate.3954 */3955for (header = &ntlm_headers[0]; *header != NULL((void*)0); header++) {3956hdrlen = strlen(*header);3957if (strncmp(value, *header, hdrlen) == 0) {3958if (hdr_item != NULL((void*)0)) {3959hdr_tree = proto_item_add_subtree(hdr_item,3960 ett_http_ntlmssp);3961} else3962hdr_tree = NULL((void*)0);3963value += hdrlen;3964dissect_http_ntlmssp(tvb, pinfo, hdr_tree, value);3965return true1;3966}3967}3968return false0;3969}3970 3971static tap_credential_t*3972basic_auth_credentials(wmem_allocator_t *scope, const char* str)3973{3974char **tokens = g_strsplit(str, ":", -1);3975 3976if (!tokens || !tokens[0] || !tokens[1]) {3977g_strfreev(tokens);3978return NULL((void*)0);3979}3980 3981tap_credential_t* auth = wmem_new0(scope, tap_credential_t)((tap_credential_t*)wmem_alloc0((scope), sizeof(tap_credential_t
)))
;3982 3983auth->username = wmem_strdup(scope, tokens[0]);3984auth->proto = "HTTP basic auth";3985 3986g_strfreev(tokens);3987 3988return auth;3989}3990 3991/*3992 * Dissect HTTP Basic authorization.3993 */3994static bool_Bool3995check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo, char *value)3996{3997static const char *basic_headers[] = {3998"Basic ",3999NULL((void*)0)4000};4001const char **header;4002size_t hdrlen;4003const uint8_t *decoded_value;4004proto_tree *hdr_tree;4005tvbuff_t *auth_tvb;4006 4007for (header = &basic_headers[0]; *header != NULL((void*)0); header++) {4008hdrlen = strlen(*header);4009if (strncmp(value, *header, hdrlen) == 0) {4010if (hdr_item != NULL((void*)0)) {4011hdr_tree = proto_item_add_subtree(hdr_item,4012 ett_http_ntlmssp);4013} else4014hdr_tree = NULL((void*)0);4015value += hdrlen;4016 4017auth_tvb = base64_to_tvb(tvb, value);4018add_new_data_source(pinfo, auth_tvb, "Basic Credentials");4019/* RFC 7617 says that the character encoding is only4020 * known to be UTF-8 if the 'charset' parameter was4021 * used. Otherwise, after Base64 decoding it could be4022 * any character encoding.4023 * XXX: Perhaps the field should be a FT_BYTES with4024 * BASE_SHOW_UTF_8_PRINTABLE?4025 */4026proto_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);4027tap_credential_t* auth = basic_auth_credentials(pinfo->pool, decoded_value);4028if (auth) {4029auth->num = auth->username_num = pinfo->num;4030auth->password_hf_id = hf_http_basic;4031tap_queue_packet(credentials_tap, pinfo, auth);4032}4033 4034return true1;4035}4036}4037return false0;4038}4039 4040/*4041 * Dissect HTTP Digest authorization.4042 */4043static bool_Bool4044check_auth_digest(proto_item* hdr_item, tvbuff_t* tvb, packet_info* pinfo _U___attribute__((unused)), char* value, int offset, int len)4045{4046proto_tree* hdr_tree;4047int queried_offset;4048 4049if (strncmp(value, "Digest", 6) == 0) {4050if (hdr_item != NULL((void*)0)) {4051hdr_tree = proto_item_add_subtree(hdr_item, ett_http_ntlmssp);4052} else {4053hdr_tree = NULL((void*)0);4054}4055offset += 21;4056len -= 21;4057while (len > 0) {4058/* Find comma/end of line */4059queried_offset = tvb_find_uint8(tvb, offset, len, ',');4060if (queried_offset > 0) {4061proto_tree_add_format_text(hdr_tree, tvb, offset, queried_offset - offset);4062len -= (queried_offset - offset);4063offset = queried_offset + 1;4064} else {4065len = 0;4066}4067}4068return true1;4069} else {4070return false0;4071}4072}4073/*4074 * Dissect HTTP CitrixAGBasic authorization.4075 */4076static bool_Bool4077check_auth_citrixbasic(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo, char *value, int offset)4078{4079static const char *basic_headers[] = {4080"CitrixAGBasic ",4081NULL((void*)0)4082};4083const char **header;4084size_t hdrlen;4085proto_tree *hdr_tree;4086char *ch_ptr;4087int data_len;4088tvbuff_t *data_tvb;4089proto_item *hidden_item;4090proto_item *pi;4091const uint8_t *user = NULL((void*)0), *passwd = NULL((void*)0);4092 4093for (header = &basic_headers[0]; *header != NULL((void*)0); header++) {4094hdrlen = strlen(*header);4095if (strncmp(value, *header, hdrlen) == 0) {4096if (hdr_item != NULL((void*)0)) {4097hdr_tree = proto_item_add_subtree(hdr_item,4098 ett_http_ntlmssp);4099} else4100hdr_tree = NULL((void*)0);4101value += hdrlen;4102offset += (int)hdrlen + 15;4103hidden_item = proto_tree_add_boolean(hdr_tree,4104 hf_http_citrix, tvb, 0, 0, 1);4105proto_item_set_hidden(hidden_item);4106 4107if(strncmp(value, "username=\"", 10) == 0) {4108value += 10;4109offset += 10;4110ch_ptr = strchr(value, '"');4111if ( ch_ptr != NULL((void*)0) ) {4112data_len = (int)(ch_ptr - value);4113if (data_len) {4114data_tvb = base64_tvb_to_new_tvb(tvb, offset, data_len);4115add_new_data_source(pinfo, data_tvb, "Username");4116/* XXX: We don't know for certain the string encoding here. */4117pi = 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);4118} else {4119pi = proto_tree_add_string(hdr_tree, hf_http_citrix_user, tvb, offset, 0, "");4120}4121proto_item_set_generated(pi);4122value += data_len + 1;4123offset += data_len + 1;4124}4125}4126if(strncmp(value, "; domain=\"", 10) == 0) {4127value += 10;4128offset += 10;4129ch_ptr = strchr(value, '"');4130if ( ch_ptr != NULL((void*)0) ) {4131data_len = (int)(ch_ptr - value);4132if (data_len) {4133data_tvb = base64_tvb_to_new_tvb(tvb, offset, data_len);4134add_new_data_source(pinfo, data_tvb, "Domain");4135pi = proto_tree_add_item(hdr_tree, hf_http_citrix_domain, data_tvb, 0, tvb_reported_length(data_tvb), ENC_UTF_80x00000002);4136} else {4137pi = proto_tree_add_string(hdr_tree, hf_http_citrix_domain, tvb, offset, 0, "");4138}4139proto_item_set_generated(pi);4140value += data_len + 1;4141offset += data_len + 1;4142}4143}4144if(strncmp(value, "; password=\"", 12) == 0) {4145value += 12;4146offset += 12;4147ch_ptr = strchr(value, '"');4148if ( ch_ptr != NULL((void*)0) ) {4149data_len = (int)(ch_ptr - value);4150if (data_len) {4151data_tvb = base64_tvb_to_new_tvb(tvb, offset, data_len);4152add_new_data_source(pinfo, data_tvb, "Password");4153pi = 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);4154} else {4155pi = proto_tree_add_string(hdr_tree, hf_http_citrix_passwd, tvb, offset, 0, "");4156}4157proto_item_set_generated(pi);4158value += data_len + 1;4159offset += data_len + 1;4160}4161}4162if(strncmp(value, "; AGESessionId=\"", 16) == 0) {4163value += 16;4164offset += 16;4165ch_ptr = strchr(value, '"');4166if ( ch_ptr != NULL((void*)0) ) {4167data_len = (int)(ch_ptr - value);4168if (data_len) {4169data_tvb = base64_tvb_to_new_tvb(tvb, offset, data_len);4170add_new_data_source(pinfo, data_tvb, "Session ID");4171pi = proto_tree_add_item(hdr_tree, hf_http_citrix_session, data_tvb, 0, tvb_reported_length(data_tvb), ENC_UTF_80x00000002);4172} else {4173pi = proto_tree_add_string(hdr_tree, hf_http_citrix_session, tvb,4174 offset, 0, "");4175}4176proto_item_set_generated(pi);4177}4178}4179if (user != NULL((void*)0) && passwd != NULL((void*)0)) {4180 4181tap_credential_t* auth = wmem_new0(pinfo->pool, tap_credential_t)((tap_credential_t*)wmem_alloc0((pinfo->pool), sizeof(tap_credential_t
)))
;4182 4183auth->username = wmem_strdup(pinfo->pool, user);4184auth->proto = "HTTP CitrixAGBasic auth";4185auth->num = auth->username_num = pinfo->num;4186auth->password_hf_id = hf_http_citrix_passwd;4187tap_queue_packet(credentials_tap, pinfo, auth);4188}4189return true1;4190}4191}4192return false0;4193}4194 4195static bool_Bool4196check_auth_kerberos(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo, const char *value)4197{4198proto_tree *hdr_tree;4199 4200if (strncmp(value, "Kerberos ", 9) == 0) {4201if (hdr_item != NULL((void*)0)) {4202hdr_tree = proto_item_add_subtree(hdr_item, ett_http_kerberos);4203} else4204hdr_tree = NULL((void*)0);4205 4206dissect_http_kerberos(tvb, pinfo, hdr_tree, value);4207return true1;4208}4209return false0;4210}4211 4212static int4213dissect_http_on_stream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,4214 http_conv_t *conv_data, bool_Bool end_of_stream, const uint32_t *seq)4215{4216intoffset = 0;4217intlen = 0;4218 4219while (tvb_reported_length_remaining(tvb, offset) > 0) {4220/* Switch protocol if the data starts after response headers. */4221if (conv_data->startframe &&4222(pinfo->num > conv_data->startframe ||4223(pinfo->num == conv_data->startframe && offset >= conv_data->startoffset))) {4224/* Increase pinfo->can_desegment because we are traversing4225 * http and want to preserve desegmentation functionality for4226 * the proxied protocol4227 */4228if (pinfo->can_desegment > 0)4229pinfo->can_desegment++;4230if (conv_data->next_handle) {4231call_dissector_only(conv_data->next_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree, NULL((void*)0));4232} else {4233call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);4234}4235/*4236 * If a subdissector requests reassembly, be sure not to4237 * include the preceding HTTP headers.4238 */4239if (pinfo->desegment_len) {4240pinfo->desegment_offset += offset;4241}4242break;4243}4244len = dissect_http_message(tvb, offset, pinfo, tree, conv_data, "HTTP", proto_http, end_of_stream, seq);4245if (len < 0)4246break;4247offset += len;4248 4249/*4250 * OK, we've set the Protocol and Info columns for the4251 * first HTTP message; set a fence so that subsequent4252 * HTTP messages don't overwrite the Info column.4253 */4254col_set_fence(pinfo->cinfo, COL_INFO);4255}4256/* dissect_http_message() returns -2 if message is not valid HTTP */4257return (len == -2)4258? 04259: (int)tvb_captured_length(tvb);4260}4261 4262static int4263dissect_http_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)4264{4265struct tcpinfo *tcpinfo = (struct tcpinfo *)data;4266conversation_t *conversation;4267http_conv_t *conv_data;4268bool_Bool end_of_stream;4269 4270conv_data = get_http_conversation_data(pinfo, &conversation);4271 4272/* Call HTTP2 dissector directly when detected via heuristics, but not4273 * when it was upgraded (the conversation started with HTTP). */4274if (conversation_get_proto_data(conversation, proto_http2) &&4275 !conv_data->startframe) {4276if (pinfo->can_desegment > 0)4277pinfo->can_desegment++;4278return call_dissector_only(http2_handle, tvb, pinfo, tree, data);4279}4280 4281/*4282 * Check if this is proxied connection and if so, hand of dissection to the4283 * payload-dissector.4284 * Response code 200 means "OK" and strncmp() == 0 means the strings match exactly */4285http_req_res_t *curr_req_res = conv_data->req_res_tail;4286if(pinfo->num >= conv_data->startframe &&4287 curr_req_res &&4288 curr_req_res->response_code == 200 &&4289 curr_req_res->request_method &&4290 strncmp(curr_req_res->request_method, "CONNECT", 7) == 0 &&4291 curr_req_res->request_uri) {4292if (conv_data->startframe == 0 && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {4293conv_data->startframe = pinfo->num;4294conv_data->startoffset = 0;4295copy_address_wmem(wmem_file_scope(), &conv_data->server_addr, &pinfo->dst);4296conv_data->server_port = pinfo->destport;4297}4298http_payload_subdissector(tvb, tree, pinfo, conv_data, data);4299 4300return tvb_captured_length(tvb);4301}4302 4303/* XXX - how to detect end-of-stream without tcpinfo */4304end_of_stream = (tcpinfo && IS_TH_FIN(tcpinfo->flags)(tcpinfo->flags & 0x0001));4305return dissect_http_on_stream(tvb, pinfo, tree, conv_data, end_of_stream, tcpinfo ? &tcpinfo->seq : NULL((void*)0));4306}4307 4308static bool_Bool4309dissect_http_heur_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)4310{4311int offset = 0, next_offset, linelen;4312conversation_t *conversation;4313 4314 4315/* Check if we have a line terminated by CRLF4316 * Return the length of the line (not counting the line terminator at4317 * the end), or, if we don't find a line terminator:4318 *4319 *if "deseg" is true, return -1;4320 */4321linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, true1);4322if((linelen == -1)||(linelen == 8)){4323return false0;4324}4325 4326/* Check if the line start or ends with the HTTP token */4327if((tvb_strncaseeql(tvb, linelen-8, "HTTP/1.", 7) == 0)||(tvb_strncaseeql(tvb, 0, "HTTP/1.", 7) == 0)){4328conversation = find_or_create_conversation(pinfo);4329conversation_set_dissector_from_frame_number(conversation, pinfo->num, http_tcp_handle);4330dissect_http_tcp(tvb, pinfo, tree, data);4331return true1;4332}4333 4334return false0;4335}4336 4337static int4338dissect_http_tls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))4339{4340conversation_t *conversation;4341http_conv_t *conv_data;4342bool_Bool end_of_stream;4343 4344conv_data = get_http_conversation_data(pinfo, &conversation);4345 4346struct tlsinfo *tlsinfo = (struct tlsinfo *)data;4347end_of_stream = (tlsinfo && tlsinfo->end_of_stream);4348return dissect_http_on_stream(tvb, pinfo, tree, conv_data, end_of_stream, tlsinfo ? &tlsinfo->seq : NULL((void*)0));4349}4350 4351static bool_Bool4352dissect_http_heur_tls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)4353{4354int offset = 0, next_offset, linelen;4355conversation_t *conversation;4356http_conv_t*conv_data;4357 4358conversation = find_or_create_conversation(pinfo);4359conv_data = (http_conv_t *)conversation_get_proto_data(conversation, proto_http);4360/* A http conversation was previously started, assume it is still active */4361if (conv_data) {4362dissect_http_tls(tvb, pinfo, tree, data);4363return true1;4364}4365 4366/* Check if we have a line terminated by CRLF4367 * Return the length of the line (not counting the line terminator at4368 * the end), or, if we don't find a line terminator:4369 *4370 *if "deseg" is true, return -1;4371 */4372linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, true1);4373if((linelen == -1)||(linelen == 8)){4374return false0;4375}4376 4377/* Check if the line start or ends with the HTTP token */4378if((tvb_strncaseeql(tvb, linelen-8, "HTTP/1.", 7) != 0) && (tvb_strncaseeql(tvb, 0, "HTTP/1.", 7) != 0)) {4379 /* we couldn't find the Magic Hello HTTP/1.X. */4380return false0;4381}4382 4383dissect_http_tls(tvb, pinfo, tree, data);4384return true1;4385}4386 4387static int4388dissect_http_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))4389{4390conversation_t *conversation;4391http_conv_t *conv_data;4392 4393conv_data = get_http_conversation_data(pinfo, &conversation);4394 4395/*4396 * XXX - we need to provide an end-of-stream indication.4397 */4398return dissect_http_on_stream(tvb, pinfo, tree, conv_data, false0, NULL((void*)0));4399}4400 4401static int4402dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))4403{4404conversation_t *conversation;4405http_conv_t *conv_data;4406 4407conv_data = get_http_conversation_data(pinfo, &conversation);4408 4409/*4410 * XXX - what should be done about reassembly, pipelining, etc.4411 * here?4412 */4413return dissect_http_on_stream(tvb, pinfo, tree, conv_data, false0, NULL((void*)0));4414}4415 4416static int4417dissect_ssdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))4418{4419conversation_t *conversation;4420http_conv_t*conv_data;4421 4422conv_data = get_http_conversation_data(pinfo, &conversation);4423dissect_http_message(tvb, 0, pinfo, tree, conv_data, "SSDP", proto_ssdp, false0, NULL((void*)0));4424return tvb_captured_length(tvb);4425}4426 4427static void4428range_delete_http_tls_callback(uint32_t port, void *ptr _U___attribute__((unused))) {4429ssl_dissector_delete(port, http_tls_handle);4430}4431 4432static void4433range_add_http_tls_callback(uint32_t port, void *ptr _U___attribute__((unused))) {4434ssl_dissector_add(port, http_tls_handle);4435}4436 4437static void reinit_http(void) {4438http_tcp_range = prefs_get_range_value("http", "tcp.port");4439 4440http_sctp_range = prefs_get_range_value("http", "sctp.port");4441 4442range_foreach(http_tls_range, range_delete_http_tls_callback, NULL((void*)0));4443wmem_free(wmem_epan_scope(), http_tls_range);4444http_tls_range = range_copy(wmem_epan_scope(), global_http_tls_range);4445range_foreach(http_tls_range, range_add_http_tls_callback, NULL((void*)0));4446}4447 4448void4449proto_register_http(void)4450{4451static hf_register_info hf[] = {4452 { &hf_http_notification,4453 { "Notification", "http.notification",4454FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,4455"true if HTTP notification", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4456 { &hf_http_response,4457 { "Response", "http.response",4458FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,4459"true if HTTP response", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4460 { &hf_http_request,4461 { "Request", "http.request",4462FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,4463"true if HTTP request", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4464 { &hf_http_basic,4465 { "Credentials", "http.authbasic",4466FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4467 { &hf_http_citrix,4468 { "Citrix AG Auth", "http.authcitrix",4469FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,4470"true if CitrixAGBasic Auth", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4471 { &hf_http_citrix_user,4472 { "Citrix AG Username", "http.authcitrix.user",4473FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4474 { &hf_http_citrix_domain,4475 { "Citrix AG Domain", "http.authcitrix.domain",4476FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4477 { &hf_http_citrix_passwd,4478 { "Citrix AG Password", "http.authcitrix.password",4479FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4480 { &hf_http_citrix_session,4481 { "Citrix AG Session ID", "http.authcitrix.session",4482FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4483 { &hf_http_response_line,4484 { "Response line", "http.response.line",4485FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4486 { &hf_http_request_line,4487 { "Request line", "http.request.line",4488FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4489 { &hf_http_request_method,4490 { "Request Method", "http.request.method",4491FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4492"HTTP Request Method", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4493 { &hf_http_request_uri,4494 { "Request URI", "http.request.uri",4495FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4496"HTTP Request-URI", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4497 { &hf_http_request_path,4498 { "Request URI Path", "http.request.uri.path",4499FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4500"HTTP Request-URI Path", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4501 { &hf_http_request_path_segment,4502 { "Request URI Path Segment", "http.request.uri.path.segment",4503FT_STRING, BASE_NONE, NULL((void*)0), 0,4504NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },4505 { &hf_http_request_query,4506 { "Request URI Query", "http.request.uri.query",4507FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4508"HTTP Request-URI Query", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4509 { &hf_http_request_query_parameter,4510 { "Request URI Query Parameter", "http.request.uri.query.parameter",4511FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4512"HTTP Request-URI Query Parameter", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4513 { &hf_http_request_version,4514 { "Request Version", "http.request.version",4515FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4516"HTTP Request HTTP-Version", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4517 { &hf_http_response_version,4518 { "Response Version", "http.response.version",4519FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4520"HTTP Response HTTP-Version", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4521 { &hf_http_request_full_uri,4522 { "Full request URI", "http.request.full_uri",4523FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4524"The full requested URI (including host name)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4525 { &hf_http_response_code,4526 { "Status Code", "http.response.code",4527FT_UINT24, BASE_DEC, NULL((void*)0), 0x0,4528"HTTP Response Status Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4529 { &hf_http_response_code_desc,4530 { "Status Code Description", "http.response.code.desc",4531FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4532"HTTP Response Status Code Description", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4533 { &hf_http_response_phrase,4534 { "Response Phrase", "http.response.phrase",4535 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4536"HTTP Response Reason Phrase", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4537 { &hf_http_authorization,4538 { "Authorization", "http.authorization",4539FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4540"HTTP Authorization header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4541 { &hf_http_proxy_authenticate,4542 { "Proxy-Authenticate", "http.proxy_authenticate",4543FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4544"HTTP Proxy-Authenticate header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4545 { &hf_http_proxy_authorization,4546 { "Proxy-Authorization", "http.proxy_authorization",4547FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4548"HTTP Proxy-Authorization header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4549 { &hf_http_proxy_connect_host,4550 { "Proxy-Connect-Hostname", "http.proxy_connect_host",4551FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4552"HTTP Proxy Connect Hostname", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4553 { &hf_http_proxy_connect_port,4554 { "Proxy-Connect-Port", "http.proxy_connect_port",4555FT_UINT16, BASE_DEC, NULL((void*)0), 0x0,4556"HTTP Proxy Connect Port", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4557 { &hf_http_www_authenticate,4558 { "WWW-Authenticate", "http.www_authenticate",4559FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4560"HTTP WWW-Authenticate header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4561 { &hf_http_content_type,4562 { "Content-Type", "http.content_type",4563FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4564"HTTP Content-Type header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4565 { &hf_http_content_length_header,4566 { "Content-Length", "http.content_length_header",4567FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4568"HTTP Content-Length header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4569 { &hf_http_content_length,4570 { "Content length", "http.content_length",4571FT_UINT64, BASE_DEC, NULL((void*)0), 0x0,4572NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4573 { &hf_http_content_encoding,4574 { "Content-Encoding", "http.content_encoding",4575FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4576"HTTP Content-Encoding header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4577 { &hf_http_transfer_encoding,4578 { "Transfer-Encoding", "http.transfer_encoding",4579FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4580"HTTP Transfer-Encoding header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4581 { &hf_http_upgrade,4582 { "Upgrade", "http.upgrade",4583FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4584"HTTP Upgrade header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4585 { &hf_http_user_agent,4586 { "User-Agent", "http.user_agent",4587FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4588"HTTP User-Agent header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4589 { &hf_http_host,4590 { "Host", "http.host",4591FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4592"HTTP Host", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4593 { &hf_http_range,4594 { "Range", "http.range",4595FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4596"HTTP Range", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4597 { &hf_http_content_range,4598 { "Content-Range", "http.content_range",4599FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4600"HTTP Content-Range", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4601 { &hf_http_connection,4602 { "Connection", "http.connection",4603FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4604"HTTP Connection", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4605 { &hf_http_cookie,4606 { "Cookie", "http.cookie",4607FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4608"HTTP Cookie", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4609 { &hf_http_cookie_pair,4610 { "Cookie pair", "http.cookie_pair",4611FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4612"A name/value HTTP cookie pair", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4613 { &hf_http_accept,4614 { "Accept", "http.accept",4615FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4616"HTTP Accept", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4617 { &hf_http_referer,4618 { "Referer", "http.referer",4619FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4620"HTTP Referer", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4621 { &hf_http_accept_language,4622 { "Accept-Language", "http.accept_language",4623FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4624"HTTP Accept Language", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4625 { &hf_http_accept_encoding,4626 { "Accept Encoding", "http.accept_encoding",4627FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4628"HTTP Accept Encoding", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4629 { &hf_http_date,4630 { "Date", "http.date",4631FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4632"HTTP Date", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4633 { &hf_http_cache_control,4634 { "Cache-Control", "http.cache_control",4635FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4636"HTTP Cache Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4637 { &hf_http_server,4638 { "Server", "http.server",4639FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4640"HTTP Server", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4641 { &hf_http_location,4642 { "Location", "http.location",4643FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4644"HTTP Location", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4645 { &hf_http_sec_websocket_accept,4646 { "Sec-WebSocket-Accept", "http.sec_websocket_accept",4647FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4648NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4649 { &hf_http_sec_websocket_extensions,4650 { "Sec-WebSocket-Extensions", "http.sec_websocket_extensions",4651FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4652NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4653 { &hf_http_sec_websocket_key,4654 { "Sec-WebSocket-Key", "http.sec_websocket_key",4655FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4656NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4657 { &hf_http_sec_websocket_protocol,4658 { "Sec-WebSocket-Protocol", "http.sec_websocket_protocol",4659FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4660NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4661 { &hf_http_sec_websocket_version,4662 { "Sec-WebSocket-Version", "http.sec_websocket_version",4663FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4664NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4665 { &hf_http_set_cookie,4666 { "Set-Cookie", "http.set_cookie",4667FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4668"HTTP Set Cookie", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4669 { &hf_http_last_modified,4670 { "Last-Modified", "http.last_modified",4671FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4672"HTTP Last Modified", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4673 { &hf_http_x_forwarded_for,4674 { "X-Forwarded-For", "http.x_forwarded_for",4675FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4676"HTTP X-Forwarded-For", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4677 { &hf_http_http2_settings,4678 { "HTTP2-Settings", "http.http2_settings",4679FT_STRING, BASE_NONE, NULL((void*)0), 0x0,4680NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4681 { &hf_http_request_in,4682 { "Request in frame", "http.request_in",4683FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST)((gpointer) (glong) (FT_FRAMENUM_REQUEST)), 0,4684"This packet is a response to the packet with this number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4685 { &hf_http_response_in,4686 { "Response in frame", "http.response_in",4687FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE)((gpointer) (glong) (FT_FRAMENUM_RESPONSE)), 0,4688"This packet will be responded in the packet with this number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4689 { &hf_http_time,4690 { "Time since request", "http.time",4691FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0,4692"Time since the request was sent", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4693 { &hf_http_chunked_trailer_part,4694 { "trailer-part", "http.chunked_trailer_part",4695FT_STRING, BASE_NONE, NULL((void*)0), 0,4696"Optional trailer in a chunked body", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4697 { &hf_http_chunk_boundary,4698 { "Chunk boundary", "http.chunk_boundary",4699FT_BYTES, BASE_NONE, NULL((void*)0), 0,4700NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4701 { &hf_http_chunk_size,4702 { "Chunk size", "http.chunk_size",4703FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, &units_octet_octets, 0,4704NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4705 { &hf_http_chunk_data,4706 { "Chunk data", "http.chunk_data",4707FT_BYTES, BASE_NONE, NULL((void*)0), 0,4708NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4709 { &hf_http_file_data,4710 { "File Data", "http.file_data",4711FT_BYTES, BASE_NONE, NULL((void*)0), 0,4712NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4713 { &hf_http_unknown_header,4714 { "Unknown header", "http.unknown_header",4715FT_STRING, BASE_NONE, NULL((void*)0), 0,4716NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4717 { &hf_http_http2_settings_uri,4718 { "HTTP2 Settings URI", "http.http2_settings_uri",4719FT_BYTES, BASE_NONE, NULL((void*)0), 0,4720NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},4721 4722/* Body fragments */4723 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)} }
,4724};4725static int *ett[] = {4726&ett_http,4727&ett_http_ntlmssp,4728&ett_http_kerberos,4729&ett_http_request,4730&ett_http_request_uri,4731&ett_http_request_path,4732&ett_http_request_query,4733&ett_http_chunked_response,4734&ett_http_chunk_data,4735&ett_http_encoded_entity,4736&ett_http_header_item,4737&ett_http_http2_settings_item,4738REASSEMBLE_INIT_ETT_ITEMS(http_body)&ett_http_body_fragment, &ett_http_body_fragments,4739};4740 4741static ei_register_info ei[] = {4742{ &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)}}
}},4743{ &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)}}
}},4744{ &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)}}
}},4745{ &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)}}
}},4746{ &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)}}
}},4747{ &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)}}
}},4748{ &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)}}
}},4749{ &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)}}
}},4750{ &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)}}
}}4751 4752};4753 4754/* UAT for header fields */4755static uat_field_t custom_header_uat_fields[] = {4756UAT_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)}
,4757UAT_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)}
,4758UAT_END_FIELDS{((void*)0),((void*)0),PT_TXTMOD_NONE,{0,0,0},{0,0,0},0,0,((void
*)0)}
4759};4760 4761module_t *http_module;4762expert_module_t* expert_http;4763uat_t* headers_uat;4764 4765proto_http = proto_register_protocol("Hypertext Transfer Protocol", "HTTP", "http");4766proto_ssdp = proto_register_protocol("Simple Service Discovery Protocol", "SSDP", "ssdp");4767 4768proto_register_field_array(proto_http, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));4769proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));4770expert_http = expert_register_protocol(proto_http);4771expert_register_field_array(expert_http, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));4772 4773http_handle = register_dissector("http", dissect_http, proto_http);4774http_tcp_handle = register_dissector("http-over-tcp", dissect_http_tcp, proto_http);4775http_tls_handle = register_dissector("http-over-tls", dissect_http_tls, proto_http); /* RFC 2818 */4776http_sctp_handle = register_dissector("http-over-sctp", dissect_http_sctp, proto_http);4777 4778reassembly_table_register(&http_streaming_reassembly_table, &addresses_ports_reassembly_table_functions);4779 4780http_module = prefs_register_protocol(proto_http, reinit_http);4781prefs_register_bool_preference(http_module, "desegment_headers",4782 "Reassemble HTTP headers spanning multiple TCP segments",4783 "Whether the HTTP dissector should reassemble headers "4784 "of a request spanning multiple TCP segments. "4785"To use this option, you must also enable "4786"\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",4787 &http_desegment_headers);4788prefs_register_bool_preference(http_module, "desegment_body",4789 "Reassemble HTTP bodies spanning multiple TCP segments",4790 "Whether the HTTP dissector should use the "4791 "\"Content-length:\" value, if present, to reassemble "4792 "the body of a request spanning multiple TCP segments, "4793 "and reassemble chunked data spanning multiple TCP segments. "4794"To use this option, you must also enable "4795"\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",4796 &http_desegment_body);4797prefs_register_bool_preference(http_module, "dechunk_body",4798 "Reassemble chunked transfer-coded bodies",4799 "Whether to reassemble bodies of entities that are transferred "4800 "using the \"Transfer-Encoding: chunked\" method",4801 &http_dechunk_body);4802#if defined(HAVE_ZLIB1) || defined(HAVE_ZLIBNG) || defined(HAVE_BROTLI1)4803prefs_register_bool_preference(http_module, "decompress_body",4804 "Uncompress entity bodies",4805 "Whether to uncompress entity bodies that are compressed "4806 "using \"Content-Encoding: \"",4807 &http_decompress_body);4808#endif4809prefs_register_bool_preference(http_module, "check_ascii_headers",4810 "Reject non-ASCII headers as invalid HTTP",4811 "Whether to treat non-ASCII in headers as non-HTTP data "4812 "and allow other dissectors to process it",4813 &http_check_ascii_headers);4814prefs_register_obsolete_preference(http_module, "tcp_alternate_port");4815 4816range_convert_str(wmem_epan_scope(), &global_http_tls_range, TLS_DEFAULT_RANGE"443", 65535);4817prefs_register_range_preference(http_module, "tls.port", "SSL/TLS Ports",4818"SSL/TLS Ports range",4819&global_http_tls_range, 65535);4820prefs_register_obsolete_preference(http_module, "ssl.port");4821/* UAT */4822headers_uat = uat_new("Custom HTTP Header Fields",4823 sizeof(header_field_t),4824 "custom_http_header_fields",4825 true1,4826 &header_fields,4827 &num_header_fields,4828 /* specifies named fields, so affects dissection4829 and the set of named fields */4830 UAT_AFFECTS_DISSECTION0x00000001|UAT_AFFECTS_FIELDS0x00000002,4831 NULL((void*)0),4832 header_fields_copy_cb,4833 header_fields_update_cb,4834 header_fields_free_cb,4835 header_fields_post_update_cb,4836 header_fields_reset_cb,4837 custom_header_uat_fields4838);4839 4840prefs_register_uat_preference(http_module, "custom_http_header_fields", "Custom HTTP header fields",4841 "A table to define custom HTTP header for which fields can be setup and used for filtering/data extraction etc.",4842 headers_uat);4843 4844/*4845 * Dissectors shouldn't register themselves in this table;4846 * instead, they should call "http_tcp_dissector_add()", and4847 * we'll register the port number they specify as a port4848 * for HTTP, and register them in our subdissector table.4849 *4850 * This only works for protocols such as IPP that run over4851 * HTTP on a specific non-HTTP port.4852 */4853port_subdissector_table = register_dissector_table("http.port",4854 "TCP port for protocols using HTTP", proto_http, FT_UINT16, BASE_DEC);4855 4856/*4857 * Maps the lowercase Upgrade header value.4858 * https://tools.ietf.org/html/rfc7230#section-8.64859 */4860upgrade_subdissector_table = register_dissector_table("http.upgrade", "HTTP Upgrade", proto_http, FT_STRING, STRING_CASE_SENSITIVE0);4861 4862/*4863 * Heuristic dissectors SHOULD register themselves in4864 * this table using the standard heur_dissector_add()4865 * function.4866 */4867heur_subdissector_list = register_heur_dissector_list_with_description("http", "HTTP payload fallback", proto_http);4868 4869/*4870 * Register for tapping4871 */4872http_tap = register_tap("http"); /* HTTP statistics tap */4873http_follow_tap = register_tap("http_follow"); /* HTTP Follow tap */4874credentials_tap = register_tap("credentials"); /* credentials tap */4875 4876register_follow_stream(proto_http, "http_follow", tcp_follow_conv_filter, tcp_follow_index_filter, tcp_follow_address_filter,4877tcp_port_to_display, follow_tvb_tap_listener,4878get_tcp_stream_count, NULL((void*)0));4879http_eo_tap = register_export_object(proto_http, http_eo_packet, NULL((void*)0));4880 4881/* compile patterns, excluding "/" */4882ws_mempbrk_compile(&pbrk_gen_delims, ":?#[]@");4883/* exclude "=", separating key and value should be done separately */4884ws_mempbrk_compile(&pbrk_sub_delims, "!$&'()*+,;");4885 4886}4887 4888/*4889 * Called by dissectors for protocols that run atop HTTP/TCP.4890 */4891void4892http_tcp_dissector_add(uint32_t port, dissector_handle_t handle)4893{4894/*4895 * Register ourselves as the handler for that port number4896 * over TCP. "Auto-preference" not needed4897 */4898dissector_add_uint("tcp.port", port, http_tcp_handle);4899 4900/*4901 * And register them in *our* table for that port.4902 */4903dissector_add_uint("http.port", port, handle);4904}4905 4906WS_DLL_PUBLIC__attribute__ ((visibility ("default"))) extern4907void http_tcp_dissector_delete(uint32_t port)4908{4909/*4910 * Unregister ourselves as the handler for that port number4911 * over TCP. "Auto-preference" not needed4912 */4913dissector_delete_uint("tcp.port", port, NULL((void*)0));4914 4915/*4916 * And unregister them in *our* table for that port.4917 */4918dissector_delete_uint("http.port", port, NULL((void*)0));4919}4920 4921void4922http_tcp_port_add(uint32_t port)4923{4924/*4925 * Register ourselves as the handler for that port number4926 * over TCP. We rely on our caller having registered4927 * themselves for the appropriate media type.4928 * No "auto-preference" used.4929 */4930dissector_add_uint("tcp.port", port, http_tcp_handle);4931}4932 4933void4934proto_reg_handoff_http(void)4935{4936dissector_handle_t ssdp_handle;4937 4938media_handle = find_dissector_add_dependency("media", proto_http);4939http2_handle = find_dissector("http2");4940/*4941 * XXX - is there anything to dissect in the body of an SSDP4942 * request or reply? I.e., should there be an SSDP dissector?4943 */4944ssdp_handle = create_dissector_handle(dissect_ssdp, proto_ssdp);4945dissector_add_uint_with_preference("udp.port", UDP_PORT_SSDP1900, ssdp_handle);4946 4947/*4948 * TLS Application-Layer Protocol Negotiation (ALPN) protocol ID.4949 */4950dissector_add_string("tls.alpn", "http/1.1", http_tls_handle);4951 4952ntlmssp_handle = find_dissector_add_dependency("ntlmssp", proto_http);4953gssapi_handle = find_dissector_add_dependency("gssapi", proto_http);4954sstp_handle = find_dissector_add_dependency("sstp", proto_http);4955 4956stats_tree_cfg *st_config;4957st_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) );4958stats_tree_set_first_column_name(st_config, "Packet Type");4959st_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) );4960stats_tree_set_first_column_name(st_config, "Request Type");4961st_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) );4962stats_tree_set_first_column_name(st_config, "Packet Type");4963st_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) );4964stats_tree_set_first_column_name(st_config, "Sequence Type");4965 4966dissector_add_uint("acdr.tls_application_port", 443, http_handle);4967dissector_add_uint("acdr.tls_application", TLS_APP_HTTP, http_handle);4968dissector_add_uint("acdr.tls_application", TLS_APP_TR069, http_handle);4969dissector_add_uint("ippusb", 0, http_tcp_handle);4970}4971 4972/*4973 * Content-Type: message/http4974 */4975 4976static int proto_message_http;4977static int ett_message_http;4978 4979static int4980dissect_message_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))4981{4982proto_tree*subtree;4983proto_item*ti;4984intoffset = 0, next_offset;4985intlen;4986 4987col_append_str(pinfo->cinfo, COL_INFO, " (message/http)");4988if (tree) {4989ti = proto_tree_add_item(tree, proto_message_http,4990tvb, 0, -1, ENC_NA0x00000000);4991subtree = proto_item_add_subtree(ti, ett_message_http);4992while (tvb_offset_exists(tvb, offset)) {4993len = tvb_find_line_end(tvb, offset,4994tvb_ensure_captured_length_remaining(tvb, offset),4995&next_offset, false0);4996if (len == -1)4997break;4998proto_tree_add_format_text(subtree, tvb, offset, len);4999offset = next_offset;5000}5001}5002return tvb_captured_length(tvb);5003}5004 5005void5006proto_register_message_http(void)5007{5008static int *ett[] = {5009&ett_message_http,5010};5011 5012proto_message_http = proto_register_protocol("Media Type: message/http", "message/http", "message-http");5013proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));5014}5015 5016void5017proto_reg_handoff_message_http(void)5018{5019dissector_handle_t message_http_handle;5020 5021message_http_handle = create_dissector_handle(dissect_message_http,5022proto_message_http);5023 5024dissector_add_string("media_type", "message/http", message_http_handle);5025 5026heur_dissector_add("tcp", dissect_http_heur_tcp, "HTTP over TCP", "http_tcp", proto_http, HEURISTIC_ENABLE);5027heur_dissector_add("tls", dissect_http_heur_tls, "HTTP over TLS", "http_tls", proto_http, HEURISTIC_ENABLE);5028 5029proto_http2 = proto_get_id_by_filter_name("http2");5030 5031dissector_add_uint_range_with_preference("tcp.port", TCP_DEFAULT_RANGE"80,3128,3132,5985,8080,8088,11371,1900,2869,2710", http_tcp_handle);5032dissector_add_uint_range_with_preference("sctp.port", SCTP_DEFAULT_RANGE"80", http_sctp_handle);5033 5034/*5035 * Get the content type and Internet media type table5036 */5037media_type_subdissector_table = find_dissector_table("media_type");5038 5039streaming_content_type_dissector_table = find_dissector_table("streaming_content_type");5040 5041reinit_http();5042}5043 5044/*5045 * Editor modelines - https://www.wireshark.org/tools/modelines.html5046 *5047 * Local variables:5048 * c-basic-offset: 85049 * tab-width: 85050 * indent-tabs-mode: t5051 * End:5052 *5053 * vi: set shiftwidth=8 tabstop=8 noexpandtab:5054 * :indentSize=8:tabSize=8:noTabs=false:5055 */
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)

FAQs

How to extract packet data from Wireshark? ›

Wireshark→ File→ Export specified packets)

To export the data into the Wireshark, there are multiple options such as Exports specified packets, Exporting packet Dissection, Export Packet Bytes, exporting PDU to File, exporting TLS session, and Export Objects.

How do I analyze a Wireshark packet? ›

To analyze data packets in Wireshark, first, open the corresponding file that has been saved after the packet capturing process. Next, users can narrow their search by using Wireshark's filter options. Below are just a few possibilities for using Wireshark filters: Showing only traffic from a particular port.

Why can't i see HTTP packets in Wireshark? ›

Please confirm that you are capturing the right network packets. In the Wire shark, you can see the protocol tab. For the http protocol, just mention the same as HTTP, and for the https protocol, mention HTTPS . Normally, you are not able to see the HTTPS packet because it is encrypted.

How to extract HTTP files from Wireshark? ›

Option 1: In the Wireshark menu go to File / Export Object / HTTP... then select the object you want to export and click 'Save' (or 'Save All'). Also documented at par.

How to copy Wireshark data to text? ›

Highlight the line, right-click, and select Copy > Description or Copy > Value, then paste it into your text document.

How do hackers use Wireshark? ›

Wireshark can also be used as a tool for hackers. This usually involves reading and writing data transmitted over an unsecure or compromised network. Nefarious actors may seek out confidential data such as credit-card information, passwords, search queries, private messages, emails, financial transactions, and more.

How do I capture packets on my router with Wireshark? ›

Input the IP address to the address bar in the web browser and you will visit the GUI of the SMB router. After logging into the page, go to Network-Switch-Mirror, enable Port Mirror, select the port connecting to your PC in the Mirroring Port and the port you want to capture packets in the Mirrored Port, click Save.

How to view HTTPS packets in Wireshark? ›

Observe the traffic captured in the top Wireshark packet list pane. To view only HTTPS traffic, type ssl (lower case) in the Filter box and press Enter. Select the first TLS packet labeled Client Hello. Observe the destination IP address.

How do I only show HTTP traffic in Wireshark? ›

We can do this by writing “http” in the Wireshark filters bar and then press send. » Apply a port filter: we may also apply a TCP protocol on its port. We can do this by writing “tcp. port==80” in the Wireshark filters bar then press send.

How to view HTTP headers in Wireshark? ›

You can view the response headers for any http. request within Wireshark by selecting the request and right clicking. A menu will appear and then you select Follow -> HTTP Stream.

How do I read a package in Wireshark? ›

You can easily find packets once you have captured some packets or have read in a previously saved capture file. Simply select Edit → Find Packet… ​ in the main menu. Wireshark will open a toolbar between the main toolbar and the packet list shown in Figure 6.12, “The “Find Packet” toolbar”.

References

Top Articles
Latest Posts
Article information

Author: Eusebia Nader

Last Updated:

Views: 6199

Rating: 5 / 5 (60 voted)

Reviews: 83% of readers found this page helpful

Author information

Name: Eusebia Nader

Birthday: 1994-11-11

Address: Apt. 721 977 Ebert Meadows, Jereville, GA 73618-6603

Phone: +2316203969400

Job: International Farming Consultant

Hobby: Reading, Photography, Shooting, Singing, Magic, Kayaking, Mushroom hunting

Introduction: My name is Eusebia Nader, I am a encouraging, brainy, lively, nice, famous, healthy, clever person who loves writing and wants to share my knowledge and understanding with you.