diameter: change GArray into wmem_array.
[metze/wireshark/wip.git] / epan / req_resp_hdrs.c
1 /* req_resp_hdrs.c
2  * Routines handling protocols with a request/response line, headers,
3  * a blank line, and an optional body.
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include "config.h"
25
26 #include <glib.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #include <epan/packet.h>
31 #include <epan/strutil.h>
32
33 #include <epan/req_resp_hdrs.h>
34
35 /*
36  * Optionally do reassembly of the request/response line, headers, and body.
37  */
38 gboolean
39 req_resp_hdrs_do_reassembly(tvbuff_t *tvb, const int offset, packet_info *pinfo,
40     const gboolean desegment_headers, const gboolean desegment_body)
41 {
42         gint            next_offset;
43         gint            next_offset_sav;
44         gint            length_remaining, reported_length_remaining;
45         int             linelen;
46         gchar           *header_val;
47         int             content_length;
48         gboolean        content_length_found = FALSE;
49         gboolean        content_type_found = FALSE;
50         gboolean        chunked_encoding = FALSE;
51         gboolean        keepalive_found = FALSE;
52         gchar           *line;
53         gchar           *content_type = NULL;
54
55         /*
56          * Do header desegmentation if we've been told to.
57          *
58          * RFC 2616 defines HTTP messages as being either of the
59          * Request or the Response type
60          * (HTTP-message = Request | Response).
61          * Request and Response are defined as:
62          *     Request = Request-Line
63          *         *(( general-header
64          *         | request-header
65          *         | entity-header ) CRLF)
66          *         CRLF
67          *         [ message-body ]
68          *     Response = Status-Line
69          *         *(( general-header
70          *         | response-header
71          *         | entity-header ) CRLF)
72          *         CRLF
73          *         [ message-body ]
74          * that's why we can always assume two consecutive line
75          * endings (we allow CR, LF, or CRLF, as some clients
76          * or servers might not use a full CRLF) to mark the end
77          * of the headers.  The worst thing that would happen
78          * otherwise would be the packet not being desegmented
79          * or being interpreted as only headers.
80          *
81          * RFC 2326 says RTSP works the same way; RFC 3261 says SIP
82          * works the same way.
83          */
84
85         /*
86          * If header desegmentation is activated, check that all
87          * headers are in this tvbuff (search for an empty line
88          * marking end of headers) or request one more byte (we
89          * don't know how many bytes we'll need, so we just ask
90          * for one).
91          */
92         if (desegment_headers && pinfo->can_desegment) {
93                 next_offset = offset;
94                 for (;;) {
95                         next_offset_sav = next_offset;
96
97                         reported_length_remaining =
98                             tvb_reported_length_remaining(tvb, next_offset);
99
100                         /*
101                          * Request one more byte if there're no
102                          * bytes left in the reported data (if there're
103                          * bytes left in the reported data, but not in
104                          * the available data, requesting more bytes
105                          * won't help, as those bytes weren't captured).
106                          */
107                         if (reported_length_remaining < 1) {
108                                 pinfo->desegment_offset = offset;
109                                 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
110                                 return FALSE;
111                         }
112
113                         length_remaining = tvb_captured_length_remaining(tvb,
114                             next_offset);
115
116                         /*
117                          * Request one more byte if we cannot find a
118                          * header (i.e. a line end).
119                          */
120                         linelen = tvb_find_line_end(tvb, next_offset,
121                             length_remaining, &next_offset, TRUE);
122                         if (linelen == -1 &&
123                             length_remaining >= reported_length_remaining) {
124                                 /*
125                                  * Not enough data; ask for one more
126                                  * byte.
127                                  */
128                                 pinfo->desegment_offset = offset;
129                                 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
130                                 return FALSE;
131                         }
132
133                         if (linelen == 0) {
134                                 /*
135                                  * We found the end of the headers.
136                                  */
137                                 break;
138                         }
139
140                         /*
141                          * Is this a Content-Length or Transfer-Encoding
142                          * header?  If not, it either means that we are in
143                          * a different header line, or that we are
144                          * at the end of the headers, or that there
145                          * isn't enough data; the two latter cases
146                          * have already been handled above.
147                          */
148                         if (desegment_body) {
149                                 /* Optimization to avoid fetching the whole (potentially very long)
150                                  * line and doing expensive string comparisons if the first
151                                  * character doesn't match. Shaves about 20% off the load time of
152                                  * one of my sample files that's HTTP-alike. */
153                                 guchar first_byte = tvb_get_guint8(tvb, next_offset_sav);
154                                 if (! (first_byte == 'c' || first_byte == 'C' ||
155                                        first_byte == 't' || first_byte == 'T')) {
156                                         continue;
157                                 }
158
159                                 /*
160                                  * Check if we've found Content-Length.
161                                  */
162                                 line = tvb_get_string_enc(wmem_packet_scope(), tvb, next_offset_sav, linelen, ENC_UTF_8|ENC_NA);
163                                 if (g_ascii_strncasecmp(line, "Content-Length:", 15) == 0) {
164                                         /* XXX - what if it doesn't fit in an int?
165                                            (Do not "fix" that by making this
166                                            a "long"; make it a gint64 or a
167                                            guint64.) */
168                                         if (sscanf(line+15,"%i", &content_length) == 1)
169                                                 content_length_found = TRUE;
170                                 } else if (g_ascii_strncasecmp(line, "Content-Type:", 13) == 0) {
171                                         content_type_found = TRUE;
172                                         content_type = line+13;
173                                         while (*content_type == ' ') {
174                                                 content_type++;
175                                         }
176                                 } else if (g_ascii_strncasecmp(line, "Connection:", 11) == 0) {
177                                         /* Check for keep-alive */
178                                         header_val = line+11;
179                                         if(header_val){
180                                                 while(*header_val==' '){
181                                                         header_val++;
182                                                 }
183                                                 if(!g_ascii_strncasecmp(header_val, "Keep-Alive", 10)){
184                                                         keepalive_found = TRUE;
185                                                 }
186                                         }
187                                 } else if (g_ascii_strncasecmp( line, "Transfer-Encoding:", 18) == 0) {
188                                         /*
189                                          * Find out if this Transfer-Encoding is
190                                          * chunked.  It should be, since there
191                                          * really aren't any other types, but
192                                          * RFC 2616 allows for them.
193                                          */
194                                         gchar *p;
195                                         guint len;
196
197                                         header_val = line+18;
198                                         p = header_val;
199                                         len = (guint) strlen(header_val);
200                                         /* Skip white space */
201                                         while (p < header_val + len &&
202                                             (*p == ' ' || *p == '\t'))
203                                                 p++;
204                                         if (p <= header_val + len) {
205                                                 if (g_ascii_strncasecmp(p, "chunked", 7)
206                                                     == 0) {
207                                                         /*
208                                                          * Don't bother looking
209                                                          * for extensions;
210                                                          * since we don't
211                                                          * understand them,
212                                                          * they should be
213                                                          * ignored.
214                                                          */
215                                                         chunked_encoding = TRUE;
216                                                 }
217                                         }
218                                 }
219                         }
220                 }
221         }
222
223         /*
224          * The above loop ends when we reached the end of the headers, so
225          * there should be content_length bytes after the 4 terminating bytes
226          * and next_offset points to after the end of the headers.
227          */
228         if (desegment_body) {
229                 if (chunked_encoding) {
230                         /*
231                          * This data is chunked, so we need to keep pulling
232                          * data until we reach the end of the stream, or a
233                          * zero sized chunk.
234                          *
235                          * XXX
236                          * This doesn't bother with trailing headers; I don't
237                          * think they are really used, and we'd have to use
238                          * is_http_request_or_reply() to determine if it was
239                          * a trailing header, or the start of a new response.
240                          */
241                         gboolean done_chunking = FALSE;
242
243                         while (!done_chunking) {
244                                 guint chunk_size = 0;
245                                 gint  chunk_offset = 0;
246                                 gchar *chunk_string = NULL;
247                                 gchar *c = NULL;
248
249                                 reported_length_remaining =
250                                     tvb_reported_length_remaining(tvb,
251                                     next_offset);
252
253                                 if (reported_length_remaining < 1) {
254                                         pinfo->desegment_offset = offset;
255                                         pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
256                                         return FALSE;
257                                 }
258
259                                 length_remaining = tvb_captured_length_remaining(tvb,
260                                     next_offset);
261
262                                 linelen = tvb_find_line_end(tvb, next_offset,
263                                                 length_remaining, &chunk_offset, TRUE);
264
265                                 if (linelen == -1 &&
266                                     length_remaining >=
267                                     reported_length_remaining) {
268                                          pinfo->desegment_offset = offset;
269                                          pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
270                                          return FALSE;
271                                 }
272
273                                 /* We have a line with the chunk size in it.*/
274                                 chunk_string = tvb_get_string_enc(wmem_packet_scope(), tvb, next_offset,
275                                     linelen, ENC_ASCII);
276                                 c = chunk_string;
277
278                                 /*
279                                  * We don't care about the extensions.
280                                  */
281                                 if ((c = strchr(c, ';'))) {
282                                         *c = '\0';
283                                 }
284
285                                 if (sscanf(chunk_string, "%x", &chunk_size) < 1) {
286                                         /* We couldn't get the chunk size,
287                                          * so stop trying.
288                                          */
289                                         return TRUE;
290                                 }
291                                 if (chunk_size > 1U<<31) {
292                                         /* Chunk size is unreasonable. */
293                                         /* XXX What /is/ reasonable? */
294                                         return TRUE;
295                                 }
296
297                                 if (chunk_size == 0) {
298                                         /*
299                                          * This is the last chunk.  Let's pull in the
300                                          * trailing CRLF.
301                                          */
302                                         linelen = tvb_find_line_end(tvb,
303                                             chunk_offset, length_remaining, &chunk_offset, TRUE);
304
305                                         if (linelen == -1 &&
306                                             length_remaining >=
307                                             reported_length_remaining) {
308                                                 pinfo->desegment_offset = offset;
309                                                 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
310                                                 return FALSE;
311                                         }
312
313                                         pinfo->desegment_offset = chunk_offset;
314                                         pinfo->desegment_len = 0;
315                                         done_chunking = TRUE;
316                                 } else {
317                                         /*
318                                          * Skip to the next chunk if we
319                                          * already have it
320                                          */
321                                         if (reported_length_remaining >
322                                                 (gint) chunk_size) {
323
324                                                 next_offset = chunk_offset
325                                                     + chunk_size + 2;
326                                         } else {
327                                                 /*
328                                                  * Fetch this chunk, plus the
329                                                  * trailing CRLF.
330                                                  */
331                                                 pinfo->desegment_offset = offset;
332                                                 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
333                                                 return FALSE;
334                                         }
335                                 }
336
337                         }
338                 } else if (content_length_found) {
339                         if (content_length >= 128*1024) { /* MS-RPCH stipulate that the content-length must be between 128K and 2G */
340                                 gchar *tmp;
341                                 if (content_type_found &&
342                                 strncmp(content_type, "application/rpc", 15) == 0) {
343                                         /* It looks like a RPC_IN_DATA request or a RPC_OUT_DATA response
344                                          * in which the content-length is meaningless
345                                          */
346                                         return TRUE;
347                                 }
348                                 /* Following sizeof will return the length of the string + \0 we need to not count it*/
349                                 tmp = tvb_get_string_enc(wmem_packet_scope(), tvb, 0, sizeof("RPC_OUT_DATA") - 1, ENC_ASCII);
350                                 if ((strncmp(tmp, "RPC_IN_DATA", sizeof("RPC_IN_DATA") - 1) == 0) ||
351                                     (strncmp(tmp, "RPC_OUT_DATA", sizeof("RPC_OUT_DATA") - 1) == 0)) {
352                                         return TRUE;
353                                 }
354                         }
355                         /* next_offset has been set to the end of the headers */
356                         if (!tvb_bytes_exist(tvb, next_offset, content_length)) {
357                                 length_remaining = tvb_captured_length_remaining(tvb,
358                                     next_offset);
359                                 reported_length_remaining =
360                                     tvb_reported_length_remaining(tvb, next_offset);
361                                 if (length_remaining < reported_length_remaining) {
362                                         /*
363                                          * It's a waste of time asking for more
364                                          * data, because that data wasn't captured.
365                                          */
366                                         return TRUE;
367                                 }
368                                 if (length_remaining == -1)
369                                         length_remaining = 0;
370                                 pinfo->desegment_offset = offset;
371                                 pinfo->desegment_len =
372                                     content_length - length_remaining;
373                                 return FALSE;
374                         }
375                 } else if (content_type_found && pinfo->can_desegment) {
376                         /* We found a content-type but no content-length.
377                          * This is probably a HTTP header for a session with
378                          * only one HTTP PDU and where the content spans
379                          * until the end of the tcp session, unless there
380                          * is a keepalive header present in which case we
381                          * assume there is no message body at all and thus
382                          * we won't do any reassembly.
383                          * Set up tcp reassembly until the end of this session.
384                          */
385                         length_remaining = tvb_captured_length_remaining(tvb, next_offset);
386                         reported_length_remaining = tvb_reported_length_remaining(tvb, next_offset);
387                         if (length_remaining < reported_length_remaining) {
388                                 /*
389                                  * It's a waste of time asking for more
390                                  * data, because that data wasn't captured.
391                                  */
392                                 return TRUE;
393                         }
394
395                         if (keepalive_found) {
396                                 /* We have a keep-alive but no content-length.
397                                  * Assume there is no message body and don't
398                                  * do any reassembly.
399                                  */
400                                 return TRUE;
401                         }
402
403                         pinfo->desegment_offset = offset;
404                         pinfo->desegment_len = DESEGMENT_UNTIL_FIN;
405
406                         return FALSE;
407                 }
408
409         }
410
411         /*
412          * No further desegmentation needed.
413          */
414         return TRUE;
415 }
416
417 /*
418  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
419  *
420  * Local variables:
421  * c-basic-offset: 8
422  * tab-width: 8
423  * indent-tabs-mode: t
424  * End:
425  *
426  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
427  * :indentSize=8:tabSize=8:noTabs=false:
428  */