Frame numbers are unsigned.
[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.17 2003/05/09 01:41:28 tpot 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         int len;
56
57         /* display a string from the tree and return the new offset */
58
59         len = tvb_strnlen(tvb, offset, -1);
60         if (len == -1) {
61                 /*
62                  * XXX - throw an exception?
63                  */
64                 len = tvb_length_remaining(tvb, offset);
65         }
66         str = g_malloc(len+1);
67         tvb_memcpy(tvb, (guint8 *)str, offset, len);
68         str[len] = '\0';
69
70         proto_tree_add_string(tree, hf_index, tvb, offset, len+1, str);
71
72         /* Return a copy of the string if requested */
73
74         if (data)
75                 *data = str;
76         else
77                 g_free(str);
78
79         return  offset+len+1;
80 }
81
82
83 int display_unicode_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, char **data)
84 {
85         char *str, *p;
86         int len;
87         int charoffset;
88         guint16 character;
89
90         /* display a unicode string from the tree and return new offset */
91
92         /*
93          * Get the length of the string.
94          * XXX - is it a bug or a feature that this will throw an exception
95          * if we don't find the '\0'?  I think it's a feature.
96          */
97         len = 0;
98         while ((character = tvb_get_letohs(tvb, offset + len)) != '\0')
99                 len += 2;
100         len += 2;       /* count the '\0' too */
101
102         /*
103          * Allocate a buffer for the string; "len" is the length in
104          * bytes, not the length in characters.
105          */
106         str = g_malloc(len/2);
107
108         /*
109          * XXX - this assumes the string is just ISO 8859-1; we need
110          * to better handle multiple character sets in Ethereal,
111          * including Unicode/ISO 10646, and multiple encodings of
112          * that character set (UCS-2, UTF-8, etc.).
113          */
114         charoffset = offset;
115         p = str;
116         while ((character = tvb_get_letohs(tvb, charoffset)) != '\0') {
117                 *p++ = character;
118                 charoffset += 2;
119         }
120         *p = '\0';
121
122         proto_tree_add_string(tree, hf_index, tvb, offset, len, str);
123
124         if (data)
125                 *data = str;
126         else
127                 g_free(str);
128
129         return  offset+len;
130 }
131
132 /* Max string length for displaying Unicode strings.  */
133 #define MAX_UNICODE_STR_LEN     256
134
135 /* Turn a little-endian Unicode '\0'-terminated string into a string we
136    can display.
137    XXX - for now, we just handle the ISO 8859-1 characters.
138    If exactlen==TRUE then us_lenp contains the exact len of the string in
139    bytes. It might not be null terminated !
140    bc specifies the number of bytes in the byte parameters; Windows 2000,
141    at least, appears, in some cases, to put only 1 byte of 0 at the end
142    of a Unicode string if the byte count
143 */
144 static gchar *
145 unicode_to_str(tvbuff_t *tvb, int offset, int *us_lenp, gboolean exactlen,
146                    guint16 bc)
147 {
148   static gchar  str[3][MAX_UNICODE_STR_LEN+3+1];
149   static gchar *cur;
150   gchar        *p;
151   guint16       uchar;
152   int           len;
153   int           us_len;
154   int           overflow = 0;
155
156   if (cur == &str[0][0]) {
157     cur = &str[1][0];
158   } else if (cur == &str[1][0]) {
159     cur = &str[2][0];
160   } else {
161     cur = &str[0][0];
162   }
163   p = cur;
164   len = MAX_UNICODE_STR_LEN;
165   us_len = 0;
166   for (;;) {
167     if (bc == 0)
168       break;
169     if (bc == 1) {
170       /* XXX - explain this */
171       if (!exactlen)
172         us_len += 1;    /* this is a one-byte null terminator */
173       break;
174     }
175     uchar = tvb_get_letohs(tvb, offset);
176     if (uchar == 0) {
177       us_len += 2;      /* this is a two-byte null terminator */
178       break;
179     }
180     if (len > 0) {
181       if ((uchar & 0xFF00) == 0)
182         *p++ = uchar;   /* ISO 8859-1 */
183       else
184         *p++ = '?';     /* not 8859-1 */
185       len--;
186     } else
187       overflow = 1;
188     offset += 2;
189     bc -= 2;
190     us_len += 2;
191     if(exactlen){
192       if(us_len>= *us_lenp){
193         break;
194       }
195     }
196   }
197   if (overflow) {
198     /* Note that we're not showing the full string.  */
199     *p++ = '.';
200     *p++ = '.';
201     *p++ = '.';
202   }
203   *p = '\0';
204   *us_lenp = us_len;
205   return cur;
206 }
207
208 /* nopad == TRUE : Do not add any padding before this string
209  * exactlen == TRUE : len contains the exact len of the string in bytes.
210  * bc: pointer to variable with amount of data left in the byte parameters
211  *   region
212  */
213 const gchar *
214 get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp,
215     gboolean useunicode, int *len, gboolean nopad, gboolean exactlen,
216     guint16 *bcp)
217 {
218   static gchar  str[3][MAX_UNICODE_STR_LEN+3+1];
219   static gchar *cur;
220   const gchar *string;
221   int string_len;
222   unsigned int copylen;
223
224   if (*bcp == 0) {
225     /* Not enough data in buffer */
226     return NULL;
227   }
228   if (useunicode) {
229     if ((!nopad) && (*offsetp % 2)) {
230       /*
231        * XXX - this should be an offset relative to the beginning of the SMB,
232        * not an offset relative to the beginning of the frame; if the stuff
233        * before the SMB has an odd number of bytes, an offset relative to
234        * the beginning of the frame will give the wrong answer.
235        */
236       (*offsetp)++;   /* Looks like a pad byte there sometimes */
237       (*bcp)--;
238       if (*bcp == 0) {
239         /* Not enough data in buffer */
240         return NULL;
241       }
242     }
243     if(exactlen){
244       string_len = *len;
245     }
246     string = unicode_to_str(tvb, *offsetp, &string_len, exactlen, *bcp);
247   } else {
248     if(exactlen){
249       /*
250        * The string we return must be null-terminated.
251        */
252       if (cur == &str[0][0]) {
253         cur = &str[1][0];
254       } else if (cur == &str[1][0]) {
255         cur = &str[2][0];
256       } else {
257         cur = &str[0][0];
258       }
259       copylen = *len;
260       if (copylen > MAX_UNICODE_STR_LEN)
261         copylen = MAX_UNICODE_STR_LEN;
262       tvb_memcpy(tvb, (guint8 *)cur, *offsetp, copylen);
263       cur[copylen] = '\0';
264       if (copylen > MAX_UNICODE_STR_LEN)
265         strcat(cur, "...");
266       string_len = *len;
267       string = cur;
268     } else {
269       string_len = tvb_strsize(tvb, *offsetp);
270       string = tvb_get_ptr(tvb, *offsetp, string_len);
271     }
272   }
273   *len = string_len;
274   return string;
275 }
276
277 int
278 dissect_smb_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
279 {
280         /* display data as unknown */
281
282         proto_tree_add_text(tree, tvb, offset, -1, "Data (%u bytes)",
283             tvb_reported_length_remaining(tvb, offset));
284
285         return offset+tvb_length_remaining(tvb, offset);
286 }
287
288 /* Dissect a NTLM response. This is documented at
289    http://ubiqx.org/cifs/SMB.html#8, para 2.8.5.3 */
290
291 static int hf_ntlmv2_response = -1;
292 static int hf_ntlmv2_response_hmac = -1;
293 static int hf_ntlmv2_response_header = -1;
294 static int hf_ntlmv2_response_reserved = -1;
295 static int hf_ntlmv2_response_time = -1;
296 static int hf_ntlmv2_response_chal = -1;
297 static int hf_ntlmv2_response_unknown = -1;
298 static int hf_ntlmv2_response_name = -1;
299 static int hf_ntlmv2_response_name_type = -1;
300 static int hf_ntlmv2_response_name_len = -1;
301
302 static gint ett_ntlmv2_response = -1;
303 static gint ett_ntlmv2_response_name = -1;
304
305 /* Name types */
306
307 const value_string ntlm_name_types[] = {
308         { NTLM_NAME_END, "End of list" },
309         { NTLM_NAME_NB_HOST, "NetBIOS host name" },
310         { NTLM_NAME_NB_DOMAIN, "NetBIOS domain name" },
311         { NTLM_NAME_DNS_HOST, "DNS host name" },
312         { NTLM_NAME_DNS_DOMAIN, "DNS domain name" },
313         { 0, NULL }
314 };
315
316 int
317 dissect_ntlmv2_response(tvbuff_t *tvb, proto_tree *tree, int offset, int len)
318 {
319         proto_item *ntlmv2_item = NULL;
320         proto_tree *ntlmv2_tree = NULL;
321
322         /* Dissect NTLMv2 bits&pieces */
323
324         if (tree) {
325                 ntlmv2_item = proto_tree_add_item(
326                         tree, hf_ntlmv2_response, tvb, 
327                         offset, len, TRUE);
328                 ntlmv2_tree = proto_item_add_subtree(
329                         ntlmv2_item, ett_ntlmv2_response);
330         }
331
332         proto_tree_add_item(
333                 ntlmv2_tree, hf_ntlmv2_response_hmac, tvb,
334                 offset, 16, TRUE);
335
336         offset += 16;
337
338         proto_tree_add_item(
339                 ntlmv2_tree, hf_ntlmv2_response_header, tvb,
340                 offset, 4, TRUE);
341
342         offset += 4;
343
344         proto_tree_add_item(
345                 ntlmv2_tree, hf_ntlmv2_response_reserved, tvb,
346                 offset, 4, TRUE);
347
348         offset += 4;
349
350         offset = dissect_smb_64bit_time(
351                 tvb, ntlmv2_tree, offset, hf_ntlmv2_response_time);
352
353         proto_tree_add_item(
354                 ntlmv2_tree, hf_ntlmv2_response_chal, tvb,
355                 offset, 8, TRUE);
356
357         offset += 8;
358
359         proto_tree_add_item(
360                 ntlmv2_tree, hf_ntlmv2_response_unknown, tvb,
361                 offset, 4, TRUE);
362
363         offset += 4;
364
365         /* Variable length list of names */
366
367         while(1) {
368                 guint16 name_type = tvb_get_letohs(tvb, offset);
369                 guint16 name_len = tvb_get_letohs(tvb, offset + 2);
370                 proto_tree *name_tree = NULL;
371                 proto_item *name_item = NULL;
372                 char *name = NULL;
373
374                 if (ntlmv2_tree) {
375                         name_item = proto_tree_add_item(
376                                 ntlmv2_tree, hf_ntlmv2_response_name, 
377                                 tvb, offset, 0, TRUE);
378                         name_tree = proto_item_add_subtree(
379                                 name_item, ett_ntlmv2_response_name);
380                 }
381
382                 /* Dissect name header */
383
384                 proto_tree_add_item(
385                         name_tree, hf_ntlmv2_response_name_type, tvb,
386                         offset, 2, TRUE);
387
388                 offset += 2;
389
390                 proto_tree_add_item(
391                         name_tree, hf_ntlmv2_response_name_len, tvb,
392                         offset, 2, TRUE);
393
394                 offset += 2;
395
396                 /* Dissect name */
397
398                 if (name_len > 0) {
399                         name = tvb_fake_unicode(
400                                 tvb, offset, name_len / 2, TRUE);
401
402                         proto_tree_add_text(
403                                 name_tree, tvb, offset, name_len, 
404                                 "Name: %s", name);
405                 } else
406                         name = g_strdup("NULL");
407
408                 if (name_type == 0)
409                         proto_item_append_text(
410                                 name_item, "%s", 
411                                 val_to_str(name_type, ntlm_name_types,
412                                            "Unknown"));
413                 else
414                         proto_item_append_text(
415                                 name_item, "%s, %s",
416                                 val_to_str(name_type, ntlm_name_types,
417                                            "Unknown"), name);
418
419                 g_free(name);
420
421                 offset += name_len;
422
423                 proto_item_set_len(name_item, name_len + 4);
424
425                 if (name_type == 0) /* End of list */
426                         break;
427         };
428
429         return offset;
430 }
431
432 void register_smb_common(int proto_smb)
433 {
434         static hf_register_info hf[] = {
435
436                 { &hf_ntlmv2_response,
437                   { "NTLMv2 Response", "smb.ntlmv2response", FT_BYTES, 
438                     BASE_HEX, NULL, 0x0, "", HFILL }},
439
440                 { &hf_ntlmv2_response_hmac,
441                   { "HMAC", "smb.ntlmv2response.hmac", FT_BYTES, BASE_HEX, 
442                     NULL, 0x0, "", HFILL }},
443
444                 { &hf_ntlmv2_response_header,
445                   { "Header", "smb.ntlmv2response.header", FT_UINT32, 
446                     BASE_HEX, NULL, 0x0, "", HFILL }},
447
448                 { &hf_ntlmv2_response_reserved,
449                   { "Reserved", "smb.ntlmv2response.reserved", FT_UINT32, 
450                     BASE_HEX, NULL, 0x0, "", HFILL }},
451
452                 { &hf_ntlmv2_response_time,
453                   { "Time", "smb.ntlmv2response.time", FT_ABSOLUTE_TIME, 
454                     BASE_NONE, NULL, 0, "", HFILL }},
455
456                 { &hf_ntlmv2_response_chal,
457                   { "Client challenge", "smb.ntlmv2response.chal", FT_BYTES, 
458                     BASE_HEX, NULL, 0x0, "", HFILL }},
459
460                 { &hf_ntlmv2_response_unknown,
461                   { "Unknown", "smb.ntlmv2response.unknown", FT_UINT32, 
462                     BASE_HEX, NULL, 0x0, "", HFILL }},
463
464                 { &hf_ntlmv2_response_name,
465                   { "Name", "smb.ntlmv2response.name", FT_STRING, BASE_NONE, 
466                     NULL, 0x0, "", HFILL }},
467
468                 { &hf_ntlmv2_response_name_type,
469                   { "Name type", "smb.ntlmv2response.name.type", FT_UINT32, 
470                     BASE_DEC, VALS(ntlm_name_types), 0x0, "", HFILL }},
471
472                 { &hf_ntlmv2_response_name_len,
473                   { "Name len", "smb.ntlmv2response.name.len", FT_UINT32, 
474                     BASE_DEC, NULL, 0x0, "", HFILL }}
475         };
476
477         static gint *ett[] = {
478                 &ett_ntlmv2_response,
479                 &ett_ntlmv2_response_name
480         };
481
482         proto_register_subtree_array(ett, array_length(ett));
483         proto_register_field_array(proto_smb, hf, array_length(hf));
484 }