1 /* packet-http.c
2  * Routines for HTTP packet disassembly
3  * RFC 1945 (HTTP/1.0)
4  * RFC 2616 (HTTP/1.1)
5  *
6  * Guy Harris <guy@alum.mit.edu>
7  *
8  * Copyright 2017, Eugene Adell <eugene.adell@gmail.com>
9  * Copyright 2004, Jerry Talkington <jtalkington@users.sourceforge.net>
10  * Copyright 2002, Tim Potter <tpot@samba.org>
11  * Copyright 1999, Andrew Tridgell <tridge@samba.org>
12  *
13  * Wireshark - Network traffic analyzer
14  * By Gerald Combs <gerald@wireshark.org>
15  * Copyright 1998 Gerald Combs
16  *
17  * SPDX-License-Identifier: GPL-2.0-or-later
18  */
19 
20 #include "config.h"
21 
22 #include <errno.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/strutil.h>
31 #include <epan/stats_tree.h>
32 #include <epan/to_str.h>
33 #include <epan/req_resp_hdrs.h>
34 #include <epan/proto_data.h>
35 #include <epan/export_object.h>
36 #include <epan/exceptions.h>
37 #include <epan/show_exception.h>
38 
39 #include "packet-http.h"
40 #include "packet-http2.h"
41 #include "packet-tcp.h"
42 #include "packet-tls.h"
43 #include "packet-acdr.h"
44 
45 #include <ui/tap-credentials.h>
46 
47 void proto_register_http(void);
48 void proto_reg_handoff_http(void);
49 void proto_register_message_http(void);
50 void proto_reg_handoff_message_http(void);
51 
52 static int http_tap = -1;
53 static int http_eo_tap = -1;
54 static int http_follow_tap = -1;
55 static int credentials_tap = -1;
56 
57 static int proto_http = -1;
58 static int proto_http2 = -1;
59 static int proto_ssdp = -1;
60 static int hf_http_notification = -1;
61 static int hf_http_response = -1;
62 static int hf_http_request = -1;
63 static int hf_http_response_number = -1;
64 static int hf_http_request_number = -1;
65 static int hf_http_response_line = -1;
66 static int hf_http_request_line = -1;
67 static int hf_http_basic = -1;
68 static int hf_http_citrix = -1;
69 static int hf_http_citrix_user = -1;
70 static int hf_http_citrix_domain = -1;
71 static int hf_http_citrix_passwd = -1;
72 static int hf_http_citrix_session = -1;
73 static int hf_http_request_method = -1;
74 static int hf_http_request_uri = -1;
75 static int hf_http_request_full_uri = -1;
76 static int hf_http_request_path = -1;
77 static int hf_http_request_query = -1;
78 static int hf_http_request_query_parameter = -1;
79 static int hf_http_request_version = -1;
80 static int hf_http_response_version = -1;
81 static int hf_http_response_code = -1;
82 static int hf_http_response_code_desc = -1;
83 static int hf_http_response_for_uri = -1;
84 static int hf_http_response_phrase = -1;
85 static int hf_http_authorization = -1;
86 static int hf_http_proxy_authenticate = -1;
87 static int hf_http_proxy_authorization = -1;
88 static int hf_http_proxy_connect_host = -1;
89 static int hf_http_proxy_connect_port = -1;
90 static int hf_http_www_authenticate = -1;
91 static int hf_http_content_type = -1;
92 static int hf_http_content_length_header = -1;
93 static int hf_http_content_length = -1;
94 static int hf_http_content_encoding = -1;
95 static int hf_http_transfer_encoding = -1;
96 static int hf_http_upgrade = -1;
97 static int hf_http_user_agent = -1;
98 static int hf_http_host = -1;
99 static int hf_http_connection = -1;
100 static int hf_http_cookie = -1;
101 static int hf_http_cookie_pair = -1;
102 static int hf_http_accept = -1;
103 static int hf_http_referer = -1;
104 static int hf_http_accept_language = -1;
105 static int hf_http_accept_encoding = -1;
106 static int hf_http_date = -1;
107 static int hf_http_cache_control = -1;
108 static int hf_http_server = -1;
109 static int hf_http_location = -1;
110 static int hf_http_sec_websocket_accept = -1;
111 static int hf_http_sec_websocket_extensions = -1;
112 static int hf_http_sec_websocket_key = -1;
113 static int hf_http_sec_websocket_protocol = -1;
114 static int hf_http_sec_websocket_version = -1;
115 static int hf_http_set_cookie = -1;
116 static int hf_http_last_modified = -1;
117 static int hf_http_x_forwarded_for = -1;
118 static int hf_http_http2_settings = -1;
119 static int hf_http_request_in = -1;
120 static int hf_http_response_in = -1;
121 static int hf_http_next_request_in = -1;
122 static int hf_http_next_response_in = -1;
123 static int hf_http_prev_request_in = -1;
124 static int hf_http_prev_response_in = -1;
125 static int hf_http_time = -1;
126 static int hf_http_chunk_size = -1;
127 static int hf_http_chunk_boundary = -1;
128 static int hf_http_chunked_trailer_part = -1;
129 static int hf_http_file_data = -1;
130 static int hf_http_unknown_header = -1;
131 static int hf_http_http2_settings_uri = -1;
132 
133 static gint ett_http = -1;
134 static gint ett_http_ntlmssp = -1;
135 static gint ett_http_kerberos = -1;
136 static gint ett_http_request = -1;
137 static gint ett_http_request_path = -1;
138 static gint ett_http_request_query = -1;
139 static gint ett_http_chunked_response = -1;
140 static gint ett_http_chunk_data = -1;
141 static gint ett_http_encoded_entity = -1;
142 static gint ett_http_header_item = -1;
143 static gint ett_http_http2_settings_item = -1;
144 
145 static expert_field ei_http_chat = EI_INIT;
146 static expert_field ei_http_te_and_length = EI_INIT;
147 static expert_field ei_http_te_unknown = EI_INIT;
148 static expert_field ei_http_subdissector_failed = EI_INIT;
149 static expert_field ei_http_tls_port = EI_INIT;
150 static expert_field ei_http_leading_crlf = EI_INIT;
151 static expert_field ei_http_bad_header_name = EI_INIT;
152 static expert_field ei_http_decompression_failed = EI_INIT;
153 static expert_field ei_http_decompression_disabled = EI_INIT;
154 
155 static dissector_handle_t http_handle;
156 static dissector_handle_t http_tcp_handle;
157 static dissector_handle_t http_tls_handle;
158 static dissector_handle_t http_sctp_handle;
159 
160 static dissector_handle_t media_handle;
161 static dissector_handle_t http2_handle;
162 static dissector_handle_t sstp_handle;
163 static dissector_handle_t ntlmssp_handle;
164 static dissector_handle_t gssapi_handle;
165 
166 /* Stuff for generation/handling of fields for custom HTTP headers */
167 typedef struct _header_field_t {
168 	gchar* header_name;
169 	gchar* header_desc;
170 } header_field_t;
171 
172 static header_field_t* header_fields;
173 static guint num_header_fields;
174 
175 static GHashTable* header_fields_hash;
176 static hf_register_info* dynamic_hf;
177 static guint dynamic_hf_size;
178 
179 static gboolean
header_fields_update_cb(void * r,char ** err)180 header_fields_update_cb(void *r, char **err)
181 {
182 	header_field_t *rec = (header_field_t *)r;
183 	char c;
184 
185 	if (rec->header_name == NULL) {
186 		*err = g_strdup("Header name can't be empty");
187 		return FALSE;
188 	}
189 
190 	g_strstrip(rec->header_name);
191 	if (rec->header_name[0] == 0) {
192 		*err = g_strdup("Header name can't be empty");
193 		return FALSE;
194 	}
195 
196 	/* Check for invalid characters (to avoid asserting out when
197 	 * registering the field).
198 	 */
199 	c = proto_check_field_name(rec->header_name);
200 	if (c) {
201 		*err = g_strdup_printf("Header name can't contain '%c'", c);
202 		return FALSE;
203 	}
204 
205 	*err = NULL;
206 	return TRUE;
207 }
208 
209 static void *
header_fields_copy_cb(void * n,const void * o,size_t siz _U_)210 header_fields_copy_cb(void* n, const void* o, size_t siz _U_)
211 {
212 	header_field_t* new_rec = (header_field_t*)n;
213 	const header_field_t* old_rec = (const header_field_t*)o;
214 
215 	new_rec->header_name = g_strdup(old_rec->header_name);
216 	new_rec->header_desc = g_strdup(old_rec->header_desc);
217 
218 	return new_rec;
219 }
220 
221 static void
header_fields_free_cb(void * r)222 header_fields_free_cb(void*r)
223 {
224 	header_field_t* rec = (header_field_t*)r;
225 
226 	g_free(rec->header_name);
227 	g_free(rec->header_desc);
228 }
229 
230 UAT_CSTRING_CB_DEF(header_fields, header_name, header_field_t)
231 UAT_CSTRING_CB_DEF(header_fields, header_desc, header_field_t)
232 
233 /*
234  * desegmentation of HTTP headers
235  * (when we are over TCP or another protocol providing the desegmentation API)
236  */
237 static gboolean http_desegment_headers = TRUE;
238 
239 /*
240  * desegmentation of HTTP bodies
241  * (when we are over TCP or another protocol providing the desegmentation API)
242  * TODO let the user filter on content-type the bodies he wants desegmented
243  */
244 static gboolean http_desegment_body = TRUE;
245 
246 /*
247  * De-chunking of content-encoding: chunk entity bodies.
248  */
249 static gboolean http_dechunk_body = TRUE;
250 
251 /*
252  * Decompression of zlib or brotli encoded entities.
253  */
254 #if defined(HAVE_ZLIB) || defined(HAVE_BROTLI)
255 static gboolean http_decompress_body = TRUE;
256 #endif
257 
258 /* Simple Service Discovery Protocol
259  * SSDP is implemented atop HTTP (yes, it really *does* run over UDP).
260  * SSDP is the discovery protocol of Universal Plug and Play
261  * UPnP   http://www.upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
262  */
263 #define TCP_PORT_SSDP			1900
264 #define UDP_PORT_SSDP			1900
265 
266 /*
267  * TCP and TLS ports
268  *
269  * 2710 is the XBT BitTorrent tracker
270  */
271 
272 #define TCP_DEFAULT_RANGE "80,3128,3132,5985,8080,8088,11371,1900,2869,2710"
273 #define SCTP_DEFAULT_RANGE "80"
274 #define TLS_DEFAULT_RANGE "443"
275 
276 static range_t *global_http_sctp_range = NULL;
277 static range_t *global_http_tls_range = NULL;
278 
279 static range_t *http_tcp_range = NULL;
280 static range_t *http_sctp_range = NULL;
281 static range_t *http_tls_range = NULL;
282 
283 typedef void (*ReqRespDissector)(tvbuff_t*, proto_tree*, int, const guchar*,
284 				 const guchar*, http_conv_t *);
285 
286 /**
287  * Transfer codings from
288  * https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#transfer-coding
289  * Note: chunked encoding is handled separately.
290  */
291 typedef enum _http_transfer_coding {
292 	HTTP_TE_NONE,           /* Dummy value for header which is not set */
293 	/* HTTP_TE_CHUNKED, */
294 	HTTP_TE_COMPRESS,
295 	HTTP_TE_DEFLATE,
296 	HTTP_TE_GZIP,
297 	HTTP_TE_IDENTITY,
298 	HTTP_TE_UNKNOWN,    /* Header was set, but no valid name was found */
299 } http_transfer_coding;
300 
301 /*
302  * Structure holding information from headers needed by main
303  * HTTP dissector code.
304  */
305 typedef struct {
306 	char	*content_type;
307 	char	*content_type_parameters;
308 	gboolean have_content_length;
309 	gint64   content_length;
310 	char     *content_encoding;
311 	gboolean transfer_encoding_chunked;
312 	http_transfer_coding transfer_encoding;
313 	char    *upgrade;
314 } headers_t;
315 
316 static gint parse_http_status_code(const guchar *line, const guchar *lineend);
317 static int is_http_request_or_reply(const gchar *data, int linelen,
318 				    http_type_t *type, ReqRespDissector
319 				    *reqresp_dissector, http_conv_t *conv_data);
320 static guint chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
321 					proto_tree *tree, int offset);
322 static void process_header(tvbuff_t *tvb, int offset, int next_offset,
323 			   const guchar *line, int linelen, int colon_offset,
324 			   packet_info *pinfo, proto_tree *tree,
325 			   headers_t *eh_ptr, http_conv_t *conv_data,
326 			   http_type_t http_type);
327 static gint find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len);
328 static gboolean check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb,
329 				   packet_info *pinfo, gchar *value);
330 static gboolean check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb,
331 				 packet_info *pinfo, gchar *value);
332 static gboolean check_auth_digest(proto_item* hdr_item, tvbuff_t* tvb, packet_info* pinfo _U_, gchar* value, int offset, int len);
333 static gboolean check_auth_citrixbasic(proto_item *hdr_item, tvbuff_t *tvb,
334 				 gchar *value, int offset);
335 static gboolean check_auth_kerberos(proto_item *hdr_item, tvbuff_t *tvb,
336 				   packet_info *pinfo, const gchar *value);
337 
338 static dissector_table_t port_subdissector_table;
339 static dissector_table_t media_type_subdissector_table;
340 static dissector_table_t upgrade_subdissector_table;
341 static heur_dissector_list_t heur_subdissector_list;
342 
343 /* Used for HTTP Export Object feature */
344 typedef struct _http_eo_t {
345 	guint32  pkt_num;
346 	gchar   *hostname;
347 	gchar   *filename;
348 	gchar   *content_type;
349 	guint32  payload_len;
350 	const guint8 *payload_data;
351 } http_eo_t;
352 
353 static tap_packet_status
http_eo_packet(void * tapdata,packet_info * pinfo,epan_dissect_t * edt _U_,const void * data)354 http_eo_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
355 {
356 	export_object_list_t *object_list = (export_object_list_t *)tapdata;
357 	const http_eo_t *eo_info = (const http_eo_t *)data;
358 	export_object_entry_t *entry;
359 
360 	if(eo_info) { /* We have data waiting for us */
361 		/* These values will be freed when the Export Object window
362 		 * is closed. */
363 		entry = g_new(export_object_entry_t, 1);
364 
365 		entry->pkt_num = pinfo->num;
366 		entry->hostname = g_strdup(eo_info->hostname);
367 		entry->content_type = g_strdup(eo_info->content_type);
368 		entry->filename = eo_info->filename ? g_path_get_basename(eo_info->filename) : NULL;
369 		entry->payload_len = eo_info->payload_len;
370 		entry->payload_data = (guint8 *)g_memdup2(eo_info->payload_data, eo_info->payload_len);
371 
372 		object_list->add_entry(object_list->gui_data, entry);
373 
374 		return TAP_PACKET_REDRAW; /* State changed - window should be redrawn */
375 	} else {
376 		return TAP_PACKET_DONT_REDRAW; /* State unchanged - no window updates needed */
377 	}
378 }
379 
380 /* --- HTTP Status Codes */
381 /* Note: The reference for uncommented entries is RFC 2616 */
382 const value_string vals_http_status_code[] = {
383 	{ 100, "Continue" },
384 	{ 101, "Switching Protocols" },
385 	{ 102, "Processing" },                     /* RFC 2518 */
386 	{ 103, "Early Hints" },                    /* RFC-ietf-httpbis-early-hints-05 */
387 	{ 199, "Informational - Others" },
388 
389 	{ 200, "OK"},
390 	{ 201, "Created"},
391 	{ 202, "Accepted"},
392 	{ 203, "Non-authoritative Information"},
393 	{ 204, "No Content"},
394 	{ 205, "Reset Content"},
395 	{ 206, "Partial Content"},
396 	{ 207, "Multi-Status"},                    /* RFC 4918 */
397 	{ 208, "Already Reported"},                /* RFC 5842 */
398 	{ 226, "IM Used"},                         /* RFC 3229 */
399 	{ 299, "Success - Others"},
400 
401 	{ 300, "Multiple Choices"},
402 	{ 301, "Moved Permanently"},
403 	{ 302, "Found"},
404 	{ 303, "See Other"},
405 	{ 304, "Not Modified"},
406 	{ 305, "Use Proxy"},
407 	{ 307, "Temporary Redirect"},
408 	{ 308, "Permanent Redirect"},              /* RFC 7538 */
409 	{ 399, "Redirection - Others"},
410 
411 	{ 400, "Bad Request"},
412 	{ 401, "Unauthorized"},
413 	{ 402, "Payment Required"},
414 	{ 403, "Forbidden"},
415 	{ 404, "Not Found"},
416 	{ 405, "Method Not Allowed"},
417 	{ 406, "Not Acceptable"},
418 	{ 407, "Proxy Authentication Required"},
419 	{ 408, "Request Time-out"},
420 	{ 409, "Conflict"},
421 	{ 410, "Gone"},
422 	{ 411, "Length Required"},
423 	{ 412, "Precondition Failed"},
424 	{ 413, "Request Entity Too Large"},
425 	{ 414, "Request-URI Too Long"},
426 	{ 415, "Unsupported Media Type"},
427 	{ 416, "Requested Range Not Satisfiable"},
428 	{ 417, "Expectation Failed"},
429 	{ 418, "I'm a teapot"},                    /* RFC 2324 */
430 	{ 421, "Misdirected Request"},             /* RFC 7540 */
431 	{ 422, "Unprocessable Entity"},            /* RFC 4918 */
432 	{ 423, "Locked"},                          /* RFC 4918 */
433 	{ 424, "Failed Dependency"},               /* RFC 4918 */
434 	{ 425, "Too Early"},                       /* RFC 8470 */
435 	{ 426, "Upgrade Required"},                /* RFC 2817 */
436 	{ 428, "Precondition Required"},           /* RFC 6585 */
437 	{ 429, "Too Many Requests"},               /* RFC 6585 */
438 	{ 431, "Request Header Fields Too Large"}, /* RFC 6585 */
439 	{ 451, "Unavailable For Legal Reasons"},   /* RFC 7725 */
440 	{ 499, "Client Error - Others"},
441 
442 	{ 500, "Internal Server Error"},
443 	{ 501, "Not Implemented"},
444 	{ 502, "Bad Gateway"},
445 	{ 503, "Service Unavailable"},
446 	{ 504, "Gateway Time-out"},
447 	{ 505, "HTTP Version not supported"},
448 	{ 506, "Variant Also Negotiates"},         /* RFC 2295 */
449 	{ 507, "Insufficient Storage"},            /* RFC 4918 */
450 	{ 508, "Loop Detected"},                   /* RFC 5842 */
451 	{ 510, "Not Extended"},                    /* RFC 2774 */
452 	{ 511, "Network Authentication Required"}, /* RFC 6585 */
453 	{ 599, "Server Error - Others"},
454 
455 	{ 0, 	NULL}
456 };
457 
458 static const gchar* st_str_reqs = "HTTP Requests by Server";
459 static const gchar* st_str_reqs_by_srv_addr = "HTTP Requests by Server Address";
460 static const gchar* st_str_reqs_by_http_host = "HTTP Requests by HTTP Host";
461 static const gchar* st_str_resps_by_srv_addr = "HTTP Responses by Server Address";
462 
463 static int st_node_reqs = -1;
464 static int st_node_reqs_by_srv_addr = -1;
465 static int st_node_reqs_by_http_host = -1;
466 static int st_node_resps_by_srv_addr = -1;
467 
468 /* HTTP/Load Distribution stats init function */
469 static void
http_reqs_stats_tree_init(stats_tree * st)470 http_reqs_stats_tree_init(stats_tree* st)
471 {
472 	st_node_reqs = stats_tree_create_node(st, st_str_reqs, 0, STAT_DT_INT, TRUE);
473 	st_node_reqs_by_srv_addr = stats_tree_create_node(st, st_str_reqs_by_srv_addr, st_node_reqs, STAT_DT_INT, TRUE);
474 	st_node_reqs_by_http_host = stats_tree_create_node(st, st_str_reqs_by_http_host, st_node_reqs, STAT_DT_INT, TRUE);
475 	st_node_resps_by_srv_addr = stats_tree_create_node(st, st_str_resps_by_srv_addr, 0, STAT_DT_INT, TRUE);
476 }
477 
478 /* HTTP/Load Distribution stats packet function */
479 static tap_packet_status
http_reqs_stats_tree_packet(stats_tree * st,packet_info * pinfo,epan_dissect_t * edt _U_,const void * p)480 http_reqs_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
481 {
482 	const http_info_value_t* v = (const http_info_value_t*)p;
483 	int reqs_by_this_host;
484 	int reqs_by_this_addr;
485 	int resps_by_this_addr;
486 	int i = v->response_code;
487 	gchar *ip_str;
488 
489 
490 	if (v->request_method) {
491 		ip_str = address_to_str(NULL, &pinfo->dst);
492 
493 		tick_stat_node(st, st_str_reqs, 0, FALSE);
494 		tick_stat_node(st, st_str_reqs_by_srv_addr, st_node_reqs, TRUE);
495 		tick_stat_node(st, st_str_reqs_by_http_host, st_node_reqs, TRUE);
496 		reqs_by_this_addr = tick_stat_node(st, ip_str, st_node_reqs_by_srv_addr, TRUE);
497 
498 		if (v->http_host) {
499 			reqs_by_this_host = tick_stat_node(st, v->http_host, st_node_reqs_by_http_host, TRUE);
500 			tick_stat_node(st, ip_str, reqs_by_this_host, FALSE);
501 
502 			tick_stat_node(st, v->http_host, reqs_by_this_addr, FALSE);
503 		}
504 
505 		wmem_free(NULL, ip_str);
506 
507 		return TAP_PACKET_REDRAW;
508 
509 	} else if (i != 0) {
510 		ip_str = address_to_str(NULL, &pinfo->src);
511 
512 		tick_stat_node(st, st_str_resps_by_srv_addr, 0, FALSE);
513 		resps_by_this_addr = tick_stat_node(st, ip_str, st_node_resps_by_srv_addr, TRUE);
514 
515 		if ( (i>100)&&(i<400) ) {
516 			tick_stat_node(st, "OK", resps_by_this_addr, FALSE);
517 		} else {
518 			tick_stat_node(st, "KO", resps_by_this_addr, FALSE);
519 		}
520 
521 		wmem_free(NULL, ip_str);
522 
523 		return TAP_PACKET_REDRAW;
524 	}
525 
526 	return TAP_PACKET_DONT_REDRAW;
527 }
528 
529 
530 static int st_node_requests_by_host = -1;
531 static const gchar *st_str_requests_by_host = "HTTP Requests by HTTP Host";
532 
533 /* HTTP/Requests stats init function */
534 static void
http_req_stats_tree_init(stats_tree * st)535 http_req_stats_tree_init(stats_tree* st)
536 {
537 	st_node_requests_by_host = stats_tree_create_node(st, st_str_requests_by_host, 0, STAT_DT_INT, TRUE);
538 }
539 
540 /* HTTP/Requests stats packet function */
541 static tap_packet_status
http_req_stats_tree_packet(stats_tree * st,packet_info * pinfo _U_,epan_dissect_t * edt _U_,const void * p)542 http_req_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p)
543 {
544 	const http_info_value_t* v = (const http_info_value_t*)p;
545 	int reqs_by_this_host;
546 
547 	if (v->request_method) {
548 		tick_stat_node(st, st_str_requests_by_host, 0, FALSE);
549 
550 		if (v->http_host) {
551 			reqs_by_this_host = tick_stat_node(st, v->http_host, st_node_requests_by_host, TRUE);
552 
553 			if (v->request_uri) {
554 				tick_stat_node(st, v->request_uri, reqs_by_this_host, TRUE);
555 			}
556 		}
557 
558 		return TAP_PACKET_REDRAW;
559 	}
560 
561 	return TAP_PACKET_DONT_REDRAW;
562 }
563 
564 static const gchar *st_str_packets = "Total HTTP Packets";
565 static const gchar *st_str_requests = "HTTP Request Packets";
566 static const gchar *st_str_responses = "HTTP Response Packets";
567 static const gchar *st_str_resp_broken = "???: broken";
568 static const gchar *st_str_resp_100 = "1xx: Informational";
569 static const gchar *st_str_resp_200 = "2xx: Success";
570 static const gchar *st_str_resp_300 = "3xx: Redirection";
571 static const gchar *st_str_resp_400 = "4xx: Client Error";
572 static const gchar *st_str_resp_500 = "5xx: Server Error";
573 static const gchar *st_str_other = "Other HTTP Packets";
574 
575 static int st_node_packets = -1;
576 static int st_node_requests = -1;
577 static int st_node_responses = -1;
578 static int st_node_resp_broken = -1;
579 static int st_node_resp_100 = -1;
580 static int st_node_resp_200 = -1;
581 static int st_node_resp_300 = -1;
582 static int st_node_resp_400 = -1;
583 static int st_node_resp_500 = -1;
584 static int st_node_other = -1;
585 
586 
587 /* HTTP/Packet Counter stats init function */
588 static void
http_stats_tree_init(stats_tree * st)589 http_stats_tree_init(stats_tree* st)
590 {
591 	st_node_packets = stats_tree_create_node(st, st_str_packets, 0, STAT_DT_INT, TRUE);
592 	st_node_requests = stats_tree_create_pivot(st, st_str_requests, st_node_packets);
593 	st_node_responses = stats_tree_create_node(st, st_str_responses, st_node_packets, STAT_DT_INT, TRUE);
594 	st_node_resp_broken = stats_tree_create_node(st, st_str_resp_broken, st_node_responses, STAT_DT_INT, TRUE);
595 	st_node_resp_100    = stats_tree_create_node(st, st_str_resp_100,    st_node_responses, STAT_DT_INT, TRUE);
596 	st_node_resp_200    = stats_tree_create_node(st, st_str_resp_200,    st_node_responses, STAT_DT_INT, TRUE);
597 	st_node_resp_300    = stats_tree_create_node(st, st_str_resp_300,    st_node_responses, STAT_DT_INT, TRUE);
598 	st_node_resp_400    = stats_tree_create_node(st, st_str_resp_400,    st_node_responses, STAT_DT_INT, TRUE);
599 	st_node_resp_500    = stats_tree_create_node(st, st_str_resp_500,    st_node_responses, STAT_DT_INT, TRUE);
600 	st_node_other = stats_tree_create_node(st, st_str_other, st_node_packets, STAT_DT_INT, FALSE);
601 }
602 
603 /* HTTP/Packet Counter stats packet function */
604 static tap_packet_status
http_stats_tree_packet(stats_tree * st,packet_info * pinfo _U_,epan_dissect_t * edt _U_,const void * p)605 http_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p)
606 {
607 	const http_info_value_t* v = (const http_info_value_t*)p;
608 	guint i = v->response_code;
609 	int resp_grp;
610 	const gchar *resp_str;
611 	gchar str[64];
612 
613 	tick_stat_node(st, st_str_packets, 0, FALSE);
614 
615 	if (i) {
616 		tick_stat_node(st, st_str_responses, st_node_packets, FALSE);
617 
618 		if ( (i<100)||(i>=600) ) {
619 			resp_grp = st_node_resp_broken;
620 			resp_str = st_str_resp_broken;
621 		} else if (i<200) {
622 			resp_grp = st_node_resp_100;
623 			resp_str = st_str_resp_100;
624 		} else if (i<300) {
625 			resp_grp = st_node_resp_200;
626 			resp_str = st_str_resp_200;
627 		} else if (i<400) {
628 			resp_grp = st_node_resp_300;
629 			resp_str = st_str_resp_300;
630 		} else if (i<500) {
631 			resp_grp = st_node_resp_400;
632 			resp_str = st_str_resp_400;
633 		} else {
634 			resp_grp = st_node_resp_500;
635 			resp_str = st_str_resp_500;
636 		}
637 
638 		tick_stat_node(st, resp_str, st_node_responses, FALSE);
639 
640 		g_snprintf(str, sizeof(str), "%u %s", i,
641 			   val_to_str(i, vals_http_status_code, "Unknown (%d)"));
642 		tick_stat_node(st, str, resp_grp, FALSE);
643 	} else if (v->request_method) {
644 		stats_tree_tick_pivot(st,st_node_requests,v->request_method);
645 	} else {
646 		tick_stat_node(st, st_str_other, st_node_packets, FALSE);
647 	}
648 
649 	return TAP_PACKET_REDRAW;
650 }
651 
652 /*
653 Generates a referer tree - a best-effort representation of which web request led to which.
654 
655 Some challenges:
656 A user can be forwarded to a single sites from multiple sources. For example,
657 google.com -> foo.com and bing.com -> foo.com. A URI alone is not unique.
658 
659 Additionally, if a user has a subsequent request to foo.com -> bar.com, the
660 full chain could either be:
661 	google.com -> foo.com -> bar.com, or
662 	bing.com   -> foo.com -> bar.com,
663 
664 This indicates that a URI and its referer are not unique. Only a URI and its
665 full referer chain are unique. However, HTTP requests only contain the URI
666 and the immediate referer. This means that any attempt at generating a
667 referer tree is inherently going to be a best-effort approach.
668 
669 This code assumes that the referer in a request is from the most-recent request
670 to that referer.
671 
672 * To maintain readability of the statistics, whenever a site is visited, all
673 prior referers are 'ticked' as well, so that one can easily see the breakdown.
674 */
675 
676 /* Root node for all referer statistics */
677 static int st_node_requests_by_referer = -1;
678 /* Referer statistics root node's text */
679 static const gchar *st_str_request_sequences = "HTTP Request Sequences";
680 
681 /* Mapping of URIs to the most-recently seen node id */
682 static wmem_map_t* refstats_uri_to_node_id_hash = NULL;
683 /* Mapping of node ids to the node's URI ('name' value) */
684 static wmem_map_t* refstats_node_id_to_uri_hash = NULL;
685 /* Mapping of node ids to the parent node id */
686 static wmem_map_t* refstats_node_id_to_parent_node_id_hash = NULL;
687 
688 
689 /* HTTP/Request Sequences stats init function */
690 static void
http_seq_stats_tree_init(stats_tree * st)691 http_seq_stats_tree_init(stats_tree* st)
692 {
693 	gint root_node_id = 0;
694 	gpointer root_node_id_p = GINT_TO_POINTER(root_node_id);
695 	gpointer node_id_p = NULL;
696 	gchar *uri = NULL;
697 
698 	refstats_node_id_to_parent_node_id_hash = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
699 	refstats_node_id_to_uri_hash = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
700 	refstats_uri_to_node_id_hash = wmem_map_new(wmem_file_scope(), wmem_str_hash, g_str_equal);
701 
702 	/* Add the root node and its mappings */
703 	st_node_requests_by_referer = stats_tree_create_node(st, st_str_request_sequences, root_node_id, STAT_DT_INT, TRUE);
704 	node_id_p = GINT_TO_POINTER(st_node_requests_by_referer);
705 	uri = wmem_strdup(wmem_file_scope(), st_str_request_sequences);
706 
707 	wmem_map_insert(refstats_uri_to_node_id_hash, uri, node_id_p);
708 	wmem_map_insert(refstats_node_id_to_uri_hash, node_id_p, uri);
709 	wmem_map_insert(refstats_node_id_to_parent_node_id_hash, node_id_p, root_node_id_p);
710 }
711 
712 static gint
http_seq_stats_tick_referer(stats_tree * st,const gchar * arg_referer_uri)713 http_seq_stats_tick_referer(stats_tree* st, const gchar* arg_referer_uri)
714 {
715 	gint root_node_id = st_node_requests_by_referer;
716 	gpointer root_node_id_p = GINT_TO_POINTER(st_node_requests_by_referer);
717 	gint referer_node_id;
718 	gpointer referer_node_id_p;
719 	gint referer_parent_node_id;
720 	gpointer referer_parent_node_id_p;
721 	gchar *referer_uri;
722 
723 	/* Tick the referer's URI */
724 	/* Does the node exist? */
725 	if (!wmem_map_lookup_extended(refstats_uri_to_node_id_hash, arg_referer_uri, NULL, &referer_node_id_p)) {
726 		/* The node for the referer didn't already exist, create the mappings */
727 		referer_node_id = tick_stat_node(st, arg_referer_uri, root_node_id, TRUE);
728 		referer_node_id_p = GINT_TO_POINTER(referer_node_id);
729 		referer_parent_node_id_p = root_node_id_p;
730 
731 		referer_uri = wmem_strdup(wmem_file_scope(), arg_referer_uri);
732 		wmem_map_insert(refstats_uri_to_node_id_hash, referer_uri, referer_node_id_p);
733 		wmem_map_insert(refstats_node_id_to_uri_hash, referer_node_id_p, referer_uri);
734 		wmem_map_insert(refstats_node_id_to_parent_node_id_hash, referer_node_id_p, referer_parent_node_id_p);
735 	} else {
736 		/* The node for the referer already exists, tick it */
737 		referer_parent_node_id_p = wmem_map_lookup(refstats_node_id_to_parent_node_id_hash, referer_node_id_p);
738 		referer_parent_node_id = GPOINTER_TO_INT(referer_parent_node_id_p);
739 		referer_node_id = tick_stat_node(st, arg_referer_uri, referer_parent_node_id, TRUE);
740 	}
741 	return referer_node_id;
742 }
743 
744 static void
http_seq_stats_tick_request(stats_tree * st,const gchar * arg_full_uri,gint referer_node_id)745 http_seq_stats_tick_request(stats_tree* st, const gchar* arg_full_uri, gint referer_node_id)
746 {
747 	gpointer referer_node_id_p = GINT_TO_POINTER(referer_node_id);
748 	gint node_id;
749 	gpointer node_id_p;
750 	gchar *uri;
751 
752 	node_id = tick_stat_node(st, arg_full_uri, referer_node_id, TRUE);
753 	node_id_p = GINT_TO_POINTER(node_id);
754 
755 	/* Update the mappings. Even if the URI was already seen, the URI->node mapping may need to be updated */
756 
757 	/* Is this a new node? */
758 	uri = (gchar *) wmem_map_lookup(refstats_node_id_to_uri_hash, node_id_p);
759 	if (!uri) {
760 		/* node not found, add mappings for the node and uri */
761 		uri = wmem_strdup(wmem_file_scope(), arg_full_uri);
762 
763 		wmem_map_insert(refstats_uri_to_node_id_hash, uri, node_id_p);
764 		wmem_map_insert(refstats_node_id_to_uri_hash, node_id_p, uri);
765 		wmem_map_insert(refstats_node_id_to_parent_node_id_hash, node_id_p, referer_node_id_p);
766 	} else {
767 		/* We've seen the node id before. Update the URI mapping refer to this node id*/
768 		wmem_map_insert(refstats_uri_to_node_id_hash, uri, node_id_p);
769 	}
770 }
771 
772 static gchar*
determine_http_location_target(const gchar * base_url,const gchar * location_url)773 determine_http_location_target(const gchar *base_url, const gchar * location_url)
774 {
775 	/* Resolving a base URI + relative URI to an absolute URI ("Relative Resolution")
776 	is complicated. Because of that, we take shortcuts that may result in
777 	inaccurate results, but is also significantly simpler.
778 	It would be best to use an external library to do this for us.
779 	For reference, the RFC is located at https://tools.ietf.org/html/rfc3986#section-5.4
780 
781 	Returns NULL if the resolution fails
782 	*/
783 	gchar *final_target;
784 
785 	/* base_url must be an absolute URL.*/
786 	if (strstr(base_url, "://") == NULL){
787 		return NULL;
788 	}
789 
790 	/* Empty Location */
791 	if (location_url[0] == '\0') {
792 		final_target = wmem_strdup(wmem_packet_scope(), base_url);
793 		return final_target;
794 	}
795 	/* Protocol Relative */
796 	else if (g_str_has_prefix(location_url, "//") ) {
797 		char *base_scheme = g_uri_parse_scheme(base_url);
798 		if (base_scheme == NULL) {
799 			return NULL;
800 		}
801 		final_target = wmem_strdup_printf(wmem_packet_scope(), "%s:%s", base_scheme, location_url);
802 		g_free(base_scheme);
803 		return final_target;
804 	}
805 	/* Absolute URL*/
806 	else if (strstr(location_url, "://") != NULL) {
807 		final_target = wmem_strdup(wmem_packet_scope(), location_url);
808 		return final_target;
809 	}
810 	/* Relative */
811 	else {
812 		gchar *start_fragment = strstr(base_url, "#");
813 		gchar *start_query = NULL;
814 		gchar *base_url_no_fragment = NULL;
815 		gchar *base_url_no_query = NULL;
816 
817 		/* Strip off the fragment (which should never be present)*/
818 		if (start_fragment == NULL) {
819 			base_url_no_fragment = wmem_strdup(wmem_packet_scope(), base_url);
820 		}
821 		else {
822 			base_url_no_fragment = wmem_strndup(wmem_packet_scope(), base_url, start_fragment - base_url);
823 		}
824 
825 		/* Strip off the query (Queries are stripped from all relative URIs) */
826 		start_query = strstr(base_url_no_fragment, "?");
827 		if (start_query == NULL) {
828 			base_url_no_query = wmem_strdup(wmem_packet_scope(), base_url_no_fragment);
829 		}
830 		else {
831 			base_url_no_query = wmem_strndup(wmem_packet_scope(), base_url_no_fragment, start_query - base_url_no_fragment);
832 		}
833 
834 		/* A leading question mark (?) means to replace the old query with the new*/
835 		if (g_str_has_prefix(location_url, "?")) {
836 			final_target = wmem_strdup_printf(wmem_packet_scope(), "%s%s", base_url_no_query, location_url);
837 			return final_target;
838 		}
839 		/* A leading slash means to put the location after the netloc */
840 		else if (g_str_has_prefix(location_url, "/")) {
841 			gchar *scheme_end = strstr(base_url_no_query, "://") + 3;
842 			gchar *netloc_end;
843 			gint netloc_length;
844 			if (scheme_end[0] == '\0') {
845 				return NULL;
846 			}
847 			netloc_end = strstr(scheme_end, "/");
848 			if (netloc_end == NULL) {
849 				return NULL;
850 			}
851 			netloc_length = (gint) (netloc_end - base_url_no_query);
852 			final_target = wmem_strdup_printf(wmem_packet_scope(), "%.*s%s", netloc_length, base_url_no_query, location_url);
853 			return final_target;
854 		}
855 		/* Otherwise, it replaces the last element in the URI */
856 		else {
857 			gchar *scheme_end = strstr(base_url_no_query, "://") + 3;
858 			gchar *end_of_path = g_strrstr(scheme_end, "/");
859 
860 			if (end_of_path != NULL) {
861 				gint base_through_path = (gint) (end_of_path - base_url_no_query);
862 				final_target = wmem_strdup_printf(wmem_packet_scope(), "%.*s/%s", base_through_path, base_url_no_query, location_url);
863 			}
864 			else {
865 				final_target = wmem_strdup_printf(wmem_packet_scope(), "%s/%s", base_url_no_query, location_url);
866 			}
867 
868 			return final_target;
869 		}
870 	}
871 	return NULL;
872 }
873 
874 /* HTTP/Request Sequences stats packet function */
875 static tap_packet_status
http_seq_stats_tree_packet(stats_tree * st,packet_info * pinfo _U_,epan_dissect_t * edt _U_,const void * p)876 http_seq_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p)
877 {
878 	const http_info_value_t* v = (const http_info_value_t*)p;
879 
880 	/* Track HTTP Redirects */
881 	if (v->location_target && v->location_base_uri) {
882 		gint referer_node_id;
883 		gint parent_node_id;
884 		gpointer parent_node_id_p;
885 		gpointer current_node_id_p;
886 		gchar *uri = NULL;
887 
888 		gchar *absolute_target = determine_http_location_target(v->location_base_uri, v->location_target);
889 		/* absolute_target is NULL if the resolution fails */
890 		if (absolute_target != NULL) {
891 			/* We assume the user makes the request to the absolute_target */
892 			/* Tick the base URI */
893 			referer_node_id = http_seq_stats_tick_referer(st, v->location_base_uri);
894 
895 			/* Tick the location header's resolved URI */
896 			http_seq_stats_tick_request(st, absolute_target, referer_node_id);
897 
898 			/* Tick all stats nodes above the location */
899 			current_node_id_p = GINT_TO_POINTER(referer_node_id);
900 			while (wmem_map_lookup_extended(refstats_node_id_to_parent_node_id_hash, current_node_id_p, NULL, &parent_node_id_p)) {
901 				parent_node_id = GPOINTER_TO_INT(parent_node_id_p);
902 				uri = (gchar *) wmem_map_lookup(refstats_node_id_to_uri_hash, current_node_id_p);
903 				tick_stat_node(st, uri, parent_node_id, TRUE);
904 				current_node_id_p = parent_node_id_p;
905 			}
906 		}
907 	}
908 
909 	/* Track HTTP Requests/Referers */
910 	if (v->request_method && v->referer_uri && v->full_uri) {
911 		gint referer_node_id;
912 		gint parent_node_id;
913 		gpointer parent_node_id_p;
914 		gpointer current_node_id_p;
915 		gchar *uri = NULL;
916 		/* Tick the referer's URI */
917 		referer_node_id = http_seq_stats_tick_referer(st, v->referer_uri);
918 
919 		/* Tick the request's URI */
920 		http_seq_stats_tick_request(st, v->full_uri, referer_node_id);
921 
922 		/* Tick all stats nodes above the referer */
923 		current_node_id_p = GINT_TO_POINTER(referer_node_id);
924 		while (wmem_map_lookup_extended(refstats_node_id_to_parent_node_id_hash, current_node_id_p, NULL, &parent_node_id_p)) {
925 			parent_node_id = GPOINTER_TO_INT(parent_node_id_p);
926 			uri = (gchar *) wmem_map_lookup(refstats_node_id_to_uri_hash, current_node_id_p);
927 			tick_stat_node(st, uri, parent_node_id, TRUE);
928 			current_node_id_p = parent_node_id_p;
929 		}
930 	}
931 	return TAP_PACKET_DONT_REDRAW;
932 }
933 
934 
935 static void
dissect_http_ntlmssp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,const char * line)936 dissect_http_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
937 		     const char *line)
938 {
939 	tvbuff_t *ntlmssp_tvb;
940 
941 	ntlmssp_tvb = base64_to_tvb(tvb, line);
942 	add_new_data_source(pinfo, ntlmssp_tvb, "NTLMSSP / GSSAPI Data");
943 	if (tvb_strneql(ntlmssp_tvb, 0, "NTLMSSP", 7) == 0)
944 		call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo, tree);
945 	else
946 		call_dissector(gssapi_handle, ntlmssp_tvb, pinfo, tree);
947 }
948 
949 static void
dissect_http_kerberos(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,const char * line)950 dissect_http_kerberos(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
951 		     const char *line)
952 {
953 	tvbuff_t *kerberos_tvb;
954 
955 	kerberos_tvb = base64_to_tvb(tvb, line + 9); /* skip 'Kerberos ' which is 9 chars */
956 	add_new_data_source(pinfo, kerberos_tvb, "Kerberos Data");
957 	call_dissector(gssapi_handle, kerberos_tvb, pinfo, tree);
958 
959 }
960 
961 
962 static http_conv_t *
get_http_conversation_data(packet_info * pinfo,conversation_t ** conversation)963 get_http_conversation_data(packet_info *pinfo, conversation_t **conversation)
964 {
965 	http_conv_t	*conv_data;
966 
967 	*conversation = find_or_create_conversation(pinfo);
968 
969 	/* Retrieve information from conversation
970 	 * or add it if it isn't there yet
971 	 */
972 	conv_data = (http_conv_t *)conversation_get_proto_data(*conversation, proto_http);
973 	if(!conv_data) {
974 		/* Setup the conversation structure itself */
975 		conv_data = wmem_new0(wmem_file_scope(), http_conv_t);
976 
977 		conversation_add_proto_data(*conversation, proto_http,
978 					    conv_data);
979 	}
980 
981 	return conv_data;
982 }
983 
984 /**
985  * create a new http_req_res_t and add it to the conversation.
986  * @return the new allocated object which is already added to the linked list
987  */
push_req_res(http_conv_t * conv_data)988 static http_req_res_t* push_req_res(http_conv_t *conv_data)
989 {
990 	http_req_res_t *req_res = wmem_new0(wmem_file_scope(), http_req_res_t);
991 	nstime_set_unset(&(req_res->req_ts));
992 	req_res->number = ++conv_data->req_res_num;
993 
994 	if (! conv_data->req_res_tail) {
995 		conv_data->req_res_tail = req_res;
996 	} else {
997 		req_res->prev = conv_data->req_res_tail;
998 		conv_data->req_res_tail->next = req_res;
999 		conv_data->req_res_tail = req_res;
1000 	}
1001 
1002 	return req_res;
1003 }
1004 
1005 /**
1006  * push a request frame number and its time stamp to the conversation data.
1007  */
push_req(http_conv_t * conv_data,packet_info * pinfo)1008 static void push_req(http_conv_t *conv_data, packet_info *pinfo)
1009 {
1010 	/* a request will always create a new http_req_res_t object */
1011 	http_req_res_t *req_res = push_req_res(conv_data);
1012 
1013 	req_res->req_framenum = pinfo->num;
1014 	req_res->req_ts = pinfo->abs_ts;
1015 
1016 	p_add_proto_data(wmem_file_scope(), pinfo, proto_http, 0, req_res);
1017 }
1018 
1019 /**
1020  * push a response frame number to the conversation data.
1021  */
push_res(http_conv_t * conv_data,packet_info * pinfo)1022 static void push_res(http_conv_t *conv_data, packet_info *pinfo)
1023 {
1024 	/* a response will create a new http_req_res_t object: if no
1025 	   object exists, or if one exists for another response. In
1026 	   both cases the corresponding request was not
1027 	   detected/included in the conversation. In all other cases
1028 	   the http_req_res_t object created by the request is
1029 	   used. */
1030 	http_req_res_t *req_res = conv_data->req_res_tail;
1031 	if (!req_res || req_res->res_framenum > 0) {
1032 		req_res = push_req_res(conv_data);
1033 	}
1034 	req_res->res_framenum = pinfo->num;
1035 	p_add_proto_data(wmem_file_scope(), pinfo, proto_http, 0, req_res);
1036 }
1037 
1038 /*
1039  * TODO: remove this ugly global variable.
1040  * XXX: do we really want to have to pass this from one function to another?
1041  */
1042 static http_info_value_t	*stat_info;
1043 
1044 static int
dissect_http_message(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,http_conv_t * conv_data,const char * proto_tag,int proto,gboolean end_of_stream)1045 dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
1046 		     proto_tree *tree, http_conv_t *conv_data,
1047 		     const char* proto_tag, int proto, gboolean end_of_stream)
1048 {
1049 	proto_tree	*http_tree = NULL;
1050 	proto_item	*ti = NULL;
1051 	proto_item	*hidden_item;
1052 	const guchar	*line, *firstline;
1053 	gint		next_offset;
1054 	const guchar	*linep, *lineend;
1055 	int		orig_offset;
1056 	int		first_linelen, linelen;
1057 	gboolean	is_request_or_reply, is_tls = FALSE;
1058 	gboolean	saw_req_resp_or_header;
1059 	http_type_t     http_type;
1060 	proto_item	*hdr_item = NULL;
1061 	ReqRespDissector reqresp_dissector;
1062 	proto_tree	*req_tree;
1063 	int		colon_offset;
1064 	headers_t	headers;
1065 	int		datalen;
1066 	int		reported_datalen = -1;
1067 	dissector_handle_t handle;
1068 	gboolean	dissected = FALSE;
1069 	gboolean	first_loop = TRUE;
1070 	gboolean	have_seen_http = FALSE;
1071 	/*guint		i;*/
1072 	/*http_info_value_t *si;*/
1073 	http_eo_t       *eo_info;
1074 	heur_dtbl_entry_t *hdtbl_entry;
1075 	int reported_length;
1076 	guint16 word;
1077 	gboolean	leading_crlf = FALSE;
1078 	http_message_info_t message_info;
1079 
1080 	reported_length = tvb_reported_length_remaining(tvb, offset);
1081 	if (reported_length < 1) {
1082 		return -1;
1083 	}
1084 
1085 	/* RFC 2616
1086 	 *   In the interest of robustness, servers SHOULD ignore any empty
1087 	 *   line(s) received where a Request-Line is expected. In other words, if
1088 	 *   the server is reading the protocol stream at the beginning of a
1089 	 *   message and receives a CRLF first, it should ignore the CRLF.
1090 	 */
1091 	if (reported_length > 3) {
1092 		word = tvb_get_ntohs(tvb,offset);
1093 		if (word == 0x0d0a) {
1094 			leading_crlf = TRUE;
1095 			offset += 2;
1096 		}
1097 	}
1098 
1099 	/*
1100 	 * If we previously dissected an HTTP request in this conversation then
1101 	 * we should be pretty sure that whatever we got in this TVB is
1102 	 * actually HTTP (even if what we have here is part of a file being
1103 	 * transferred over HTTP).
1104 	 */
1105 	if (conv_data->request_uri)
1106 		have_seen_http = TRUE;
1107 
1108 	/*
1109 	 * If this is binary data then there's no point in doing all the string
1110 	 * operations below: they'll just be slow on this data.
1111 	 */
1112 	if (!g_ascii_isprint(tvb_get_guint8(tvb, offset))) {
1113 		/*
1114 		 * But, if we've seen some real HTTP then we're sure this is
1115 		 * an HTTP conversation.  Mark it as such.
1116 		 */
1117 		if (have_seen_http) {
1118 			col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);
1119 			col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1120 			ti = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA);
1121 			http_tree = proto_item_add_subtree(ti, ett_http);
1122 
1123 			call_data_dissector(tvb, pinfo, http_tree);
1124 		}
1125 		return -1;
1126 	}
1127 
1128 	/*
1129 	 * Is this a request or response?
1130 	 *
1131 	 * Note that "tvb_find_line_end()" will return a value that
1132 	 * is not longer than what's in the buffer, so the
1133 	 * "tvb_get_ptr()" call won't throw an exception.
1134 	 */
1135 	first_linelen = tvb_find_line_end(tvb, offset,
1136 	    tvb_ensure_captured_length_remaining(tvb, offset), &next_offset,
1137 	    TRUE);
1138 
1139 	if (first_linelen == -1) {
1140 		/* No complete line was found in this segment, do
1141 		 * desegmentation if we're told to.
1142 		 */
1143 		if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
1144 		    http_desegment_headers, http_desegment_body, FALSE)) {
1145 			/*
1146 			 * More data needed for desegmentation.
1147 			 */
1148 			return -1;
1149 		}
1150 	}
1151 
1152 	/*
1153 	 * Is the first line a request or response?
1154 	 *
1155 	 * Note that "tvb_find_line_end()" will return a value that
1156 	 * is not longer than what's in the buffer, so the
1157 	 * "tvb_get_ptr()" call won't throw an exception.
1158 	 */
1159 	firstline = tvb_get_ptr(tvb, offset, first_linelen);
1160 	http_type = HTTP_OTHERS;	/* type not known yet */
1161 	is_request_or_reply = is_http_request_or_reply((const gchar *)firstline,
1162 	    first_linelen, &http_type, NULL, conv_data);
1163 	if (is_request_or_reply) {
1164 		gboolean try_desegment_body;
1165 
1166 		/*
1167 		 * Yes, it's a request or response.
1168 		 * Put the first line from the buffer into the summary
1169 		 * (but leave out the line terminator).
1170 		 */
1171 		col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", format_text(wmem_packet_scope(), firstline, first_linelen));
1172 
1173 		/*
1174 		 * Do header desegmentation if we've been told to,
1175 		 * and do body desegmentation if we've been told to and
1176 		 * we find a Content-Length header in requests.
1177 		 *
1178 		 * The following cases (from RFC 7230, Section 3.3) never have a
1179 		 * response body, so do not attempt to desegment the body for:
1180 		 * * Responses to HEAD requests.
1181 		 * * 2xx responses to CONNECT requests.
1182 		 * * 1xx, 204 No Content, 304 Not Modified responses.
1183 		 *
1184 		 * Additionally if we are at the end of stream, no more segments
1185 		 * will be added so disable body segmentation too in that case.
1186 		 */
1187 		try_desegment_body = (http_desegment_body && !end_of_stream);
1188 		if (try_desegment_body && http_type == HTTP_RESPONSE) {
1189 			/*
1190 			 * conv_data->response_code is not yet set, so extract
1191 			 * the response code from the current line.
1192 			 */
1193 			gint response_code = parse_http_status_code(firstline, firstline + first_linelen);
1194 			if ((g_strcmp0(conv_data->request_method, "HEAD") == 0 ||
1195 				(response_code / 100 == 2 &&
1196 					(g_strcmp0(conv_data->request_method, "CONNECT") == 0 ||
1197 					 g_strcmp0(conv_data->request_method, "SSTP_DUPLEX_POST") == 0)) ||
1198 				response_code / 100 == 1 ||
1199 				response_code == 204 ||
1200 				response_code == 304)) {
1201 				/* No response body is present. */
1202 				try_desegment_body = FALSE;
1203 			}
1204 		}
1205 		if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
1206 		    http_desegment_headers, try_desegment_body, http_type == HTTP_RESPONSE)) {
1207 			/*
1208 			 * More data needed for desegmentation.
1209 			 */
1210 			return -1;
1211 		}
1212 	} else if (have_seen_http) {
1213 		 /*
1214 		  * If we know this is HTTP then call it continuation.
1215 		  */
1216 		col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1217 	}
1218 
1219 	if (is_request_or_reply || have_seen_http) {
1220 		/*
1221 		 * Now set COL_PROTOCOL and create the http tree for the
1222 		 * cases where we set COL_INFO above.
1223 		 */
1224 		col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);
1225 		ti = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA);
1226 		http_tree = proto_item_add_subtree(ti, ett_http);
1227 
1228 		if (leading_crlf) {
1229 			proto_tree_add_expert(http_tree, pinfo, &ei_http_leading_crlf, tvb, offset-2, 2);
1230 		}
1231 	}
1232 
1233 	is_tls = proto_is_frame_protocol(pinfo->layers, "tls");
1234 
1235 	stat_info = wmem_new(wmem_packet_scope(), http_info_value_t);
1236 	stat_info->framenum = pinfo->num;
1237 	stat_info->response_code = 0;
1238 	stat_info->request_method = NULL;
1239 	stat_info->request_uri = NULL;
1240 	stat_info->referer_uri = NULL;
1241 	stat_info->http_host = NULL;
1242 	stat_info->full_uri = NULL;
1243 	stat_info->location_target = NULL;
1244 	stat_info->location_base_uri = NULL;
1245 
1246 	orig_offset = offset;
1247 
1248 	/*
1249 	 * Process the packet data, a line at a time.
1250 	 */
1251 	http_type = HTTP_OTHERS;	/* type not known yet */
1252 	headers.content_type = NULL;	/* content type not known yet */
1253 	headers.content_type_parameters = NULL;	/* content type parameters too */
1254 	headers.have_content_length = FALSE;	/* content length not known yet */
1255 	headers.content_length = 0;		/* content length set to 0 (avoid a gcc warning) */
1256 	headers.content_encoding = NULL; /* content encoding not known yet */
1257 	headers.transfer_encoding_chunked = FALSE;
1258 	headers.transfer_encoding = HTTP_TE_NONE;
1259 	headers.upgrade = NULL;         /* assume no upgrade header */
1260 	saw_req_resp_or_header = FALSE;	/* haven't seen anything yet */
1261 	while (tvb_offset_exists(tvb, offset)) {
1262 		/*
1263 		 * Find the end of the line.
1264 		 * XXX - what if we don't find it because the packet
1265 		 * is cut short by a snapshot length or the header is
1266 		 * split across TCP segments?  How much dissection should
1267 		 * we do on it?
1268 		 */
1269 		linelen = tvb_find_line_end(tvb, offset,
1270 		    tvb_ensure_captured_length_remaining(tvb, offset), &next_offset,
1271 		    FALSE);
1272 		if (linelen < 0)
1273 			return -1;
1274 
1275 		/*
1276 		 * Get a buffer that refers to the line.
1277 		 *
1278 		 * Note that "tvb_find_line_end()" will return a value that
1279 		 * is not longer than what's in the buffer, so the
1280 		 * "tvb_get_ptr()" call won't throw an exception.
1281 		 */
1282 		line = tvb_get_ptr(tvb, offset, linelen);
1283 		lineend = line + linelen;
1284 		colon_offset = -1;
1285 
1286 		/*
1287 		 * OK, does it look like an HTTP request or response?
1288 		 */
1289 		reqresp_dissector = NULL;
1290 		is_request_or_reply =
1291 		    is_http_request_or_reply((const gchar *)line,
1292 		    linelen, &http_type, &reqresp_dissector, conv_data);
1293 		if (is_request_or_reply)
1294 			goto is_http;
1295 
1296 		/*
1297 		 * No.  Does it look like a blank line (as would appear
1298 		 * at the end of an HTTP request)?
1299 		 */
1300 		if (linelen == 0)
1301 			goto is_http;	/* Yes. */
1302 
1303 		/*
1304 		 * No.  Does it look like a header?
1305 		 */
1306 		colon_offset = offset;
1307 
1308 		linep = (const guchar *)memchr(line, ':', linelen);
1309 		if (linep) {
1310 			/*
1311 			 * Colon found, assume it is a header.
1312 			 */
1313 			colon_offset += (int)(linep - line);
1314 			goto is_http;
1315 		}
1316 
1317 		/*
1318 		 * We haven't seen the colon yet.
1319 		 *
1320 		 * If we've already seen an HTTP request or response
1321 		 * line, or a header line, and we're at the end of
1322 		 * the tvbuff, we assume this is an incomplete header
1323 		 * line.  (We quit this loop after seeing a blank line,
1324 		 * so if we've seen a request or response line, or a
1325 		 * header line, this is probably more of the request
1326 		 * or response we're presumably seeing.  There is some
1327 		 * risk of false positives, but the same applies for
1328 		 * full request or response lines or header lines,
1329 		 * although that's less likely.)
1330 		 *
1331 		 * We throw an exception in that case, by checking for
1332 		 * the existence of the next byte after the last one
1333 		 * in the line.  If it exists, "tvb_ensure_bytes_exist()"
1334 		 * throws no exception, and we fall through to the
1335 		 * "not HTTP" case.  If it doesn't exist,
1336 		 * "tvb_ensure_bytes_exist()" will throw the appropriate
1337 		 * exception.
1338 		 */
1339 		if (saw_req_resp_or_header)
1340 			tvb_ensure_bytes_exist(tvb, offset, linelen + 1);
1341 
1342 		/*
1343 		 * We don't consider this part of an HTTP request or
1344 		 * reply, so we don't display it.
1345 		 * (Yeah, that means we don't display, say, a text/http
1346 		 * page, but you can get that from the data pane.)
1347 		 */
1348 		break;
1349 
1350 	is_http:
1351 		if ((tree) && (http_tree == NULL)) {
1352 			ti = proto_tree_add_item(tree, proto, tvb, orig_offset, -1, ENC_NA);
1353 			http_tree = proto_item_add_subtree(ti, ett_http);
1354 			if (leading_crlf) {
1355 				proto_tree_add_expert(http_tree, pinfo, &ei_http_leading_crlf, tvb, orig_offset-2, 2);
1356 			}
1357 		}
1358 
1359 		if (first_loop && !is_tls && pinfo->ptype == PT_TCP &&
1360 				(pinfo->srcport == 443 || pinfo->destport == 443)) {
1361 			expert_add_info(pinfo, ti, &ei_http_tls_port);
1362 		}
1363 
1364 		first_loop = FALSE;
1365 
1366 		/*
1367 		 * Process this line.
1368 		 */
1369 
1370 		if (linelen == 0) {
1371 			/*
1372 			 * This is a blank line, which means that
1373 			 * whatever follows it isn't part of this
1374 			 * request or reply.
1375 			 */
1376 			proto_tree_add_format_text(http_tree, tvb, offset, next_offset - offset);
1377 			offset = next_offset;
1378 			break;
1379 		}
1380 
1381 		/*
1382 		 * Not a blank line - either a request, a reply, or a header
1383 		 * line.
1384 		 */
1385 		saw_req_resp_or_header = TRUE;
1386 		if (is_request_or_reply) {
1387 			char *text = tvb_format_text(pinfo->pool, tvb, offset, next_offset - offset);
1388 
1389 			req_tree = proto_tree_add_subtree(http_tree, tvb,
1390 				    offset, next_offset - offset, ett_http_request, &hdr_item, text);
1391 
1392 			expert_add_info_format(pinfo, hdr_item, &ei_http_chat, "%s", text);
1393 			if (reqresp_dissector) {
1394 				reqresp_dissector(tvb, req_tree, offset, line,
1395 						  lineend, conv_data);
1396 			}
1397 		} else {
1398 			/*
1399 			 * Header.
1400 			 */
1401 			process_header(tvb, offset, next_offset, line, linelen,
1402 			    colon_offset, pinfo, http_tree, &headers, conv_data,
1403 			    http_type);
1404 		}
1405 		offset = next_offset;
1406 	}
1407 	if (stat_info->http_host && stat_info->request_uri) {
1408 		proto_item *e_ti;
1409 		gchar      *uri;
1410 
1411 		if ((g_ascii_strncasecmp(stat_info->request_uri, "http://", 7) == 0) ||
1412 		    (g_ascii_strncasecmp(stat_info->request_uri, "https://", 8) == 0) ||
1413 		    (g_ascii_strncasecmp(conv_data->request_method, "CONNECT", 7) == 0)) {
1414 			uri = wmem_strdup(wmem_packet_scope(), stat_info->request_uri);
1415 		}
1416 		else {
1417 			uri = wmem_strdup_printf(wmem_packet_scope(), "%s://%s%s",
1418 				    is_tls ? "https" : "http",
1419 				    g_strstrip(wmem_strdup(wmem_packet_scope(), stat_info->http_host)), stat_info->request_uri);
1420 		}
1421 		stat_info->full_uri = wmem_strdup(wmem_packet_scope(), uri);
1422 		conv_data->full_uri = wmem_strdup(wmem_file_scope(), uri);
1423 		if (tree) {
1424 			e_ti = proto_tree_add_string(http_tree,
1425 					     hf_http_request_full_uri, tvb, 0,
1426 					     0, uri);
1427 
1428 			proto_item_set_url(e_ti);
1429 			proto_item_set_generated(e_ti);
1430 		}
1431 	}
1432 
1433 	if (!PINFO_FD_VISITED(pinfo)) {
1434 		if (http_type == HTTP_REQUEST) {
1435 			push_req(conv_data, pinfo);
1436 		} else if (http_type == HTTP_RESPONSE) {
1437 			push_res(conv_data, pinfo);
1438 		}
1439 	}
1440 
1441 	if (tree) {
1442 		proto_item *pi;
1443 		http_req_res_t *curr = (http_req_res_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_http, 0);
1444 		http_req_res_t *prev = curr ? curr->prev : NULL;
1445 		http_req_res_t *next = curr ? curr->next : NULL;
1446 
1447 		switch (http_type) {
1448 
1449 		case HTTP_NOTIFICATION:
1450 			hidden_item = proto_tree_add_boolean(http_tree,
1451 					    hf_http_notification, tvb, 0, 0, 1);
1452 			proto_item_set_hidden(hidden_item);
1453 			break;
1454 
1455 		case HTTP_RESPONSE:
1456 			hidden_item = proto_tree_add_boolean(http_tree,
1457 					    hf_http_response, tvb, 0, 0, 1);
1458 			proto_item_set_hidden(hidden_item);
1459 
1460 			if (curr) {
1461 				nstime_t delta;
1462 
1463 				pi = proto_tree_add_uint_format(http_tree, hf_http_response_number, tvb, 0, 0, curr->number, "HTTP response %u/%u", curr->number, conv_data->req_res_num);
1464 				proto_item_set_generated(pi);
1465 
1466 				if (! nstime_is_unset(&(curr->req_ts))) {
1467 					nstime_delta(&delta, &pinfo->abs_ts, &(curr->req_ts));
1468 					pi = proto_tree_add_time(http_tree, hf_http_time, tvb, 0, 0, &delta);
1469 					proto_item_set_generated(pi);
1470 				}
1471 			}
1472 			if (prev && prev->req_framenum) {
1473 				pi = proto_tree_add_uint(http_tree, hf_http_prev_request_in, tvb, 0, 0, prev->req_framenum);
1474 				proto_item_set_generated(pi);
1475 			}
1476 			if (prev && prev->res_framenum) {
1477 				pi = proto_tree_add_uint(http_tree, hf_http_prev_response_in, tvb, 0, 0, prev->res_framenum);
1478 				proto_item_set_generated(pi);
1479 			}
1480 			if (curr && curr->req_framenum) {
1481 				pi = proto_tree_add_uint(http_tree, hf_http_request_in, tvb, 0, 0, curr->req_framenum);
1482 				proto_item_set_generated(pi);
1483 			}
1484 			if (next && next->req_framenum) {
1485 				pi = proto_tree_add_uint(http_tree, hf_http_next_request_in, tvb, 0, 0, next->req_framenum);
1486 				proto_item_set_generated(pi);
1487 			}
1488 			if (next && next->res_framenum) {
1489 				pi = proto_tree_add_uint(http_tree, hf_http_next_response_in, tvb, 0, 0, next->res_framenum);
1490 				proto_item_set_generated(pi);
1491 			}
1492 
1493 			/*
1494 			 * add the request URI to the response to allow filtering responses filtered by URI
1495 			 */
1496 			if (conv_data && (conv_data->full_uri || conv_data->request_uri)) {
1497 				if (conv_data->full_uri) {
1498 					pi = proto_tree_add_string(http_tree, hf_http_response_for_uri, tvb, 0, 0, conv_data->full_uri);
1499 				}
1500 				else {
1501 					pi = proto_tree_add_string(http_tree, hf_http_response_for_uri, tvb, 0, 0, conv_data->request_uri);
1502 				}
1503 				proto_item_set_generated(pi);
1504 			}
1505 
1506 			break;
1507 
1508 		case HTTP_REQUEST:
1509 			hidden_item = proto_tree_add_boolean(http_tree,
1510 					    hf_http_request, tvb, 0, 0, 1);
1511 			proto_item_set_hidden(hidden_item);
1512 
1513 			if (curr) {
1514 				pi = proto_tree_add_uint_format(http_tree, hf_http_request_number, tvb, 0, 0, curr->number, "HTTP request %u/%u", curr->number, conv_data->req_res_num);
1515 				proto_item_set_generated(pi);
1516 			}
1517 			if (prev && prev->req_framenum) {
1518 				pi = proto_tree_add_uint(http_tree, hf_http_prev_request_in, tvb, 0, 0, prev->req_framenum);
1519 				proto_item_set_generated(pi);
1520 			}
1521 			if (curr && curr->res_framenum) {
1522 				pi = proto_tree_add_uint(http_tree, hf_http_response_in, tvb, 0, 0, curr->res_framenum);
1523 				proto_item_set_generated(pi);
1524 			}
1525 			if (next && next->req_framenum) {
1526 				pi = proto_tree_add_uint(http_tree, hf_http_next_request_in, tvb, 0, 0, next->req_framenum);
1527 				proto_item_set_generated(pi);
1528 			}
1529 
1530 			break;
1531 
1532 		case HTTP_OTHERS:
1533 		default:
1534 			break;
1535 		}
1536 	}
1537 
1538 	/* Give the follw tap what we've currently dissected */
1539 	if(have_tap_listener(http_follow_tap)) {
1540 		tap_queue_packet(http_follow_tap, pinfo, tvb_new_subset_length(tvb, 0, offset));
1541 	}
1542 
1543 	reported_datalen = tvb_reported_length_remaining(tvb, offset);
1544 	datalen = tvb_captured_length_remaining(tvb, offset);
1545 
1546 	/*
1547 	 * If a content length was supplied, the amount of data to be
1548 	 * processed as HTTP payload is the minimum of the content
1549 	 * length and the amount of data remaining in the frame.
1550 	 *
1551 	 * If a message is received with both a Transfer-Encoding
1552 	 * header field and a Content-Length header field, the latter
1553 	 * MUST be ignored.
1554 	 *
1555 	 * If no content length was supplied (or if a bad content length
1556 	 * was supplied), the amount of data to be processed is the amount
1557 	 * of data remaining in the frame.
1558 	 *
1559 	 * If there was no Content-Length entity header, we should
1560 	 * accumulate all data until the end of the connection.
1561 	 * That'd require that the TCP dissector call subdissectors
1562 	 * for all frames with FIN, even if they contain no data,
1563 	 * which would require subdissectors to deal intelligently
1564 	 * with empty segments.
1565 	 *
1566 	 * According to RFC 2616, however, 1xx responses, 204 responses,
1567 	 * and 304 responses MUST NOT include a message body; if no
1568 	 * content length is specified for them, we don't attempt to
1569 	 * dissect the body.
1570 	 *
1571 	 * XXX - it says the same about responses to HEAD requests;
1572 	 * unless there's a way to determine from the response
1573 	 * whether it's a response to a HEAD request, we have to
1574 	 * keep information about the request and associate that with
1575 	 * the response in order to handle that.
1576 	 */
1577 	if (headers.have_content_length &&
1578 	    headers.transfer_encoding == HTTP_TE_NONE) {
1579 		if (datalen > headers.content_length)
1580 			datalen = (int)headers.content_length;
1581 
1582 		/*
1583 		 * XXX - limit the reported length in the tvbuff we'll
1584 		 * hand to a subdissector to be no greater than the
1585 		 * content length.
1586 		 *
1587 		 * We really need both unreassembled and "how long it'd
1588 		 * be if it were reassembled" lengths for tvbuffs, so
1589 		 * that we throw the appropriate exceptions for
1590 		 * "not enough data captured" (running past the length),
1591 		 * "packet needed reassembly" (within the length but
1592 		 * running past the unreassembled length), and
1593 		 * "packet is malformed" (running past the reassembled
1594 		 * length).
1595 		 */
1596 		if (reported_datalen > headers.content_length)
1597 			reported_datalen = (int)headers.content_length;
1598 	} else {
1599 		switch (http_type) {
1600 
1601 		case HTTP_REQUEST:
1602 			/*
1603 			 * Requests have no content if there's no
1604 			 * Content-Length header and no Transfer-Encoding
1605 			 * header.
1606 			 */
1607 			if (headers.transfer_encoding == HTTP_TE_NONE)
1608 				datalen = 0;
1609 			else
1610 				reported_datalen = -1;
1611 			break;
1612 
1613 		case HTTP_RESPONSE:
1614 			if ((stat_info->response_code/100) == 1 ||
1615 			    stat_info->response_code == 204 ||
1616 			    stat_info->response_code == 304)
1617 				datalen = 0;	/* no content! */
1618 			else {
1619 				/*
1620 				 * XXX - responses to HEAD requests,
1621 				 * and possibly other responses,
1622 				 * "MUST NOT" include a
1623 				 * message-body.
1624 				 */
1625 				reported_datalen = -1;
1626 			}
1627 			break;
1628 
1629 		default:
1630 			/*
1631 			 * XXX - what about HTTP_NOTIFICATION?
1632 			 */
1633 			reported_datalen = -1;
1634 			break;
1635 		}
1636 	}
1637 
1638 	if (datalen > 0) {
1639 		/*
1640 		 * There's stuff left over; process it.
1641 		 */
1642 		tvbuff_t *next_tvb;
1643 		guint chunked_datalen = 0;
1644 		char *media_str = NULL;
1645 		const gchar *file_data;
1646 
1647 		/*
1648 		 * Create a tvbuff for the payload.
1649 		 *
1650 		 * The amount of data to be processed that's
1651 		 * available in the tvbuff is "datalen", which
1652 		 * is the minimum of the amount of data left in
1653 		 * the tvbuff and any specified content length.
1654 		 *
1655 		 * The amount of data to be processed that's in
1656 		 * this frame, regardless of whether it was
1657 		 * captured or not, is "reported_datalen",
1658 		 * which, if no content length was specified,
1659 		 * is -1, i.e. "to the end of the frame.
1660 		 */
1661 		next_tvb = tvb_new_subset_length_caplen(tvb, offset, datalen,
1662 		    reported_datalen);
1663 
1664 		/*
1665 		 * Handle *transfer* encodings.
1666 		 */
1667 		if (headers.transfer_encoding_chunked) {
1668 			if (!http_dechunk_body) {
1669 				/* Chunking disabled, cannot dissect further. */
1670 				call_data_dissector(next_tvb, pinfo, http_tree);
1671 				goto body_dissected;
1672 			}
1673 
1674 			chunked_datalen = chunked_encoding_dissector(
1675 			    &next_tvb, pinfo, http_tree, 0);
1676 
1677 			if (chunked_datalen == 0) {
1678 				/*
1679 				 * The chunks weren't reassembled,
1680 				 * or there was a single zero
1681 				 * length chunk.
1682 				 */
1683 				goto body_dissected;
1684 			} else {
1685 				/*
1686 				 * Add a new data source for the
1687 				 * de-chunked data.
1688 				 */
1689 #if 0 /* Handled in chunked_encoding_dissector() */
1690 				tvb_set_child_real_data_tvbuff(tvb,
1691 					next_tvb);
1692 #endif
1693 				add_new_data_source(pinfo, next_tvb,
1694 					"De-chunked entity body");
1695 				/* chunked-body might be smaller than
1696 				 * datalen. */
1697 				datalen = chunked_datalen;
1698 			}
1699 		}
1700 		/* Handle other transfer codings after de-chunking. */
1701 		switch (headers.transfer_encoding) {
1702 		case HTTP_TE_COMPRESS:
1703 		case HTTP_TE_DEFLATE:
1704 		case HTTP_TE_GZIP:
1705 			/*
1706 			 * We currently can't handle, for example, "gzip",
1707 			 * "compress", or "deflate" as *transfer* encodings;
1708 			 * just handle them as data for now.
1709 			 */
1710 			call_data_dissector(next_tvb, pinfo, http_tree);
1711 			goto body_dissected;
1712 		default:
1713 			/* Nothing to do for "identity" or when header is
1714 			 * missing or invalid. */
1715 			break;
1716 		}
1717 		/*
1718 		 * At this point, any chunked *transfer* coding has been removed
1719 		 * (the entity body has been dechunked) so it can be presented
1720 		 * for the following operation (*content* encoding), or it has
1721 		 * been been handed off to the data dissector.
1722 		 *
1723 		 * Handle *content* encodings other than "identity" (which
1724 		 * shouldn't appear in a Content-Encoding header, but
1725 		 * we handle it in any case).
1726 		 */
1727 		if (headers.content_encoding != NULL &&
1728 		    g_ascii_strcasecmp(headers.content_encoding, "identity") != 0) {
1729 			/*
1730 			 * We currently don't handle, for example, "compress";
1731 			 * just handle them as data for now.
1732 			 *
1733 			 * After July 7, 2004 the LZW patent expired, so
1734 			 * support could be added.  However, I don't think
1735 			 * that anybody ever really implemented "compress",
1736 			 * due to the aforementioned patent.
1737 			 */
1738 			tvbuff_t *uncomp_tvb = NULL;
1739 			proto_item *e_ti = NULL;
1740 			proto_tree *e_tree = NULL;
1741 
1742 #ifdef HAVE_ZLIB
1743 			if (http_decompress_body &&
1744 			    (g_ascii_strcasecmp(headers.content_encoding, "gzip") == 0 ||
1745 			     g_ascii_strcasecmp(headers.content_encoding, "deflate") == 0 ||
1746 			     g_ascii_strcasecmp(headers.content_encoding, "x-gzip") == 0 ||
1747 			     g_ascii_strcasecmp(headers.content_encoding, "x-deflate") == 0))
1748 			{
1749 				uncomp_tvb = tvb_child_uncompress(tvb, next_tvb, 0,
1750 				    tvb_captured_length(next_tvb));
1751 			}
1752 #endif
1753 
1754 #ifdef HAVE_BROTLI
1755 			if (http_decompress_body &&
1756 			    g_ascii_strcasecmp(headers.content_encoding, "br") == 0)
1757 			{
1758 				uncomp_tvb = tvb_child_uncompress_brotli(tvb, next_tvb, 0,
1759 				    tvb_captured_length(next_tvb));
1760 			}
1761 #endif
1762 
1763 			/*
1764 			 * Add the encoded entity to the protocol tree
1765 			 */
1766 			e_tree = proto_tree_add_subtree_format(http_tree, next_tvb,
1767 					0, tvb_captured_length(next_tvb), ett_http_encoded_entity, &e_ti,
1768 					"Content-encoded entity body (%s): %u bytes",
1769 					headers.content_encoding,
1770 					tvb_captured_length(next_tvb));
1771 
1772 			if (uncomp_tvb != NULL) {
1773 				/*
1774 				 * Decompression worked
1775 				 */
1776 
1777 				/* XXX - Don't free this, since it's possible
1778 				 * that the data was only partially
1779 				 * decompressed, such as when desegmentation
1780 				 * isn't enabled.
1781 				 *
1782 				tvb_free(next_tvb);
1783 				*/
1784 				proto_item_append_text(e_ti, " -> %u bytes", tvb_captured_length(uncomp_tvb));
1785 				next_tvb = uncomp_tvb;
1786 				add_new_data_source(pinfo, next_tvb,
1787 				    "Uncompressed entity body");
1788 			} else {
1789 #if defined(HAVE_ZLIB) || defined(HAVE_BROTLI)
1790 				if (http_decompress_body) {
1791 					expert_add_info(pinfo, e_ti, &ei_http_decompression_failed);
1792 				}
1793 				else {
1794 					expert_add_info(pinfo, e_ti, &ei_http_decompression_disabled);
1795 				}
1796 #endif
1797 				call_data_dissector(next_tvb, pinfo, e_tree);
1798 
1799 				goto body_dissected;
1800 			}
1801 		}
1802 		/*
1803 		 * Note that a new data source is added for the entity body
1804 		 * only if it was content-encoded and/or transfer-encoded.
1805 		 */
1806 
1807 		/* Save values for the Export Object GUI feature if we have
1808 		 * an active listener to process it (which happens when
1809 		 * the export object window is open). */
1810 		if(have_tap_listener(http_eo_tap)) {
1811 			eo_info = wmem_new(wmem_packet_scope(), http_eo_t);
1812 
1813 			eo_info->hostname = conv_data->http_host;
1814 			eo_info->filename = conv_data->request_uri;
1815 			eo_info->content_type = headers.content_type;
1816 			eo_info->payload_len = tvb_captured_length(next_tvb);
1817 			eo_info->payload_data = tvb_get_ptr(next_tvb, 0, eo_info->payload_len);
1818 
1819 			tap_queue_packet(http_eo_tap, pinfo, eo_info);
1820 		}
1821 
1822 		/* Save values for the Export Object GUI feature if we have
1823 		 * an active listener to process it (which happens when
1824 		 * the export object window is open). */
1825 		if(have_tap_listener(http_follow_tap)) {
1826 			tap_queue_packet(http_follow_tap, pinfo, next_tvb);
1827 		}
1828 		file_data = tvb_get_string_enc(wmem_packet_scope(), next_tvb, 0, tvb_captured_length(next_tvb), ENC_ASCII);
1829 		proto_tree_add_string_format_value(http_tree, hf_http_file_data,
1830 			next_tvb, 0, tvb_captured_length(next_tvb), file_data, "%u bytes", tvb_captured_length(next_tvb));
1831 
1832 		if (tvb_captured_length(next_tvb) == 0)
1833 			goto body_dissected;
1834 
1835 		/*
1836 		 * Do subdissector checks.
1837 		 *
1838 		 * First, if we have a Content-Type value, check whether
1839 		 * there's a subdissector for that media type.
1840 		 */
1841 		handle = NULL;
1842 		if (headers.content_type != NULL) {
1843 			/*
1844 			 * We didn't find any subdissector that
1845 			 * registered for the port, and we have a
1846 			 * Content-Type value.  Is there any subdissector
1847 			 * for that content type?
1848 			 */
1849 			if (headers.content_type_parameters)
1850 				media_str = wmem_strdup(wmem_packet_scope(), headers.content_type_parameters);
1851 
1852 			/*
1853 			 * Calling the string handle for the media type
1854 			 * dissector table will set pinfo->match_string
1855 			 * to headers.content_type for us.
1856 			 */
1857 			pinfo->match_string = headers.content_type;
1858 			handle = dissector_get_string_handle(
1859 			    media_type_subdissector_table,
1860 			    headers.content_type);
1861 			if (handle == NULL &&
1862 			    strncmp(headers.content_type, "multipart/", sizeof("multipart/")-1) == 0) {
1863 				/* Try to decode the unknown multipart subtype anyway */
1864 				handle = dissector_get_string_handle(
1865 				    media_type_subdissector_table,
1866 				    "multipart/");
1867 			}
1868 		}
1869 
1870 		/*
1871 		 * Now, if we didn't find such a subdissector, check
1872 		 * whether some subdissector asked that they be called
1873 		 * if HTTP traffic was on some particular port.  This
1874 		 * handles protocols that use HTTP syntax but don't have
1875 		 * a media type and instead use a specified port.
1876 		 */
1877 		if (handle == NULL) {
1878 			handle = dissector_get_uint_handle(port_subdissector_table,
1879 			    pinfo->match_uint);
1880 		}
1881 
1882 		message_info.type = http_type;
1883 		message_info.media_str = media_str;
1884 		if (handle != NULL) {
1885 			/*
1886 			 * We have a subdissector - call it.
1887 			 */
1888 			dissected = call_dissector_only(handle, next_tvb, pinfo, tree, &message_info);
1889 			if (!dissected)
1890 				expert_add_info(pinfo, http_tree, &ei_http_subdissector_failed);
1891 		}
1892 
1893 		if (!dissected) {
1894 			/*
1895 			 * We don't have a subdissector or we have one and it did not
1896 			 * dissect the payload - try the heuristic subdissectors.
1897 			 */
1898 			dissected = dissector_try_heuristic(heur_subdissector_list,
1899 							    next_tvb, pinfo, tree, &hdtbl_entry, NULL);
1900 		}
1901 
1902 		if (dissected) {
1903 			/*
1904 			 * The subdissector dissected the body.
1905 			 * Fix up the top-level item so that it doesn't
1906 			 * include the stuff for that protocol.
1907 			 */
1908 			if (ti != NULL)
1909 				proto_item_set_len(ti, offset);
1910 		} else {
1911 			if (headers.content_type != NULL) {
1912 				/*
1913 				 * Calling the default media handle if there is a content-type that
1914 				 * wasn't handled above.
1915 				 */
1916 				call_dissector_with_data(media_handle, next_tvb, pinfo, tree, &message_info);
1917 			} else {
1918 				/* Call the default data dissector */
1919 				call_data_dissector(next_tvb, pinfo, http_tree);
1920 			}
1921 		}
1922 
1923 	body_dissected:
1924 		/*
1925 		 * We've processed "datalen" bytes worth of data
1926 		 * (which may be no data at all); advance the
1927 		 * offset past whatever data we've processed.
1928 		 */
1929 		offset += datalen;
1930 	}
1931 
1932 	/* Detect protocol changes after receiving full response headers. */
1933 	if (conv_data->request_method && http_type == HTTP_RESPONSE && pinfo->desegment_offset <= 0 && pinfo->desegment_len <= 0) {
1934 		dissector_handle_t next_handle = NULL;
1935 		gboolean server_acked = FALSE;
1936 
1937 		/*
1938 		 * SSTP uses a special request method (instead of the Upgrade
1939 		 * header) and expects a 200 response to set up the session.
1940 		 */
1941 		if (strcmp(conv_data->request_method, "SSTP_DUPLEX_POST") == 0 && conv_data->response_code == 200) {
1942 			next_handle = sstp_handle;
1943 			server_acked = TRUE;
1944 		}
1945 
1946 		/*
1947 		 * An HTTP/1.1 upgrade only proceeds if the server responds
1948 		 * with 101 Switching Protocols. See RFC 7230 Section 6.7.
1949 		 */
1950 		if (headers.upgrade && conv_data->response_code == 101) {
1951 			next_handle = dissector_get_string_handle(upgrade_subdissector_table, headers.upgrade);
1952 			if (!next_handle) {
1953 				char *slash_pos = strchr(headers.upgrade, '/');
1954 				if (slash_pos) {
1955 					/* Try again without version suffix. */
1956 					next_handle = dissector_get_string_handle(upgrade_subdissector_table,
1957 							wmem_strndup(wmem_packet_scope(), headers.upgrade, slash_pos - headers.upgrade));
1958 				}
1959 			}
1960 			server_acked = TRUE;
1961 		}
1962 
1963 		if (server_acked) {
1964 			conv_data->startframe = pinfo->num;
1965 			conv_data->startoffset = offset;
1966 			conv_data->next_handle = next_handle;
1967 			copy_address_wmem(wmem_file_scope(), &conv_data->server_addr, &pinfo->src);
1968 			conv_data->server_port = pinfo->srcport;
1969 		}
1970 	}
1971 
1972 	tap_queue_packet(http_tap, pinfo, stat_info);
1973 
1974 	return offset - orig_offset;
1975 }
1976 
1977 /* This can be used to dissect an HTTP request until such time
1978  * that a more complete dissector is written for that HTTP request.
1979  * This simple dissector only puts the request method, URI, and
1980  * protocol version into a sub-tree.
1981  */
1982 static void
basic_request_dissector(tvbuff_t * tvb,proto_tree * tree,int offset,const guchar * line,const guchar * lineend,http_conv_t * conv_data)1983 basic_request_dissector(tvbuff_t *tvb, proto_tree *tree, int offset,
1984 			const guchar *line, const guchar *lineend,
1985 			http_conv_t *conv_data)
1986 {
1987 	const guchar *next_token;
1988 	const gchar *request_uri;
1989 	gchar *query_str, *parameter_str, *path_str;
1990 	int request_uri_len, query_str_len, parameter_str_len;
1991 	int tokenlen, query_offset, path_len;
1992 	proto_item *ti, *tj;
1993 	proto_tree *query_tree, *path_tree;
1994 
1995 	/* The first token is the method. */
1996 	tokenlen = get_token_len(line, lineend, &next_token);
1997 	if (tokenlen == 0)
1998 		return;
1999 	proto_tree_add_item(tree, hf_http_request_method, tvb, offset, tokenlen,
2000 			    ENC_ASCII|ENC_NA);
2001 	if ((next_token - line) > 2 && next_token[-1] == ' ' && next_token[-2] == ' ') {
2002 	  /* Two spaces in a now indicates empty URI, so roll back one here */
2003 	  next_token--;
2004 	}
2005 	offset += (int) (next_token - line);
2006 	line = next_token;
2007 
2008 	/* The next token is the URI. */
2009 	tokenlen = get_token_len(line, lineend, &next_token);
2010 
2011 	/* Save the request URI for various later uses */
2012 	request_uri = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_ASCII);
2013 	stat_info->request_uri = wmem_strdup(wmem_packet_scope(), request_uri);
2014 	conv_data->request_uri = wmem_strdup(wmem_file_scope(), request_uri);
2015 
2016 	tj = proto_tree_add_string(tree, hf_http_request_uri, tvb, offset, tokenlen, request_uri);
2017 	if (( query_str = strchr(request_uri, '?')) != NULL) {
2018 		if (strlen(query_str) > 1) {
2019 			query_str++;
2020 			query_str_len = (int)strlen(query_str);
2021 			request_uri_len = (int)strlen(request_uri);
2022 			path_len = request_uri_len - query_str_len;
2023 			query_offset = offset + path_len;
2024 			path_tree = proto_item_add_subtree(tj, ett_http_request_path);
2025 			path_str = wmem_strndup(wmem_packet_scope(), request_uri, path_len-1);
2026 			proto_tree_add_string(path_tree, hf_http_request_path, tvb, offset, path_len-1, path_str);
2027 			ti = proto_tree_add_string(path_tree, hf_http_request_query, tvb, query_offset, query_str_len, query_str);
2028 			query_tree = proto_item_add_subtree(ti, ett_http_request_query);
2029 			for ( parameter_str = strtok(query_str, "&"); parameter_str; parameter_str = strtok(NULL, "&") ) {
2030 				parameter_str_len = (int) strlen(parameter_str);
2031 				proto_tree_add_string(query_tree, hf_http_request_query_parameter, tvb, query_offset, parameter_str_len, parameter_str);
2032 				query_offset += parameter_str_len + 1;
2033 			}
2034 		}
2035 	}
2036 	offset += (int) (next_token - line);
2037 	line = next_token;
2038 
2039 	/* Everything to the end of the line is the version. */
2040 	tokenlen = (int) (lineend - line);
2041 	proto_tree_add_item(tree, hf_http_request_version, tvb, offset, tokenlen,
2042 	    ENC_ASCII|ENC_NA);
2043 }
2044 
2045 static gint
parse_http_status_code(const guchar * line,const guchar * lineend)2046 parse_http_status_code(const guchar *line, const guchar *lineend)
2047 {
2048 	const guchar *next_token;
2049 	int tokenlen;
2050 	gchar response_code_chars[4];
2051 	gint32 status_code = 0;
2052 
2053 	/*
2054 	 * The first token is the HTTP Version.
2055 	 */
2056 	tokenlen = get_token_len(line, lineend, &next_token);
2057 	if (tokenlen == 0)
2058 		return 0;
2059 	line = next_token;
2060 
2061 	/*
2062 	 * The second token is the Status Code.
2063 	 */
2064 	tokenlen = get_token_len(line, lineend, &next_token);
2065 	if (tokenlen != 3)
2066 		return 0;
2067 
2068 	memcpy(response_code_chars, line, 3);
2069 	response_code_chars[3] = '\0';
2070 	if (!ws_strtoi32(response_code_chars, NULL, &status_code))
2071 		return 0;
2072 
2073 	return status_code;
2074 }
2075 
2076 static void
basic_response_dissector(tvbuff_t * tvb,proto_tree * tree,int offset,const guchar * line,const guchar * lineend,http_conv_t * conv_data _U_)2077 basic_response_dissector(tvbuff_t *tvb, proto_tree *tree, int offset,
2078 			 const guchar *line, const guchar *lineend,
2079 			 http_conv_t *conv_data _U_)
2080 {
2081 	const guchar *next_token;
2082 	int tokenlen;
2083 	gchar response_code_chars[4];
2084 	proto_item *r_ti;
2085 
2086 	/*
2087 	 * The first token is the HTTP Version.
2088 	 */
2089 	tokenlen = get_token_len(line, lineend, &next_token);
2090 	if (tokenlen == 0)
2091 		return;
2092 	proto_tree_add_item(tree, hf_http_response_version, tvb, offset, tokenlen,
2093 			    ENC_ASCII|ENC_NA);
2094 	/* Advance to the start of the next token. */
2095 	offset += (int) (next_token - line);
2096 	line = next_token;
2097 
2098 	/*
2099 	 * The second token is the Status Code.
2100 	 */
2101 	tokenlen = get_token_len(line, lineend, &next_token);
2102 	if (tokenlen < 3)
2103 		return;
2104 
2105 	/* The Status Code characters must be copied into a null-terminated
2106 	 * buffer for strtoul() to parse them into an unsigned integer value.
2107 	 */
2108 	memcpy(response_code_chars, line, 3);
2109 	response_code_chars[3] = '\0';
2110 
2111 	stat_info->response_code = conv_data->response_code =
2112 		(guint)strtoul(response_code_chars, NULL, 10);
2113 
2114 	proto_tree_add_uint(tree, hf_http_response_code, tvb, offset, 3,
2115 			    stat_info->response_code);
2116 
2117 	r_ti = proto_tree_add_string(tree, hf_http_response_code_desc,
2118 		tvb, offset, 3, val_to_str(stat_info->response_code,
2119 		vals_http_status_code, "Unknown (%d)"));
2120 
2121 	proto_item_set_generated(r_ti);
2122 
2123 	/* Advance to the start of the next token. */
2124 	offset += (int) (next_token - line);
2125 	line = next_token;
2126 
2127 	/*
2128 	 * The remaining tokens in the line comprise the Reason Phrase.
2129 	 */
2130 	tokenlen = (int) (lineend - line);
2131 	if (tokenlen >= 1) {
2132 		proto_tree_add_item(tree, hf_http_response_phrase, tvb, offset,
2133 				tokenlen, ENC_ASCII|ENC_NA);
2134 	}
2135 }
2136 
2137 #if 0 /* XXX: Replaced by code creating the "Dechunked" tvb O(N) rather than O(N^2) */
2138 /*
2139  * Dissect the http data chunks and add them to the tree.
2140  */
2141 static int
2142 chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
2143 			   proto_tree *tree, int offset)
2144 {
2145 	guint8 *chunk_string = NULL;
2146 	guint32 chunk_size = 0;
2147 	gint chunk_offset = 0;
2148 	guint32 datalen = 0;
2149 	gint linelen = 0;
2150 	gint chunks_decoded = 0;
2151 	tvbuff_t *tvb = NULL;
2152 	tvbuff_t *new_tvb = NULL;
2153 	gint chunked_data_size = 0;
2154 	proto_tree *subtree;
2155 	proto_item *ti;
2156 
2157 	if (tvb_ptr == NULL || *tvb_ptr == NULL) {
2158 		return 0;
2159 	}
2160 
2161 	tvb = *tvb_ptr;
2162 
2163 	datalen = tvb_reported_length_remaining(tvb, offset);
2164 
2165 	subtree = proto_tree_add_subtree(tree, tvb, offset, datalen,
2166 					 ett_http_chunked_response, NULL, "HTTP chunked response");
2167 
2168 	while (datalen > 0) {
2169 		proto_item *chunk_ti = NULL, *chuck_size_item;
2170 		proto_tree *chunk_subtree = NULL;
2171 		tvbuff_t *data_tvb = NULL; /*  */
2172 		gchar *c = NULL;
2173 		guint8 *raw_data;
2174 		gint raw_len = 0;
2175 
2176 		linelen = tvb_find_line_end(tvb, offset, -1, &chunk_offset, TRUE);
2177 
2178 		if (linelen <= 0) {
2179 			/* Can't get the chunk size line */
2180 			break;
2181 		}
2182 
2183 		chunk_string = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, linelen, ENC_ASCII);
2184 
2185 		if (chunk_string == NULL) {
2186 			/* Can't get the chunk size line */
2187 			break;
2188 		}
2189 
2190 		c = (gchar*) chunk_string;
2191 
2192 		/*
2193 		 * We don't care about the extensions.
2194 		 */
2195 		if ((c = strchr(c, ';'))) {
2196 			*c = '\0';
2197 		}
2198 
2199 		chunk_size = (guint32)strtol((gchar*)chunk_string, NULL, 16);
2200 
2201 		if (chunk_size > datalen) {
2202 			/*
2203 			 * The chunk size is more than what's in the tvbuff,
2204 			 * so either the user hasn't enabled decoding, or all
2205 			 * of the segments weren't captured.
2206 			 */
2207 			chunk_size = datalen;
2208 		}
2209 #if 0
2210 		  else if (new_tvb == NULL) {
2211 			new_tvb = tvb_new_composite();
2212 		}
2213 
2214 
2215 
2216 		if (new_tvb != NULL && chunk_size != 0) {
2217 			tvbuff_t *chunk_tvb = NULL;
2218 
2219 			chunk_tvb = tvb_new_subset_length_caplen(tvb, chunk_offset,
2220 			    chunk_size, datalen);
2221 
2222 			tvb_composite_append(new_tvb, chunk_tvb);
2223 
2224 		}
2225 #endif
2226 
2227 		chunked_data_size += chunk_size;
2228 
2229 		raw_data = wmem_alloc(pinfo->pool, chunked_data_size);
2230 		raw_len = 0;
2231 
2232 		if (new_tvb != NULL) {
2233 			raw_len = tvb_captured_length_remaining(new_tvb, 0);
2234 			tvb_memcpy(new_tvb, raw_data, 0, raw_len);
2235 
2236 			tvb_free(new_tvb);
2237 		}
2238 
2239 		tvb_memcpy(tvb, (guint8 *)(raw_data + raw_len),
2240 			    chunk_offset, chunk_size);
2241 
2242 		/* Don't create a new tvb if we have a single chunk with
2243 		 * a size of zero (meaning it is the end of the chunks). */
2244 		if(chunked_data_size > 0) {
2245 			new_tvb = tvb_new_real_data(raw_data,
2246 			      chunked_data_size, chunked_data_size);
2247 		}
2248 
2249 
2250 		if (subtree) {
2251 			if(chunk_size == 0) {
2252 				chunk_subtree = proto_tree_add_subtree(subtree, tvb,
2253 					    offset, chunk_offset - offset + chunk_size + 2,
2254 					    ett_http_chunk_data, NULL, "End of chunked encoding");
2255 			} else {
2256 				chunk_subtree = proto_tree_add_subtree_format(subtree, tvb,
2257 					    offset,
2258 					    chunk_offset - offset + chunk_size + 2,
2259 					    ett_http_chunk_data, NULL, "Data chunk (%u octets)", chunk_size);
2260 			}
2261 
2262 			chuck_size_item = proto_tree_add_uint(chunk_subtree, hf_http_chunk_size, tvb, offset,
2263 			    1, chunk_size);
2264 			proto_item_set_len(chuck_size_item, chunk_offset - offset);
2265 
2266 			/*
2267 			 * XXX - just add the chunk's data as an item?
2268 			 *
2269 			 * Using the data dissector means that, in
2270 			 * TShark, you get the entire chunk dumped
2271 			 * out in hex, in addition to whatever
2272 			 * dissection is done on the reassembled data.
2273 			 */
2274 			data_tvb = tvb_new_subset_length(tvb, chunk_offset, chunk_size);
2275 			call_data_dissector(data_tvb, pinfo, chunk_subtree);
2276 
2277 			proto_tree_add_item(chunk_subtree, hf_http_chunked_boundary, tvb,
2278 								chunk_offset + chunk_size, 2, ENC_NA);
2279 		}
2280 
2281 		chunks_decoded++;
2282 		offset = chunk_offset + chunk_size + 2;
2283 		datalen = tvb_reported_length_remaining(tvb, offset);
2284 	}
2285 
2286 	if (new_tvb != NULL) {
2287 
2288 		/* Placeholder for the day that composite tvbuffer's will work.
2289 		tvb_composite_finalize(new_tvb);
2290 		/ * tvb_set_reported_length(new_tvb, chunked_data_size); * /
2291 		*/
2292 
2293 		/*
2294 		 * XXX - Don't free this, since the tvbuffer that was passed
2295 		 * may be used if the data spans multiple frames and reassembly
2296 		 * isn't enabled.
2297 		 *
2298 		tvb_free(*tvb_ptr);
2299 		 */
2300 		*tvb_ptr = new_tvb;
2301 
2302 	} else {
2303 		/*
2304 		 * We didn't create a new tvb, so don't allow sub dissectors
2305 		 * try to decode the non-existent entity body.
2306 		 */
2307 		chunks_decoded = -1;
2308 	}
2309 
2310 	return chunks_decoded;
2311 
2312 }
2313 #else
2314 /*
2315  * Dissect the http data chunks and add them to the tree.
2316  */
2317 static guint
chunked_encoding_dissector(tvbuff_t ** tvb_ptr,packet_info * pinfo,proto_tree * tree,int offset)2318 chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
2319 			   proto_tree *tree, int offset)
2320 {
2321 	tvbuff_t	*tvb;
2322 	guint32		 datalen;
2323 	guint32		 orig_datalen;
2324 	gint		 chunked_data_size;
2325 	proto_tree	*subtree;
2326 	proto_item	*pi_chunked = NULL;
2327 	guint8		*raw_data;
2328 	gint		 raw_len;
2329 
2330 	if ((tvb_ptr == NULL) || (*tvb_ptr == NULL)) {
2331 		return 0;
2332 	}
2333 
2334 	tvb = *tvb_ptr;
2335 
2336 	datalen = tvb_reported_length_remaining(tvb, offset);
2337 
2338 	subtree = proto_tree_add_subtree(tree, tvb, offset, datalen,
2339 					 ett_http_chunked_response, &pi_chunked,
2340 					 "HTTP chunked response");
2341 
2342 	/* Dechunk the "chunked response" to a new memory buffer */
2343 	orig_datalen      = datalen;
2344 	raw_data	      = (guint8 *)wmem_alloc(pinfo->pool, datalen);
2345 	raw_len		      = 0;
2346 	chunked_data_size = 0;
2347 
2348 	while (datalen > 0) {
2349 		tvbuff_t *data_tvb;
2350 		guint32	  chunk_size;
2351 		gint	  chunk_offset;
2352 		guint8	 *chunk_string;
2353 		gint	  linelen;
2354 		gchar	 *c;
2355 
2356 		linelen = tvb_find_line_end(tvb, offset, -1, &chunk_offset, TRUE);
2357 
2358 		if (linelen <= 0) {
2359 			/* Can't get the chunk size line */
2360 			break;
2361 		}
2362 
2363 		chunk_string = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, linelen, ENC_ASCII);
2364 
2365 		if (chunk_string == NULL) {
2366 			/* Can't get the chunk size line */
2367 			break;
2368 		}
2369 
2370 		c = (gchar*)chunk_string;
2371 
2372 		/*
2373 		 * We don't care about the extensions.
2374 		 */
2375 		if ((c = strchr(c, ';'))) {
2376 			*c = '\0';
2377 		}
2378 
2379 		chunk_size = (guint32)strtol((gchar*)chunk_string, NULL, 16);
2380 
2381 		if (chunk_size > datalen) {
2382 			/*
2383 			 * The chunk size is more than what's in the tvbuff,
2384 			 * so either the user hasn't enabled decoding, or all
2385 			 * of the segments weren't captured.
2386 			 */
2387 			chunk_size = datalen;
2388 		}
2389 
2390 		chunked_data_size += chunk_size;
2391 
2392 		DISSECTOR_ASSERT((raw_len+chunk_size) <= orig_datalen);
2393 		tvb_memcpy(tvb, (guint8 *)(raw_data + raw_len), chunk_offset, chunk_size);
2394 		raw_len += chunk_size;
2395 
2396 		if (subtree) {
2397 			proto_tree *chunk_subtree;
2398 			proto_item *chunk_size_item;
2399 
2400 			if(chunk_size == 0) {
2401 				chunk_subtree = proto_tree_add_subtree(subtree, tvb,
2402 					    offset,
2403 					    chunk_offset - offset + chunk_size + 2,
2404 					    ett_http_chunk_data, NULL,
2405 					    "End of chunked encoding");
2406 			} else {
2407 				chunk_subtree = proto_tree_add_subtree_format(subtree, tvb,
2408 					    offset,
2409 					    chunk_offset - offset + chunk_size + 2,
2410 					    ett_http_chunk_data, NULL,
2411 					    "Data chunk (%u octets)", chunk_size);
2412 			}
2413 
2414 			chunk_size_item = proto_tree_add_uint(chunk_subtree, hf_http_chunk_size, tvb, offset,
2415 			    1, chunk_size);
2416 			proto_item_set_len(chunk_size_item, chunk_offset - offset);
2417 
2418 			/* last-chunk does not have chunk-data CRLF. */
2419 			if (chunk_size > 0) {
2420 				/*
2421 				 * XXX - just add the chunk's data as an item?
2422 				 *
2423 				 * Using the data dissector means that, in
2424 				 * TShark, you get the entire chunk dumped
2425 				 * out in hex, in addition to whatever
2426 				 * dissection is done on the reassembled data.
2427 				 */
2428 				data_tvb = tvb_new_subset_length(tvb, chunk_offset, chunk_size);
2429 				call_data_dissector(data_tvb, pinfo, chunk_subtree);
2430 
2431 				proto_tree_add_item(chunk_subtree, hf_http_chunk_boundary, tvb,
2432 									chunk_offset + chunk_size, 2, ENC_NA);
2433 			}
2434 		}
2435 
2436 		offset  = chunk_offset + chunk_size;  /* beginning of next chunk */
2437 		if (chunk_size > 0) offset += 2; /* CRLF of chunk */
2438 		datalen = tvb_reported_length_remaining(tvb, offset);
2439 
2440 		/* This is the last chunk */
2441 		if (chunk_size == 0) {
2442 			/* Check for: trailer-part CRLF.
2443 			 * trailer-part   = *( header-field CRLF ) */
2444 			gint trailer_offset = offset, trailer_len;
2445 			gint header_field_len;
2446 			/* Skip all header-fields. */
2447 			do {
2448 				trailer_len = trailer_offset - offset;
2449 				header_field_len = tvb_find_line_end(tvb,
2450 					trailer_offset,
2451 					datalen - trailer_len,
2452 					&trailer_offset, TRUE);
2453 			} while (header_field_len > 0);
2454 			if (trailer_len > 0) {
2455 				proto_tree_add_item(subtree,
2456 					hf_http_chunked_trailer_part,
2457 					tvb, offset, trailer_len, ENC_ASCII|ENC_NA);
2458 				offset += trailer_len;
2459 				datalen -= trailer_len;
2460 			}
2461 
2462 			/* last CRLF of chunked-body is found. */
2463 			if (header_field_len == 0) {
2464 				proto_tree_add_format_text(subtree, tvb, offset,
2465 					trailer_offset - offset);
2466 				datalen -= trailer_offset - offset;
2467 			}
2468 			break;
2469 		}
2470 	}
2471 
2472 	/* datalen is the remaining bytes that are available for consumption. If
2473 	 * smaller than orig_datalen, then bytes were consumed. */
2474 	if (datalen < orig_datalen) {
2475 		tvbuff_t *new_tvb;
2476 		proto_item_set_len(pi_chunked, orig_datalen - datalen);
2477 		new_tvb = tvb_new_child_real_data(tvb, raw_data, chunked_data_size, chunked_data_size);
2478 		*tvb_ptr = new_tvb;
2479 	}
2480 
2481 	/* Size of chunked-body or 0 if none was found. */
2482 	return orig_datalen - datalen;
2483 }
2484 #endif
2485 
2486 static gboolean
conversation_dissector_is_http(conversation_t * conv,guint32 frame_num)2487 conversation_dissector_is_http(conversation_t *conv, guint32 frame_num)
2488 {
2489 	dissector_handle_t conv_handle;
2490 
2491 	if (conv == NULL)
2492 		return FALSE;
2493 	conv_handle = conversation_get_dissector(conv, frame_num);
2494 	return conv_handle == http_handle ||
2495 	       conv_handle == http_tcp_handle ||
2496 	       conv_handle == http_sctp_handle;
2497 }
2498 
2499 /* Call a subdissector to handle HTTP CONNECT's traffic */
2500 static void
http_payload_subdissector(tvbuff_t * tvb,proto_tree * tree,packet_info * pinfo,http_conv_t * conv_data,void * data)2501 http_payload_subdissector(tvbuff_t *tvb, proto_tree *tree,
2502 			  packet_info *pinfo, http_conv_t *conv_data, void* data)
2503 {
2504 	guint32 *ptr = NULL;
2505 	guint32 uri_port, saved_port, srcport, destport;
2506 	gchar **strings; /* An array for splitting the request URI into hostname and port */
2507 	proto_item *item;
2508 	proto_tree *proxy_tree;
2509 	conversation_t *conv;
2510 	gboolean from_server = pinfo->srcport == conv_data->server_port &&
2511 		addresses_equal(&conv_data->server_addr, &pinfo->src);
2512 
2513 	/* Grab the destination port number from the request URI to find the right subdissector */
2514 	strings = wmem_strsplit(wmem_packet_scope(), conv_data->request_uri, ":", 2);
2515 
2516 	if(strings[0] != NULL && strings[1] != NULL) {
2517 		/*
2518 		 * The string was successfully split in two
2519 		 * Create a proxy-connect subtree
2520 		 */
2521 		if(tree) {
2522 			item = proto_tree_add_item(tree, proto_http, tvb, 0, -1, ENC_NA);
2523 			proxy_tree = proto_item_add_subtree(item, ett_http);
2524 
2525 			item = proto_tree_add_string(proxy_tree, hf_http_proxy_connect_host,
2526 						     tvb, 0, 0, strings[0]);
2527 			proto_item_set_generated(item);
2528 
2529 			item = proto_tree_add_uint(proxy_tree, hf_http_proxy_connect_port,
2530 						   tvb, 0, 0, (guint32)strtol(strings[1], NULL, 10) );
2531 			proto_item_set_generated(item);
2532 		}
2533 
2534 		uri_port = (int)strtol(strings[1], NULL, 10); /* Convert string to a base-10 integer */
2535 
2536 		if (!from_server) {
2537 			srcport = pinfo->srcport;
2538 			destport = uri_port;
2539 		} else {
2540 			srcport = uri_port;
2541 			destport = pinfo->destport;
2542 		}
2543 
2544 		conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, ENDPOINT_TCP, srcport, destport, 0);
2545 
2546 		/* We may get stuck in a recursion loop if we let process_tcp_payload() call us.
2547 		 * So, if the port in the URI is one we're registered for or we have set up a
2548 		 * conversation (e.g., one we detected heuristically or via Decode-As) call the data
2549 		 * dissector directly.
2550 		 */
2551 		if (value_is_in_range(http_tcp_range, uri_port) ||
2552 		    conversation_dissector_is_http(conv, pinfo->num)) {
2553 			call_data_dissector(tvb, pinfo, tree);
2554 		} else {
2555 			/* set pinfo->{src/dst port} and call the TCP sub-dissector lookup */
2556 			if (!from_server)
2557 				ptr = &pinfo->destport;
2558 			else
2559 				ptr = &pinfo->srcport;
2560 
2561 			/* Increase pinfo->can_desegment because we are traversing
2562 			 * http and want to preserve desegmentation functionality for
2563 			 * the proxied protocol
2564 			 */
2565 			if( pinfo->can_desegment>0 )
2566 				pinfo->can_desegment++;
2567 
2568 			saved_port = *ptr;
2569 			*ptr = uri_port;
2570 			decode_tcp_ports(tvb, 0, pinfo, tree,
2571 				pinfo->srcport, pinfo->destport, NULL,
2572 				(struct tcpinfo *)data);
2573 			*ptr = saved_port;
2574 		}
2575 	}
2576 }
2577 
2578 
2579 
2580 /*
2581  * XXX - this won't handle HTTP 0.9 replies, but they're all data
2582  * anyway.
2583  */
2584 static int
is_http_request_or_reply(const gchar * data,int linelen,http_type_t * type,ReqRespDissector * reqresp_dissector,http_conv_t * conv_data)2585 is_http_request_or_reply(const gchar *data, int linelen, http_type_t *type,
2586 			 ReqRespDissector *reqresp_dissector,
2587 			 http_conv_t *conv_data)
2588 {
2589 	int isHttpRequestOrReply = FALSE;
2590 
2591 	/*
2592 	 * From RFC 2774 - An HTTP Extension Framework
2593 	 *
2594 	 * Support the command prefix that identifies the presence of
2595 	 * a "mandatory" header.
2596 	 */
2597 	if (linelen >= 2 && strncmp(data, "M-", 2) == 0) {
2598 		data += 2;
2599 		linelen -= 2;
2600 	}
2601 
2602 	/*
2603 	 * From draft-cohen-gena-client-01.txt, available from the uPnP forum:
2604 	 *	NOTIFY, SUBSCRIBE, UNSUBSCRIBE
2605 	 *
2606 	 * From draft-ietf-dasl-protocol-00.txt, a now vanished Microsoft draft:
2607 	 *	SEARCH
2608 	 */
2609 	if ((linelen >= 5 && strncmp(data, "HTTP/", 5) == 0) ||
2610 		(linelen >= 3 && strncmp(data, "ICY", 3) == 0)) {
2611 		*type = HTTP_RESPONSE;
2612 		isHttpRequestOrReply = TRUE;	/* response */
2613 		if (reqresp_dissector)
2614 			*reqresp_dissector = basic_response_dissector;
2615 	} else {
2616 		const guchar * ptr = (const guchar *)data;
2617 		int		 indx = 0;
2618 
2619 		/* Look for the space following the Method */
2620 		while (indx < linelen) {
2621 			if (*ptr == ' ')
2622 				break;
2623 			else {
2624 				ptr++;
2625 				indx++;
2626 			}
2627 		}
2628 
2629 		/* Check the methods that have same length */
2630 		switch (indx) {
2631 
2632 		case 3:
2633 			if (strncmp(data, "GET", indx) == 0 ||
2634 			    strncmp(data, "PUT", indx) == 0) {
2635 				*type = HTTP_REQUEST;
2636 				isHttpRequestOrReply = TRUE;
2637 			}
2638 			break;
2639 
2640 		case 4:
2641 			if (strncmp(data, "COPY", indx) == 0 ||
2642 			    strncmp(data, "HEAD", indx) == 0 ||
2643 			    strncmp(data, "LOCK", indx) == 0 ||
2644 			    strncmp(data, "MOVE", indx) == 0 ||
2645 			    strncmp(data, "POLL", indx) == 0 ||
2646 			    strncmp(data, "POST", indx) == 0) {
2647 				*type = HTTP_REQUEST;
2648 				isHttpRequestOrReply = TRUE;
2649 			}
2650 			break;
2651 
2652 		case 5:
2653 			if (strncmp(data, "BCOPY", indx) == 0 ||
2654 				strncmp(data, "BMOVE", indx) == 0 ||
2655 				strncmp(data, "MKCOL", indx) == 0 ||
2656 				strncmp(data, "TRACE", indx) == 0 ||
2657 				strncmp(data, "PATCH", indx) == 0 ||  /* RFC 5789 */
2658 				strncmp(data, "LABEL", indx) == 0 ||  /* RFC 3253 8.2 */
2659 				strncmp(data, "MERGE", indx) == 0) {  /* RFC 3253 11.2 */
2660 				*type = HTTP_REQUEST;
2661 				isHttpRequestOrReply = TRUE;
2662 			}
2663 			break;
2664 
2665 		case 6:
2666 			if (strncmp(data, "DELETE", indx) == 0 ||
2667 				strncmp(data, "SEARCH", indx) == 0 ||
2668 				strncmp(data, "UNLOCK", indx) == 0 ||
2669 				strncmp(data, "REPORT", indx) == 0 ||  /* RFC 3253 3.6 */
2670 				strncmp(data, "UPDATE", indx) == 0) {  /* RFC 3253 7.1 */
2671 				*type = HTTP_REQUEST;
2672 				isHttpRequestOrReply = TRUE;
2673 			}
2674 			else if (strncmp(data, "NOTIFY", indx) == 0) {
2675 				*type = HTTP_NOTIFICATION;
2676 				isHttpRequestOrReply = TRUE;
2677 			}
2678 			break;
2679 
2680 		case 7:
2681 			if (strncmp(data, "BDELETE", indx) == 0 ||
2682 			    strncmp(data, "CONNECT", indx) == 0 ||
2683 			    strncmp(data, "OPTIONS", indx) == 0 ||
2684 			    strncmp(data, "CHECKIN", indx) == 0) {  /* RFC 3253 4.4, 9.4 */
2685 				*type = HTTP_REQUEST;
2686 				isHttpRequestOrReply = TRUE;
2687 			}
2688 			break;
2689 
2690 		case 8:
2691 			if (strncmp(data, "PROPFIND", indx) == 0 ||
2692 			    strncmp(data, "CHECKOUT", indx) == 0 || /* RFC 3253 4.3, 9.3 */
2693 			    strncmp(data, "CCM_POST", indx) == 0) {
2694 				*type = HTTP_REQUEST;
2695 				isHttpRequestOrReply = TRUE;
2696 			}
2697 			break;
2698 
2699 		case 9:
2700 			if (strncmp(data, "SUBSCRIBE", indx) == 0) {
2701 				*type = HTTP_NOTIFICATION;
2702 				isHttpRequestOrReply = TRUE;
2703 			} else if (strncmp(data, "PROPPATCH", indx) == 0 ||
2704 			    strncmp(data, "BPROPFIND", indx) == 0) {
2705 				*type = HTTP_REQUEST;
2706 				isHttpRequestOrReply = TRUE;
2707 			}
2708 			break;
2709 
2710 		case 10:
2711 			if (strncmp(data, "BPROPPATCH", indx) == 0 ||
2712 				strncmp(data, "UNCHECKOUT", indx) == 0 ||  /* RFC 3253 4.5 */
2713 				strncmp(data, "MKACTIVITY", indx) == 0) {  /* RFC 3253 13.5 */
2714 				*type = HTTP_REQUEST;
2715 				isHttpRequestOrReply = TRUE;
2716 			}
2717 			break;
2718 
2719 		case 11:
2720 			if (strncmp(data, "MKWORKSPACE", indx) == 0 || /* RFC 3253 6.3 */
2721 			    strncmp(data, "RPC_CONNECT", indx) == 0 || /* [MS-RPCH] 2.1.1.1.1 */
2722 			    strncmp(data, "RPC_IN_DATA", indx) == 0) { /* [MS-RPCH] 2.1.2.1.1 */
2723 				*type = HTTP_REQUEST;
2724 				isHttpRequestOrReply = TRUE;
2725 			} else if (strncmp(data, "UNSUBSCRIBE", indx) == 0) {
2726 				*type = HTTP_NOTIFICATION;
2727 				isHttpRequestOrReply = TRUE;
2728 			}
2729 			break;
2730 
2731 		case 12:
2732 			if (strncmp(data, "RPC_OUT_DATA", indx) == 0) { /* [MS-RPCH] 2.1.2.1.2 */
2733 				*type = HTTP_REQUEST;
2734 				isHttpRequestOrReply = TRUE;
2735 			}
2736 			break;
2737 
2738 		case 15:
2739 			if (strncmp(data, "VERSION-CONTROL", indx) == 0) {  /* RFC 3253 3.5 */
2740 				*type = HTTP_REQUEST;
2741 				isHttpRequestOrReply = TRUE;
2742 			}
2743 			break;
2744 
2745 		case 16:
2746 			if (strncmp(data, "BASELINE-CONTROL", indx) == 0) {  /* RFC 3253 12.6 */
2747 				*type = HTTP_REQUEST;
2748 				isHttpRequestOrReply = TRUE;
2749 			} else if (strncmp(data, "SSTP_DUPLEX_POST", indx) == 0) {  /* MS SSTP */
2750 				*type = HTTP_REQUEST;
2751 				isHttpRequestOrReply = TRUE;
2752 			}
2753 			break;
2754 
2755 		default:
2756 			break;
2757 		}
2758 
2759 		if (isHttpRequestOrReply && reqresp_dissector) {
2760 			*reqresp_dissector = basic_request_dissector;
2761 
2762 			stat_info->request_method = wmem_strndup(wmem_packet_scope(), data, indx);
2763 			conv_data->request_method = wmem_strndup(wmem_file_scope(), data, indx);
2764 		}
2765 
2766 
2767 
2768 	}
2769 
2770 	return isHttpRequestOrReply;
2771 }
2772 
2773 /*
2774  * Process headers.
2775  */
2776 typedef struct {
2777 	const char	*name;
2778 	gint		*hf;
2779 	int		special;
2780 } header_info;
2781 
2782 #define HDR_NO_SPECIAL			0
2783 #define HDR_AUTHORIZATION		1
2784 #define HDR_AUTHENTICATE		2
2785 #define HDR_CONTENT_TYPE		3
2786 #define HDR_CONTENT_LENGTH		4
2787 #define HDR_CONTENT_ENCODING		5
2788 #define HDR_TRANSFER_ENCODING		6
2789 #define HDR_HOST			7
2790 #define HDR_UPGRADE			8
2791 #define HDR_COOKIE			9
2792 #define HDR_WEBSOCKET_PROTOCOL		10
2793 #define HDR_WEBSOCKET_EXTENSIONS	11
2794 #define HDR_REFERER			12
2795 #define HDR_LOCATION			13
2796 #define HDR_HTTP2_SETTINGS		14
2797 
2798 static const header_info headers[] = {
2799 	{ "Authorization", &hf_http_authorization, HDR_AUTHORIZATION },
2800 	{ "Proxy-Authorization", &hf_http_proxy_authorization, HDR_AUTHORIZATION },
2801 	{ "Proxy-Authenticate", &hf_http_proxy_authenticate, HDR_AUTHENTICATE },
2802 	{ "WWW-Authenticate", &hf_http_www_authenticate, HDR_AUTHENTICATE },
2803 	{ "Content-Type", &hf_http_content_type, HDR_CONTENT_TYPE },
2804 	{ "Content-Length", &hf_http_content_length_header, HDR_CONTENT_LENGTH },
2805 	{ "Content-Encoding", &hf_http_content_encoding, HDR_CONTENT_ENCODING },
2806 	{ "Transfer-Encoding", &hf_http_transfer_encoding, HDR_TRANSFER_ENCODING },
2807 	{ "Upgrade", &hf_http_upgrade, HDR_UPGRADE },
2808 	{ "User-Agent",	&hf_http_user_agent, HDR_NO_SPECIAL },
2809 	{ "Host", &hf_http_host, HDR_HOST },
2810 	{ "Connection", &hf_http_connection, HDR_NO_SPECIAL },
2811 	{ "Cookie", &hf_http_cookie, HDR_COOKIE },
2812 	{ "Accept", &hf_http_accept, HDR_NO_SPECIAL },
2813 	{ "Referer", &hf_http_referer, HDR_REFERER },
2814 	{ "Accept-Language", &hf_http_accept_language, HDR_NO_SPECIAL },
2815 	{ "Accept-Encoding", &hf_http_accept_encoding, HDR_NO_SPECIAL },
2816 	{ "Date", &hf_http_date, HDR_NO_SPECIAL },
2817 	{ "Cache-Control", &hf_http_cache_control, HDR_NO_SPECIAL },
2818 	{ "Server", &hf_http_server, HDR_NO_SPECIAL },
2819 	{ "Location", &hf_http_location, HDR_LOCATION },
2820 	{ "Sec-WebSocket-Accept", &hf_http_sec_websocket_accept, HDR_NO_SPECIAL },
2821 	{ "Sec-WebSocket-Extensions", &hf_http_sec_websocket_extensions, HDR_WEBSOCKET_EXTENSIONS },
2822 	{ "Sec-WebSocket-Key", &hf_http_sec_websocket_key, HDR_NO_SPECIAL },
2823 	{ "Sec-WebSocket-Protocol", &hf_http_sec_websocket_protocol, HDR_WEBSOCKET_PROTOCOL },
2824 	{ "Sec-WebSocket-Version", &hf_http_sec_websocket_version, HDR_NO_SPECIAL },
2825 	{ "Set-Cookie", &hf_http_set_cookie, HDR_NO_SPECIAL },
2826 	{ "Last-Modified", &hf_http_last_modified, HDR_NO_SPECIAL },
2827 	{ "X-Forwarded-For", &hf_http_x_forwarded_for, HDR_NO_SPECIAL },
2828 	{ "HTTP2-Settings", &hf_http_http2_settings, HDR_HTTP2_SETTINGS },
2829 };
2830 
2831 /*
2832  * Look up a header name (assume lower-case header_name).
2833  */
2834 static gint*
get_hf_for_header(char * header_name)2835 get_hf_for_header(char* header_name)
2836 {
2837 	gint* hf_id = NULL;
2838 
2839 	if (header_fields_hash) {
2840 		hf_id = (gint*) g_hash_table_lookup(header_fields_hash, header_name);
2841 	} else {
2842 		hf_id = NULL;
2843 	}
2844 
2845 	return hf_id;
2846 }
2847 
2848 /*
2849  *
2850  */
2851 static void
deregister_header_fields(void)2852 deregister_header_fields(void)
2853 {
2854 	if (dynamic_hf) {
2855 		/* Deregister all fields */
2856 		for (guint i = 0; i < dynamic_hf_size; i++) {
2857 			proto_deregister_field (proto_http, *(dynamic_hf[i].p_id));
2858 			g_free (dynamic_hf[i].p_id);
2859 		}
2860 
2861 		proto_add_deregistered_data (dynamic_hf);
2862 		dynamic_hf = NULL;
2863 		dynamic_hf_size = 0;
2864 	}
2865 
2866 	if (header_fields_hash) {
2867 		g_hash_table_destroy (header_fields_hash);
2868 		header_fields_hash = NULL;
2869 	}
2870 }
2871 
2872 static void
header_fields_post_update_cb(void)2873 header_fields_post_update_cb(void)
2874 {
2875 	gint* hf_id;
2876 	gchar* header_name;
2877 	gchar* header_name_key;
2878 
2879 	deregister_header_fields();
2880 
2881 	if (num_header_fields) {
2882 		header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
2883 		dynamic_hf = g_new0(hf_register_info, num_header_fields);
2884 		dynamic_hf_size = num_header_fields;
2885 
2886 		for (guint i = 0; i < dynamic_hf_size; i++) {
2887 			hf_id = g_new(gint,1);
2888 			*hf_id = -1;
2889 			header_name = g_strdup(header_fields[i].header_name);
2890 			header_name_key = g_ascii_strdown(header_name, -1);
2891 
2892 			dynamic_hf[i].p_id = hf_id;
2893 			dynamic_hf[i].hfinfo.name = header_name;
2894 			dynamic_hf[i].hfinfo.abbrev = g_strdup_printf("http.header.%s", header_name);
2895 			dynamic_hf[i].hfinfo.type = FT_STRING;
2896 			dynamic_hf[i].hfinfo.display = BASE_NONE;
2897 			dynamic_hf[i].hfinfo.strings = NULL;
2898 			dynamic_hf[i].hfinfo.bitmask = 0;
2899 			dynamic_hf[i].hfinfo.blurb = g_strdup(header_fields[i].header_desc);
2900 			HFILL_INIT(dynamic_hf[i]);
2901 
2902 			g_hash_table_insert(header_fields_hash, header_name_key, hf_id);
2903 		}
2904 
2905 		proto_register_field_array(proto_http, dynamic_hf, dynamic_hf_size);
2906 	}
2907 }
2908 
2909 static void
header_fields_reset_cb(void)2910 header_fields_reset_cb(void)
2911 {
2912 	deregister_header_fields();
2913 }
2914 
2915 /**
2916  * Parses the transfer-coding, returning TRUE if everything was fully understood
2917  * or FALSE when unknown names were encountered.
2918  */
2919 static gboolean
http_parse_transfer_coding(const char * value,headers_t * eh_ptr)2920 http_parse_transfer_coding(const char *value, headers_t *eh_ptr)
2921 {
2922 	gboolean is_fully_parsed = TRUE;
2923 
2924 	/* Mark header as set, but with unknown encoding. */
2925 	eh_ptr->transfer_encoding = HTTP_TE_UNKNOWN;
2926 
2927 	while (*value) {
2928 		/* skip OWS (SP / HTAB) and commas; stop at the end. */
2929 		while (*value == ' ' || *value == '\t' || *value == ',')
2930 			value++;
2931 		if (!*value)
2932 			break;
2933 
2934 		if (g_str_has_prefix(value, "chunked")) {
2935 			eh_ptr->transfer_encoding_chunked = TRUE;
2936 			value += sizeof("chunked") - 1;
2937 			continue;
2938 		}
2939 
2940 		/* For now assume that chunked can only combined with exactly
2941 		 * one other (compression) encoding. Anything else is
2942 		 * unsupported. */
2943 		if (eh_ptr->transfer_encoding != HTTP_TE_UNKNOWN) {
2944 			/* No more transfer codings are expected. */
2945 			is_fully_parsed = FALSE;
2946 			break;
2947 		}
2948 
2949 		if (g_str_has_prefix(value, "compress")) {
2950 			eh_ptr->transfer_encoding = HTTP_TE_COMPRESS;
2951 			value += sizeof("compress") - 1;
2952 		} else if (g_str_has_prefix(value, "deflate")) {
2953 			eh_ptr->transfer_encoding = HTTP_TE_DEFLATE;
2954 			value += sizeof("deflate") - 1;
2955 		} else if (g_str_has_prefix(value, "gzip")) {
2956 			eh_ptr->transfer_encoding = HTTP_TE_GZIP;
2957 			value += sizeof("gzip") - 1;
2958 		} else if (g_str_has_prefix(value, "identity")) {
2959 			eh_ptr->transfer_encoding = HTTP_TE_IDENTITY;
2960 			value += sizeof("identity") - 1;
2961 		} else if (g_str_has_prefix(value, "x-compress")) {
2962 			eh_ptr->transfer_encoding = HTTP_TE_COMPRESS;
2963 			value += sizeof("x-compress") - 1;
2964 		} else if (g_str_has_prefix(value, "x-gzip")) {
2965 			eh_ptr->transfer_encoding = HTTP_TE_GZIP;
2966 			value += sizeof("x-gzip") - 1;
2967 		} else {
2968 			/* Unknown transfer encoding, skip until next comma.
2969 			 * Stop when no more names are found. */
2970 			is_fully_parsed = FALSE;
2971 			value = strchr(value, ',');
2972 			if (!value)
2973 				break;
2974 		}
2975 	}
2976 
2977 	return is_fully_parsed;
2978 }
2979 
2980 static gboolean
is_token_char(char c)2981 is_token_char(char c)
2982 {
2983 	/* tchar according to https://tools.ietf.org/html/rfc7230#section-3.2.6 */
2984 	return strchr("!#$%&\\:*+-.^_`|~", c) || g_ascii_isalnum(c);
2985 }
2986 
2987 static void
process_header(tvbuff_t * tvb,int offset,int next_offset,const guchar * line,int linelen,int colon_offset,packet_info * pinfo,proto_tree * tree,headers_t * eh_ptr,http_conv_t * conv_data,http_type_t http_type)2988 process_header(tvbuff_t *tvb, int offset, int next_offset,
2989 	       const guchar *line, int linelen, int colon_offset,
2990 	       packet_info *pinfo, proto_tree *tree, headers_t *eh_ptr,
2991 	       http_conv_t *conv_data, http_type_t http_type)
2992 {
2993 	int len;
2994 	int line_end_offset;
2995 	int header_len;
2996 	gint hf_index;
2997 	guchar c;
2998 	int value_offset;
2999 	int value_len;
3000 	char *value;
3001 	char *header_name;
3002 	char *p;
3003 	guchar *up;
3004 	proto_item *hdr_item, *it;
3005 	int i;
3006 	int* hf_id;
3007 	tap_credential_t* auth;
3008 
3009 	len = next_offset - offset;
3010 	line_end_offset = offset + linelen;
3011 	header_len = colon_offset - offset;
3012 
3013 	/*
3014 	 * Validate the header name. This allows no space between the field name
3015 	 * and colon (RFC 7230, Section. 3.2.4).
3016 	 */
3017 	gboolean valid_header_name = header_len != 0;
3018 	if (valid_header_name) {
3019 		for (i = 0; i < header_len; i++) {
3020 			/*
3021 			 * NUL is not a valid character; treat it specially
3022 			 * due to C's notion that strings are NUL-terminated.
3023 			 */
3024 			if (line[i] == '\0') {
3025 				valid_header_name = FALSE;
3026 				break;
3027 			}
3028 			if (!is_token_char(line[i])) {
3029 				valid_header_name = FALSE;
3030 				break;
3031 			}
3032 		}
3033 	}
3034 	/**
3035 	 * Not a valid header name? Just add a line plus expert info.
3036 	 */
3037 	if (!valid_header_name) {
3038 		if (http_type == HTTP_REQUEST) {
3039 			hf_index = hf_http_request_line;
3040 		} else if (http_type == HTTP_RESPONSE) {
3041 			hf_index = hf_http_response_line;
3042 		} else {
3043 			hf_index = hf_http_unknown_header;
3044 		}
3045 		it = proto_tree_add_item(tree, hf_index, tvb, offset, len, ENC_NA|ENC_ASCII);
3046 		proto_item_set_text(it, "%s", format_text(wmem_packet_scope(), line, len));
3047 		expert_add_info(pinfo, it, &ei_http_bad_header_name);
3048 		return;
3049 	}
3050 
3051 	/*
3052 	 * Make a null-terminated, all-lower-case version of the header
3053 	 * name.
3054 	 */
3055 	header_name = wmem_ascii_strdown(wmem_packet_scope(), &line[0], header_len);
3056 
3057 	hf_index = find_header_hf_value(tvb, offset, header_len);
3058 
3059 	/*
3060 	 * Skip whitespace after the colon.
3061 	 */
3062 	value_offset = colon_offset + 1;
3063 	while (value_offset < line_end_offset
3064 			&& ((c = line[value_offset - offset]) == ' ' || c == '\t'))
3065 		value_offset++;
3066 
3067 	/*
3068 	 * Fetch the value.
3069 	 *
3070 	 * XXX - the line may well have a NUL in it.  Wireshark should
3071 	 * really treat strings extracted from packets as counted
3072 	 * strings, so that NUL isn't any different from any other
3073 	 * character.  For now, we just allocate a buffer that's
3074 	 * value_len+1 bytes long, copy value_len bytes, and stick
3075 	 * in a NUL terminator, so that the buffer for value actually
3076 	 * has value_len bytes in it.
3077 	 */
3078 	value_len = line_end_offset - value_offset;
3079 	value = (char *)wmem_alloc(wmem_packet_scope(), value_len+1);
3080 	memcpy(value, &line[value_offset - offset], value_len);
3081 	value[value_len] = '\0';
3082 
3083 	if (hf_index == -1) {
3084 		/*
3085 		 * Not a header we know anything about.
3086 		 * Check if a HF generated from UAT information exists.
3087 		 */
3088 		hf_id = get_hf_for_header(header_name);
3089 
3090 		if (tree) {
3091 			if (!hf_id) {
3092 				if (http_type == HTTP_REQUEST ||
3093 					http_type == HTTP_RESPONSE) {
3094 					it = proto_tree_add_item(tree,
3095 						http_type == HTTP_RESPONSE ?
3096 						hf_http_response_line :
3097 						hf_http_request_line,
3098 						tvb, offset, len,
3099 						ENC_NA|ENC_ASCII);
3100 					proto_item_set_text(it, "%s",
3101 							format_text(wmem_packet_scope(), line, len));
3102 				} else {
3103 					gchar* str = format_text(wmem_packet_scope(), line, len);
3104 					proto_tree_add_string_format(tree, hf_http_unknown_header, tvb, offset,
3105 						len, str, "%s", str);
3106 				}
3107 
3108 			} else {
3109 				proto_tree_add_string_format(tree,
3110 					*hf_id, tvb, offset, len,
3111 					value, "%s", format_text(wmem_packet_scope(), line, len));
3112 				if (http_type == HTTP_REQUEST ||
3113 					http_type == HTTP_RESPONSE) {
3114 					it = proto_tree_add_item(tree,
3115 						http_type == HTTP_RESPONSE ?
3116 						hf_http_response_line :
3117 						hf_http_request_line,
3118 						tvb, offset, len,
3119 						ENC_NA|ENC_ASCII);
3120 					proto_item_set_text(it, "%s",
3121 							format_text(wmem_packet_scope(), line, len));
3122 					proto_item_set_hidden(it);
3123 				}
3124 			}
3125 		}
3126 	} else {
3127 		/*
3128 		 * Add it to the protocol tree as a particular field,
3129 		 * but display the line as is.
3130 		 */
3131 		if (tree) {
3132 			header_field_info *hfinfo;
3133 			guint32 tmp;
3134 
3135 			hfinfo = proto_registrar_get_nth(*headers[hf_index].hf);
3136 			switch(hfinfo->type){
3137 			case FT_UINT8:
3138 			case FT_UINT16:
3139 			case FT_UINT24:
3140 			case FT_UINT32:
3141 			case FT_INT8:
3142 			case FT_INT16:
3143 			case FT_INT24:
3144 			case FT_INT32:
3145 				tmp=(guint32)strtol(value, NULL, 10);
3146 				hdr_item = proto_tree_add_uint(tree, *headers[hf_index].hf, tvb, offset, len, tmp);
3147 				if (http_type == HTTP_REQUEST ||
3148 					http_type == HTTP_RESPONSE) {
3149 					it = proto_tree_add_item(tree,
3150 						http_type == HTTP_RESPONSE ?
3151 						hf_http_response_line :
3152 						hf_http_request_line,
3153 						tvb, offset, len,
3154 						ENC_NA|ENC_ASCII);
3155 					proto_item_set_text(it, "%d", tmp);
3156 					proto_item_set_hidden(it);
3157 				}
3158 				break;
3159 			default:
3160 				hdr_item = proto_tree_add_string_format(tree,
3161 				    *headers[hf_index].hf, tvb, offset, len,
3162 				    value, "%s", format_text(wmem_packet_scope(), line, len));
3163 				if (http_type == HTTP_REQUEST ||
3164 					http_type == HTTP_RESPONSE) {
3165 					it = proto_tree_add_item(tree,
3166 						http_type == HTTP_RESPONSE ?
3167 						hf_http_response_line :
3168 						hf_http_request_line,
3169 						tvb, offset, len,
3170 						ENC_NA|ENC_ASCII);
3171 					proto_item_set_text(it, "%s",
3172 							format_text(wmem_packet_scope(), line, len));
3173 					proto_item_set_hidden(it);
3174 				}
3175 			}
3176 		} else
3177 			hdr_item = NULL;
3178 
3179 		/*
3180 		 * Do any special processing that particular headers
3181 		 * require.
3182 		 */
3183 		switch (headers[hf_index].special) {
3184 
3185 		case HDR_AUTHORIZATION:
3186 			if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))
3187 				break;	/* dissected NTLMSSP */
3188 			if (check_auth_basic(hdr_item, tvb, pinfo, value))
3189 				break; /* dissected basic auth */
3190 			if (check_auth_citrixbasic(hdr_item, tvb, value, offset))
3191 				break; /* dissected citrix basic auth */
3192 			if (check_auth_kerberos(hdr_item, tvb, pinfo, value))
3193 				break;
3194 			if (check_auth_digest(hdr_item, tvb, pinfo, value, offset, value_len))
3195 				break;/* dissected digest basic auth */
3196 			auth = wmem_new0(wmem_packet_scope(), tap_credential_t);
3197 			auth->num = pinfo->num;
3198 			auth->password_hf_id = *headers[hf_index].hf;
3199 			auth->proto = "HTTP header auth";
3200 			auth->username = wmem_strdup(wmem_packet_scope(), TAP_CREDENTIALS_PLACEHOLDER);
3201 			tap_queue_packet(credentials_tap, pinfo, auth);
3202 			break;
3203 
3204 		case HDR_AUTHENTICATE:
3205 			if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))
3206 				break; /* dissected NTLMSSP */
3207 			check_auth_kerberos(hdr_item, tvb, pinfo, value);
3208 			break;
3209 
3210 		case HDR_CONTENT_TYPE:
3211 			eh_ptr->content_type = (gchar*) wmem_memdup(wmem_packet_scope(), (guint8*)value,value_len + 1);
3212 
3213 			for (i = 0; i < value_len; i++) {
3214 				c = value[i];
3215 				if (c == ';' || g_ascii_isspace(c)) {
3216 					/*
3217 					 * End of subtype - either
3218 					 * white space or a ";"
3219 					 * separating the subtype from
3220 					 * a parameter.
3221 					 */
3222 					break;
3223 				}
3224 
3225 				/*
3226 				 * Map the character to lower case;
3227 				 * content types are case-insensitive.
3228 				 */
3229 				eh_ptr->content_type[i] = g_ascii_tolower(eh_ptr->content_type[i]);
3230 			}
3231 			eh_ptr->content_type[i] = '\0';
3232 			/*
3233 			 * Now find the start of the optional parameters;
3234 			 * skip the optional white space and the semicolon
3235 			 * if this has not been done before.
3236 			 */
3237 			i++;
3238 			while (i < value_len) {
3239 				c = eh_ptr->content_type[i];
3240 				if (c == ';' || g_ascii_isspace(c))
3241 					/* Skip till start of parameters */
3242 					i++;
3243 				else
3244 					break;
3245 			}
3246 			if (i < value_len)
3247 				eh_ptr->content_type_parameters = eh_ptr->content_type + i;
3248 			else
3249 				eh_ptr->content_type_parameters = NULL;
3250 			break;
3251 
3252 		case HDR_CONTENT_LENGTH:
3253 			errno = 0;
3254 			eh_ptr->content_length = g_ascii_strtoll(value, &p, 10);
3255 			up = (guchar *)p;
3256 			if (eh_ptr->content_length < 0 ||
3257 			    p == value ||
3258 			    errno == ERANGE ||
3259 			    (*up != '\0' && !g_ascii_isspace(*up))) {
3260 				/*
3261 				 * Content length not valid; pretend
3262 				 * we don't have it.
3263 				 */
3264 				eh_ptr->have_content_length = FALSE;
3265 			} else {
3266 				proto_tree *header_tree;
3267 				proto_item *tree_item;
3268 				/*
3269 				 * We do have a valid content length.
3270 				 */
3271 				eh_ptr->have_content_length = TRUE;
3272 				header_tree = proto_item_add_subtree(hdr_item, ett_http_header_item);
3273 				tree_item = proto_tree_add_uint64(header_tree, hf_http_content_length,
3274 					tvb, offset, len, eh_ptr->content_length);
3275 				proto_item_set_generated(tree_item);
3276 				if (eh_ptr->transfer_encoding != HTTP_TE_NONE) {
3277 					expert_add_info(pinfo, hdr_item, &ei_http_te_and_length);
3278 				}
3279 			}
3280 			break;
3281 
3282 		case HDR_CONTENT_ENCODING:
3283 			eh_ptr->content_encoding = wmem_strndup(wmem_packet_scope(), value, value_len);
3284 			break;
3285 
3286 		case HDR_TRANSFER_ENCODING:
3287 			if (eh_ptr->have_content_length) {
3288 				expert_add_info(pinfo, hdr_item, &ei_http_te_and_length);
3289 			}
3290 			if (!http_parse_transfer_coding(value, eh_ptr)) {
3291 				expert_add_info(pinfo, hdr_item, &ei_http_te_unknown);
3292 			}
3293 			break;
3294 
3295 		case HDR_HOST:
3296 			stat_info->http_host = wmem_strndup(wmem_packet_scope(), value, value_len);
3297 			conv_data->http_host = wmem_strndup(wmem_file_scope(), value, value_len);
3298 			break;
3299 
3300 		case HDR_UPGRADE:
3301 			eh_ptr->upgrade = wmem_ascii_strdown(wmem_packet_scope(), value, value_len);
3302 			break;
3303 
3304 		case HDR_COOKIE:
3305 			if (hdr_item) {
3306 				proto_tree *cookie_tree;
3307 				char *part, *part_end;
3308 				int part_len;
3309 
3310 				cookie_tree = proto_item_add_subtree(hdr_item, ett_http_header_item);
3311 				for (i = 0; i < value_len; ) {
3312 					/* skip whitespace and ';' (terminates at '\0' or earlier) */
3313 					c = value[i];
3314 					while (c == ';' || g_ascii_isspace(c))
3315 						c = value[++i];
3316 
3317 					if (i >= value_len)
3318 						break;
3319 
3320 					/* find "cookie=foo " in "cookie=foo ; bar" */
3321 					part = value + i;
3322 					part_end = (char *)memchr(part, ';', value_len - i);
3323 					if (part_end)
3324 						part_len =(int)(part_end - part);
3325 					else
3326 						part_len = value_len - i;
3327 
3328 					/* finally add cookie to tree */
3329 					proto_tree_add_item(cookie_tree, hf_http_cookie_pair,
3330 						tvb, value_offset + i, part_len, ENC_NA|ENC_ASCII);
3331 					i += part_len;
3332 				}
3333 			}
3334 			break;
3335 
3336 		case HDR_WEBSOCKET_PROTOCOL:
3337 			if (http_type == HTTP_RESPONSE) {
3338 				conv_data->websocket_protocol = wmem_strndup(wmem_file_scope(), value, value_len);
3339 			}
3340 			break;
3341 
3342 		case HDR_WEBSOCKET_EXTENSIONS:
3343 			if (http_type == HTTP_RESPONSE) {
3344 				conv_data->websocket_extensions = wmem_strndup(wmem_file_scope(), value, value_len);
3345 			}
3346 			break;
3347 
3348 		case HDR_REFERER:
3349 			stat_info->referer_uri = wmem_strndup(wmem_packet_scope(), value, value_len);
3350 			break;
3351 
3352 		case HDR_LOCATION:
3353 			if (conv_data->request_uri){
3354 				stat_info->location_target = wmem_strndup(wmem_packet_scope(), value, value_offset);
3355 				stat_info->location_base_uri = wmem_strdup(wmem_packet_scope(), conv_data->full_uri);
3356 			}
3357 			break;
3358 		case HDR_HTTP2_SETTINGS:
3359 		{
3360 			proto_tree* settings_tree = proto_item_add_subtree(hdr_item, ett_http_http2_settings_item);
3361 			tvbuff_t* new_tvb = base64uri_tvb_to_new_tvb(tvb, value_offset, value_len);
3362 			add_new_data_source(pinfo, new_tvb, "Base64uri decoded");
3363 			TRY{
3364 				dissect_http2_settings_ext(new_tvb, pinfo, settings_tree, 0);
3365 			} CATCH_ALL{
3366 				show_exception(tvb, pinfo, settings_tree, EXCEPT_CODE, GET_MESSAGE);
3367 			}
3368 			ENDTRY;
3369 
3370 			break;
3371 		}
3372 		}
3373 	}
3374 }
3375 
3376 /* Returns index of header tag in headers */
3377 static gint
find_header_hf_value(tvbuff_t * tvb,int offset,guint header_len)3378 find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len)
3379 {
3380 	guint i;
3381 
3382 	for (i = 0; i < array_length(headers); i++) {
3383 		if (header_len == strlen(headers[i].name) &&
3384 			tvb_strncaseeql(tvb, offset,
3385 				    headers[i].name, header_len) == 0)
3386 			return i;
3387 	}
3388 
3389 	return -1;
3390 }
3391 
3392 /*
3393  * Dissect Microsoft's abomination called NTLMSSP over HTTP.
3394  */
3395 static gboolean
check_auth_ntlmssp(proto_item * hdr_item,tvbuff_t * tvb,packet_info * pinfo,gchar * value)3396 check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo, gchar *value)
3397 {
3398 	static const char *ntlm_headers[] = {
3399 		"NTLM ",
3400 		"Negotiate ",
3401 		NULL
3402 	};
3403 	const char **header;
3404 	size_t hdrlen;
3405 	proto_tree *hdr_tree;
3406 
3407 	/*
3408 	 * Check for NTLM credentials and challenge; those can
3409 	 * occur with WWW-Authenticate.
3410 	 */
3411 	for (header = &ntlm_headers[0]; *header != NULL; header++) {
3412 		hdrlen = strlen(*header);
3413 		if (strncmp(value, *header, hdrlen) == 0) {
3414 			if (hdr_item != NULL) {
3415 				hdr_tree = proto_item_add_subtree(hdr_item,
3416 				    ett_http_ntlmssp);
3417 			} else
3418 				hdr_tree = NULL;
3419 			value += hdrlen;
3420 			dissect_http_ntlmssp(tvb, pinfo, hdr_tree, value);
3421 			return TRUE;
3422 		}
3423 	}
3424 	return FALSE;
3425 }
3426 
3427 static tap_credential_t*
basic_auth_credentials(gchar * str)3428 basic_auth_credentials(gchar* str)
3429 {
3430 	gchar **tokens = g_strsplit(str, ":", -1);
3431 
3432 	if (!tokens || !tokens[0] || !tokens[1]) {
3433 		g_strfreev(tokens);
3434 		return NULL;
3435 	}
3436 
3437 	tap_credential_t* auth = wmem_new0(wmem_packet_scope(), tap_credential_t);
3438 
3439 	auth->username = wmem_strdup(wmem_packet_scope(), tokens[0]);
3440 	auth->proto = "HTTP basic auth";
3441 
3442 	g_strfreev(tokens);
3443 
3444 	return auth;
3445 }
3446 
3447 /*
3448  * Dissect HTTP Basic authorization.
3449  */
3450 static gboolean
check_auth_basic(proto_item * hdr_item,tvbuff_t * tvb,packet_info * pinfo,gchar * value)3451 check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo, gchar *value)
3452 {
3453 	static const char *basic_headers[] = {
3454 		"Basic ",
3455 		NULL
3456 	};
3457 	const char **header;
3458 	size_t hdrlen;
3459 	proto_tree *hdr_tree;
3460 	gsize len;
3461 
3462 	for (header = &basic_headers[0]; *header != NULL; header++) {
3463 		hdrlen = strlen(*header);
3464 		if (strncmp(value, *header, hdrlen) == 0) {
3465 			if (hdr_item != NULL) {
3466 				hdr_tree = proto_item_add_subtree(hdr_item,
3467 				    ett_http_ntlmssp);
3468 			} else
3469 				hdr_tree = NULL;
3470 			value += hdrlen;
3471 
3472 			if (strlen(value) > 1) {
3473 				g_base64_decode_inplace(value, &len);
3474 				value[len] = 0;
3475 			}
3476 			proto_tree_add_string(hdr_tree, hf_http_basic, tvb,
3477 			    0, 0, value);
3478 			tap_credential_t* auth = basic_auth_credentials(value);
3479 			if (auth) {
3480 				auth->num = auth->username_num = pinfo->num;
3481 				auth->password_hf_id = hf_http_basic;
3482 				tap_queue_packet(credentials_tap, pinfo, auth);
3483 			}
3484 
3485 			return TRUE;
3486 		}
3487 	}
3488 	return FALSE;
3489 }
3490 
3491 /*
3492  * Dissect HTTP Digest authorization.
3493  */
3494 static gboolean
check_auth_digest(proto_item * hdr_item,tvbuff_t * tvb,packet_info * pinfo _U_,gchar * value,int offset,int len)3495 check_auth_digest(proto_item* hdr_item, tvbuff_t* tvb, packet_info* pinfo _U_, gchar* value, int offset, int len)
3496 {
3497 	proto_tree* hdr_tree;
3498 	int queried_offset;
3499 
3500 	if (strncmp(value, "Digest", 6) == 0) {
3501 		if (hdr_item != NULL) {
3502 			hdr_tree = proto_item_add_subtree(hdr_item, ett_http_ntlmssp);
3503 		} else {
3504 			hdr_tree = NULL;
3505 		}
3506 		offset += 21;
3507 		len -= 21;
3508 		while (len > 0) {
3509 			/* Find comma/end of line */
3510 			queried_offset = tvb_find_guint8(tvb, offset, len, ',');
3511 			if (queried_offset > 0) {
3512 				proto_tree_add_format_text(hdr_tree, tvb, offset, queried_offset - offset);
3513 				len -= (queried_offset - offset);
3514 				offset = queried_offset + 1;
3515 			} else {
3516 				len = 0;
3517 			}
3518 		}
3519 		return TRUE;
3520 	} else {
3521 		return FALSE;
3522 	}
3523 }
3524 /*
3525  * Dissect HTTP CitrixAGBasic authorization.
3526  */
3527 static gboolean
check_auth_citrixbasic(proto_item * hdr_item,tvbuff_t * tvb,gchar * value,int offset)3528 check_auth_citrixbasic(proto_item *hdr_item, tvbuff_t *tvb, gchar *value, int offset)
3529 {
3530 	static const char *basic_headers[] = {
3531 		"CitrixAGBasic ",
3532 		NULL
3533 	};
3534 	const char **header;
3535 	size_t hdrlen;
3536 	proto_tree *hdr_tree;
3537 	char *ch_ptr;
3538 	int data_len;
3539 	char *data_val;
3540 	proto_item *hidden_item;
3541 	proto_item *pi;
3542 	gsize len;
3543 
3544 	for (header = &basic_headers[0]; *header != NULL; header++) {
3545 		hdrlen = strlen(*header);
3546 		if (strncmp(value, *header, hdrlen) == 0) {
3547 			if (hdr_item != NULL) {
3548 				hdr_tree = proto_item_add_subtree(hdr_item,
3549 				    ett_http_ntlmssp);
3550 			} else
3551 				hdr_tree = NULL;
3552 			value += hdrlen;
3553 			offset += (int)hdrlen + 15;
3554 			hidden_item = proto_tree_add_boolean(hdr_tree,
3555 					    hf_http_citrix, tvb, 0, 0, 1);
3556 			proto_item_set_hidden(hidden_item);
3557 
3558 			if(strncmp(value, "username=\"", 10) == 0) {
3559 				value += 10;
3560 				offset += 10;
3561 				ch_ptr = strchr(value, '"');
3562 				if ( ch_ptr != NULL ) {
3563 					data_len = (int)(ch_ptr - value + 1);
3564 					data_val = wmem_strndup(wmem_packet_scope(), value, data_len);
3565 					if (data_len > 1) {
3566 						g_base64_decode_inplace(data_val, &len);
3567 						data_val[len] = 0;
3568 					}
3569 					pi = proto_tree_add_string(hdr_tree, hf_http_citrix_user, tvb,
3570 					    offset , data_len - 1, data_val);
3571 					proto_item_set_generated(pi);
3572 					value += data_len;
3573 					offset += data_len;
3574 				}
3575 			}
3576 			if(strncmp(value, "; domain=\"", 10) == 0) {
3577 				value += 10;
3578 				offset += 10;
3579 				ch_ptr = strchr(value, '"');
3580 				if ( ch_ptr != NULL ) {
3581 					data_len = (int)(ch_ptr - value + 1);
3582 					data_val = wmem_strndup(wmem_packet_scope(), value, data_len);
3583 					if (data_len > 1) {
3584 						g_base64_decode_inplace(data_val, &len);
3585 						data_val[len] = 0;
3586 					}
3587 					pi = proto_tree_add_string(hdr_tree, hf_http_citrix_domain, tvb,
3588 					    offset, data_len - 1, data_val);
3589 					proto_item_set_generated(pi);
3590 					value += data_len;
3591 					offset += data_len;
3592 				}
3593 			}
3594 			if(strncmp(value, "; password=\"", 12) == 0) {
3595 				value += 12;
3596 				offset += 12;
3597 				ch_ptr = strchr(value, '"');
3598 				if ( ch_ptr != NULL ) {
3599 					data_len = (int)(ch_ptr - value + 1);
3600 					data_val = wmem_strndup(wmem_packet_scope(), value, data_len);
3601 					if (data_len > 1) {
3602 						g_base64_decode_inplace(data_val, &len);
3603 						data_val[len] = 0;
3604 					}
3605 					pi = proto_tree_add_string(hdr_tree, hf_http_citrix_passwd, tvb,
3606 					    offset, data_len - 1, data_val);
3607 					proto_item_set_generated(pi);
3608 					value += data_len;
3609 					offset += data_len;
3610 				}
3611 			}
3612 			if(strncmp(value, "; AGESessionId=\"", 16) == 0) {
3613 				value += 16;
3614 				offset += 16;
3615 				ch_ptr = strchr(value, '"');
3616 				if ( ch_ptr != NULL ) {
3617 					data_len = (int)(ch_ptr - value + 1);
3618 					data_val = wmem_strndup(wmem_packet_scope(), value, data_len);
3619 					if (data_len > 1) {
3620 						g_base64_decode_inplace(data_val, &len);
3621 						data_val[len] = 0;
3622 					}
3623 					pi = proto_tree_add_string(hdr_tree, hf_http_citrix_session, tvb,
3624 					    offset, data_len - 1, data_val);
3625 					proto_item_set_generated(pi);
3626 				}
3627 			}
3628 			return TRUE;
3629 		}
3630 	}
3631 	return FALSE;
3632 }
3633 
3634 static gboolean
check_auth_kerberos(proto_item * hdr_item,tvbuff_t * tvb,packet_info * pinfo,const gchar * value)3635 check_auth_kerberos(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo, const gchar *value)
3636 {
3637 	proto_tree *hdr_tree;
3638 
3639 	if (strncmp(value, "Kerberos ", 9) == 0) {
3640 		if (hdr_item != NULL) {
3641 			hdr_tree = proto_item_add_subtree(hdr_item, ett_http_kerberos);
3642 		} else
3643 			hdr_tree = NULL;
3644 
3645 		dissect_http_kerberos(tvb, pinfo, hdr_tree, value);
3646 		return TRUE;
3647 	}
3648 	return FALSE;
3649 }
3650 
3651 static void
dissect_http_on_stream(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,http_conv_t * conv_data,gboolean end_of_stream)3652 dissect_http_on_stream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3653     http_conv_t *conv_data, gboolean end_of_stream)
3654 {
3655 	int		offset = 0;
3656 	int		len;
3657 
3658 	while (tvb_reported_length_remaining(tvb, offset) > 0) {
3659 		/* Switch protocol if the data starts after response headers. */
3660 		if (conv_data->startframe &&
3661 				(pinfo->num > conv_data->startframe ||
3662 				(pinfo->num == conv_data->startframe && offset >= conv_data->startoffset))) {
3663 			/* Increase pinfo->can_desegment because we are traversing
3664 			 * http and want to preserve desegmentation functionality for
3665 			 * the proxied protocol
3666 			 */
3667 			if (pinfo->can_desegment > 0)
3668 				pinfo->can_desegment++;
3669 			if (conv_data->next_handle) {
3670 				call_dissector_only(conv_data->next_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree, NULL);
3671 			} else {
3672 				call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
3673 			}
3674 			/*
3675 			 * If a subdissector requests reassembly, be sure not to
3676 			 * include the preceding HTTP headers.
3677 			 */
3678 			if (pinfo->desegment_len) {
3679 				pinfo->desegment_offset += offset;
3680 			}
3681 			break;
3682 		}
3683 		len = dissect_http_message(tvb, offset, pinfo, tree, conv_data, "HTTP", proto_http, end_of_stream);
3684 		if (len == -1)
3685 			break;
3686 		offset += len;
3687 
3688 		/*
3689 		 * OK, we've set the Protocol and Info columns for the
3690 		 * first HTTP message; set a fence so that subsequent
3691 		 * HTTP messages don't overwrite the Info column.
3692 		 */
3693 		col_set_fence(pinfo->cinfo, COL_INFO);
3694 	}
3695 }
3696 
3697 static int
dissect_http_tcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3698 dissect_http_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
3699 {
3700 	struct tcpinfo *tcpinfo = (struct tcpinfo *)data;
3701 	conversation_t *conversation;
3702 	http_conv_t *conv_data;
3703 	gboolean end_of_stream;
3704 
3705 	conv_data = get_http_conversation_data(pinfo, &conversation);
3706 
3707 	/* Call HTTP2 dissector directly when detected via heuristics, but not
3708 	 * when it was upgraded (the conversation started with HTTP). */
3709 	if (conversation_get_proto_data(conversation, proto_http2) &&
3710 	    !conv_data->startframe) {
3711 		if (pinfo->can_desegment > 0)
3712 			pinfo->can_desegment++;
3713 		return call_dissector_only(http2_handle, tvb, pinfo, tree, data);
3714 	}
3715 
3716 	/*
3717 	 * Check if this is proxied connection and if so, hand of dissection to the
3718 	 * payload-dissector.
3719 	 * Response code 200 means "OK" and strncmp() == 0 means the strings match exactly */
3720 	if(pinfo->num >= conv_data->startframe &&
3721 	   conv_data->response_code == 200 &&
3722 	   conv_data->request_method &&
3723 	   strncmp(conv_data->request_method, "CONNECT", 7) == 0 &&
3724 	   conv_data->request_uri) {
3725 		if (conv_data->startframe == 0 && !PINFO_FD_VISITED(pinfo)) {
3726 			conv_data->startframe = pinfo->num;
3727 			conv_data->startoffset = 0;
3728 			copy_address_wmem(wmem_file_scope(), &conv_data->server_addr, &pinfo->dst);
3729 			conv_data->server_port = pinfo->destport;
3730 		}
3731 		http_payload_subdissector(tvb, tree, pinfo, conv_data, data);
3732 
3733 		return tvb_captured_length(tvb);
3734 	}
3735 
3736 	/* XXX - how to detect end-of-stream without tcpinfo */
3737 	end_of_stream = (tcpinfo && IS_TH_FIN(tcpinfo->flags));
3738 	dissect_http_on_stream(tvb, pinfo, tree, conv_data, end_of_stream);
3739 	return tvb_captured_length(tvb);
3740 }
3741 
3742 static gboolean
dissect_http_heur_tcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3743 dissect_http_heur_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3744 {
3745 	gint offset = 0, next_offset, linelen;
3746 	conversation_t  *conversation;
3747 
3748 
3749 	/* Check if we have a line terminated by CRLF
3750 	 * Return the length of the line (not counting the line terminator at
3751 	 * the end), or, if we don't find a line terminator:
3752 	 *
3753 	 *	if "deseg" is true, return -1;
3754 	 */
3755 	linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, TRUE);
3756 	if((linelen == -1)||(linelen == 8)){
3757 		return FALSE;
3758 	}
3759 
3760 	/* Check if the line start or ends with the HTTP token */
3761 	if((tvb_strncaseeql(tvb, linelen-8, "HTTP/1.", 7) == 0)||(tvb_strncaseeql(tvb, 0, "HTTP/1.", 7) == 0)){
3762 		conversation = find_or_create_conversation(pinfo);
3763 		conversation_set_dissector_from_frame_number(conversation, pinfo->num, http_tcp_handle);
3764 		dissect_http_tcp(tvb, pinfo, tree, data);
3765 		return TRUE;
3766 	}
3767 
3768 	return FALSE;
3769 }
3770 
3771 static int
dissect_http_tls(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3772 dissect_http_tls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3773 {
3774 	conversation_t *conversation;
3775 	http_conv_t *conv_data;
3776 
3777 	conv_data = get_http_conversation_data(pinfo, &conversation);
3778 
3779 	/*
3780 	 * XXX - we need to provide an end-of-stream indication.
3781 	 */
3782 	dissect_http_on_stream(tvb, pinfo, tree, conv_data, FALSE);
3783 	return tvb_captured_length(tvb);
3784 }
3785 
3786 static gboolean
dissect_http_heur_tls(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3787 dissect_http_heur_tls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3788 {
3789 	gint offset = 0, next_offset, linelen;
3790 	conversation_t  *conversation;
3791 	http_conv_t	*conv_data;
3792 
3793 	conversation = find_or_create_conversation(pinfo);
3794 	conv_data = (http_conv_t *)conversation_get_proto_data(conversation, proto_http);
3795 	/* A http conversation was previously started, assume it is still active */
3796 	if (conv_data) {
3797 		dissect_http_tls(tvb, pinfo, tree, data);
3798 		return TRUE;
3799 	}
3800 
3801 	/* Check if we have a line terminated by CRLF
3802 	 * Return the length of the line (not counting the line terminator at
3803 	 * the end), or, if we don't find a line terminator:
3804 	 *
3805 	 *	if "deseg" is true, return -1;
3806 	 */
3807 	linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, TRUE);
3808 	if((linelen == -1)||(linelen == 8)){
3809 		return FALSE;
3810 	}
3811 
3812 	/* Check if the line start or ends with the HTTP token */
3813 	if((tvb_strncaseeql(tvb, linelen-8, "HTTP/1.", 7) != 0) && (tvb_strncaseeql(tvb, 0, "HTTP/1.", 7) != 0)) {
3814 	        /* we couldn't find the Magic Hello HTTP/1.X. */
3815 		return FALSE;
3816 	}
3817 
3818         conv_data = wmem_new0(wmem_file_scope(), http_conv_t);
3819         conversation_add_proto_data(conversation, proto_http, conv_data);
3820 	dissect_http_tls(tvb, pinfo, tree, data);
3821 	return TRUE;
3822 }
3823 
3824 static int
dissect_http_sctp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3825 dissect_http_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3826 {
3827 	conversation_t *conversation;
3828 	http_conv_t *conv_data;
3829 
3830 	conv_data = get_http_conversation_data(pinfo, &conversation);
3831 
3832 	/*
3833 	 * XXX - we need to provide an end-of-stream indication.
3834 	 */
3835 	dissect_http_on_stream(tvb, pinfo, tree, conv_data, FALSE);
3836 	return tvb_captured_length(tvb);
3837 }
3838 
3839 static int
dissect_http(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3840 dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3841 {
3842 	conversation_t *conversation;
3843 	http_conv_t *conv_data;
3844 
3845 	conv_data = get_http_conversation_data(pinfo, &conversation);
3846 
3847 	/*
3848 	 * XXX - what should be done about reassembly, pipelining, etc.
3849 	 * here?
3850 	 */
3851 	dissect_http_on_stream(tvb, pinfo, tree, conv_data, FALSE);
3852 	return tvb_captured_length(tvb);
3853 }
3854 
3855 static int
dissect_ssdp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3856 dissect_ssdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3857 {
3858 	conversation_t  *conversation;
3859 	http_conv_t	*conv_data;
3860 
3861 	conv_data = get_http_conversation_data(pinfo, &conversation);
3862 	dissect_http_message(tvb, 0, pinfo, tree, conv_data, "SSDP", proto_ssdp, FALSE);
3863 	return tvb_captured_length(tvb);
3864 }
3865 
3866 static void
range_delete_http_tls_callback(guint32 port,gpointer ptr _U_)3867 range_delete_http_tls_callback(guint32 port, gpointer ptr _U_) {
3868 	ssl_dissector_delete(port, http_tls_handle);
3869 }
3870 
3871 static void
range_add_http_tls_callback(guint32 port,gpointer ptr _U_)3872 range_add_http_tls_callback(guint32 port, gpointer ptr _U_) {
3873 	ssl_dissector_add(port, http_tls_handle);
3874 }
3875 
reinit_http(void)3876 static void reinit_http(void) {
3877 	http_tcp_range = prefs_get_range_value("http", "tcp.port");
3878 
3879 	dissector_delete_uint_range("sctp.port", http_sctp_range, http_sctp_handle);
3880 	wmem_free(wmem_epan_scope(), http_sctp_range);
3881 	http_sctp_range = range_copy(wmem_epan_scope(), global_http_sctp_range);
3882 	dissector_add_uint_range("sctp.port", http_sctp_range, http_sctp_handle);
3883 
3884 	range_foreach(http_tls_range, range_delete_http_tls_callback, NULL);
3885 	wmem_free(wmem_epan_scope(), http_tls_range);
3886 	http_tls_range = range_copy(wmem_epan_scope(), global_http_tls_range);
3887 	range_foreach(http_tls_range, range_add_http_tls_callback, NULL);
3888 }
3889 
3890 void
proto_register_http(void)3891 proto_register_http(void)
3892 {
3893 	static hf_register_info hf[] = {
3894 	    { &hf_http_notification,
3895 	      { "Notification", "http.notification",
3896 		FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3897 		"TRUE if HTTP notification", HFILL }},
3898 	    { &hf_http_response,
3899 	      { "Response", "http.response",
3900 		FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3901 		"TRUE if HTTP response", HFILL }},
3902 	    { &hf_http_request,
3903 	      { "Request", "http.request",
3904 		FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3905 		"TRUE if HTTP request", HFILL }},
3906 	    { &hf_http_response_number,
3907 	      { "Response number", "http.response_number",
3908 		FT_UINT32, BASE_DEC, NULL, 0x0,
3909 		NULL, HFILL }},
3910 	    { &hf_http_request_number,
3911 	      { "Request number", "http.request_number",
3912 		FT_UINT32, BASE_DEC, NULL, 0x0,
3913 		NULL, HFILL }},
3914 	    { &hf_http_basic,
3915 	      { "Credentials", "http.authbasic",
3916 		FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3917 	    { &hf_http_citrix,
3918 	      { "Citrix AG Auth", "http.authcitrix",
3919 		FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3920 		"TRUE if CitrixAGBasic Auth", HFILL }},
3921 	    { &hf_http_citrix_user,
3922 	      { "Citrix AG Username", "http.authcitrix.user",
3923 		FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3924 	    { &hf_http_citrix_domain,
3925 	      { "Citrix AG Domain", "http.authcitrix.domain",
3926 		FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3927 	    { &hf_http_citrix_passwd,
3928 	      { "Citrix AG Password", "http.authcitrix.password",
3929 		FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3930 	    { &hf_http_citrix_session,
3931 	      { "Citrix AG Session ID", "http.authcitrix.session",
3932 		FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3933 	    { &hf_http_response_line,
3934 	      { "Response line", "http.response.line",
3935 		FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3936 	    { &hf_http_request_line,
3937 	      { "Request line", "http.request.line",
3938 		FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3939 	    { &hf_http_request_method,
3940 	      { "Request Method", "http.request.method",
3941 		FT_STRING, BASE_NONE, NULL, 0x0,
3942 		"HTTP Request Method", HFILL }},
3943 	    { &hf_http_request_uri,
3944 	      { "Request URI", "http.request.uri",
3945 		FT_STRING, STR_UNICODE, NULL, 0x0,
3946 		"HTTP Request-URI", HFILL }},
3947 	    { &hf_http_request_path,
3948 	      { "Request URI Path", "http.request.uri.path",
3949 		FT_STRING, STR_UNICODE, NULL, 0x0,
3950 		"HTTP Request-URI Path", HFILL }},
3951 	    { &hf_http_request_query,
3952 	      { "Request URI Query", "http.request.uri.query",
3953 		FT_STRING, STR_UNICODE, NULL, 0x0,
3954 		"HTTP Request-URI Query", HFILL }},
3955 	    { &hf_http_request_query_parameter,
3956 	      { "Request URI Query Parameter", "http.request.uri.query.parameter",
3957 		FT_STRING, STR_UNICODE, NULL, 0x0,
3958 		"HTTP Request-URI Query Parameter", HFILL }},
3959 	    { &hf_http_request_version,
3960 	      { "Request Version", "http.request.version",
3961 		FT_STRING, BASE_NONE, NULL, 0x0,
3962 		"HTTP Request HTTP-Version", HFILL }},
3963 	    { &hf_http_response_version,
3964 	      { "Response Version", "http.response.version",
3965 		FT_STRING, BASE_NONE, NULL, 0x0,
3966 		"HTTP Response HTTP-Version", HFILL }},
3967 	    { &hf_http_request_full_uri,
3968 	      { "Full request URI", "http.request.full_uri",
3969 		FT_STRING, BASE_NONE, NULL, 0x0,
3970 		"The full requested URI (including host name)", HFILL }},
3971 	    { &hf_http_response_code,
3972 	      { "Status Code", "http.response.code",
3973 		FT_UINT16, BASE_DEC, NULL, 0x0,
3974 		"HTTP Response Status Code", HFILL }},
3975 	    { &hf_http_response_code_desc,
3976 	      { "Status Code Description", "http.response.code.desc",
3977 		FT_STRING, BASE_NONE, NULL, 0x0,
3978 		"HTTP Response Status Code Description", HFILL }},
3979 	    { &hf_http_response_for_uri,
3980 	      { "Request URI", "http.response_for.uri",
3981 		FT_STRING, STR_UNICODE, NULL, 0x0,
3982 		"HTTP Response For-URI", HFILL }},
3983 	    { &hf_http_response_phrase,
3984 	      { "Response Phrase", "http.response.phrase",
3985 	        FT_STRING, BASE_NONE, NULL, 0x0,
3986 		"HTTP Response Reason Phrase", HFILL }},
3987 	    { &hf_http_authorization,
3988 	      { "Authorization", "http.authorization",
3989 		FT_STRING, BASE_NONE, NULL, 0x0,
3990 		"HTTP Authorization header", HFILL }},
3991 	    { &hf_http_proxy_authenticate,
3992 	      { "Proxy-Authenticate", "http.proxy_authenticate",
3993 		FT_STRING, BASE_NONE, NULL, 0x0,
3994 		"HTTP Proxy-Authenticate header", HFILL }},
3995 	    { &hf_http_proxy_authorization,
3996 	      { "Proxy-Authorization", "http.proxy_authorization",
3997 		FT_STRING, BASE_NONE, NULL, 0x0,
3998 		"HTTP Proxy-Authorization header", HFILL }},
3999 	    { &hf_http_proxy_connect_host,
4000 	      { "Proxy-Connect-Hostname", "http.proxy_connect_host",
4001 		FT_STRING, BASE_NONE, NULL, 0x0,
4002 		"HTTP Proxy Connect Hostname", HFILL }},
4003 	    { &hf_http_proxy_connect_port,
4004 	      { "Proxy-Connect-Port", "http.proxy_connect_port",
4005 		FT_UINT16, BASE_DEC, NULL, 0x0,
4006 		"HTTP Proxy Connect Port", HFILL }},
4007 	    { &hf_http_www_authenticate,
4008 	      { "WWW-Authenticate", "http.www_authenticate",
4009 		FT_STRING, BASE_NONE, NULL, 0x0,
4010 		"HTTP WWW-Authenticate header", HFILL }},
4011 	    { &hf_http_content_type,
4012 	      { "Content-Type", "http.content_type",
4013 		FT_STRING, BASE_NONE, NULL, 0x0,
4014 		"HTTP Content-Type header", HFILL }},
4015 	    { &hf_http_content_length_header,
4016 	      { "Content-Length", "http.content_length_header",
4017 		FT_STRING, BASE_NONE, NULL, 0x0,
4018 		"HTTP Content-Length header", HFILL }},
4019 	    { &hf_http_content_length,
4020 	      { "Content length", "http.content_length",
4021 		FT_UINT64, BASE_DEC, NULL, 0x0,
4022 		NULL, HFILL }},
4023 	    { &hf_http_content_encoding,
4024 	      { "Content-Encoding", "http.content_encoding",
4025 		FT_STRING, BASE_NONE, NULL, 0x0,
4026 		"HTTP Content-Encoding header", HFILL }},
4027 	    { &hf_http_transfer_encoding,
4028 	      { "Transfer-Encoding", "http.transfer_encoding",
4029 		FT_STRING, BASE_NONE, NULL, 0x0,
4030 		"HTTP Transfer-Encoding header", HFILL }},
4031 	    { &hf_http_upgrade,
4032 	      { "Upgrade", "http.upgrade",
4033 		FT_STRING, BASE_NONE, NULL, 0x0,
4034 		"HTTP Upgrade header", HFILL }},
4035 	    { &hf_http_user_agent,
4036 	      { "User-Agent", "http.user_agent",
4037 		FT_STRING, BASE_NONE, NULL, 0x0,
4038 		"HTTP User-Agent header", HFILL }},
4039 	    { &hf_http_host,
4040 	      { "Host", "http.host",
4041 		FT_STRING, BASE_NONE, NULL, 0x0,
4042 		"HTTP Host", HFILL }},
4043 	    { &hf_http_connection,
4044 	      { "Connection", "http.connection",
4045 		FT_STRING, BASE_NONE, NULL, 0x0,
4046 		"HTTP Connection", HFILL }},
4047 	    { &hf_http_cookie,
4048 	      { "Cookie", "http.cookie",
4049 		FT_STRING, BASE_NONE, NULL, 0x0,
4050 		"HTTP Cookie", HFILL }},
4051 	    { &hf_http_cookie_pair,
4052 	      { "Cookie pair", "http.cookie_pair",
4053 		FT_STRING, BASE_NONE, NULL, 0x0,
4054 		"A name/value HTTP cookie pair", HFILL }},
4055 	    { &hf_http_accept,
4056 	      { "Accept", "http.accept",
4057 		FT_STRING, BASE_NONE, NULL, 0x0,
4058 		"HTTP Accept", HFILL }},
4059 	    { &hf_http_referer,
4060 	      { "Referer", "http.referer",
4061 		FT_STRING, BASE_NONE, NULL, 0x0,
4062 		"HTTP Referer", HFILL }},
4063 	    { &hf_http_accept_language,
4064 	      { "Accept-Language", "http.accept_language",
4065 		FT_STRING, BASE_NONE, NULL, 0x0,
4066 		"HTTP Accept Language", HFILL }},
4067 	    { &hf_http_accept_encoding,
4068 	      { "Accept Encoding", "http.accept_encoding",
4069 		FT_STRING, BASE_NONE, NULL, 0x0,
4070 		"HTTP Accept Encoding", HFILL }},
4071 	    { &hf_http_date,
4072 	      { "Date", "http.date",
4073 		FT_STRING, BASE_NONE, NULL, 0x0,
4074 		"HTTP Date", HFILL }},
4075 	    { &hf_http_cache_control,
4076 	      { "Cache-Control", "http.cache_control",
4077 		FT_STRING, BASE_NONE, NULL, 0x0,
4078 		"HTTP Cache Control", HFILL }},
4079 	    { &hf_http_server,
4080 	      { "Server", "http.server",
4081 		FT_STRING, BASE_NONE, NULL, 0x0,
4082 		"HTTP Server", HFILL }},
4083 	    { &hf_http_location,
4084 	      { "Location", "http.location",
4085 		FT_STRING, BASE_NONE, NULL, 0x0,
4086 		"HTTP Location", HFILL }},
4087 	    { &hf_http_sec_websocket_accept,
4088 	      { "Sec-WebSocket-Accept", "http.sec_websocket_accept",
4089 		FT_STRING, BASE_NONE, NULL, 0x0,
4090 		NULL, HFILL }},
4091 	    { &hf_http_sec_websocket_extensions,
4092 	      { "Sec-WebSocket-Extensions", "http.sec_websocket_extensions",
4093 		FT_STRING, BASE_NONE, NULL, 0x0,
4094 		NULL, HFILL }},
4095 	    { &hf_http_sec_websocket_key,
4096 	      { "Sec-WebSocket-Key", "http.sec_websocket_key",
4097 		FT_STRING, BASE_NONE, NULL, 0x0,
4098 		NULL, HFILL }},
4099 	    { &hf_http_sec_websocket_protocol,
4100 	      { "Sec-WebSocket-Protocol", "http.sec_websocket_protocol",
4101 		FT_STRING, BASE_NONE, NULL, 0x0,
4102 		NULL, HFILL }},
4103 	    { &hf_http_sec_websocket_version,
4104 	      { "Sec-WebSocket-Version", "http.sec_websocket_version",
4105 		FT_STRING, BASE_NONE, NULL, 0x0,
4106 		NULL, HFILL }},
4107 	    { &hf_http_set_cookie,
4108 	      { "Set-Cookie", "http.set_cookie",
4109 		FT_STRING, BASE_NONE, NULL, 0x0,
4110 		"HTTP Set Cookie", HFILL }},
4111 	    { &hf_http_last_modified,
4112 	      { "Last-Modified", "http.last_modified",
4113 		FT_STRING, BASE_NONE, NULL, 0x0,
4114 		"HTTP Last Modified", HFILL }},
4115 	    { &hf_http_x_forwarded_for,
4116 	      { "X-Forwarded-For", "http.x_forwarded_for",
4117 		FT_STRING, BASE_NONE, NULL, 0x0,
4118 		"HTTP X-Forwarded-For", HFILL }},
4119 	    { &hf_http_http2_settings,
4120 	      { "HTTP2-Settings", "http.http2_settings",
4121 		FT_STRING, BASE_NONE, NULL, 0x0,
4122 		NULL, HFILL }},
4123 	    { &hf_http_request_in,
4124 	      { "Request in frame", "http.request_in",
4125 		FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0,
4126 		"This packet is a response to the packet with this number", HFILL }},
4127 	    { &hf_http_response_in,
4128 	      { "Response in frame", "http.response_in",
4129 		FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0,
4130 		"This packet will be responded in the packet with this number", HFILL }},
4131 	    { &hf_http_next_request_in,
4132 	      { "Next request in frame", "http.next_request_in",
4133 		FT_FRAMENUM, BASE_NONE, NULL, 0,
4134 		"The next HTTP request starts in packet number", HFILL }},
4135 	    { &hf_http_next_response_in,
4136 	      { "Next response in frame", "http.next_response_in",
4137 		FT_FRAMENUM, BASE_NONE, NULL, 0,
4138 		"The next HTTP response starts in packet number", HFILL }},
4139 	    { &hf_http_prev_request_in,
4140 	      { "Prev request in frame", "http.prev_request_in",
4141 		FT_FRAMENUM, BASE_NONE, NULL, 0,
4142 		"The previous HTTP request starts in packet number", HFILL }},
4143 	    { &hf_http_prev_response_in,
4144 	      { "Prev response in frame", "http.prev_response_in",
4145 		FT_FRAMENUM, BASE_NONE, NULL, 0,
4146 		"The previous HTTP response starts in packet number", HFILL }},
4147 	    { &hf_http_time,
4148 	      { "Time since request", "http.time",
4149 		FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
4150 		"Time since the request was sent", HFILL }},
4151 	    { &hf_http_chunked_trailer_part,
4152 	      { "trailer-part", "http.chunked_trailer_part",
4153 		FT_STRING, BASE_NONE, NULL, 0,
4154 		"Optional trailer in a chunked body", HFILL }},
4155 	    { &hf_http_chunk_boundary,
4156 	      { "Chunk boundary", "http.chunk_boundary",
4157 		FT_BYTES, BASE_NONE, NULL, 0,
4158 		NULL, HFILL }},
4159 	    { &hf_http_chunk_size,
4160 	      { "Chunk size", "http.chunk_size",
4161 		FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_octet_octets, 0,
4162 		NULL, HFILL }},
4163 	    { &hf_http_file_data,
4164 	      { "File Data", "http.file_data",
4165 		FT_STRING, STR_UNICODE, NULL, 0,
4166 		NULL, HFILL }},
4167 	    { &hf_http_unknown_header,
4168 	      { "Unknown header", "http.unknown_header",
4169 		FT_STRING, BASE_NONE, NULL, 0,
4170 		NULL, HFILL }},
4171 	    { &hf_http_http2_settings_uri,
4172 	      { "HTTP2 Settings URI", "http.http2_settings_uri",
4173 		FT_BYTES, BASE_NONE, NULL, 0,
4174 		NULL, HFILL }},
4175 	};
4176 	static gint *ett[] = {
4177 		&ett_http,
4178 		&ett_http_ntlmssp,
4179 		&ett_http_kerberos,
4180 		&ett_http_request,
4181 		&ett_http_request_path,
4182 		&ett_http_request_query,
4183 		&ett_http_chunked_response,
4184 		&ett_http_chunk_data,
4185 		&ett_http_encoded_entity,
4186 		&ett_http_header_item,
4187 		&ett_http_http2_settings_item
4188 	};
4189 
4190 	static ei_register_info ei[] = {
4191 		{ &ei_http_chat, { "http.chat", PI_SEQUENCE, PI_CHAT, "Formatted text", EXPFILL }},
4192 		{ &ei_http_te_and_length, { "http.te_and_length", PI_MALFORMED, PI_WARN, "The Content-Length and Transfer-Encoding header must not be set together", EXPFILL }},
4193 		{ &ei_http_te_unknown, { "http.te_unknown", PI_UNDECODED, PI_WARN, "Unknown transfer coding name in Transfer-Encoding header", EXPFILL }},
4194 		{ &ei_http_subdissector_failed, { "http.subdissector_failed", PI_MALFORMED, PI_NOTE, "HTTP body subdissector failed, trying heuristic subdissector", EXPFILL }},
4195 		{ &ei_http_tls_port, { "http.tls_port", PI_SECURITY, PI_WARN, "Unencrypted HTTP protocol detected over encrypted port, could indicate a dangerous misconfiguration.", EXPFILL }},
4196 		{ &ei_http_leading_crlf, { "http.leading_crlf", PI_MALFORMED, PI_ERROR, "Leading CRLF previous message in the stream may have extra CRLF", EXPFILL }},
4197 		{ &ei_http_bad_header_name, { "http.bad_header_name", PI_PROTOCOL, PI_WARN, "Illegal characters found in header name", EXPFILL }},
4198 		{ &ei_http_decompression_failed, { "http.decompression_failed", PI_UNDECODED, PI_WARN, "Decompression failed", EXPFILL }},
4199 		{ &ei_http_decompression_disabled, { "http.decompression_disabled", PI_UNDECODED, PI_CHAT, "Decompression disabled", EXPFILL }},
4200 	};
4201 
4202 	/* UAT for header fields */
4203 	static uat_field_t custom_header_uat_fields[] = {
4204 		UAT_FLD_CSTRING(header_fields, header_name, "Header name", "HTTP header name"),
4205 		UAT_FLD_CSTRING(header_fields, header_desc, "Field desc", "Description of the value contained in the header"),
4206 		UAT_END_FIELDS
4207 	};
4208 
4209 	module_t *http_module;
4210 	expert_module_t* expert_http;
4211 	uat_t* headers_uat;
4212 
4213 	proto_http = proto_register_protocol("Hypertext Transfer Protocol", "HTTP", "http");
4214 	proto_ssdp = proto_register_protocol("Simple Service Discovery Protocol", "SSDP", "ssdp");
4215 
4216 	proto_register_field_array(proto_http, hf, array_length(hf));
4217 	proto_register_subtree_array(ett, array_length(ett));
4218 	expert_http = expert_register_protocol(proto_http);
4219 	expert_register_field_array(expert_http, ei, array_length(ei));
4220 
4221 	http_handle = register_dissector("http", dissect_http, proto_http);
4222 	http_tcp_handle = register_dissector("http-over-tcp", dissect_http_tcp, proto_http);
4223 	http_tls_handle = register_dissector("http-over-tls", dissect_http_tls, proto_http); /* RFC 2818 */
4224 	http_sctp_handle = register_dissector("http-over-sctp", dissect_http_sctp, proto_http);
4225 
4226 	http_module = prefs_register_protocol(proto_http, reinit_http);
4227 	prefs_register_bool_preference(http_module, "desegment_headers",
4228 	    "Reassemble HTTP headers spanning multiple TCP segments",
4229 	    "Whether the HTTP dissector should reassemble headers "
4230 	    "of a request spanning multiple TCP segments. "
4231 		"To use this option, you must also enable "
4232 	"\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4233 	    &http_desegment_headers);
4234 	prefs_register_bool_preference(http_module, "desegment_body",
4235 	    "Reassemble HTTP bodies spanning multiple TCP segments",
4236 	    "Whether the HTTP dissector should use the "
4237 	    "\"Content-length:\" value, if present, to reassemble "
4238 	    "the body of a request spanning multiple TCP segments, "
4239 	    "and reassemble chunked data spanning multiple TCP segments. "
4240 		"To use this option, you must also enable "
4241 	"\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4242 	    &http_desegment_body);
4243 	prefs_register_bool_preference(http_module, "dechunk_body",
4244 	    "Reassemble chunked transfer-coded bodies",
4245 	    "Whether to reassemble bodies of entities that are transferred "
4246 	    "using the \"Transfer-Encoding: chunked\" method",
4247 	    &http_dechunk_body);
4248 #if defined(HAVE_ZLIB) || defined(HAVE_BROTLI)
4249 	prefs_register_bool_preference(http_module, "decompress_body",
4250 	    "Uncompress entity bodies",
4251 	    "Whether to uncompress entity bodies that are compressed "
4252 	    "using \"Content-Encoding: \"",
4253 	    &http_decompress_body);
4254 #endif
4255 	prefs_register_obsolete_preference(http_module, "tcp_alternate_port");
4256 
4257 	range_convert_str(wmem_epan_scope(), &global_http_sctp_range, SCTP_DEFAULT_RANGE, 65535);
4258 	prefs_register_range_preference(http_module, "sctp.port", "SCTP Ports",
4259 					"SCTP Ports range",
4260 					&global_http_sctp_range, 65535);
4261 
4262 	range_convert_str(wmem_epan_scope(), &global_http_tls_range, TLS_DEFAULT_RANGE, 65535);
4263 	prefs_register_range_preference(http_module, "tls.port", "SSL/TLS Ports",
4264 					"SSL/TLS Ports range",
4265 					&global_http_tls_range, 65535);
4266 	prefs_register_obsolete_preference(http_module, "ssl.port");
4267 	/* UAT */
4268 	headers_uat = uat_new("Custom HTTP Header Fields",
4269 			      sizeof(header_field_t),
4270 			      "custom_http_header_fields",
4271 			      TRUE,
4272 			      &header_fields,
4273 			      &num_header_fields,
4274 			      /* specifies named fields, so affects dissection
4275 			         and the set of named fields */
4276 			      UAT_AFFECTS_DISSECTION|UAT_AFFECTS_FIELDS,
4277 			      NULL,
4278 			      header_fields_copy_cb,
4279 			      header_fields_update_cb,
4280 			      header_fields_free_cb,
4281 			      header_fields_post_update_cb,
4282 			      header_fields_reset_cb,
4283 			      custom_header_uat_fields
4284 	);
4285 
4286 	prefs_register_uat_preference(http_module, "custom_http_header_fields", "Custom HTTP header fields",
4287 	    "A table to define custom HTTP header for which fields can be setup and used for filtering/data extraction etc.",
4288 	   headers_uat);
4289 
4290 	/*
4291 	 * Dissectors shouldn't register themselves in this table;
4292 	 * instead, they should call "http_tcp_dissector_add()", and
4293 	 * we'll register the port number they specify as a port
4294 	 * for HTTP, and register them in our subdissector table.
4295 	 *
4296 	 * This only works for protocols such as IPP that run over
4297 	 * HTTP on a specific non-HTTP port.
4298 	 */
4299 	port_subdissector_table = register_dissector_table("http.port",
4300 	    "TCP port for protocols using HTTP", proto_http, FT_UINT16, BASE_DEC);
4301 
4302 	/*
4303 	 * Dissectors can register themselves in this table.
4304 	 * It's just "media_type", not "http.content_type", because
4305 	 * it's an Internet media type, usable by other protocols as well.
4306 	 */
4307 	media_type_subdissector_table =
4308 	    register_dissector_table("media_type",
4309 		"Internet media type", proto_http, FT_STRING, BASE_NONE);
4310 
4311 	/*
4312 	 * Maps the lowercase Upgrade header value.
4313 	 * https://tools.ietf.org/html/rfc7230#section-8.6
4314 	 */
4315 	upgrade_subdissector_table = register_dissector_table("http.upgrade", "HTTP Upgrade", proto_http, FT_STRING, BASE_NONE);
4316 
4317 	/*
4318 	 * Heuristic dissectors SHOULD register themselves in
4319 	 * this table using the standard heur_dissector_add()
4320 	 * function.
4321 	 */
4322 	heur_subdissector_list = register_heur_dissector_list("http", proto_http);
4323 
4324 	/*
4325 	 * Register for tapping
4326 	 */
4327 	http_tap = register_tap("http"); /* HTTP statistics tap */
4328 	http_follow_tap = register_tap("http_follow"); /* HTTP Follow tap */
4329 	credentials_tap = register_tap("credentials"); /* credentials tap */
4330 
4331 	register_follow_stream(proto_http, "http_follow", tcp_follow_conv_filter, tcp_follow_index_filter, tcp_follow_address_filter,
4332 							tcp_port_to_display, follow_tvb_tap_listener);
4333 	http_eo_tap = register_export_object(proto_http, http_eo_packet, NULL);
4334 }
4335 
4336 /*
4337  * Called by dissectors for protocols that run atop HTTP/TCP.
4338  */
4339 void
http_tcp_dissector_add(guint32 port,dissector_handle_t handle)4340 http_tcp_dissector_add(guint32 port, dissector_handle_t handle)
4341 {
4342 	/*
4343 	 * Register ourselves as the handler for that port number
4344 	 * over TCP.  "Auto-preference" not needed
4345 	 */
4346 	dissector_add_uint("tcp.port", port, http_tcp_handle);
4347 
4348 	/*
4349 	 * And register them in *our* table for that port.
4350 	 */
4351 	dissector_add_uint("http.port", port, handle);
4352 }
4353 
4354 WS_DLL_PUBLIC
http_tcp_dissector_delete(guint32 port)4355 void http_tcp_dissector_delete(guint32 port)
4356 {
4357 	/*
4358 	 * Unregister ourselves as the handler for that port number
4359 	 * over TCP.  "Auto-preference" not needed
4360 	 */
4361 	dissector_delete_uint("tcp.port", port, NULL);
4362 
4363 	/*
4364 	 * And unregister them in *our* table for that port.
4365 	 */
4366 	dissector_delete_uint("http.port", port, NULL);
4367 }
4368 
4369 void
http_tcp_port_add(guint32 port)4370 http_tcp_port_add(guint32 port)
4371 {
4372 	/*
4373 	 * Register ourselves as the handler for that port number
4374 	 * over TCP.  We rely on our caller having registered
4375 	 * themselves for the appropriate media type.
4376 	 * No "auto-preference" used.
4377 	 */
4378 	dissector_add_uint("tcp.port", port, http_tcp_handle);
4379 }
4380 
4381 void
proto_reg_handoff_http(void)4382 proto_reg_handoff_http(void)
4383 {
4384 	dissector_handle_t ssdp_handle;
4385 
4386 	media_handle = find_dissector_add_dependency("media", proto_http);
4387 	http2_handle = find_dissector("http2");
4388 	/*
4389 	 * XXX - is there anything to dissect in the body of an SSDP
4390 	 * request or reply?  I.e., should there be an SSDP dissector?
4391 	 */
4392 	ssdp_handle = create_dissector_handle(dissect_ssdp, proto_ssdp);
4393 	dissector_add_uint_with_preference("udp.port", UDP_PORT_SSDP, ssdp_handle);
4394 
4395 	/*
4396 	 * TLS Application-Layer Protocol Negotiation (ALPN) protocol ID.
4397 	 */
4398 	dissector_add_string("tls.alpn", "http/1.1", http_tls_handle);
4399 
4400 	ntlmssp_handle = find_dissector_add_dependency("ntlmssp", proto_http);
4401 	gssapi_handle = find_dissector_add_dependency("gssapi", proto_http);
4402 	sstp_handle = find_dissector_add_dependency("sstp", proto_http);
4403 
4404 	stats_tree_register("http", "http",     "HTTP/Packet Counter",   0, http_stats_tree_packet,      http_stats_tree_init, NULL );
4405 	stats_tree_register("http", "http_req", "HTTP/Requests",         0, http_req_stats_tree_packet,  http_req_stats_tree_init, NULL );
4406 	stats_tree_register("http", "http_srv", "HTTP/Load Distribution",0, http_reqs_stats_tree_packet, http_reqs_stats_tree_init, NULL );
4407 	stats_tree_register("http", "http_seq", "HTTP/Request Sequences",0, http_seq_stats_tree_packet,  http_seq_stats_tree_init, NULL );
4408 
4409 	dissector_add_uint("acdr.tls_application_port", 443, http_handle);
4410 	dissector_add_uint("acdr.tls_application", TLS_APP_HTTP, http_handle);
4411 	dissector_add_uint("acdr.tls_application", TLS_APP_TR069, http_handle);
4412 	dissector_add_uint("ippusb", 0, http_tcp_handle);
4413 }
4414 
4415 /*
4416  * Content-Type: message/http
4417  */
4418 
4419 static gint proto_message_http = -1;
4420 static gint ett_message_http = -1;
4421 
4422 static int
dissect_message_http(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4423 dissect_message_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4424 {
4425 	proto_tree	*subtree;
4426 	proto_item	*ti;
4427 	gint		offset = 0, next_offset;
4428 	gint		len;
4429 
4430 	col_append_str(pinfo->cinfo, COL_INFO, " (message/http)");
4431 	if (tree) {
4432 		ti = proto_tree_add_item(tree, proto_message_http,
4433 				tvb, 0, -1, ENC_NA);
4434 		subtree = proto_item_add_subtree(ti, ett_message_http);
4435 		while (tvb_offset_exists(tvb, offset)) {
4436 			len = tvb_find_line_end(tvb, offset,
4437 					tvb_ensure_captured_length_remaining(tvb, offset),
4438 					&next_offset, FALSE);
4439 			if (len == -1)
4440 				break;
4441 			proto_tree_add_format_text(subtree, tvb, offset, len);
4442 			offset = next_offset;
4443 		}
4444 	}
4445 	return tvb_captured_length(tvb);
4446 }
4447 
4448 void
proto_register_message_http(void)4449 proto_register_message_http(void)
4450 {
4451 	static gint *ett[] = {
4452 		&ett_message_http,
4453 	};
4454 
4455 	proto_message_http = proto_register_protocol(
4456 			"Media Type: message/http",
4457 			"message/http",
4458 			"message-http"
4459 	);
4460 	proto_register_subtree_array(ett, array_length(ett));
4461 }
4462 
4463 void
proto_reg_handoff_message_http(void)4464 proto_reg_handoff_message_http(void)
4465 {
4466 	dissector_handle_t message_http_handle;
4467 
4468 	message_http_handle = create_dissector_handle(dissect_message_http,
4469 			proto_message_http);
4470 
4471 	dissector_add_string("media_type", "message/http", message_http_handle);
4472 
4473 	heur_dissector_add("tcp", dissect_http_heur_tcp, "HTTP over TCP", "http_tcp", proto_http, HEURISTIC_ENABLE);
4474 	heur_dissector_add("tls", dissect_http_heur_tls, "HTTP over TLS", "http_tls", proto_http, HEURISTIC_ENABLE);
4475 
4476 	proto_http2 = proto_get_id_by_filter_name("http2");
4477 
4478 	dissector_add_uint_range_with_preference("tcp.port", TCP_DEFAULT_RANGE, http_tcp_handle);
4479 
4480 	reinit_http();
4481 }
4482 
4483 /*
4484  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
4485  *
4486  * Local variables:
4487  * c-basic-offset: 8
4488  * tab-width: 8
4489  * indent-tabs-mode: t
4490  * End:
4491  *
4492  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
4493  * :indentSize=8:tabSize=8:noTabs=false:
4494  */
4495