2 * Routines for HTTP packet disassembly
6 * Guy Harris <guy@alum.mit.edu>
8 * Copyright 2004, Jerry Talkington <jtalkington@users.sourceforge.net>
9 * Copyright 2002, Tim Potter <tpot@samba.org>
10 * Copyright 1999, Andrew Tridgell <tridge@samba.org>
14 * Wireshark - Network traffic analyzer
15 * By Gerald Combs <gerald@wireshark.org>
16 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 #include <epan/conversation.h>
42 #include <epan/packet.h>
43 #include <epan/strutil.h>
44 #include <epan/base64.h>
45 #include <epan/emem.h>
46 #include <epan/stats_tree.h>
48 #include <epan/req_resp_hdrs.h>
49 #include "packet-http.h"
50 #include "packet-tcp.h"
51 #include <epan/prefs.h>
52 #include <epan/expert.h>
54 typedef enum _http_type {
63 static int http_tap = -1;
65 static int proto_http = -1;
66 static int hf_http_notification = -1;
67 static int hf_http_response = -1;
68 static int hf_http_request = -1;
69 static int hf_http_basic = -1;
70 static int hf_http_request_method = -1;
71 static int hf_http_request_uri = -1;
72 static int hf_http_version = -1;
73 static int hf_http_response_code = -1;
74 static int hf_http_authorization = -1;
75 static int hf_http_proxy_authenticate = -1;
76 static int hf_http_proxy_authorization = -1;
77 static int hf_http_www_authenticate = -1;
78 static int hf_http_content_type = -1;
79 static int hf_http_content_length = -1;
80 static int hf_http_content_encoding = -1;
81 static int hf_http_transfer_encoding = -1;
82 static int hf_http_user_agent = -1;
83 static int hf_http_host = -1;
84 static int hf_http_connection = -1;
85 static int hf_http_cookie = -1;
86 static int hf_http_accept = -1;
87 static int hf_http_referer = -1;
88 static int hf_http_accept_language = -1;
89 static int hf_http_accept_encoding = -1;
90 static int hf_http_date = -1;
91 static int hf_http_cache_control = -1;
92 static int hf_http_server = -1;
93 static int hf_http_location = -1;
94 static int hf_http_set_cookie = -1;
95 static int hf_http_last_modified = -1;
96 static int hf_http_x_forwarded_for = -1;
98 static gint ett_http = -1;
99 static gint ett_http_ntlmssp = -1;
100 static gint ett_http_request = -1;
101 static gint ett_http_chunked_response = -1;
102 static gint ett_http_chunk_data = -1;
103 static gint ett_http_encoded_entity = -1;
105 static dissector_handle_t data_handle;
106 static dissector_handle_t media_handle;
107 static dissector_handle_t http_handle;
110 * desegmentation of HTTP headers
111 * (when we are over TCP or another protocol providing the desegmentation API)
113 static gboolean http_desegment_headers = TRUE;
116 * desegmentation of HTTP bodies
117 * (when we are over TCP or another protocol providing the desegmentation API)
118 * TODO let the user filter on content-type the bodies he wants desegmented
120 static gboolean http_desegment_body = TRUE;
123 * De-chunking of content-encoding: chunk entity bodies.
125 static gboolean http_dechunk_body = TRUE;
128 * Decompression of zlib encoded entities.
131 static gboolean http_decompress_body = TRUE;
133 static gboolean http_decompress_body = FALSE;
137 #define TCP_PORT_HTTP 80
138 #define TCP_PORT_PROXY_HTTP 3128
139 #define TCP_PORT_PROXY_ADMIN_HTTP 3132
140 #define TCP_ALT_PORT_HTTP 8080
141 #define TCP_RADAN_HTTP 8088
142 #define TCP_PORT_HKP 11371
143 #define TCP_PORT_DAAP 3689
145 #define HTTP_PORTS (TCP_PORT_HTTP || TCP_PORT_PROXY_HTTP || TCP_PORT_PROXY_ADMIN_HTTP || TCP_ALT_PORT_HTTP || TCP_RADAN_HTTP || \
146 TCP_PORT_HKP || TCP_PORT_DAAP)
149 * SSDP is implemented atop HTTP (yes, it really *does* run over UDP).
151 #define TCP_PORT_SSDP 1900
152 #define UDP_PORT_SSDP 1900
157 static guint http_alternate_tcp_port = 0;
158 static guint alternate_tcp_port = 0;
161 * Protocols implemented atop HTTP.
164 PROTO_HTTP, /* just HTTP */
165 PROTO_SSDP, /* Simple Service Discovery Protocol */
166 PROTO_DAAP /* Digital Audio Access Protocol */
169 typedef void (*ReqRespDissector)(tvbuff_t*, proto_tree*, int, const guchar*,
173 * Structure holding information from headers needed by main
174 * HTTP dissector code.
178 char *content_type_parameters;
179 gboolean have_content_length;
180 long content_length; /* XXX - make it 64-bit? */
181 char *content_encoding;
182 char *transfer_encoding;
185 static int is_http_request_or_reply(const gchar *data, int linelen,
186 http_type_t *type, ReqRespDissector *reqresp_dissector);
187 static int chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
188 proto_tree *tree, int offset);
189 static void http_payload_subdissector(tvbuff_t *next_tvb, proto_tree *tree, proto_tree *sub_tree, packet_info *pinfo);
190 static void process_header(tvbuff_t *tvb, int offset, int next_offset,
191 const guchar *line, int linelen, int colon_offset, packet_info *pinfo,
192 proto_tree *tree, headers_t *eh_ptr);
193 static gint find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len);
194 static gboolean check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb,
195 packet_info *pinfo, gchar *value);
196 static gboolean check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb,
199 static dissector_table_t port_subdissector_table;
200 static dissector_table_t media_type_subdissector_table;
201 static heur_dissector_list_t heur_subdissector_list;
203 static dissector_handle_t ntlmssp_handle=NULL;
204 static dissector_handle_t gssapi_handle=NULL;
206 static const value_string vals_status_code[] = {
208 { 101, "Switching Protocols" },
209 { 102, "Processing" },
210 { 199, "Informational - Others" },
215 { 203, "Non-authoritative Information"},
216 { 204, "No Content"},
217 { 205, "Reset Content"},
218 { 206, "Partial Content"},
219 { 207, "Multi-Status"},
220 { 299, "Success - Others"},
222 { 300, "Multiple Choices"},
223 { 301, "Moved Permanently"},
226 { 304, "Not Modified"},
228 { 307, "Temporary Redirect"},
229 { 399, "Redirection - Others"},
231 { 400, "Bad Request"},
232 { 401, "Unauthorized"},
233 { 402, "Payment Required"},
236 { 405, "Method Not Allowed"},
237 { 406, "Not Acceptable"},
238 { 407, "Proxy Authentication Required"},
239 { 408, "Request Time-out"},
242 { 411, "Length Required"},
243 { 412, "Precondition Failed"},
244 { 413, "Request Entity Too Large"},
245 { 414, "Request-URI Too Long"},
246 { 415, "Unsupported Media Type"},
247 { 416, "Requested Range Not Satisfiable"},
248 { 417, "Expectation Failed"},
249 { 422, "Unprocessable Entity"},
251 { 424, "Failed Dependency"},
252 { 499, "Client Error - Others"},
254 { 500, "Internal Server Error"},
255 { 501, "Not Implemented"},
256 { 502, "Bad Gateway"},
257 { 503, "Service Unavailable"},
258 { 504, "Gateway Time-out"},
259 { 505, "HTTP Version not supported"},
260 { 507, "Insufficient Storage"},
261 { 599, "Server Error - Others"},
266 static const gchar* st_str_reqs = "HTTP Requests by Server";
267 static const gchar* st_str_reqs_by_srv_addr = "HTTP Requests by Server Address";
268 static const gchar* st_str_reqs_by_http_host = "HTTP Requests by HTTP Host";
269 static const gchar* st_str_resps_by_srv_addr = "HTTP Responses by Server Address";
271 static int st_node_reqs = -1;
272 static int st_node_reqs_by_srv_addr = -1;
273 static int st_node_reqs_by_http_host = -1;
274 static int st_node_resps_by_srv_addr = -1;
276 static void http_reqs_stats_tree_init(stats_tree* st) {
277 st_node_reqs = stats_tree_create_node(st, st_str_reqs, 0, TRUE);
278 st_node_reqs_by_srv_addr = stats_tree_create_node(st, st_str_reqs_by_srv_addr, st_node_reqs, TRUE);
279 st_node_reqs_by_http_host = stats_tree_create_node(st, st_str_reqs_by_http_host, st_node_reqs, TRUE);
280 st_node_resps_by_srv_addr = stats_tree_create_node(st, st_str_resps_by_srv_addr, 0, TRUE);
283 static int http_reqs_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p) {
284 const http_info_value_t* v = p;
285 int reqs_by_this_host;
286 int reqs_by_this_addr;
287 int resps_by_this_addr;
288 int i = v->response_code;
289 static gchar ip_str[256];
292 if (v->request_method) {
293 g_snprintf(ip_str,sizeof(ip_str),"%s",address_to_str(&pinfo->dst));
295 tick_stat_node(st, st_str_reqs, 0, FALSE);
296 tick_stat_node(st, st_str_reqs_by_srv_addr, st_node_reqs, TRUE);
297 tick_stat_node(st, st_str_reqs_by_http_host, st_node_reqs, TRUE);
298 reqs_by_this_addr = tick_stat_node(st, ip_str, st_node_reqs_by_srv_addr, TRUE);
301 reqs_by_this_host = tick_stat_node(st, v->http_host, st_node_reqs_by_http_host, TRUE);
302 tick_stat_node(st, ip_str, reqs_by_this_host, FALSE);
304 tick_stat_node(st, v->http_host, reqs_by_this_addr, FALSE);
310 g_snprintf(ip_str,sizeof(ip_str),"%s",address_to_str(&pinfo->src));
312 tick_stat_node(st, st_str_resps_by_srv_addr, 0, FALSE);
313 resps_by_this_addr = tick_stat_node(st, ip_str, st_node_resps_by_srv_addr, TRUE);
315 if ( (i>100)&&(i<400) ) {
316 tick_stat_node(st, "OK", resps_by_this_addr, FALSE);
318 tick_stat_node(st, "KO", resps_by_this_addr, FALSE);
328 static int st_node_requests_by_host = -1;
329 static const guint8* st_str_requests_by_host = "HTTP Requests by HTTP Host";
331 static void http_req_stats_tree_init(stats_tree* st) {
332 st_node_requests_by_host = stats_tree_create_node(st, st_str_requests_by_host, 0, TRUE);
335 static int http_req_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p) {
336 const http_info_value_t* v = p;
337 int reqs_by_this_host;
339 if (v->request_method) {
340 tick_stat_node(st, st_str_requests_by_host, 0, FALSE);
343 reqs_by_this_host = tick_stat_node(st, v->http_host, st_node_requests_by_host, TRUE);
345 if (v->request_uri) {
346 tick_stat_node(st, v->request_uri, reqs_by_this_host, TRUE);
356 static const guint8* st_str_packets = "Total HTTP Packets";
357 static const guint8* st_str_requests = "HTTP Request Packets";
358 static const guint8* st_str_responses = "HTTP Response Packets";
359 static const guint8* st_str_resp_broken = "???: broken";
360 static const guint8* st_str_resp_100 = "1xx: Informational";
361 static const guint8* st_str_resp_200 = "2xx: Success";
362 static const guint8* st_str_resp_300 = "3xx: Redirection";
363 static const guint8* st_str_resp_400 = "4xx: Client Error";
364 static const guint8* st_str_resp_500 = "5xx: Server Error";
365 static const guint8* st_str_other = "Other HTTP Packets";
367 static int st_node_packets = -1;
368 static int st_node_requests = -1;
369 static int st_node_responses = -1;
370 static int st_node_resp_broken = -1;
371 static int st_node_resp_100 = -1;
372 static int st_node_resp_200 = -1;
373 static int st_node_resp_300 = -1;
374 static int st_node_resp_400 = -1;
375 static int st_node_resp_500 = -1;
376 static int st_node_other = -1;
379 static void http_stats_tree_init(stats_tree* st) {
380 st_node_packets = stats_tree_create_node(st, st_str_packets, 0, TRUE);
381 st_node_requests = stats_tree_create_pivot(st, st_str_requests, st_node_packets);
382 st_node_responses = stats_tree_create_node(st, st_str_responses, st_node_packets, TRUE);
383 st_node_resp_broken = stats_tree_create_node(st, st_str_resp_broken, st_node_responses, TRUE);
384 st_node_resp_100 = stats_tree_create_node(st, st_str_resp_100, st_node_responses, TRUE);
385 st_node_resp_200 = stats_tree_create_node(st, st_str_resp_200, st_node_responses, TRUE);
386 st_node_resp_300 = stats_tree_create_node(st, st_str_resp_300, st_node_responses, TRUE);
387 st_node_resp_400 = stats_tree_create_node(st, st_str_resp_400, st_node_responses, TRUE);
388 st_node_resp_500 = stats_tree_create_node(st, st_str_resp_500, st_node_responses, TRUE);
389 st_node_other = stats_tree_create_node(st, st_str_other, st_node_packets,FALSE);
392 static int http_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p) {
393 const http_info_value_t* v = p;
394 guint i = v->response_code;
396 const guint8* resp_str;
397 static gchar str[64];
399 tick_stat_node(st, st_str_packets, 0, FALSE);
402 tick_stat_node(st, st_str_responses, st_node_packets, FALSE);
404 if ( (i<100)||(i>=600) ) {
405 resp_grp = st_node_resp_broken;
406 resp_str = st_str_resp_broken;
408 resp_grp = st_node_resp_100;
409 resp_str = st_str_resp_100;
411 resp_grp = st_node_resp_200;
412 resp_str = st_str_resp_200;
414 resp_grp = st_node_resp_300;
415 resp_str = st_str_resp_300;
417 resp_grp = st_node_resp_400;
418 resp_str = st_str_resp_400;
420 resp_grp = st_node_resp_500;
421 resp_str = st_str_resp_500;
424 tick_stat_node(st, resp_str, st_node_responses, FALSE);
426 g_snprintf(str, sizeof(str),"%u %s",i,match_strval(i,vals_status_code));
427 tick_stat_node(st, str, resp_grp, FALSE);
428 } else if (v->request_method) {
429 stats_tree_tick_pivot(st,st_node_requests,v->request_method);
431 tick_stat_node(st, st_str_other, st_node_packets, FALSE);
437 /* Return a tvb that contains the binary representation of a base64
441 base64_to_tvb(const char *base64)
444 char *data = g_strdup(base64);
447 len = epan_base64_decode(data);
448 tvb = tvb_new_real_data((const guint8 *)data, len, len);
450 tvb_set_free_cb(tvb, g_free);
456 dissect_http_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
459 tvbuff_t *ntlmssp_tvb;
461 ntlmssp_tvb = base64_to_tvb(line);
462 tvb_set_child_real_data_tvbuff(tvb, ntlmssp_tvb);
463 add_new_data_source(pinfo, ntlmssp_tvb, "NTLMSSP / GSSAPI Data");
464 if (tvb_strneql(ntlmssp_tvb, 0, "NTLMSSP", 7) == 0)
465 call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo, tree);
467 call_dissector(gssapi_handle, ntlmssp_tvb, pinfo, tree);
471 * TODO: remove this ugly global variable.
472 * XXX: do we really want to have to pass this from one function to another?
474 static http_info_value_t *stat_info;
477 dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
481 const char *proto_tag;
482 proto_tree *http_tree = NULL;
483 proto_item *ti = NULL;
486 const guchar *linep, *lineend;
488 int first_linelen, linelen;
489 gboolean is_request_or_reply;
490 gboolean saw_req_resp_or_header;
492 http_type_t http_type;
493 proto_item *hdr_item = NULL;
494 ReqRespDissector reqresp_dissector;
495 proto_tree *req_tree;
499 int reported_datalen = -1;
500 dissector_handle_t handle;
503 /*http_info_value_t *si;*/
504 conversation_t *conversation;
507 * Is this a request or response?
509 * Note that "tvb_find_line_end()" will return a value that
510 * is not longer than what's in the buffer, so the
511 * "tvb_get_ptr()" call won't throw an exception.
513 first_linelen = tvb_find_line_end(tvb, offset,
514 tvb_ensure_length_remaining(tvb, offset), &next_offset,
517 * Is the first line a request or response?
519 line = tvb_get_ptr(tvb, offset, first_linelen);
520 http_type = HTTP_OTHERS; /* type not known yet */
521 is_request_or_reply = is_http_request_or_reply((const gchar *)line,
522 first_linelen, &http_type, NULL);
523 if (is_request_or_reply) {
525 * Yes, it's a request or response.
526 * Do header desegmentation if we've been told to,
527 * and do body desegmentation if we've been told to and
528 * we find a Content-Length header.
530 if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
531 http_desegment_headers, http_desegment_body)) {
533 * More data needed for desegmentation.
539 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
541 if(!conversation) { /* Conversation does not exist yet - create it */
542 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
545 /* Retrieve information from conversation
546 * or add it if it isn't there yet
548 stat_info = conversation_get_proto_data(conversation, proto_http);
550 stat_info = se_alloc(sizeof(http_info_value_t));
551 stat_info->response_code = 0;
552 stat_info->request_method = NULL;
553 stat_info->request_uri = NULL;
554 stat_info->http_host = NULL;
556 conversation_add_proto_data(conversation, proto_http, stat_info);
559 switch (pinfo->match_port) {
561 case TCP_PORT_SSDP: /* TCP_PORT_SSDP = UDP_PORT_SSDP */
577 if (check_col(pinfo->cinfo, COL_PROTOCOL))
578 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);
579 if (check_col(pinfo->cinfo, COL_INFO)) {
581 * Put the first line from the buffer into the summary
582 * if it's an HTTP request or reply (but leave out the
584 * Otherwise, just call it a continuation.
586 * Note that "tvb_find_line_end()" will return a value that
587 * is not longer than what's in the buffer, so the
588 * "tvb_get_ptr()" call won't throw an exception.
590 line = tvb_get_ptr(tvb, offset, first_linelen);
591 if (is_request_or_reply)
592 col_add_str(pinfo->cinfo, COL_INFO,
593 format_text(line, first_linelen));
595 col_set_str(pinfo->cinfo, COL_INFO, "Continuation or non-HTTP traffic");
598 orig_offset = offset;
600 ti = proto_tree_add_item(tree, proto_http, tvb, offset, -1,
602 http_tree = proto_item_add_subtree(ti, ett_http);
606 * Process the packet data, a line at a time.
608 http_type = HTTP_OTHERS; /* type not known yet */
609 headers.content_type = NULL; /* content type not known yet */
610 headers.content_type_parameters = NULL; /* content type parameters too */
611 headers.have_content_length = FALSE; /* content length not known yet */
612 headers.content_encoding = NULL; /* content encoding not known yet */
613 headers.transfer_encoding = NULL; /* transfer encoding not known yet */
614 saw_req_resp_or_header = FALSE; /* haven't seen anything yet */
615 while (tvb_reported_length_remaining(tvb, offset) != 0) {
617 * Find the end of the line.
618 * XXX - what if we don't find it because the packet
619 * is cut short by a snapshot length or the header is
620 * split across TCP segments? How much dissection should
623 linelen = tvb_find_line_end(tvb, offset,
624 tvb_ensure_length_remaining(tvb, offset), &next_offset,
630 * Get a buffer that refers to the line.
632 line = tvb_get_ptr(tvb, offset, linelen);
633 lineend = line + linelen;
637 * OK, does it look like an HTTP request or response?
639 reqresp_dissector = NULL;
640 is_request_or_reply =
641 is_http_request_or_reply((const gchar *)line,
642 linelen, &http_type, &reqresp_dissector);
643 if (is_request_or_reply)
647 * No. Does it look like a blank line (as would appear
648 * at the end of an HTTP request)?
651 goto is_http; /* Yes. */
654 * No. Does it look like a header?
657 colon_offset = offset;
658 while (linep < lineend) {
662 * This must be a CHAR to be part of a token; that
663 * means it must be ASCII.
666 break; /* not ASCII, thus not a CHAR */
669 * This mustn't be a CTL to be part of a token.
671 * XXX - what about leading LWS on continuation
675 break; /* CTL, not part of a header */
678 * This mustn't be a SEP to be part of a token;
679 * a ':' ends the token, everything else is an
680 * indication that this isn't a header.
702 * It's a separator, so it's not part of a
703 * token, so it's not a field name for the
704 * beginning of a header.
706 * (We don't have to check for HT; that's
707 * already been ruled out by "iscntrl()".)
713 * This ends the token; we consider this
725 * We haven't seen the colon, but everything else looks
726 * OK for a header line.
728 * If we've already seen an HTTP request or response
729 * line, or a header line, and we're at the end of
730 * the tvbuff, we assume this is an incomplete header
731 * line. (We quit this loop after seeing a blank line,
732 * so if we've seen a request or response line, or a
733 * header line, this is probably more of the request
734 * or response we're presumably seeing. There is some
735 * risk of false positives, but the same applies for
736 * full request or response lines or header lines,
737 * although that's less likely.)
739 * We throw an exception in that case, by checking for
740 * the existence of the next byte after the last one
741 * in the line. If it exists, "tvb_ensure_bytes_exist()"
742 * throws no exception, and we fall through to the
743 * "not HTTP" case. If it doesn't exist,
744 * "tvb_ensure_bytes_exist()" will throw the appropriate
747 if (saw_req_resp_or_header)
748 tvb_ensure_bytes_exist(tvb, offset, linelen + 1);
752 * We don't consider this part of an HTTP request or
753 * reply, so we don't display it.
754 * (Yeah, that means we don't display, say, a text/http
755 * page, but you can get that from the data pane.)
765 * This is a blank line, which means that
766 * whatever follows it isn't part of this
769 proto_tree_add_text(http_tree, tvb, offset,
770 next_offset - offset, "%s",
771 tvb_format_text(tvb, offset, next_offset - offset));
772 offset = next_offset;
777 * Not a blank line - either a request, a reply, or a header
780 saw_req_resp_or_header = TRUE;
781 if (is_request_or_reply) {
783 hdr_item = proto_tree_add_text(http_tree, tvb,
784 offset, next_offset - offset, "%s",
785 tvb_format_text(tvb, offset,
786 next_offset - offset));
788 expert_add_info_format(pinfo, hdr_item, PI_SEQUENCE, PI_CHAT,
790 tvb_format_text(tvb, offset, next_offset - offset));
791 if (reqresp_dissector) {
792 if (tree) req_tree = proto_item_add_subtree(hdr_item, ett_http_request);
793 else req_tree = NULL;
795 reqresp_dissector(tvb, req_tree, offset, line, lineend);
801 process_header(tvb, offset, next_offset, line, linelen,
802 colon_offset, pinfo, http_tree, &headers);
804 offset = next_offset;
810 case HTTP_NOTIFICATION:
811 proto_tree_add_boolean_hidden(http_tree,
812 hf_http_notification, tvb, 0, 0, 1);
816 proto_tree_add_boolean_hidden(http_tree,
817 hf_http_response, tvb, 0, 0, 1);
821 proto_tree_add_boolean_hidden(http_tree,
822 hf_http_request, tvb, 0, 0, 1);
832 * If a content length was supplied, the amount of data to be
833 * processed as HTTP payload is the minimum of the content
834 * length and the amount of data remaining in the frame.
836 * If no content length was supplied (or if a bad content length
837 * was supplied), the amount of data to be processed is the amount
838 * of data remaining in the frame.
840 * If there was no Content-Length entity header, we should
841 * accumulate all data until the end of the connection.
842 * That'd require that the TCP dissector call subdissectors
843 * for all frames with FIN, even if they contain no data,
844 * which would require subdissectors to deal intelligently
845 * with empty segments.
847 * Acccording to RFC 2616, however, 1xx responses, 204 responses,
848 * and 304 responses MUST NOT include a message body; if no
849 * content length is specified for them, we don't attempt to
852 * XXX - it says the same about responses to HEAD requests;
853 * unless there's a way to determine from the response
854 * whether it's a response to a HEAD request, we have to
855 * keep information about the request and associate that with
856 * the response in order to handle that.
858 datalen = tvb_length_remaining(tvb, offset);
859 if (headers.have_content_length && headers.content_length != -1) {
860 if (datalen > headers.content_length)
861 datalen = headers.content_length;
864 * XXX - limit the reported length in the tvbuff we'll
865 * hand to a subdissector to be no greater than the
868 * We really need both unreassembled and "how long it'd
869 * be if it were reassembled" lengths for tvbuffs, so
870 * that we throw the appropriate exceptions for
871 * "not enough data captured" (running past the length),
872 * "packet needed reassembly" (within the length but
873 * running past the unreassembled length), and
874 * "packet is malformed" (running past the reassembled
877 reported_datalen = tvb_reported_length_remaining(tvb, offset);
878 if (reported_datalen > headers.content_length)
879 reported_datalen = headers.content_length;
885 * Requests have no content if there's no
886 * Content-Length header and no Transfer-Encoding
889 if (headers.transfer_encoding == NULL)
892 reported_datalen = -1;
896 if ((stat_info->response_code/100) == 1 ||
897 stat_info->response_code == 204 ||
898 stat_info->response_code == 304)
899 datalen = 0; /* no content! */
902 * XXX - responses to HEAD requests,
903 * and possibly other responses,
904 * "MUST NOT" include a
907 reported_datalen = -1;
913 * XXX - what about HTTP_NOTIFICATION?
915 reported_datalen = -1;
922 * There's stuff left over; process it.
925 void *save_private_data = NULL;
926 gint chunks_decoded = 0;
929 * Create a tvbuff for the payload.
931 * The amount of data to be processed that's
932 * available in the tvbuff is "datalen", which
933 * is the minimum of the amount of data left in
934 * the tvbuff and any specified content length.
936 * The amount of data to be processed that's in
937 * this frame, regardless of whether it was
938 * captured or not, is "reported_datalen",
939 * which, if no content length was specified,
940 * is -1, i.e. "to the end of the frame.
942 next_tvb = tvb_new_subset(tvb, offset, datalen,
945 * BEWARE - next_tvb is a subset of another tvb,
946 * so we MUST NOT attempt tvb_free(next_tvb);
950 * Handle *transfer* encodings other than "identity".
952 if (headers.transfer_encoding != NULL &&
953 strcasecmp(headers.transfer_encoding, "identity") != 0) {
954 if (http_dechunk_body &&
955 (strncasecmp(headers.transfer_encoding, "chunked", 7)
958 chunks_decoded = chunked_encoding_dissector(
959 &next_tvb, pinfo, http_tree, 0);
961 if (chunks_decoded <= 0) {
963 * The chunks weren't reassembled,
964 * or there was a single zero
970 * Add a new data source for the
973 tvb_set_child_real_data_tvbuff(tvb,
975 add_new_data_source(pinfo, next_tvb,
976 "De-chunked entity body");
980 * We currently can't handle, for example,
981 * "gzip", "compress", or "deflate" as
982 * *transfer* encodings; just handle them
985 call_dissector(data_handle, next_tvb, pinfo,
991 * At this point, any chunked *transfer* coding has been removed
992 * (the entity body has been dechunked) so it can be presented
993 * for the following operation (*content* encoding), or it has
994 * been been handed off to the data dissector.
996 * Handle *content* encodings other than "identity" (which
997 * shouldn't appear in a Content-Encoding header, but
998 * we handle it in any case).
1000 if (headers.content_encoding != NULL &&
1001 strcasecmp(headers.content_encoding, "identity") != 0) {
1003 * We currently can't handle, for example, "compress";
1004 * just handle them as data for now.
1006 * After July 7, 2004 the LZW patent expires, so support
1007 * might be added then. However, I don't think that
1008 * anybody ever really implemented "compress", due to
1009 * the aforementioned patent.
1011 tvbuff_t *uncomp_tvb = NULL;
1012 proto_item *e_ti = NULL;
1013 proto_tree *e_tree = NULL;
1015 if (http_decompress_body &&
1016 (strcasecmp(headers.content_encoding, "gzip") == 0 ||
1017 strcasecmp(headers.content_encoding, "deflate")
1020 uncomp_tvb = tvb_uncompress(next_tvb, 0,
1021 tvb_length(next_tvb));
1025 * Add the encoded entity to the protocol tree
1027 e_ti = proto_tree_add_text(http_tree, next_tvb,
1028 0, tvb_length(next_tvb),
1029 "Content-encoded entity body (%s): %u bytes",
1030 headers.content_encoding,
1031 tvb_length(next_tvb));
1032 e_tree = proto_item_add_subtree(e_ti,
1033 ett_http_encoded_entity);
1035 if (uncomp_tvb != NULL) {
1037 * Decompression worked
1040 /* XXX - Don't free this, since it's possible
1041 * that the data was only partially
1042 * decompressed, such as when desegmentation
1047 proto_item_append_text(e_ti, " -> %u bytes", tvb_length(uncomp_tvb));
1048 next_tvb = uncomp_tvb;
1049 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1050 add_new_data_source(pinfo, next_tvb,
1051 "Uncompressed entity body");
1053 if (chunks_decoded > 1) {
1054 tvb_set_child_real_data_tvbuff(tvb,
1056 add_new_data_source(pinfo, next_tvb,
1057 "Compressed entity body");
1059 call_dissector(data_handle, next_tvb, pinfo,
1062 goto body_dissected;
1066 * Note that a new data source is added for the entity body
1067 * only if it was content-encoded and/or transfer-encoded.
1071 * Do subdissector checks.
1073 * First, check whether some subdissector asked that they
1074 * be called if something was on some particular port.
1076 handle = dissector_get_port_handle(port_subdissector_table,
1078 if (handle == NULL && headers.content_type != NULL) {
1080 * We didn't find any subdissector that
1081 * registered for the port, and we have a
1082 * Content-Type value. Is there any subdissector
1083 * for that content type?
1085 save_private_data = pinfo->private_data;
1087 if (headers.content_type_parameters)
1088 pinfo->private_data = ep_strdup(headers.content_type_parameters);
1090 pinfo->private_data = NULL;
1092 * Calling the string handle for the media type
1093 * dissector table will set pinfo->match_string
1094 * to headers.content_type for us.
1096 pinfo->match_string = headers.content_type;
1097 handle = dissector_get_string_handle(
1098 media_type_subdissector_table,
1099 headers.content_type);
1101 * Calling the default media handle otherwise
1103 if (handle == NULL) {
1104 handle = media_handle;
1107 if (handle != NULL) {
1109 * We have a subdissector - call it.
1111 dissected = call_dissector(handle, next_tvb, pinfo,
1115 * We don't have a subdissector - try the heuristic
1118 dissected = dissector_try_heuristic(
1119 heur_subdissector_list, next_tvb, pinfo, tree);
1123 * The subdissector dissected the body.
1124 * Fix up the top-level item so that it doesn't
1125 * include the stuff for that protocol.
1128 proto_item_set_len(ti, offset);
1130 /* Call the subdissector (defaults to data) */
1131 http_payload_subdissector(next_tvb, tree, http_tree, pinfo);
1136 * Do *not* attempt at freeing the private data;
1137 * it may be in use by subdissectors.
1139 if (save_private_data)
1140 pinfo->private_data = save_private_data;
1142 * We've processed "datalen" bytes worth of data
1143 * (which may be no data at all); advance the
1144 * offset past whatever data we've processed.
1149 tap_queue_packet(http_tap, pinfo, stat_info);
1151 return offset - orig_offset;
1154 /* This can be used to dissect an HTTP request until such time
1155 * that a more complete dissector is written for that HTTP request.
1156 * This simple dissector only puts the request method, URI, and
1157 * protocol version into a sub-tree.
1160 basic_request_dissector(tvbuff_t *tvb, proto_tree *tree, int offset,
1161 const guchar *line, const guchar *lineend)
1163 const guchar *next_token;
1166 /* The first token is the method. */
1167 tokenlen = get_token_len(line, lineend, &next_token);
1170 proto_tree_add_item(tree, hf_http_request_method, tvb, offset, tokenlen,
1172 offset += next_token - line;
1175 /* The next token is the URI. */
1176 tokenlen = get_token_len(line, lineend, &next_token);
1179 stat_info->request_uri = se_strdup((gchar*) tvb_get_ephemeral_string(tvb, offset, tokenlen));
1180 proto_tree_add_string(tree, hf_http_request_uri, tvb, offset, tokenlen,
1181 stat_info->request_uri);
1182 offset += next_token - line;
1185 /* Everything to the end of the line is the version. */
1186 tokenlen = lineend - line;
1189 proto_tree_add_item(tree, hf_http_version, tvb, offset, tokenlen,
1194 basic_response_dissector(tvbuff_t *tvb, proto_tree *tree, int offset,
1195 const guchar *line, const guchar *lineend)
1197 const guchar *next_token;
1199 gchar response_chars[4];
1201 /* The first token is the version. */
1202 tokenlen = get_token_len(line, lineend, &next_token);
1205 proto_tree_add_item(tree, hf_http_version, tvb, offset, tokenlen,
1207 offset += next_token - line;
1210 /* The next token is the status code. */
1211 tokenlen = get_token_len(line, lineend, &next_token);
1214 memcpy(response_chars, line, 3);
1215 response_chars[3] = '\0';
1217 stat_info->response_code = strtoul(response_chars,NULL,10);
1219 proto_tree_add_uint(tree, hf_http_response_code, tvb, offset, 3,
1220 stat_info->response_code);
1224 * Dissect the http data chunks and add them to the tree.
1227 chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
1228 proto_tree *tree, int offset)
1230 guint8 *chunk_string = NULL;
1231 guint32 chunk_size = 0;
1232 gint chunk_offset = 0;
1233 guint32 datalen = 0;
1235 gint chunks_decoded = 0;
1236 tvbuff_t *tvb = NULL;
1237 tvbuff_t *new_tvb = NULL;
1238 gint chunked_data_size = 0;
1239 proto_tree *subtree = NULL;
1240 proto_item *ti = NULL;
1242 if (tvb_ptr == NULL || *tvb_ptr == NULL) {
1248 datalen = tvb_reported_length_remaining(tvb, offset);
1251 ti = proto_tree_add_text(tree, tvb, offset, datalen,
1252 "HTTP chunked response");
1253 subtree = proto_item_add_subtree(ti, ett_http_chunked_response);
1257 while (datalen != 0) {
1258 proto_item *chunk_ti = NULL;
1259 proto_tree *chunk_subtree = NULL;
1260 tvbuff_t *data_tvb = NULL;
1265 linelen = tvb_find_line_end(tvb, offset, -1, &chunk_offset, TRUE);
1268 /* Can't get the chunk size line */
1272 chunk_string = tvb_get_ephemeral_string(tvb, offset, linelen);
1274 if (chunk_string == NULL) {
1275 /* Can't get the chunk size line */
1279 c = (gchar*) chunk_string;
1282 * We don't care about the extensions.
1284 if ((c = strchr(c, ';'))) {
1288 if ( ( chunk_size = strtol((gchar*)chunk_string, NULL, 16) ) == 0 ) {
1293 if (chunk_size > datalen) {
1295 * The chunk size is more than what's in the tvbuff,
1296 * so either the user hasn't enabled decoding, or all
1297 * of the segments weren't captured.
1299 chunk_size = datalen;
1302 * chunk_size is guaranteed to be >0 from here on
1305 else if (new_tvb == NULL) {
1306 new_tvb = tvb_new_composite();
1311 if (new_tvb != NULL && chunk_size != 0) {
1312 tvbuff_t *chunk_tvb = NULL;
1314 chunk_tvb = tvb_new_subset(tvb, chunk_offset,
1315 chunk_size, datalen);
1317 tvb_composite_append(new_tvb, chunk_tvb);
1322 chunked_data_size += chunk_size;
1324 raw_data = g_malloc(chunked_data_size);
1327 if (new_tvb != NULL) {
1328 raw_len = tvb_length_remaining(new_tvb, 0);
1329 tvb_memcpy(new_tvb, raw_data, 0, raw_len);
1334 tvb_memcpy(tvb, (guint8 *)(raw_data + raw_len),
1335 chunk_offset, chunk_size);
1337 new_tvb = tvb_new_real_data(raw_data,
1338 chunked_data_size, chunked_data_size);
1339 tvb_set_free_cb(new_tvb, g_free);
1343 chunk_ti = proto_tree_add_text(subtree, tvb,
1345 chunk_offset - offset + chunk_size + 2,
1346 "Data chunk (%u octets)", chunk_size);
1348 chunk_subtree = proto_item_add_subtree(chunk_ti,
1349 ett_http_chunk_data);
1351 proto_tree_add_text(chunk_subtree, tvb, offset,
1352 chunk_offset - offset, "Chunk size: %u octets",
1355 data_tvb = tvb_new_subset(tvb, chunk_offset, chunk_size,
1360 * XXX - just use "proto_tree_add_text()"?
1361 * This means that, in TShark, you get
1362 * the entire chunk dumped out in hex,
1363 * in addition to whatever dissection is
1364 * done on the reassembled data.
1366 call_dissector(data_handle, data_tvb, pinfo,
1369 proto_tree_add_text(chunk_subtree, tvb, chunk_offset +
1370 chunk_size, 2, "Chunk boundary");
1374 offset = chunk_offset + chunk_size + 2;
1375 datalen = tvb_reported_length_remaining(tvb, offset);
1378 if (new_tvb != NULL) {
1380 /* Placeholder for the day that composite tvbuffer's will work.
1381 tvb_composite_finalize(new_tvb);
1382 / * tvb_set_reported_length(new_tvb, chunked_data_size); * /
1386 * XXX - Don't free this, since the tvbuffer that was passed
1387 * may be used if the data spans multiple frames and reassembly
1396 * We didn't create a new tvb, so don't allow sub dissectors
1397 * try to decode the non-existant entity body.
1399 chunks_decoded = -1;
1402 return chunks_decoded;
1407 http_payload_subdissector(tvbuff_t *next_tvb, proto_tree *tree, proto_tree *sub_tree, packet_info *pinfo)
1409 /* tree = the main protocol tree that the subdissector would be listed in
1410 * sub_tree = the http protocol tree
1413 struct tcpinfo *tcpinfo = pinfo->private_data;
1414 struct tcp_analysis *tcpd=NULL;
1415 gchar **strings; /* An array for spitting the request URI into hostname and port */
1417 /* Response code 200 means "OK" and strncmp() == 0 means the strings match exactly */
1418 if(stat_info->request_method != NULL && stat_info->response_code == 200 &&
1419 strncmp(stat_info->request_method, "CONNECT", 7) == 0) {
1421 /* Call a subdissector to handle HTTP CONNECT's traffic */
1422 tcpd=get_tcp_conversation_data(pinfo);
1424 /* Grab the destination port number from the request URI to find the right subdissector */
1425 strings = g_strsplit(stat_info->request_uri, ":", 2);
1427 if(strings[1] != NULL) { /* The string was successfuly split in two */
1428 proto_tree_add_text(sub_tree, next_tvb, 0, 0, "Proxy connect hostname: %s", strings[0]);
1429 proto_tree_add_text(sub_tree, next_tvb, 0, 0, "Proxy connect port: %s", strings[1]);
1431 /* Replaces the pinfo->destport or srcport with the port the http connect was done to */
1432 /* pinfo->srcport and destport are guint32 variables (epan/packet_info.h) */
1433 if (pinfo->destport == HTTP_PORTS)
1434 ptr = &pinfo->destport;
1436 ptr = &pinfo->srcport;
1438 *ptr = (int)strtol(strings[1], NULL, 10); /* Convert string to a base-10 integer */
1440 dissect_tcp_payload(next_tvb, pinfo, 0, tcpinfo->seq, /* 0 = offset */
1441 tcpinfo->nxtseq, pinfo->srcport, pinfo->destport,
1445 g_strfreev(strings); /* Free the result of g_strsplit() above */
1448 /* Call the default data dissector */
1449 call_dissector(data_handle, next_tvb, pinfo, sub_tree);
1456 * XXX - this won't handle HTTP 0.9 replies, but they're all data
1460 is_http_request_or_reply(const gchar *data, int linelen, http_type_t *type,
1461 ReqRespDissector *reqresp_dissector)
1463 int isHttpRequestOrReply = FALSE;
1467 * From RFC 2774 - An HTTP Extension Framework
1469 * Support the command prefix that identifies the presence of
1470 * a "mandatory" header.
1472 if (linelen >= 2 && strncmp(data, "M-", 2) == 0) {
1479 * From draft-cohen-gena-client-01.txt, available from the uPnP forum:
1480 * NOTIFY, SUBSCRIBE, UNSUBSCRIBE
1482 * From draft-ietf-dasl-protocol-00.txt, a now vanished Microsoft draft:
1485 if (linelen >= 5 && strncmp(data, "HTTP/", 5) == 0) {
1486 *type = HTTP_RESPONSE;
1487 isHttpRequestOrReply = TRUE; /* response */
1488 if (reqresp_dissector)
1489 *reqresp_dissector = basic_response_dissector;
1491 const guchar * ptr = (const guchar *)data;
1494 /* Look for the space following the Method */
1495 while (index < linelen) {
1504 /* Check the methods that have same length */
1508 if (strncmp(data, "GET", index) == 0 ||
1509 strncmp(data, "PUT", index) == 0) {
1510 *type = HTTP_REQUEST;
1511 isHttpRequestOrReply = TRUE;
1513 else if (strncmp(data, "ICY", index) == 0) {
1514 *type = HTTP_RESPONSE;
1515 isHttpRequestOrReply = TRUE;
1520 if (strncmp(data, "COPY", index) == 0 ||
1521 strncmp(data, "HEAD", index) == 0 ||
1522 strncmp(data, "LOCK", index) == 0 ||
1523 strncmp(data, "MOVE", index) == 0 ||
1524 strncmp(data, "POLL", index) == 0 ||
1525 strncmp(data, "POST", index) == 0) {
1526 *type = HTTP_REQUEST;
1527 isHttpRequestOrReply = TRUE;
1532 if (strncmp(data, "BCOPY", index) == 0 ||
1533 strncmp(data, "BMOVE", index) == 0 ||
1534 strncmp(data, "MKCOL", index) == 0 ||
1535 strncmp(data, "TRACE", index) == 0 ||
1536 strncmp(data, "LABEL", index) == 0 || /* RFC 3253 8.2 */
1537 strncmp(data, "MERGE", index) == 0) { /* RFC 3253 11.2 */
1538 *type = HTTP_REQUEST;
1539 isHttpRequestOrReply = TRUE;
1544 if (strncmp(data, "DELETE", index) == 0 ||
1545 strncmp(data, "SEARCH", index) == 0 ||
1546 strncmp(data, "UNLOCK", index) == 0 ||
1547 strncmp(data, "REPORT", index) == 0 || /* RFC 3253 3.6 */
1548 strncmp(data, "UPDATE", index) == 0) { /* RFC 3253 7.1 */
1549 *type = HTTP_REQUEST;
1550 isHttpRequestOrReply = TRUE;
1552 else if (strncmp(data, "NOTIFY", index) == 0) {
1553 *type = HTTP_NOTIFICATION;
1554 isHttpRequestOrReply = TRUE;
1559 if (strncmp(data, "BDELETE", index) == 0 ||
1560 strncmp(data, "CONNECT", index) == 0 ||
1561 strncmp(data, "OPTIONS", index) == 0 ||
1562 strncmp(data, "CHECKIN", index) == 0) { /* RFC 3253 4.4, 9.4 */
1563 *type = HTTP_REQUEST;
1564 isHttpRequestOrReply = TRUE;
1569 if (strncmp(data, "PROPFIND", index) == 0 ||
1570 strncmp(data, "CHECKOUT", index) == 0 || /* RFC 3253 4.3, 9.3 */
1571 strncmp(data, "CCM_POST", index) == 0) {
1572 *type = HTTP_REQUEST;
1573 isHttpRequestOrReply = TRUE;
1578 if (strncmp(data, "SUBSCRIBE", index) == 0) {
1579 *type = HTTP_NOTIFICATION;
1580 isHttpRequestOrReply = TRUE;
1581 } else if (strncmp(data, "PROPPATCH", index) == 0 ||
1582 strncmp(data, "BPROPFIND", index) == 0) {
1583 *type = HTTP_REQUEST;
1584 isHttpRequestOrReply = TRUE;
1589 if (strncmp(data, "BPROPPATCH", index) == 0 ||
1590 strncmp(data, "UNCHECKOUT", index) == 0 || /* RFC 3253 4.5 */
1591 strncmp(data, "MKACTIVITY", index) == 0) { /* RFC 3253 13.5 */
1592 *type = HTTP_REQUEST;
1593 isHttpRequestOrReply = TRUE;
1598 if (strncmp(data, "MKWORKSPACE", index) == 0) { /* RFC 3253 6.3 */
1599 *type = HTTP_REQUEST;
1600 isHttpRequestOrReply = TRUE;
1601 } else if (strncmp(data, "UNSUBSCRIBE", index) == 0) {
1602 *type = HTTP_NOTIFICATION;
1603 isHttpRequestOrReply = TRUE;
1604 } else if (strncmp(data, "RPC_CONNECT", index) == 0) {
1605 *type = HTTP_REQUEST;
1606 isHttpRequestOrReply = TRUE;
1611 if (strncmp(data, "VERSION-CONTROL", index) == 0) { /* RFC 3253 3.5 */
1612 *type = HTTP_REQUEST;
1613 isHttpRequestOrReply = TRUE;
1618 if (strncmp(data, "BASELINE-CONTROL", index) == 0) { /* RFC 3253 12.6 */
1619 *type = HTTP_REQUEST;
1620 isHttpRequestOrReply = TRUE;
1628 if (isHttpRequestOrReply && reqresp_dissector) {
1629 *reqresp_dissector = basic_request_dissector;
1630 if (!stat_info->request_method)
1631 stat_info->request_method = se_strndup(data, index+1);
1635 return isHttpRequestOrReply;
1647 #define HDR_NO_SPECIAL 0
1648 #define HDR_AUTHORIZATION 1
1649 #define HDR_AUTHENTICATE 2
1650 #define HDR_CONTENT_TYPE 3
1651 #define HDR_CONTENT_LENGTH 4
1652 #define HDR_CONTENT_ENCODING 5
1653 #define HDR_TRANSFER_ENCODING 6
1656 static const header_info headers[] = {
1657 { "Authorization", &hf_http_authorization, HDR_AUTHORIZATION },
1658 { "Proxy-Authorization", &hf_http_proxy_authorization, HDR_AUTHORIZATION },
1659 { "Proxy-Authenticate", &hf_http_proxy_authenticate, HDR_AUTHENTICATE },
1660 { "WWW-Authenticate", &hf_http_www_authenticate, HDR_AUTHENTICATE },
1661 { "Content-Type", &hf_http_content_type, HDR_CONTENT_TYPE },
1662 { "Content-Length", &hf_http_content_length, HDR_CONTENT_LENGTH },
1663 { "Content-Encoding", &hf_http_content_encoding, HDR_CONTENT_ENCODING },
1664 { "Transfer-Encoding", &hf_http_transfer_encoding, HDR_TRANSFER_ENCODING },
1665 { "User-Agent", &hf_http_user_agent, HDR_NO_SPECIAL },
1666 { "Host", &hf_http_host, HDR_HOST },
1667 { "Connection", &hf_http_connection, HDR_NO_SPECIAL },
1668 { "Cookie", &hf_http_cookie, HDR_NO_SPECIAL },
1669 { "Accept", &hf_http_accept, HDR_NO_SPECIAL },
1670 { "Referer", &hf_http_referer, HDR_NO_SPECIAL },
1671 { "Accept-Language", &hf_http_accept_language, HDR_NO_SPECIAL },
1672 { "Accept-Encoding", &hf_http_accept_encoding, HDR_NO_SPECIAL },
1673 { "Date", &hf_http_date, HDR_NO_SPECIAL },
1674 { "Cache-Control", &hf_http_cache_control, HDR_NO_SPECIAL },
1675 { "Server", &hf_http_server, HDR_NO_SPECIAL },
1676 { "Location", &hf_http_location, HDR_NO_SPECIAL },
1677 { "Set-Cookie", &hf_http_set_cookie, HDR_NO_SPECIAL },
1678 { "Last-Modified", &hf_http_last_modified, HDR_NO_SPECIAL },
1679 { "X-Forwarded-For", &hf_http_x_forwarded_for, HDR_NO_SPECIAL },
1683 process_header(tvbuff_t *tvb, int offset, int next_offset,
1684 const guchar *line, int linelen, int colon_offset,
1685 packet_info *pinfo, proto_tree *tree, headers_t *eh_ptr)
1688 int line_end_offset;
1697 proto_item *hdr_item;
1700 len = next_offset - offset;
1701 line_end_offset = offset + linelen;
1702 header_len = colon_offset - offset;
1703 hf_index = find_header_hf_value(tvb, offset, header_len);
1705 if (hf_index == -1) {
1707 * Not a header we know anything about. Just put it into
1711 proto_tree_add_text(tree, tvb, offset, len,
1712 "%s", format_text(line, len));
1716 * Skip whitespace after the colon.
1718 value_offset = colon_offset + 1;
1719 while (value_offset < line_end_offset
1720 && ((c = line[value_offset - offset]) == ' ' || c == '\t'))
1726 value_len = line_end_offset - value_offset;
1727 value = ep_strndup(&line[value_offset - offset], value_len);
1730 * Add it to the protocol tree as a particular field,
1731 * but display the line as is.
1734 hdr_item = proto_tree_add_string_format(tree,
1735 *headers[hf_index].hf, tvb, offset, len,
1736 value, "%s", format_text(line, len));
1741 * Do any special processing that particular headers
1744 switch (headers[hf_index].special) {
1746 case HDR_AUTHORIZATION:
1747 if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))
1748 break; /* dissected NTLMSSP */
1749 check_auth_basic(hdr_item, tvb, value);
1752 case HDR_AUTHENTICATE:
1753 check_auth_ntlmssp(hdr_item, tvb, pinfo, value);
1756 case HDR_CONTENT_TYPE:
1757 eh_ptr->content_type = (gchar*) ep_memdup((guint8*)value,value_len + 1);
1759 for (i = 0; i < value_len; i++) {
1761 if (c == ';' || isspace(c)) {
1763 * End of subtype - either
1764 * white space or a ";"
1765 * separating the subtype from
1772 * Map the character to lower case;
1773 * content types are case-insensitive.
1775 eh_ptr->content_type[i] = tolower(eh_ptr->content_type[i]);
1777 eh_ptr->content_type[i] = '\0';
1779 * Now find the start of the optional parameters;
1780 * skip the optional white space and the semicolon
1781 * if this has not been done before.
1784 while (i < value_len) {
1785 c = eh_ptr->content_type[i];
1786 if (c == ';' || isspace(c))
1787 /* Skip till start of parameters */
1793 eh_ptr->content_type_parameters = eh_ptr->content_type + i;
1795 eh_ptr->content_type_parameters = NULL;
1798 case HDR_CONTENT_LENGTH:
1799 eh_ptr->content_length = strtol(value, &p, 10);
1801 if (eh_ptr->content_length < 0 || p == value ||
1802 (*up != '\0' && !isspace(*up))) {
1804 * Content length not valid; pretend
1807 eh_ptr->have_content_length = FALSE;
1810 * We do have a valid content length.
1812 eh_ptr->have_content_length = TRUE;
1816 case HDR_CONTENT_ENCODING:
1817 eh_ptr->content_encoding = ep_strndup(value, value_len);
1820 case HDR_TRANSFER_ENCODING:
1821 eh_ptr->transfer_encoding = ep_strndup(value, value_len);
1825 stat_info->http_host = ep_strndup(value, value_len);
1832 /* Returns index of header tag in headers */
1834 find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len)
1838 for (i = 0; i < array_length(headers); i++) {
1839 if (header_len == strlen(headers[i].name) &&
1840 tvb_strncaseeql(tvb, offset,
1841 headers[i].name, header_len) == 0)
1849 * Dissect Microsoft's abomination called NTLMSSP over HTTP.
1852 check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo,
1855 static const char *ntlm_headers[] = {
1860 const char **header;
1862 proto_tree *hdr_tree;
1865 * Check for NTLM credentials and challenge; those can
1866 * occur with WWW-Authenticate.
1868 for (header = &ntlm_headers[0]; *header != NULL; header++) {
1869 hdrlen = strlen(*header);
1870 if (strncmp(value, *header, hdrlen) == 0) {
1871 if (hdr_item != NULL) {
1872 hdr_tree = proto_item_add_subtree(hdr_item,
1877 dissect_http_ntlmssp(tvb, pinfo, hdr_tree, value);
1885 * Dissect HTTP Basic authorization.
1888 check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb, gchar *value)
1890 static const char *basic_headers[] = {
1894 const char **header;
1896 proto_tree *hdr_tree;
1899 for (header = &basic_headers[0]; *header != NULL; header++) {
1900 hdrlen = strlen(*header);
1901 if (strncmp(value, *header, hdrlen) == 0) {
1902 if (hdr_item != NULL) {
1903 hdr_tree = proto_item_add_subtree(hdr_item,
1909 len = epan_base64_decode(value);
1911 proto_tree_add_string(hdr_tree, hf_http_basic, tvb,
1921 dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1926 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1927 len = dissect_http_message(tvb, offset, pinfo, tree);
1933 * OK, we've set the Protocol and Info columns for the
1934 * first HTTP message; make the columns non-writable,
1935 * so that we don't change it for subsequent HTTP messages.
1937 col_set_writable(pinfo->cinfo, FALSE);
1942 dissect_http_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1944 dissect_http_message(tvb, 0, pinfo, tree);
1947 static void reinit_http(void) {
1948 if ( http_alternate_tcp_port != alternate_tcp_port ) {
1950 if (alternate_tcp_port)
1951 dissector_delete("tcp.port", alternate_tcp_port, http_handle );
1953 if (http_alternate_tcp_port)
1954 dissector_add("tcp.port", http_alternate_tcp_port, http_handle);
1956 alternate_tcp_port = http_alternate_tcp_port;
1961 proto_register_http(void)
1963 static hf_register_info hf[] = {
1964 { &hf_http_notification,
1965 { "Notification", "http.notification",
1966 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1967 "TRUE if HTTP notification", HFILL }},
1968 { &hf_http_response,
1969 { "Response", "http.response",
1970 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1971 "TRUE if HTTP response", HFILL }},
1973 { "Request", "http.request",
1974 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1975 "TRUE if HTTP request", HFILL }},
1977 { "Credentials", "http.authbasic",
1978 FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1979 { &hf_http_request_method,
1980 { "Request Method", "http.request.method",
1981 FT_STRING, BASE_NONE, NULL, 0x0,
1982 "HTTP Request Method", HFILL }},
1983 { &hf_http_request_uri,
1984 { "Request URI", "http.request.uri",
1985 FT_STRING, BASE_NONE, NULL, 0x0,
1986 "HTTP Request-URI", HFILL }},
1988 { "Request Version", "http.request.version",
1989 FT_STRING, BASE_NONE, NULL, 0x0,
1990 "HTTP Request HTTP-Version", HFILL }},
1991 { &hf_http_response_code,
1992 { "Response Code", "http.response.code",
1993 FT_UINT16, BASE_DEC, NULL, 0x0,
1994 "HTTP Response Code", HFILL }},
1995 { &hf_http_authorization,
1996 { "Authorization", "http.authorization",
1997 FT_STRING, BASE_NONE, NULL, 0x0,
1998 "HTTP Authorization header", HFILL }},
1999 { &hf_http_proxy_authenticate,
2000 { "Proxy-Authenticate", "http.proxy_authenticate",
2001 FT_STRING, BASE_NONE, NULL, 0x0,
2002 "HTTP Proxy-Authenticate header", HFILL }},
2003 { &hf_http_proxy_authorization,
2004 { "Proxy-Authorization", "http.proxy_authorization",
2005 FT_STRING, BASE_NONE, NULL, 0x0,
2006 "HTTP Proxy-Authorization header", HFILL }},
2007 { &hf_http_www_authenticate,
2008 { "WWW-Authenticate", "http.www_authenticate",
2009 FT_STRING, BASE_NONE, NULL, 0x0,
2010 "HTTP WWW-Authenticate header", HFILL }},
2011 { &hf_http_content_type,
2012 { "Content-Type", "http.content_type",
2013 FT_STRING, BASE_NONE, NULL, 0x0,
2014 "HTTP Content-Type header", HFILL }},
2015 { &hf_http_content_length,
2016 { "Content-Length", "http.content_length",
2017 FT_STRING, BASE_NONE, NULL, 0x0,
2018 "HTTP Content-Length header", HFILL }},
2019 { &hf_http_content_encoding,
2020 { "Content-Encoding", "http.content_encoding",
2021 FT_STRING, BASE_NONE, NULL, 0x0,
2022 "HTTP Content-Encoding header", HFILL }},
2023 { &hf_http_transfer_encoding,
2024 { "Transfer-Encoding", "http.transfer_encoding",
2025 FT_STRING, BASE_NONE, NULL, 0x0,
2026 "HTTP Transfer-Encoding header", HFILL }},
2027 { &hf_http_user_agent,
2028 { "User-Agent", "http.user_agent",
2029 FT_STRING, BASE_NONE, NULL, 0x0,
2030 "HTTP User-Agent header", HFILL }},
2032 { "Host", "http.host",
2033 FT_STRING, BASE_NONE, NULL, 0x0,
2034 "HTTP Host", HFILL }},
2035 { &hf_http_connection,
2036 { "Connection", "http.connection",
2037 FT_STRING, BASE_NONE, NULL, 0x0,
2038 "HTTP Connection", HFILL }},
2040 { "Cookie", "http.cookie",
2041 FT_STRING, BASE_NONE, NULL, 0x0,
2042 "HTTP Cookie", HFILL }},
2044 { "Accept", "http.accept",
2045 FT_STRING, BASE_NONE, NULL, 0x0,
2046 "HTTP Accept", HFILL }},
2048 { "Referer", "http.referer",
2049 FT_STRING, BASE_NONE, NULL, 0x0,
2050 "HTTP Referer", HFILL }},
2051 { &hf_http_accept_language,
2052 { "Accept-Language", "http.accept_language",
2053 FT_STRING, BASE_NONE, NULL, 0x0,
2054 "HTTP Accept Language", HFILL }},
2055 { &hf_http_accept_encoding,
2056 { "Accept Encoding", "http.accept_encoding",
2057 FT_STRING, BASE_NONE, NULL, 0x0,
2058 "HTTP Accept Encoding", HFILL }},
2060 { "Date", "http.date",
2061 FT_STRING, BASE_NONE, NULL, 0x0,
2062 "HTTP Date", HFILL }},
2063 { &hf_http_cache_control,
2064 { "Cache-Control", "http.cache_control",
2065 FT_STRING, BASE_NONE, NULL, 0x0,
2066 "HTTP Cache Control", HFILL }},
2068 { "Server", "http.server",
2069 FT_STRING, BASE_NONE, NULL, 0x0,
2070 "HTTP Server", HFILL }},
2071 { &hf_http_location,
2072 { "Location", "http.location",
2073 FT_STRING, BASE_NONE, NULL, 0x0,
2074 "HTTP Location", HFILL }},
2075 { &hf_http_set_cookie,
2076 { "Set-Cookie", "http.set_cookie",
2077 FT_STRING, BASE_NONE, NULL, 0x0,
2078 "HTTP Set Cookie", HFILL }},
2079 { &hf_http_last_modified,
2080 { "Last-Modified", "http.last_modified",
2081 FT_STRING, BASE_NONE, NULL, 0x0,
2082 "HTTP Last Modified", HFILL }},
2083 { &hf_http_x_forwarded_for,
2084 { "X-Forwarded-For", "http.x_forwarded_for",
2085 FT_STRING, BASE_NONE, NULL, 0x0,
2086 "HTTP X-Forwarded-For", HFILL }},
2088 static gint *ett[] = {
2092 &ett_http_chunked_response,
2093 &ett_http_chunk_data,
2094 &ett_http_encoded_entity,
2096 module_t *http_module;
2098 proto_http = proto_register_protocol("Hypertext Transfer Protocol",
2100 proto_register_field_array(proto_http, hf, array_length(hf));
2101 proto_register_subtree_array(ett, array_length(ett));
2102 register_dissector("http", dissect_http, proto_http);
2103 http_module = prefs_register_protocol(proto_http, reinit_http);
2104 prefs_register_bool_preference(http_module, "desegment_headers",
2105 "Reassemble HTTP headers spanning multiple TCP segments",
2106 "Whether the HTTP dissector should reassemble headers "
2107 "of a request spanning multiple TCP segments. "
2108 "To use this option, you must also enable "
2109 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2110 &http_desegment_headers);
2111 prefs_register_bool_preference(http_module, "desegment_body",
2112 "Reassemble HTTP bodies spanning multiple TCP segments",
2113 "Whether the HTTP dissector should use the "
2114 "\"Content-length:\" value, if present, to reassemble "
2115 "the body of a request spanning multiple TCP segments, "
2116 "and reassemble chunked data spanning multiple TCP segments. "
2117 "To use this option, you must also enable "
2118 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2119 &http_desegment_body);
2120 prefs_register_bool_preference(http_module, "dechunk_body",
2121 "Reassemble chunked transfer-coded bodies",
2122 "Whether to reassemble bodies of entities that are transfered "
2123 "using the \"Transfer-Encoding: chunked\" method",
2124 &http_dechunk_body);
2126 prefs_register_bool_preference(http_module, "decompress_body",
2127 "Uncompress entity bodies",
2128 "Whether to uncompress entity bodies that are compressed "
2129 "using \"Content-Encoding: \"",
2130 &http_decompress_body);
2132 prefs_register_uint_preference(http_module, "tcp_alternate_port",
2133 "Alternate TCP port",
2134 "Decode packets on this TCP port as HTTP",
2135 10,&http_alternate_tcp_port);
2137 http_handle = create_dissector_handle(dissect_http, proto_http);
2140 * Dissectors shouldn't register themselves in this table;
2141 * instead, they should call "http_dissector_add()", and
2142 * we'll register the port number they specify as a port
2143 * for HTTP, and register them in our subdissector table.
2145 * This only works for protocols such as IPP that run over
2146 * HTTP on a specific non-HTTP port.
2148 port_subdissector_table = register_dissector_table("http.port",
2149 "TCP port for protocols using HTTP", FT_UINT16, BASE_DEC);
2152 * Dissectors can register themselves in this table.
2153 * It's just "media_type", not "http.content_type", because
2154 * it's an Internet media type, usable by other protocols as well.
2156 media_type_subdissector_table =
2157 register_dissector_table("media_type",
2158 "Internet media type", FT_STRING, BASE_NONE);
2161 * Heuristic dissectors SHOULD register themselves in
2162 * this table using the standard heur_dissector_add()
2165 register_heur_dissector_list("http", &heur_subdissector_list);
2168 * Register for tapping
2170 http_tap = register_tap("http");
2174 * Called by dissectors for protocols that run atop HTTP/TCP.
2177 http_dissector_add(guint32 port, dissector_handle_t handle)
2180 * Register ourselves as the handler for that port number
2183 dissector_add("tcp.port", port, http_handle);
2186 * And register them in *our* table for that port.
2188 dissector_add("http.port", port, handle);
2192 proto_reg_handoff_http(void)
2194 dissector_handle_t http_udp_handle;
2196 data_handle = find_dissector("data");
2197 media_handle = find_dissector("media");
2199 dissector_add("tcp.port", TCP_PORT_HTTP, http_handle);
2200 dissector_add("tcp.port", TCP_PORT_PROXY_HTTP, http_handle);
2201 dissector_add("tcp.port", TCP_ALT_PORT_HTTP, http_handle);
2202 dissector_add("tcp.port", TCP_RADAN_HTTP, http_handle);
2203 dissector_add("tcp.port", TCP_PORT_PROXY_ADMIN_HTTP, http_handle);
2204 dissector_add("tcp.port", TCP_PORT_HKP, http_handle);
2207 * XXX - is there anything to dissect in the body of an SSDP
2208 * request or reply? I.e., should there be an SSDP dissector?
2210 dissector_add("tcp.port", TCP_PORT_SSDP, http_handle);
2211 http_udp_handle = create_dissector_handle(dissect_http_udp, proto_http);
2212 dissector_add("udp.port", UDP_PORT_SSDP, http_udp_handle);
2214 ntlmssp_handle = find_dissector("ntlmssp");
2215 gssapi_handle = find_dissector("gssapi");
2217 stats_tree_register("http","http","HTTP/Packet Counter", http_stats_tree_packet, http_stats_tree_init, NULL );
2218 stats_tree_register("http","http_req","HTTP/Requests", http_req_stats_tree_packet, http_req_stats_tree_init, NULL );
2219 stats_tree_register("http","http_srv","HTTP/Load Distribution",http_reqs_stats_tree_packet,http_reqs_stats_tree_init, NULL );
2224 * Content-Type: message/http
2227 static gint proto_message_http = -1;
2228 static gint ett_message_http = -1;
2229 static dissector_handle_t message_http_handle;
2232 dissect_message_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2234 proto_tree *subtree;
2236 gint offset = 0, next_offset;
2239 if (check_col(pinfo->cinfo, COL_INFO))
2240 col_append_str(pinfo->cinfo, COL_INFO, " (message/http)");
2242 ti = proto_tree_add_item(tree, proto_message_http,
2244 subtree = proto_item_add_subtree(ti, ett_message_http);
2245 while (tvb_reported_length_remaining(tvb, offset) != 0) {
2246 len = tvb_find_line_end(tvb, offset,
2247 tvb_ensure_length_remaining(tvb, offset),
2248 &next_offset, FALSE);
2251 proto_tree_add_text(subtree, tvb, offset, next_offset - offset,
2252 "%s", tvb_format_text(tvb, offset, len));
2253 offset = next_offset;
2259 proto_register_message_http(void)
2261 static gint *ett[] = {
2265 proto_message_http = proto_register_protocol(
2266 "Media Type: message/http",
2270 proto_register_subtree_array(ett, array_length(ett));
2274 proto_reg_handoff_message_http(void)
2276 message_http_handle = create_dissector_handle(dissect_message_http,
2277 proto_message_http);
2279 dissector_add_string("media_type", "message/http", message_http_handle);