da505dcab38a011f6cb43911dfd5a72f32cdd79e
[obnox/wireshark/wip.git] / packet-http.c
1 /* packet-http.c
2  * Routines for HTTP packet disassembly
3  *
4  * Guy Harris <guy@alum.mit.edu>
5  *
6  * Copyright 2004, Jerry Talkington <jtalkington@users.sourceforge.net>
7  * Copyright 2002, Tim Potter <tpot@samba.org>
8  * Copyright 1999, Andrew Tridgell <tridge@samba.org>
9  *
10  * $Id: packet-http.c,v 1.102 2004/05/04 07:12:03 guy Exp $
11  *
12  * Ethereal - Network traffic analyzer
13  * By Gerald Combs <gerald@ethereal.com>
14  * Copyright 1998 Gerald Combs
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <string.h>
36 #include <ctype.h>
37
38 #include <glib.h>
39 #include <epan/packet.h>
40 #include <epan/strutil.h>
41
42 #include "util.h"
43 #include "req_resp_hdrs.h"
44 #include "packet-http.h"
45 #include "prefs.h"
46
47 typedef enum _http_type {
48         HTTP_REQUEST,
49         HTTP_RESPONSE,
50         HTTP_NOTIFICATION,
51         HTTP_OTHERS
52 } http_type_t;
53
54 #include "tap.h"
55
56 static int http_tap = -1;
57
58 static int proto_http = -1;
59 static int hf_http_notification = -1;
60 static int hf_http_response = -1;
61 static int hf_http_request = -1;
62 static int hf_http_basic = -1;
63 static int hf_http_request_method = -1;
64 static int hf_http_response_code = -1;
65 static int hf_http_authorization = -1;
66 static int hf_http_proxy_authenticate = -1;
67 static int hf_http_proxy_authorization = -1;
68 static int hf_http_www_authenticate = -1;
69 static int hf_http_content_type = -1;
70 static int hf_http_content_length = -1;
71 static int hf_http_content_encoding = -1;
72 static int hf_http_transfer_encoding = -1;
73
74 static gint ett_http = -1;
75 static gint ett_http_ntlmssp = -1;
76 static gint ett_http_request = -1;
77 static gint ett_http_chunked_response = -1;
78 static gint ett_http_chunk_data = -1;
79 static gint ett_http_encoded_entity = -1;
80
81 static dissector_handle_t data_handle;
82 static dissector_handle_t media_handle;
83 static dissector_handle_t http_handle;
84
85 /*
86  * desegmentation of HTTP headers
87  * (when we are over TCP or another protocol providing the desegmentation API)
88  */
89 static gboolean http_desegment_headers = FALSE;
90
91 /*
92  * desegmentation of HTTP bodies
93  * (when we are over TCP or another protocol providing the desegmentation API)
94  * TODO let the user filter on content-type the bodies he wants desegmented
95  */
96 static gboolean http_desegment_body = FALSE;
97
98 #define TCP_PORT_HTTP                   80
99 #define TCP_PORT_PROXY_HTTP             3128
100 #define TCP_PORT_PROXY_ADMIN_HTTP       3132
101 #define TCP_ALT_PORT_HTTP               8080
102
103 /*
104  * SSDP is implemented atop HTTP (yes, it really *does* run over UDP).
105  */
106 #define TCP_PORT_SSDP                   1900
107 #define UDP_PORT_SSDP                   1900
108
109 /*
110  * Protocols implemented atop HTTP.
111  */
112 typedef enum {
113         PROTO_HTTP,             /* just HTTP */
114         PROTO_SSDP              /* Simple Service Discovery Protocol */
115 } http_proto_t;
116
117 typedef void (*RequestDissector)(tvbuff_t*, proto_tree*, int);
118
119 /*
120  * Structure holding information from headers needed by main
121  * HTTP dissector code.
122  */
123 typedef struct {
124         char    *content_type;
125         char    *content_type_parameters;
126         long    content_length; /* XXX - make it 64-bit? */
127         char    *content_encoding;
128         char    *transfer_encoding;
129 } headers_t;
130
131 static int is_http_request_or_reply(const gchar *data, int linelen, http_type_t *type,
132                 RequestDissector *req_dissector, int *req_strlen);
133 static int chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
134                 proto_tree *tree, int offset);
135 static void process_header(tvbuff_t *tvb, int offset, int next_offset,
136     const guchar *line, int linelen, int colon_offset, packet_info *pinfo,
137     proto_tree *tree, headers_t *eh_ptr);
138 static gint find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len);
139 static gboolean check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb,
140     packet_info *pinfo, gchar *value);
141 static gboolean check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb,
142     gchar *value);
143
144 static dissector_table_t port_subdissector_table;
145 static dissector_table_t media_type_subdissector_table;
146 static heur_dissector_list_t heur_subdissector_list;
147
148 static dissector_handle_t ntlmssp_handle=NULL;
149
150
151 /* Return a tvb that contains the binary representation of a base64
152    string */
153
154 static tvbuff_t *
155 base64_to_tvb(const char *base64)
156 {
157         tvbuff_t *tvb;
158         char *data = g_strdup(base64);
159         size_t len;
160
161         len = base64_decode(data);
162         tvb = tvb_new_real_data((const guint8 *)data, len, len);
163
164         tvb_set_free_cb(tvb, g_free);
165
166         return tvb;
167 }
168
169 static void
170 dissect_http_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
171     const char *line)
172 {
173         tvbuff_t *ntlmssp_tvb;
174
175         ntlmssp_tvb = base64_to_tvb(line);
176         tvb_set_child_real_data_tvbuff(tvb, ntlmssp_tvb);
177         add_new_data_source(pinfo, ntlmssp_tvb, "NTLMSSP Data");
178
179         call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo, tree);
180 }
181
182 static void
183 cleanup_headers(void *arg)
184 {
185         headers_t *headers = arg;
186
187         if (headers->content_type != NULL)
188                 g_free(headers->content_type);
189         /*
190          * The content_type_parameters field actually points into the
191          * content_type headers, so don't free it, as that'll double-free
192          * some memory.
193          */
194         if (headers->content_encoding != NULL)
195                 g_free(headers->content_encoding);
196         if (headers->transfer_encoding != NULL)
197                 g_free(headers->transfer_encoding);
198 }
199
200 /*
201  * TODO: remove this ugly global variable.
202  *
203  * XXX - we leak "http_info_value_t" structures.
204  * XXX - this gets overwritten if there's more than one HTTP request or
205  * reply in the tvbuff.
206  */
207 static http_info_value_t        *stat_info;
208
209 static int
210 dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
211     proto_tree *tree)
212 {
213         http_proto_t    proto;
214         char            *proto_tag;
215         proto_tree      *http_tree = NULL;
216         proto_item      *ti = NULL;
217         const guchar    *line;
218         gint            next_offset;
219         const guchar    *linep, *lineend;
220         int             orig_offset;
221         int             first_linelen, linelen;
222         gboolean        is_request_or_reply;
223         gboolean        saw_req_resp_or_header;
224         guchar          c;
225         http_type_t     http_type;
226         proto_item      *hdr_item;
227         RequestDissector req_dissector;
228         int             req_strlen;
229         proto_tree      *req_tree;
230         int             colon_offset;
231         headers_t       headers;
232         int             datalen;
233         int             reported_datalen;
234         dissector_handle_t handle;
235         gboolean        dissected;
236
237         /*
238          * Is this a request or response?
239          *
240          * Note that "tvb_find_line_end()" will return a value that
241          * is not longer than what's in the buffer, so the
242          * "tvb_get_ptr()" call won't throw an exception.
243          */
244         first_linelen = tvb_find_line_end(tvb, offset,
245             tvb_ensure_length_remaining(tvb, offset), &next_offset,
246             FALSE);
247         /*
248          * Is the first line a request or response?
249          */
250         line = tvb_get_ptr(tvb, offset, first_linelen);
251         http_type = HTTP_OTHERS;        /* type not known yet */
252         is_request_or_reply = is_http_request_or_reply((const gchar *)line,
253                         first_linelen, &http_type, NULL, NULL);
254         if (is_request_or_reply) {
255                 /*
256                  * Yes, it's a request or response.
257                  * Do header desegmentation if we've been told to,
258                  * and do body desegmentation if we've been told to and
259                  * we find a Content-Length header.
260                  */
261                 if (!req_resp_hdrs_do_reassembly(tvb, pinfo,
262                     http_desegment_headers, http_desegment_body)) {
263                         /*
264                          * More data needed for desegmentation.
265                          */
266                         return -1;
267                 }
268         }
269
270         stat_info = g_malloc(sizeof(http_info_value_t));
271         stat_info->response_code = 0;
272         stat_info->request_method = NULL;
273
274         switch (pinfo->match_port) {
275
276         case TCP_PORT_SSDP:     /* TCP_PORT_SSDP = UDP_PORT_SSDP */
277                 proto = PROTO_SSDP;
278                 proto_tag = "SSDP";
279                 break;
280
281         default:
282                 proto = PROTO_HTTP;
283                 proto_tag = "HTTP";
284                 break;
285         }
286
287         if (check_col(pinfo->cinfo, COL_PROTOCOL))
288                 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);
289         if (check_col(pinfo->cinfo, COL_INFO)) {
290                 /*
291                  * Put the first line from the buffer into the summary
292                  * if it's an HTTP request or reply (but leave out the
293                  * line terminator).
294                  * Otherwise, just call it a continuation.
295                  *
296                  * Note that "tvb_find_line_end()" will return a value that
297                  * is not longer than what's in the buffer, so the
298                  * "tvb_get_ptr()" call won't throw an exception.
299                  */
300                 line = tvb_get_ptr(tvb, offset, first_linelen);
301                 if (is_request_or_reply)
302                         col_add_str(pinfo->cinfo, COL_INFO,
303                             format_text(line, first_linelen));
304                 else
305                         col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
306         }
307
308         orig_offset = offset;
309         if (tree) {
310                 ti = proto_tree_add_item(tree, proto_http, tvb, offset, -1,
311                     FALSE);
312                 http_tree = proto_item_add_subtree(ti, ett_http);
313         }
314
315         /*
316          * Process the packet data, a line at a time.
317          */
318         http_type = HTTP_OTHERS;        /* type not known yet */
319         headers.content_type = NULL;    /* content type not known yet */
320         headers.content_type_parameters = NULL; /* content type parameters too */
321         headers.content_length = -1;    /* content length not known yet */
322         headers.content_encoding = NULL; /* content encoding not known yet */
323         headers.transfer_encoding = NULL; /* transfer encoding not known yet */
324         saw_req_resp_or_header = FALSE; /* haven't seen anything yet */
325         CLEANUP_PUSH(cleanup_headers, &headers);
326         while (tvb_reported_length_remaining(tvb, offset) != 0) {
327                 /*
328                  * Find the end of the line.
329                  */
330                 linelen = tvb_find_line_end(tvb, offset,
331                     tvb_ensure_length_remaining(tvb, offset), &next_offset,
332                     FALSE);
333                 if (linelen < 0)
334                         return -1;
335
336                 /*
337                  * Get a buffer that refers to the line.
338                  */
339                 line = tvb_get_ptr(tvb, offset, linelen);
340                 lineend = line + linelen;
341                 colon_offset = -1;
342
343                 /*
344                  * OK, does it look like an HTTP request or response?
345                  */
346                 req_dissector = NULL;
347                 is_request_or_reply = is_http_request_or_reply((const gchar *)line,
348                                 linelen, &http_type, &req_dissector, &req_strlen);
349                 if (is_request_or_reply)
350                         goto is_http;
351
352                 /*
353                  * No.  Does it look like a blank line (as would appear
354                  * at the end of an HTTP request)?
355                  */
356                 if (linelen == 0)
357                         goto is_http;   /* Yes. */
358
359                 /*
360                  * No.  Does it look like a header?
361                  */
362                 linep = line;
363                 colon_offset = offset;
364                 while (linep < lineend) {
365                         c = *linep++;
366
367                         /*
368                          * This must be a CHAR to be part of a token; that
369                          * means it must be ASCII.
370                          */
371                         if (!isascii(c))
372                                 break;  /* not ASCII, thus not a CHAR */
373
374                         /*
375                          * This mustn't be a CTL to be part of a token;
376                          * that means it must be printable.
377                          *
378                          * XXX - what about leading LWS on continuation
379                          * lines of a header?
380                          */
381                         if (!isprint(c))
382                                 break;  /* not printable, not a header */
383
384                         /*
385                          * This mustn't be a SEP to be part of a token;
386                          * a ':' ends the token, everything else is an
387                          * indication that this isn't a header.
388                          */
389                         switch (c) {
390
391                         case '(':
392                         case ')':
393                         case '<':
394                         case '>':
395                         case '@':
396                         case ',':
397                         case ';':
398                         case '\\':
399                         case '"':
400                         case '/':
401                         case '[':
402                         case ']':
403                         case '?':
404                         case '=':
405                         case '{':
406                         case '}':
407                         case ' ':
408                                 /*
409                                  * It's a separator, so it's not part of a
410                                  * token, so it's not a field name for the
411                                  * beginning of a header.
412                                  *
413                                  * (We don't have to check for HT; that's
414                                  * already been ruled out by "isprint()".)
415                                  */
416                                 goto not_http;
417
418                         case ':':
419                                 /*
420                                  * This ends the token; we consider this
421                                  * to be a header.
422                                  */
423                                 goto is_http;
424
425                         default:
426                                 colon_offset++;
427                                 break;
428                         }
429                 }
430
431                 /*
432                  * We haven't seen the colon, but everything else looks
433                  * OK for a header line.
434                  *
435                  * If we've already seen an HTTP request or response
436                  * line, or a header line, and we're at the end of
437                  * the tvbuff, we assume this is an incomplete header
438                  * line.  (We quit this loop after seeing a blank line,
439                  * so if we've seen a request or response line, or a
440                  * header line, this is probably more of the request
441                  * or response we're presumably seeing.  There is some
442                  * risk of false positives, but the same applies for
443                  * full request or response lines or header lines,
444                  * although that's less likely.)
445                  *
446                  * We throw an exception in that case, by checking for
447                  * the existence of the next byte after the last one
448                  * in the line.  If it exists, "tvb_ensure_bytes_exist()"
449                  * throws no exception, and we fall through to the
450                  * "not HTTP" case.  If it doesn't exist,
451                  * "tvb_ensure_bytes_exist()" will throw the appropriate
452                  * exception.
453                  */
454                 if (saw_req_resp_or_header)
455                         tvb_ensure_bytes_exist(tvb, offset, linelen + 1);
456
457         not_http:
458                 /*
459                  * We don't consider this part of an HTTP request or
460                  * reply, so we don't display it.
461                  * (Yeah, that means we don't display, say, a text/http
462                  * page, but you can get that from the data pane.)
463                  */
464                 break;
465
466         is_http:
467                 /*
468                  * Process this line.
469                  */
470                 if (linelen == 0) {
471                         /*
472                          * This is a blank line, which means that
473                          * whatever follows it isn't part of this
474                          * request or reply.
475                          */
476                         proto_tree_add_text(http_tree, tvb, offset,
477                             next_offset - offset, "%s",
478                             tvb_format_text(tvb, offset, next_offset - offset));
479                         offset = next_offset;
480                         break;
481                 }
482
483                 /*
484                  * Not a blank line - either a request, a reply, or a header
485                  * line.
486                  */ 
487                 saw_req_resp_or_header = TRUE;
488                 if (is_request_or_reply) {
489                         if (tree) {
490                                 hdr_item = proto_tree_add_text(http_tree, tvb,
491                                     offset, next_offset - offset, "%s",
492                                     tvb_format_text(tvb, offset,
493                                       next_offset - offset));
494                                 if (req_dissector) {
495                                         req_tree = proto_item_add_subtree(
496                                             hdr_item, ett_http_request);
497                                         req_dissector(tvb, req_tree,
498                                             req_strlen);
499                                 }
500                         }
501                 } else {
502                         /*
503                          * Header.
504                          */
505                         process_header(tvb, offset, next_offset, line, linelen,
506                             colon_offset, pinfo, http_tree, &headers);
507                 }
508                 offset = next_offset;
509         }
510
511         if (tree) {
512                 switch (http_type) {
513
514                 case HTTP_NOTIFICATION:
515                         proto_tree_add_boolean_hidden(http_tree,
516                             hf_http_notification, tvb, 0, 0, 1);
517                         break;
518
519                 case HTTP_RESPONSE:
520                         proto_tree_add_boolean_hidden(http_tree,
521                             hf_http_response, tvb, 0, 0, 1);
522                         break;
523
524                 case HTTP_REQUEST:
525                         proto_tree_add_boolean_hidden(http_tree,
526                             hf_http_request, tvb, 0, 0, 1);
527                         break;
528
529                 case HTTP_OTHERS:
530                 default:
531                         break;
532                 }
533         }
534
535         /*
536          * If a content length was supplied, the amount of data to be
537          * processed as HTTP payload is the minimum of the content
538          * length and the amount of data remaining in the frame.
539          *
540          * If no content length was supplied (or if a bad content length
541          * was supplied), the amount of data to be processed is the amount
542          * of data remaining in the frame.
543          *
544          * If there was no Content-Length entity header, we should
545          * accumulate all data until the end of the connection.
546          * That'd require that the TCP dissector call subdissectors
547          * for all frames with FIN, even if they contain no data,
548          * which would require subdissectors to deal intelligently
549          * with empty segments.
550          *
551          * Acccording to RFC 2616, however, 1xx responses, 204 responses,
552          * and 304 responses MUST NOT include a message body; if no
553          * content length is specified for them, we don't attempt to
554          * dissect the body.
555          *
556          * XXX - it says the same about responses to HEAD requests;
557          * unless there's a way to determine from the response
558          * whether it's a response to a HEAD request, we have to
559          * keep information about the request and associate that with
560          * the response in order to handle that.
561          */
562         datalen = tvb_length_remaining(tvb, offset);
563         if (headers.content_length != -1) {
564                 if (datalen > headers.content_length)
565                         datalen = headers.content_length;
566
567                 /*
568                  * XXX - limit the reported length in the tvbuff we'll
569                  * hand to a subdissector to be no greater than the
570                  * content length.
571                  *
572                  * We really need both unreassembled and "how long it'd
573                  * be if it were reassembled" lengths for tvbuffs, so
574                  * that we throw the appropriate exceptions for
575                  * "not enough data captured" (running past the length),
576                  * "packet needed reassembly" (within the length but
577                  * running past the unreassembled length), and
578                  * "packet is malformed" (running past the reassembled
579                  * length).
580                  */
581                 reported_datalen = tvb_reported_length_remaining(tvb, offset);
582                 if (reported_datalen > headers.content_length)
583                         reported_datalen = headers.content_length;
584         } else {
585                 if ((stat_info->response_code/100) == 1 ||
586                     stat_info->response_code == 204 ||
587                     stat_info->response_code == 304)
588                         datalen = 0;    /* no content! */
589                 else
590                         reported_datalen = -1;
591         }
592
593         if (datalen > 0) {
594                 /*
595                  * There's stuff left over; process it.
596                  */
597                 tvbuff_t *next_tvb;
598                 void *save_private_data = NULL;
599                 gint chunks_decoded = 0;
600
601                 /*
602                  * Create a tvbuff for the payload.
603                  *
604                  * The amount of data to be processed that's
605                  * available in the tvbuff is "datalen", which
606                  * is the minimum of the amount of data left in
607                  * the tvbuff and any specified content length.
608                  *
609                  * The amount of data to be processed that's in
610                  * this frame, regardless of whether it was
611                  * captured or not, is "reported_datalen",
612                  * which, if no content length was specified,
613                  * is -1, i.e. "to the end of the frame.
614                  */
615                 next_tvb = tvb_new_subset(tvb, offset, datalen,
616                     reported_datalen);
617
618                 /*
619                  * Handle transfer encodings other than "identity".
620                  */
621                 if (headers.transfer_encoding != NULL &&
622                     strcasecmp(headers.transfer_encoding, "identity") != 0) {
623                         if (strcasecmp(headers.transfer_encoding, "chunked")
624                             == 0) {
625
626                                 chunks_decoded = chunked_encoding_dissector(
627                                     &next_tvb, pinfo, http_tree, 0);
628
629                                 if (chunks_decoded <= 0) {
630                                         /* 
631                                          * The chunks weren't reassembled,
632                                          * or there was a single zero
633                                          * length chunk.
634                                          */
635                                         goto body_dissected;
636                                 }
637
638                         } else {
639                                 /*
640                                  * We currently can't handle, for example, "gzip",
641                                  * "compress", or "deflate"; just handle them
642                                  * as data for now.
643                                  */
644                                 call_dissector(data_handle, next_tvb, pinfo,
645                                     http_tree);
646                                 goto body_dissected;
647                         }
648                 }
649
650                 /*
651                  * Handle content encodings other than "identity" (which
652                  * shouldn't appear in a Content-Encoding header, but
653                  * we handle it in any case).
654                  */
655                 if (headers.content_encoding != NULL &&
656                     strcasecmp(headers.content_encoding, "identity") != 0) {
657                         /*
658                          * We currently can't handle, for example, "gzip",
659                          * "compress", or "deflate"; just handle them as
660                          * data for now.
661                          */
662                         proto_item *e_ti = NULL;
663                         proto_tree *e_tree = NULL;
664
665                         e_ti = proto_tree_add_text(http_tree, next_tvb, 0,
666                             tvb_length(next_tvb), "Encoded entity-body (%s)",
667                             headers.content_encoding);
668
669                         e_tree = proto_item_add_subtree(e_ti,
670                             ett_http_encoded_entity);
671
672                         call_dissector(data_handle, next_tvb, pinfo, e_tree);
673                         
674                         goto body_dissected;
675                 }
676
677                 /*
678                  * Do subdissector checks.
679                  *
680                  * First, check whether some subdissector asked that they
681                  * be called if something was on some particular port.
682                  */
683                 handle = dissector_get_port_handle(port_subdissector_table,
684                     pinfo->match_port);
685                 if (handle == NULL && headers.content_type != NULL) {
686                         /*
687                          * We didn't find any subdissector that
688                          * registered for the port, and we have a
689                          * Content-Type value.  Is there any subdissector
690                          * for that content type?
691                          */
692                         save_private_data = pinfo->private_data;
693                         /*
694                          * XXX - this won't get freed if the subdissector
695                          * throws an exception.  Do we really need to
696                          * strdup it?
697                          */
698                         if (headers.content_type_parameters)
699                                 pinfo->private_data = g_strdup(headers.content_type_parameters);
700                         else
701                                 pinfo->private_data = NULL;
702                         /*
703                          * Calling the string handle for the media type
704                          * dissector table will set pinfo->match_string
705                          * to headers.content_type for us.
706                          */
707                         pinfo->match_string = headers.content_type;
708                         handle = dissector_get_string_handle(
709                             media_type_subdissector_table,
710                             headers.content_type);
711                         /*
712                          * Calling the default media handle otherwise
713                          */
714                         if (handle == NULL) {
715                             handle = media_handle;
716                         }
717                 }
718                 if (handle != NULL) {
719                         /*
720                          * We have a subdissector - call it.
721                          */
722                         dissected = call_dissector(handle, next_tvb, pinfo,
723                             tree);
724                 } else {
725                         /*
726                          * We don't have a subdissector - try the heuristic
727                          * subdissectors.
728                          */
729                         dissected = dissector_try_heuristic(
730                             heur_subdissector_list, next_tvb, pinfo, tree);
731                 }
732                 if (dissected) {
733                         /*
734                          * The subdissector dissected the body.
735                          * Fix up the top-level item so that it doesn't
736                          * include the stuff for that protocol.
737                          */
738                         if (ti != NULL)
739                                 proto_item_set_len(ti, offset);
740                 } else {
741                         call_dissector(data_handle, next_tvb, pinfo,
742                             http_tree);
743                 }
744
745         body_dissected:
746                 /*
747                  * Do *not* attempt at freeing the private data;
748                  * it may be in use by subdissectors.
749                  */
750                 if (save_private_data)
751                         pinfo->private_data = save_private_data;
752                 /*
753                  * We've processed "datalen" bytes worth of data
754                  * (which may be no data at all); advance the
755                  * offset past whatever data we've processed.
756                  */
757                 offset += datalen;
758         }
759
760         /*
761          * Clean up any header stuff, by calling and popping the cleanup
762          * handler.
763          */
764         CLEANUP_CALL_AND_POP;
765
766         tap_queue_packet(http_tap, pinfo, stat_info);
767
768         return offset - orig_offset;
769 }
770
771 /* This can be used to dissect an HTTP request until such time
772  * that a more complete dissector is written for that HTTP request.
773  * This simple dissectory only puts http.request_method into a sub-tree.
774  */
775 static void
776 basic_request_dissector(tvbuff_t *tvb, proto_tree *tree, int req_strlen)
777 {
778         proto_tree_add_item(tree, hf_http_request_method, tvb, 0, req_strlen, FALSE);
779 }
780
781 static void
782 basic_response_dissector(tvbuff_t *tvb, proto_tree *tree, int resp_strlen)
783 {
784         gchar *data;
785         int minor, major, status_code;
786
787         /* BEWARE - sscanf() only operates on C strings.
788          * The pointer returned by tvb_get_ptr points into the real data,
789          * which is not necessarily NULL terminated. For this reason,
790          * the sscanf() call is only applied to a buffer guaranteed to
791          * only contain a NULL terminated string. */
792         data = g_strndup((const gchar *)tvb_get_ptr(tvb, 5, resp_strlen), resp_strlen);
793         if (sscanf((const gchar *)data, "%d.%d %d", &minor, &major, &status_code) == 3) {
794                 proto_tree_add_uint(tree, hf_http_response_code, tvb, 9, 3, status_code);
795                 stat_info->response_code = status_code;
796         }
797         g_free(data);
798 }
799
800 /*
801  * Dissect the http data chunks and add them to the tree.
802  */
803 static int
804 chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
805     proto_tree *tree, int offset)
806 {
807         guint8 *chunk_string = NULL;
808         gint chunk_size = 0;
809         gint chunk_offset = 0;
810         gint datalen = 0;
811         gint linelen = 0;
812         gint chunks_decoded = 0;
813         tvbuff_t *tvb = NULL;
814         tvbuff_t *new_tvb = NULL;
815         gint chunked_data_size = 0;
816         proto_tree *subtree = NULL;
817         proto_item *ti = NULL;
818         
819         if (tvb_ptr == NULL || *tvb_ptr == NULL) {
820                 return 0;
821         }
822
823         tvb = *tvb_ptr;
824
825         datalen = tvb_reported_length_remaining(tvb, offset);
826
827         if (tree) {
828                 ti = proto_tree_add_text(tree, tvb, offset, datalen,
829                     "HTTP chunked response");
830                 subtree = proto_item_add_subtree(ti, ett_http_chunked_response);
831         }
832
833
834         while (datalen != 0) {
835                 proto_item *chunk_ti = NULL;
836                 proto_tree *chunk_subtree = NULL;
837                 tvbuff_t *data_tvb = NULL;
838                 gchar *c = NULL;
839
840                 linelen = tvb_find_line_end(tvb, offset, -1, &chunk_offset, TRUE);
841
842                 if (linelen <= 0) {
843                         /* Can't get the chunk size line */
844                         return chunks_decoded;
845                 }
846
847                 chunk_string = tvb_get_string(tvb, offset, linelen);
848
849                 if (chunk_string == NULL) {
850                         /* Can't get the chunk size line */
851                         return chunks_decoded;
852                 }
853                 
854                 c = chunk_string;
855
856                 /*
857                  * We don't care about the extensions.
858                  */
859                 if ((c = strchr(c, ';'))) {
860                         *c = '\0';
861                 }
862
863                 if (sscanf(chunk_string, "%x", &chunk_size) != 1) {
864                         g_free(chunk_string);
865                         return chunks_decoded;
866                 }
867
868                 g_free(chunk_string);
869
870
871                 if (chunk_size > datalen) {
872                         /*
873                          * The chunk size is more than what's in the tvbuff,
874                          * so either the user hasn't enabled decoding, or all
875                          * of the segments weren't captured.
876                          */
877                         chunk_size = datalen;
878                 }/* else if (new_tvb == NULL) {
879                         new_tvb = tvb_new_composite();
880                 }
881
882
883
884                 if (new_tvb != NULL && chunk_size != 0) {
885                         tvbuff_t *chunk_tvb = NULL;
886                         
887                         chunk_tvb = tvb_new_subset(tvb, chunk_offset,
888                             chunk_size, datalen);
889
890                         tvb_composite_append(new_tvb, chunk_tvb);
891
892                 }
893                 */
894                 
895                 chunked_data_size += chunk_size;
896
897                 if (chunk_size != 0) {
898                         guint8 *raw_data = g_malloc(chunked_data_size);
899                         gint raw_len = 0;
900
901                         if (new_tvb != NULL) {
902                                 raw_len = tvb_length_remaining(new_tvb, 0);
903                                 tvb_memcpy(new_tvb, raw_data, 0, raw_len);
904
905                                 tvb_free(new_tvb);
906                         }
907
908                         tvb_memcpy(tvb, (guint8 *)(raw_data + raw_len),
909                             chunk_offset, chunk_size);
910
911                         new_tvb = tvb_new_real_data(raw_data,
912                             chunked_data_size, chunked_data_size);
913
914                 }
915                 
916                 if (subtree) {
917                         if (chunk_size == 0) {
918                                 chunk_ti = proto_tree_add_text(subtree, tvb,
919                                     offset,
920                                     chunk_offset - offset + chunk_size + 2,
921                                     "Data chunk (last chunk)");
922                         } else {
923                                 chunk_ti = proto_tree_add_text(subtree, tvb,
924                                     offset,
925                                     chunk_offset - offset + chunk_size + 2,
926                                     "Data chunk (%u octets)", chunk_size);
927                         }
928
929                         chunk_subtree = proto_item_add_subtree(chunk_ti,
930                             ett_http_chunk_data);
931
932                         proto_tree_add_text(chunk_subtree, tvb, offset,
933                             chunk_offset - offset, "Chunk size: %u octets",
934                             chunk_size);
935
936                         data_tvb = tvb_new_subset(tvb, chunk_offset, chunk_size,
937                             datalen);
938
939                 
940                         if (chunk_size > 0) { 
941                                 call_dissector(data_handle, data_tvb, pinfo,
942                                     chunk_subtree);
943                         }
944
945                         proto_tree_add_text(chunk_subtree, tvb, chunk_offset +
946                             chunk_size, 2, "Chunk boundary");
947                 }
948
949                 chunks_decoded++;
950                 offset = chunk_offset + chunk_size + 2;
951                 datalen = tvb_reported_length_remaining(tvb, offset);
952         }
953
954         if (new_tvb != NULL) {
955
956                 /* Placeholder for the day that composite tvbuffer's will work.
957                 tvb_composite_finalize(new_tvb);
958                 / * tvb_set_reported_length(new_tvb, chunked_data_size); * /
959                 */
960
961                 tvb_set_child_real_data_tvbuff(tvb, new_tvb);
962                 add_new_data_source(pinfo, new_tvb, "De-chunked entity body");
963
964                 tvb_free(*tvb_ptr);
965                 *tvb_ptr = new_tvb;
966                 
967         } else {
968                 /*
969                  * We didn't create a new tvb, so don't allow sub dissectors
970                  * try to decode the non-existant entity body.
971                  */
972                 chunks_decoded = -1;
973         }
974         
975         return chunks_decoded;
976
977 }
978
979
980 /*
981  * XXX - this won't handle HTTP 0.9 replies, but they're all data
982  * anyway.
983  */
984 static int
985 is_http_request_or_reply(const gchar *data, int linelen, http_type_t *type,
986                 RequestDissector *req_dissector, int *req_strlen)
987 {
988         int isHttpRequestOrReply = FALSE;
989         int prefix_len = 0;
990
991         /*
992          * From RFC 2774 - An HTTP Extension Framework
993          *
994          * Support the command prefix that identifies the presence of
995          * a "mandatory" header.
996          */
997         if (linelen >= 2 && strncmp(data, "M-", 2) == 0) {
998                 data += 2;
999                 linelen -= 2;
1000                 prefix_len = 2;
1001         }
1002
1003         /*
1004          * From draft-cohen-gena-client-01.txt, available from the uPnP forum:
1005          *      NOTIFY, SUBSCRIBE, UNSUBSCRIBE
1006          *
1007          * From draft-ietf-dasl-protocol-00.txt, a now vanished Microsoft draft:
1008          *      SEARCH
1009          */
1010         if (linelen >= 5 && strncmp(data, "HTTP/", 5) == 0) {
1011                 *type = HTTP_RESPONSE;
1012                 isHttpRequestOrReply = TRUE;    /* response */
1013                 if (req_dissector) {
1014                         *req_dissector = basic_response_dissector;
1015                         *req_strlen = linelen - 5;
1016                 }
1017         } else {
1018                 const guchar * ptr = (const guchar *)data;
1019                 int              index = 0;
1020
1021                 /* Look for the space following the Method */
1022                 while (index < linelen) {
1023                         if (*ptr == ' ')
1024                                 break;
1025                         else {
1026                                 ptr++;
1027                                 index++;
1028                         }
1029                 }
1030
1031                 /* Check the methods that have same length */
1032                 switch (index) {
1033
1034                 case 3:
1035                         if (strncmp(data, "GET", index) == 0 ||
1036                             strncmp(data, "PUT", index) == 0) {
1037                                 *type = HTTP_REQUEST;
1038                                 isHttpRequestOrReply = TRUE;
1039                         }
1040                         else if (strncmp(data, "ICY", index) == 0) {
1041                                 *type = HTTP_RESPONSE;
1042                                 isHttpRequestOrReply = TRUE;
1043                         }
1044                         break;
1045
1046                 case 4:
1047                         if (strncmp(data, "COPY", index) == 0 ||
1048                             strncmp(data, "HEAD", index) == 0 ||
1049                             strncmp(data, "LOCK", index) == 0 ||
1050                             strncmp(data, "MOVE", index) == 0 ||
1051                             strncmp(data, "POLL", index) == 0 ||
1052                             strncmp(data, "POST", index) == 0) {
1053                                 *type = HTTP_REQUEST;
1054                                 isHttpRequestOrReply = TRUE;
1055                         }
1056                         break;
1057
1058                 case 5:
1059                         if (strncmp(data, "BCOPY", index) == 0 ||
1060                                 strncmp(data, "BMOVE", index) == 0 ||
1061                                 strncmp(data, "MKCOL", index) == 0 ||
1062                                 strncmp(data, "TRACE", index) == 0) {
1063                                 *type = HTTP_REQUEST;
1064                                 isHttpRequestOrReply = TRUE;
1065                         }
1066                         break;
1067
1068                 case 6:
1069                         if (strncmp(data, "DELETE", index) == 0 ||
1070                                 strncmp(data, "SEARCH", index) == 0 ||
1071                                 strncmp(data, "UNLOCK", index) == 0) {
1072                                 *type = HTTP_REQUEST;
1073                                 isHttpRequestOrReply = TRUE;
1074                         }
1075                         else if (strncmp(data, "NOTIFY", index) == 0) {
1076                                 *type = HTTP_NOTIFICATION;
1077                                 isHttpRequestOrReply = TRUE;
1078                         }
1079                         break;
1080
1081                 case 7:
1082                         if (strncmp(data, "BDELETE", index) == 0 ||
1083                             strncmp(data, "CONNECT", index) == 0 ||
1084                             strncmp(data, "OPTIONS", index) == 0) {
1085                                 *type = HTTP_REQUEST;
1086                                 isHttpRequestOrReply = TRUE;
1087                         }
1088                         break;
1089
1090                 case 8:
1091                         if (strncmp(data, "PROPFIND", index) == 0) {
1092                                 *type = HTTP_REQUEST;
1093                                 isHttpRequestOrReply = TRUE;
1094                         }
1095                         break;
1096
1097                 case 9:
1098                         if (strncmp(data, "SUBSCRIBE", index) == 0) {
1099                                 *type = HTTP_NOTIFICATION;
1100                                 isHttpRequestOrReply = TRUE;
1101                         } else if (strncmp(data, "PROPPATCH", index) == 0 ||
1102                             strncmp(data, "BPROPFIND", index) == 0) {
1103                                 *type = HTTP_REQUEST;
1104                                 isHttpRequestOrReply = TRUE;
1105                         }
1106                         break;
1107
1108                 case 10:
1109                         if (strncmp(data, "BPROPPATCH", index) == 0) {
1110                                 *type = HTTP_REQUEST;
1111                                 isHttpRequestOrReply = TRUE;
1112                         }
1113                         break;
1114
1115                 case 11:
1116                         if (strncmp(data, "UNSUBSCRIBE", index) == 0) {
1117                                 *type = HTTP_NOTIFICATION;
1118                                 isHttpRequestOrReply = TRUE;
1119                         }
1120                         break;
1121
1122                 default:
1123                         break;
1124                 }
1125
1126                 if (isHttpRequestOrReply && req_dissector) {
1127                         *req_dissector = basic_request_dissector;
1128                         *req_strlen = index + prefix_len;
1129                 }
1130                 if (isHttpRequestOrReply && req_dissector) {
1131                         if (!stat_info->request_method)
1132                                 stat_info->request_method = g_malloc( index+1 );
1133                                 strncpy( stat_info->request_method, data, index);
1134                                 stat_info->request_method[index] = '\0';
1135                 }
1136         }
1137
1138         return isHttpRequestOrReply;
1139 }
1140
1141 /*
1142  * Process headers.
1143  */
1144 typedef struct {
1145         char    *name;
1146         gint    *hf;
1147         int     special;
1148 } header_info;
1149
1150 #define HDR_NO_SPECIAL          0
1151 #define HDR_AUTHORIZATION       1
1152 #define HDR_AUTHENTICATE        2
1153 #define HDR_CONTENT_TYPE        3
1154 #define HDR_CONTENT_LENGTH      4
1155 #define HDR_CONTENT_ENCODING    5
1156 #define HDR_TRANSFER_ENCODING   6
1157
1158 static const header_info headers[] = {
1159         { "Authorization", &hf_http_authorization, HDR_AUTHORIZATION },
1160         { "Proxy-Authorization", &hf_http_proxy_authorization, HDR_AUTHORIZATION },
1161         { "Proxy-Authenticate", &hf_http_proxy_authenticate, HDR_AUTHENTICATE },
1162         { "WWW-Authenticate", &hf_http_www_authenticate, HDR_AUTHENTICATE },
1163         { "Content-Type", &hf_http_content_type, HDR_CONTENT_TYPE },
1164         { "Content-Length", &hf_http_content_length, HDR_CONTENT_LENGTH },
1165         { "Content-Encoding", &hf_http_content_encoding, HDR_CONTENT_ENCODING },
1166         { "Transfer-Encoding", &hf_http_transfer_encoding, HDR_TRANSFER_ENCODING },
1167 };
1168
1169 static void
1170 process_header(tvbuff_t *tvb, int offset, int next_offset,
1171     const guchar *line, int linelen, int colon_offset,
1172     packet_info *pinfo, proto_tree *tree, headers_t *eh_ptr)
1173 {
1174         int len;
1175         int line_end_offset;
1176         int header_len;
1177         gint hf_index;
1178         guchar c;
1179         int value_offset;
1180         int value_len;
1181         char *value;
1182         char *p;
1183         guchar *up;
1184         proto_item *hdr_item;
1185         int i;
1186
1187         len = next_offset - offset;
1188         line_end_offset = offset + linelen;
1189         header_len = colon_offset - offset;
1190         hf_index = find_header_hf_value(tvb, offset, header_len);
1191
1192         if (hf_index == -1) {
1193                 /*
1194                  * Not a header we know anything about.  Just put it into
1195                  * the tree as text.
1196                  */
1197                 if (tree) {
1198                         proto_tree_add_text(tree, tvb, offset, len,
1199                             "%s", format_text(line, len));
1200                 }
1201         } else {
1202                 /*
1203                  * Skip whitespace after the colon.
1204                  */
1205                 value_offset = colon_offset + 1;
1206                 while (value_offset < line_end_offset
1207                     && ((c = line[value_offset - offset]) == ' ' || c == '\t'))
1208                         value_offset++;
1209
1210                 /*
1211                  * Fetch the value.
1212                  */
1213                 value_len = line_end_offset - value_offset;
1214                 value = g_malloc(value_len + 1);
1215                 memcpy(value, &line[value_offset - offset], value_len);
1216                 value[value_len] = '\0';
1217                 CLEANUP_PUSH(g_free, value);
1218
1219                 /*
1220                  * Add it to the protocol tree as a particular field,
1221                  * but display the line as is.
1222                  */
1223                 if (tree) {
1224                         hdr_item = proto_tree_add_string_format(tree,
1225                             *headers[hf_index].hf, tvb, offset, len,
1226                             value, "%s", format_text(line, len));
1227                 } else
1228                         hdr_item = NULL;
1229
1230                 /*
1231                  * Do any special processing that particular headers
1232                  * require.
1233                  */
1234                 switch (headers[hf_index].special) {
1235
1236                 case HDR_AUTHORIZATION:
1237                         if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))
1238                                 break;  /* dissected NTLMSSP */
1239                         check_auth_basic(hdr_item, tvb, value);
1240                         break;
1241
1242                 case HDR_AUTHENTICATE:
1243                         check_auth_ntlmssp(hdr_item, tvb, pinfo, value);
1244                         break;
1245
1246                 case HDR_CONTENT_TYPE:
1247                         if (eh_ptr->content_type != NULL)
1248                                 g_free(eh_ptr->content_type);
1249                         eh_ptr->content_type = g_malloc(value_len + 1);
1250                         for (i = 0; i < value_len; i++) {
1251                                 c = value[i];
1252                                 if (c == ';' || isspace(c)) {
1253                                         /*
1254                                          * End of subtype - either
1255                                          * white space or a ";"
1256                                          * separating the subtype from
1257                                          * a parameter.
1258                                          */
1259                                         break;
1260                                 }
1261
1262                                 /*
1263                                  * Map the character to lower case;
1264                                  * content types are case-insensitive.
1265                                  */
1266                                 eh_ptr->content_type[i] = tolower(c);
1267                         }
1268                         eh_ptr->content_type[i] = '\0';
1269                         /*
1270                          * Now find the start of the optional parameters;
1271                          * skip the optional white space and the semicolon
1272                          * if this has not been done before.
1273                          */
1274                         i++;
1275                         while (i < value_len) {
1276                                 c = value[i];
1277                                 if (c == ';' || isspace(c))
1278                                         /* Skip till start of parameters */
1279                                         i++;
1280                                 else
1281                                         break;
1282                         }
1283                         if (i < value_len)
1284                                 eh_ptr->content_type_parameters = value + i;
1285                         else
1286                                 eh_ptr->content_type_parameters = NULL;
1287                         break;
1288
1289                 case HDR_CONTENT_LENGTH:
1290                         eh_ptr->content_length = strtol(value, &p, 10);
1291                         up = (guchar *)p;
1292                         if (eh_ptr->content_length < 0 || p == value ||
1293                             (*up != '\0' && !isspace(*up)))
1294                                 eh_ptr->content_length = -1;    /* not valid */
1295                         break;
1296
1297                 case HDR_CONTENT_ENCODING:
1298                         if (eh_ptr->content_encoding != NULL)
1299                                 g_free(eh_ptr->content_encoding);
1300                         eh_ptr->content_encoding = g_malloc(value_len + 1);
1301                         memcpy(eh_ptr->content_encoding, value, value_len);
1302                         eh_ptr->content_encoding[value_len] = '\0';
1303                         break;
1304
1305                 case HDR_TRANSFER_ENCODING:
1306                         if (eh_ptr->transfer_encoding != NULL)
1307                                 g_free(eh_ptr->transfer_encoding);
1308                         eh_ptr->transfer_encoding = g_malloc(value_len + 1);
1309                         memcpy(eh_ptr->transfer_encoding, value, value_len);
1310                         eh_ptr->transfer_encoding[value_len] = '\0';
1311                         break;
1312                 }
1313
1314                 /*
1315                  * Free the value, by calling and popping the cleanup
1316                  * handler for it.
1317                  */
1318                 CLEANUP_CALL_AND_POP;
1319         }
1320 }
1321
1322 /* Returns index of header tag in headers */
1323 static gint
1324 find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len)
1325 {
1326         guint i;
1327
1328         for (i = 0; i < array_length(headers); i++) {
1329                 if (header_len == strlen(headers[i].name) &&
1330                     tvb_strncaseeql(tvb, offset,
1331                                                 headers[i].name, header_len) == 0)
1332                         return i;
1333         }
1334
1335         return -1;
1336 }
1337
1338 /*
1339  * Dissect Microsoft's abomination called NTLMSSP over HTTP.
1340  */
1341 static gboolean
1342 check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo,
1343     gchar *value)
1344 {
1345         static const char *ntlm_headers[] = {
1346                 "NTLM ",
1347                 "Negotiate ",
1348                 NULL
1349         };
1350         const char **header;
1351         size_t hdrlen;
1352         proto_tree *hdr_tree;
1353
1354         /*
1355          * Check for NTLM credentials and challenge; those can
1356          * occur with WWW-Authenticate.
1357          */
1358         for (header = &ntlm_headers[0]; *header != NULL; header++) {
1359                 hdrlen = strlen(*header);
1360                 if (strncmp(value, *header, hdrlen) == 0) {
1361                         if (hdr_item != NULL) {
1362                                 hdr_tree = proto_item_add_subtree(hdr_item,
1363                                     ett_http_ntlmssp);
1364                         } else
1365                                 hdr_tree = NULL;
1366                         value += hdrlen;
1367                         dissect_http_ntlmssp(tvb, pinfo, hdr_tree, value);
1368                         return TRUE;
1369                 }
1370         }
1371         return FALSE;
1372 }
1373
1374 /*
1375  * Dissect HTTP Basic authorization.
1376  */
1377 static gboolean
1378 check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb, gchar *value)
1379 {
1380         static const char *basic_headers[] = {
1381                 "Basic ",
1382                 NULL
1383         };
1384         const char **header;
1385         size_t hdrlen;
1386         proto_tree *hdr_tree;
1387         size_t len;
1388
1389         for (header = &basic_headers[0]; *header != NULL; header++) {
1390                 hdrlen = strlen(*header);
1391                 if (strncmp(value, *header, hdrlen) == 0) {
1392                         if (hdr_item != NULL) {
1393                                 hdr_tree = proto_item_add_subtree(hdr_item,
1394                                     ett_http_ntlmssp);
1395                         } else
1396                                 hdr_tree = NULL;
1397                         value += hdrlen;
1398
1399                         len = base64_decode(value);
1400                         value[len] = '\0';
1401                         proto_tree_add_string(hdr_tree, hf_http_basic, tvb,
1402                             0, 0, value);
1403
1404                         return TRUE;
1405                 }
1406         }
1407         return FALSE;
1408 }
1409
1410 static void
1411 dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1412 {
1413         int             offset = 0;
1414         int             len;
1415
1416         while (tvb_reported_length_remaining(tvb, offset) != 0) {
1417                 len = dissect_http_message(tvb, offset, pinfo, tree);
1418                 if (len == -1)
1419                         break;
1420                 offset += len;
1421
1422                 /*
1423                  * OK, we've set the Protocol and Info columns for the
1424                  * first HTTP message; make the columns non-writable,
1425                  * so that we don't change it for subsequent HTTP messages.
1426                  */
1427                 col_set_writable(pinfo->cinfo, FALSE);
1428         }
1429 }
1430
1431 static void
1432 dissect_http_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1433 {
1434         dissect_http_message(tvb, 0, pinfo, tree);
1435 }
1436
1437 void
1438 proto_register_http(void)
1439 {
1440         static hf_register_info hf[] = {
1441             { &hf_http_notification,
1442               { "Notification",         "http.notification",
1443                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1444                 "TRUE if HTTP notification", HFILL }},
1445             { &hf_http_response,
1446               { "Response",             "http.response",
1447                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1448                 "TRUE if HTTP response", HFILL }},
1449             { &hf_http_request,
1450               { "Request",              "http.request",
1451                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1452                 "TRUE if HTTP request", HFILL }},
1453             { &hf_http_basic,
1454               { "Credentials",          "http.authbasic",
1455                 FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
1456             { &hf_http_request_method,
1457               { "Request Method",       "http.request.method",
1458                 FT_STRING, BASE_NONE, NULL, 0x0,
1459                 "HTTP Request Method", HFILL }},
1460             { &hf_http_response_code,
1461               { "Response Code",        "http.response.code",
1462                 FT_UINT16, BASE_DEC, NULL, 0x0,
1463                 "HTTP Response Code", HFILL }},
1464             { &hf_http_authorization,
1465               { "Authorization",        "http.authorization",
1466                 FT_STRING, BASE_NONE, NULL, 0x0,
1467                 "HTTP Authorization header", HFILL }},
1468             { &hf_http_proxy_authenticate,
1469               { "Proxy-Authenticate",   "http.proxy_authenticate",
1470                 FT_STRING, BASE_NONE, NULL, 0x0,
1471                 "HTTP Proxy-Authenticate header", HFILL }},
1472             { &hf_http_proxy_authorization,
1473               { "Proxy-Authorization",  "http.proxy_authorization",
1474                 FT_STRING, BASE_NONE, NULL, 0x0,
1475                 "HTTP Proxy-Authorization header", HFILL }},
1476             { &hf_http_www_authenticate,
1477               { "WWW-Authenticate",     "http.www_authenticate",
1478                 FT_STRING, BASE_NONE, NULL, 0x0,
1479                 "HTTP WWW-Authenticate header", HFILL }},
1480             { &hf_http_content_type,
1481               { "Content-Type", "http.content_type",
1482                 FT_STRING, BASE_NONE, NULL, 0x0,
1483                 "HTTP Content-Type header", HFILL }},
1484             { &hf_http_content_length,
1485               { "Content-Length",       "http.content_length",
1486                 FT_STRING, BASE_NONE, NULL, 0x0,
1487                 "HTTP Content-Length header", HFILL }},
1488             { &hf_http_content_encoding,
1489               { "Content-Encoding",     "http.content_encoding",
1490                 FT_STRING, BASE_NONE, NULL, 0x0,
1491                 "HTTP Content-Encoding header", HFILL }},
1492             { &hf_http_transfer_encoding,
1493               { "Transfer-Encoding",    "http.transfer_encoding",
1494                 FT_STRING, BASE_NONE, NULL, 0x0,
1495                 "HTTP Transfer-Encoding header", HFILL }},
1496         };
1497         static gint *ett[] = {
1498                 &ett_http,
1499                 &ett_http_ntlmssp,
1500                 &ett_http_request,
1501                 &ett_http_chunked_response,
1502                 &ett_http_chunk_data,
1503                 &ett_http_encoded_entity,
1504         };
1505         module_t *http_module;
1506
1507         proto_http = proto_register_protocol("Hypertext Transfer Protocol",
1508             "HTTP", "http");
1509         proto_register_field_array(proto_http, hf, array_length(hf));
1510         proto_register_subtree_array(ett, array_length(ett));
1511         http_module = prefs_register_protocol(proto_http, NULL);
1512         prefs_register_bool_preference(http_module, "desegment_headers",
1513             "Desegment all HTTP headers spanning multiple TCP segments",
1514             "Whether the HTTP dissector should desegment all headers "
1515             "of a request spanning multiple TCP segments",
1516             &http_desegment_headers);
1517         prefs_register_bool_preference(http_module, "desegment_body",
1518             "Desegment HTTP bodies spanning multiple TCP segments",
1519             "Whether the HTTP dissector should use the "
1520             "\"Content-length:\" value, if present, to desegment "
1521             "the body of a request spanning multiple TCP segments, "
1522             "and desegment chunked data spanning multiple TCP segments",
1523             &http_desegment_body);
1524
1525         http_handle = create_dissector_handle(dissect_http, proto_http);
1526
1527         /*
1528          * Dissectors shouldn't register themselves in this table;
1529          * instead, they should call "http_dissector_add()", and
1530          * we'll register the port number they specify as a port
1531          * for HTTP, and register them in our subdissector table.
1532          *
1533          * This only works for protocols such as IPP that run over
1534          * HTTP on a specific non-HTTP port.
1535          */
1536         port_subdissector_table = register_dissector_table("http.port",
1537             "TCP port for protocols using HTTP", FT_UINT16, BASE_DEC);
1538
1539         /*
1540          * Dissectors can register themselves in this table.
1541          * It's just "media_type", not "http.content_type", because
1542          * it's an Internet media type, usable by other protocols as well.
1543          */
1544         media_type_subdissector_table =
1545             register_dissector_table("media_type",
1546                 "Internet media type", FT_STRING, BASE_NONE);
1547
1548         /*
1549          * Heuristic dissectors SHOULD register themselves in
1550          * this table using the standard heur_dissector_add()
1551          * function.
1552          */
1553         register_heur_dissector_list("http", &heur_subdissector_list);
1554
1555         /*
1556          * Register for tapping
1557          */
1558         http_tap = register_tap("http");
1559 }
1560
1561 /*
1562  * Called by dissectors for protocols that run atop HTTP/TCP.
1563  */
1564 void
1565 http_dissector_add(guint32 port, dissector_handle_t handle)
1566 {
1567         /*
1568          * Register ourselves as the handler for that port number
1569          * over TCP.
1570          */
1571         dissector_add("tcp.port", port, http_handle);
1572
1573         /*
1574          * And register them in *our* table for that port.
1575          */
1576         dissector_add("http.port", port, handle);
1577 }
1578
1579 void
1580 proto_reg_handoff_http(void)
1581 {
1582         dissector_handle_t http_udp_handle;
1583
1584         data_handle = find_dissector("data");
1585         media_handle = find_dissector("media");
1586
1587         dissector_add("tcp.port", TCP_PORT_HTTP, http_handle);
1588         dissector_add("tcp.port", TCP_ALT_PORT_HTTP, http_handle);
1589         dissector_add("tcp.port", TCP_PORT_PROXY_HTTP, http_handle);
1590         dissector_add("tcp.port", TCP_PORT_PROXY_ADMIN_HTTP, http_handle);
1591
1592         /*
1593          * XXX - is there anything to dissect in the body of an SSDP
1594          * request or reply?  I.e., should there be an SSDP dissector?
1595          */
1596         dissector_add("tcp.port", TCP_PORT_SSDP, http_handle);
1597         http_udp_handle = create_dissector_handle(dissect_http_udp, proto_http);
1598         dissector_add("udp.port", UDP_PORT_SSDP, http_udp_handle);
1599
1600         ntlmssp_handle = find_dissector("ntlmssp");
1601 }
1602
1603 /*
1604  * Content-Type: message/http
1605  */
1606
1607 static gint proto_message_http = -1;
1608 static gint ett_message_http = -1;
1609 static dissector_handle_t message_http_handle;
1610
1611 static void
1612 dissect_message_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1613 {
1614         proto_tree      *subtree;
1615         proto_item      *ti;
1616         gint            offset = 0, next_offset;
1617         gint            len;
1618
1619         if (check_col(pinfo->cinfo, COL_INFO))
1620                 col_append_str(pinfo->cinfo, COL_INFO, " (message/http)");
1621         if (tree) {
1622                 ti = proto_tree_add_item(tree, proto_message_http,
1623                                 tvb, 0, -1, FALSE);
1624                 subtree = proto_item_add_subtree(ti, ett_message_http);
1625                 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1626                         len = tvb_find_line_end(tvb, offset,
1627                                         tvb_ensure_length_remaining(tvb, offset),
1628                                         &next_offset, FALSE);
1629                         if (len == -1)
1630                                 break;
1631                         proto_tree_add_text(subtree, tvb, offset, next_offset - offset,
1632                                         "%s", tvb_format_text(tvb, offset, len));
1633                         offset = next_offset;
1634                 }
1635         }
1636 }
1637
1638 void
1639 proto_register_message_http(void)
1640 {
1641         static gint *ett[] = {
1642                 &ett_message_http,
1643         };
1644
1645         proto_message_http = proto_register_protocol(
1646                         "Media Type: message/http",
1647                         "message/http",
1648                         "message-http"
1649         );
1650         proto_register_subtree_array(ett, array_length(ett));
1651         message_http_handle = create_dissector_handle(dissect_message_http,
1652                         proto_message_http);
1653 }
1654
1655 void
1656 proto_reg_handoff_message_http(void)
1657 {
1658         message_http_handle = create_dissector_handle(dissect_message_http,
1659                         proto_message_http);
1660
1661         dissector_add_string("media_type", "message/http", message_http_handle);
1662 }