In "get_unicode_or_ascii_string()", treat a negative length argument as
[obnox/wireshark/wip.git] / packet-smb-common.c
1 /* packet-smb-common.c
2  * Common routines for smb packet dissection
3  * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
4  *
5  * $Id: packet-smb-common.c,v 1.20 2004/04/03 03:50:44 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from packet-pop.c
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #include "packet-smb-common.h"
29
30 /*
31  * Share type values - used in LANMAN and in SRVSVC.
32  *
33  * XXX - should we dissect share type values, at least in SRVSVC, as
34  * a subtree with bitfields, as the 0x80000000 bit appears to be a
35  * hidden bit, with some number of bits at the bottom being the share
36  * type?
37  *
38  * Does LANMAN use that bit?
39  */
40 const value_string share_type_vals[] = {
41         {0, "Directory tree"},
42         {1, "Printer queue"},
43         {2, "Communications device"},
44         {3, "IPC"},
45         {0x80000000, "Hidden Directory tree"},
46         {0x80000001, "Hidden Printer queue"},
47         {0x80000002, "Hidden Communications device"},
48         {0x80000003, "Hidden IPC"},
49         {0, NULL}
50 };
51
52 int display_ms_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, char **data)
53 {
54         char *str;
55         gint len;
56
57         /* display a string from the tree and return the new offset */
58
59         str = tvb_get_stringz(tvb, offset, &len);
60         proto_tree_add_string(tree, hf_index, tvb, offset, len, str);
61
62         /* Return a copy of the string if requested */
63
64         if (data)
65                 *data = str;
66         else
67                 g_free(str);
68
69         return  offset+len;
70 }
71
72
73 int display_unicode_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, char **data)
74 {
75         char *str, *p;
76         int len;
77         int charoffset;
78         guint16 character;
79
80         /* display a unicode string from the tree and return new offset */
81
82         /*
83          * Get the length of the string.
84          * XXX - is it a bug or a feature that this will throw an exception
85          * if we don't find the '\0'?  I think it's a feature.
86          */
87         len = 0;
88         while ((character = tvb_get_letohs(tvb, offset + len)) != '\0')
89                 len += 2;
90         len += 2;       /* count the '\0' too */
91
92         /*
93          * Allocate a buffer for the string; "len" is the length in
94          * bytes, not the length in characters.
95          */
96         str = g_malloc(len/2);
97
98         /*
99          * XXX - this assumes the string is just ISO 8859-1; we need
100          * to better handle multiple character sets in Ethereal,
101          * including Unicode/ISO 10646, and multiple encodings of
102          * that character set (UCS-2, UTF-8, etc.).
103          */
104         charoffset = offset;
105         p = str;
106         while ((character = tvb_get_letohs(tvb, charoffset)) != '\0') {
107                 *p++ = (char) character;
108                 charoffset += 2;
109         }
110         *p = '\0';
111
112         proto_tree_add_string(tree, hf_index, tvb, offset, len, str);
113
114         if (data)
115                 *data = str;
116         else
117                 g_free(str);
118
119         return  offset+len;
120 }
121
122 /* Max string length for displaying Unicode strings.  */
123 #define MAX_UNICODE_STR_LEN     256
124
125 /* Turn a little-endian Unicode '\0'-terminated string into a string we
126    can display.
127    XXX - for now, we just handle the ISO 8859-1 characters.
128    If exactlen==TRUE then us_lenp contains the exact len of the string in
129    bytes. It might not be null terminated !
130    bc specifies the number of bytes in the byte parameters; Windows 2000,
131    at least, appears, in some cases, to put only 1 byte of 0 at the end
132    of a Unicode string if the byte count
133 */
134 static gchar *
135 unicode_to_str(tvbuff_t *tvb, int offset, int *us_lenp, gboolean exactlen,
136                    guint16 bc)
137 {
138   static gchar  str[3][MAX_UNICODE_STR_LEN+3+1];
139   static gchar *cur;
140   gchar        *p;
141   guint16       uchar;
142   int           len;
143   int           us_len;
144   gboolean      overflow = FALSE;
145
146   if (cur == &str[0][0]) {
147     cur = &str[1][0];
148   } else if (cur == &str[1][0]) {
149     cur = &str[2][0];
150   } else {
151     cur = &str[0][0];
152   }
153   p = cur;
154   len = MAX_UNICODE_STR_LEN;
155   us_len = 0;
156   for (;;) {
157     if (bc == 0)
158       break;
159     if (bc == 1) {
160       /* XXX - explain this */
161       if (!exactlen)
162         us_len += 1;    /* this is a one-byte null terminator */
163       break;
164     }
165     uchar = tvb_get_letohs(tvb, offset);
166     if (uchar == 0) {
167       us_len += 2;      /* this is a two-byte null terminator */
168       break;
169     }
170     if (len > 0) {
171       if ((uchar & 0xFF00) == 0)
172         *p++ = (gchar) uchar;   /* ISO 8859-1 */
173       else
174         *p++ = '?';     /* not 8859-1 */
175       len--;
176     } else
177       overflow = TRUE;
178     offset += 2;
179     bc -= 2;
180     us_len += 2;
181     if(exactlen){
182       if(us_len>= *us_lenp){
183         break;
184       }
185     }
186   }
187   if (overflow) {
188     /* Note that we're not showing the full string.  */
189     *p++ = '.';
190     *p++ = '.';
191     *p++ = '.';
192   }
193   *p = '\0';
194   *us_lenp = us_len;
195   return cur;
196 }
197
198 /* nopad == TRUE : Do not add any padding before this string
199  * exactlen == TRUE : len contains the exact len of the string in bytes.
200  * bc: pointer to variable with amount of data left in the byte parameters
201  *   region
202  */
203 const gchar *
204 get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp,
205     gboolean useunicode, int *len, gboolean nopad, gboolean exactlen,
206     guint16 *bcp)
207 {
208   static gchar  str[3][MAX_UNICODE_STR_LEN+3+1];
209   static gchar *cur;
210   const gchar *string;
211   int string_len;
212   int copylen;
213   gboolean overflow = FALSE;
214
215   if (*bcp == 0) {
216     /* Not enough data in buffer */
217     return NULL;
218   }
219   if (useunicode) {
220     if ((!nopad) && (*offsetp % 2)) {
221       /*
222        * XXX - this should be an offset relative to the beginning of the SMB,
223        * not an offset relative to the beginning of the frame; if the stuff
224        * before the SMB has an odd number of bytes, an offset relative to
225        * the beginning of the frame will give the wrong answer.
226        */
227       (*offsetp)++;   /* Looks like a pad byte there sometimes */
228       (*bcp)--;
229       if (*bcp == 0) {
230         /* Not enough data in buffer */
231         return NULL;
232       }
233     }
234     if(exactlen){
235       string_len = *len;
236       if (string_len < 0) {
237         /* This probably means it's a very large unsigned number; just set
238            it to the largest signed number, so that we throw the appropriate
239            exception. */
240         string_len = INT_MAX;
241       }
242     }
243     string = unicode_to_str(tvb, *offsetp, &string_len, exactlen, *bcp);
244   } else {
245     if(exactlen){
246       /*
247        * The string we return must be null-terminated.
248        */
249       if (cur == &str[0][0]) {
250         cur = &str[1][0];
251       } else if (cur == &str[1][0]) {
252         cur = &str[2][0];
253       } else {
254         cur = &str[0][0];
255       }
256       copylen = *len;
257       if (copylen < 0) {
258         /* This probably means it's a very large unsigned number; just set
259            it to the largest signed number, so that we throw the appropriate
260            exception. */
261         copylen = INT_MAX;
262       }
263       tvb_ensure_bytes_exist(tvb, *offsetp, copylen);
264       if (copylen > MAX_UNICODE_STR_LEN) {
265         copylen = MAX_UNICODE_STR_LEN;
266         overflow = TRUE;
267       }
268       tvb_memcpy(tvb, (guint8 *)cur, *offsetp, copylen);
269       cur[copylen] = '\0';
270       if (overflow)
271         strcat(cur, "...");
272       string_len = *len;
273       string = cur;
274     } else {
275       string_len = tvb_strsize(tvb, *offsetp);
276       string = tvb_get_ptr(tvb, *offsetp, string_len);
277     }
278   }
279   *len = string_len;
280   return string;
281 }
282
283 int
284 dissect_smb_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
285 {
286         /* display data as unknown */
287
288         proto_tree_add_text(tree, tvb, offset, -1, "Data (%u bytes)",
289             tvb_reported_length_remaining(tvb, offset));
290
291         return offset+tvb_length_remaining(tvb, offset);
292 }
293
294 /* Dissect a NTLM response. This is documented at
295    http://ubiqx.org/cifs/SMB.html#8, para 2.8.5.3 */
296
297 static int hf_ntlmv2_response = -1;
298 static int hf_ntlmv2_response_hmac = -1;
299 static int hf_ntlmv2_response_header = -1;
300 static int hf_ntlmv2_response_reserved = -1;
301 static int hf_ntlmv2_response_time = -1;
302 static int hf_ntlmv2_response_chal = -1;
303 static int hf_ntlmv2_response_unknown = -1;
304 static int hf_ntlmv2_response_name = -1;
305 static int hf_ntlmv2_response_name_type = -1;
306 static int hf_ntlmv2_response_name_len = -1;
307
308 static gint ett_ntlmv2_response = -1;
309 static gint ett_ntlmv2_response_name = -1;
310
311 /* Name types */
312
313 const value_string ntlm_name_types[] = {
314         { NTLM_NAME_END, "End of list" },
315         { NTLM_NAME_NB_HOST, "NetBIOS host name" },
316         { NTLM_NAME_NB_DOMAIN, "NetBIOS domain name" },
317         { NTLM_NAME_DNS_HOST, "DNS host name" },
318         { NTLM_NAME_DNS_DOMAIN, "DNS domain name" },
319         { 0, NULL }
320 };
321
322 int
323 dissect_ntlmv2_response(tvbuff_t *tvb, proto_tree *tree, int offset, int len)
324 {
325         proto_item *ntlmv2_item = NULL;
326         proto_tree *ntlmv2_tree = NULL;
327
328         /* Dissect NTLMv2 bits&pieces */
329
330         if (tree) {
331                 ntlmv2_item = proto_tree_add_item(
332                         tree, hf_ntlmv2_response, tvb, 
333                         offset, len, TRUE);
334                 ntlmv2_tree = proto_item_add_subtree(
335                         ntlmv2_item, ett_ntlmv2_response);
336         }
337
338         proto_tree_add_item(
339                 ntlmv2_tree, hf_ntlmv2_response_hmac, tvb,
340                 offset, 16, TRUE);
341
342         offset += 16;
343
344         proto_tree_add_item(
345                 ntlmv2_tree, hf_ntlmv2_response_header, tvb,
346                 offset, 4, TRUE);
347
348         offset += 4;
349
350         proto_tree_add_item(
351                 ntlmv2_tree, hf_ntlmv2_response_reserved, tvb,
352                 offset, 4, TRUE);
353
354         offset += 4;
355
356         offset = dissect_smb_64bit_time(
357                 tvb, ntlmv2_tree, offset, hf_ntlmv2_response_time);
358
359         proto_tree_add_item(
360                 ntlmv2_tree, hf_ntlmv2_response_chal, tvb,
361                 offset, 8, TRUE);
362
363         offset += 8;
364
365         proto_tree_add_item(
366                 ntlmv2_tree, hf_ntlmv2_response_unknown, tvb,
367                 offset, 4, TRUE);
368
369         offset += 4;
370
371         /* Variable length list of names */
372
373         while(1) {
374                 guint16 name_type = tvb_get_letohs(tvb, offset);
375                 guint16 name_len = tvb_get_letohs(tvb, offset + 2);
376                 proto_tree *name_tree = NULL;
377                 proto_item *name_item = NULL;
378                 char *name = NULL;
379
380                 if (ntlmv2_tree) {
381                         name_item = proto_tree_add_item(
382                                 ntlmv2_tree, hf_ntlmv2_response_name, 
383                                 tvb, offset, 0, TRUE);
384                         name_tree = proto_item_add_subtree(
385                                 name_item, ett_ntlmv2_response_name);
386                 }
387
388                 /* Dissect name header */
389
390                 proto_tree_add_item(
391                         name_tree, hf_ntlmv2_response_name_type, tvb,
392                         offset, 2, TRUE);
393
394                 offset += 2;
395
396                 proto_tree_add_item(
397                         name_tree, hf_ntlmv2_response_name_len, tvb,
398                         offset, 2, TRUE);
399
400                 offset += 2;
401
402                 /* Dissect name */
403
404                 if (name_len > 0) {
405                         name = tvb_fake_unicode(
406                                 tvb, offset, name_len / 2, TRUE);
407
408                         proto_tree_add_text(
409                                 name_tree, tvb, offset, name_len, 
410                                 "Name: %s", name);
411                 } else
412                         name = g_strdup("NULL");
413
414                 if (name_type == 0)
415                         proto_item_append_text(
416                                 name_item, "%s", 
417                                 val_to_str(name_type, ntlm_name_types,
418                                            "Unknown"));
419                 else
420                         proto_item_append_text(
421                                 name_item, "%s, %s",
422                                 val_to_str(name_type, ntlm_name_types,
423                                            "Unknown"), name);
424
425                 g_free(name);
426
427                 offset += name_len;
428
429                 proto_item_set_len(name_item, name_len + 4);
430
431                 if (name_type == 0) /* End of list */
432                         break;
433         };
434
435         return offset;
436 }
437
438 void register_smb_common(int proto_smb)
439 {
440         static hf_register_info hf[] = {
441
442                 { &hf_ntlmv2_response,
443                   { "NTLMv2 Response", "smb.ntlmv2response", FT_BYTES, 
444                     BASE_HEX, NULL, 0x0, "", HFILL }},
445
446                 { &hf_ntlmv2_response_hmac,
447                   { "HMAC", "smb.ntlmv2response.hmac", FT_BYTES, BASE_HEX, 
448                     NULL, 0x0, "", HFILL }},
449
450                 { &hf_ntlmv2_response_header,
451                   { "Header", "smb.ntlmv2response.header", FT_UINT32, 
452                     BASE_HEX, NULL, 0x0, "", HFILL }},
453
454                 { &hf_ntlmv2_response_reserved,
455                   { "Reserved", "smb.ntlmv2response.reserved", FT_UINT32, 
456                     BASE_HEX, NULL, 0x0, "", HFILL }},
457
458                 { &hf_ntlmv2_response_time,
459                   { "Time", "smb.ntlmv2response.time", FT_ABSOLUTE_TIME, 
460                     BASE_NONE, NULL, 0, "", HFILL }},
461
462                 { &hf_ntlmv2_response_chal,
463                   { "Client challenge", "smb.ntlmv2response.chal", FT_BYTES, 
464                     BASE_HEX, NULL, 0x0, "", HFILL }},
465
466                 { &hf_ntlmv2_response_unknown,
467                   { "Unknown", "smb.ntlmv2response.unknown", FT_UINT32, 
468                     BASE_HEX, NULL, 0x0, "", HFILL }},
469
470                 { &hf_ntlmv2_response_name,
471                   { "Name", "smb.ntlmv2response.name", FT_STRING, BASE_NONE, 
472                     NULL, 0x0, "", HFILL }},
473
474                 { &hf_ntlmv2_response_name_type,
475                   { "Name type", "smb.ntlmv2response.name.type", FT_UINT32, 
476                     BASE_DEC, VALS(ntlm_name_types), 0x0, "", HFILL }},
477
478                 { &hf_ntlmv2_response_name_len,
479                   { "Name len", "smb.ntlmv2response.name.len", FT_UINT32, 
480                     BASE_DEC, NULL, 0x0, "", HFILL }}
481         };
482
483         static gint *ett[] = {
484                 &ett_ntlmv2_response,
485                 &ett_ntlmv2_response_name
486         };
487
488         proto_register_subtree_array(ett, array_length(ett));
489         proto_register_field_array(proto_smb, hf, array_length(hf));
490 }