Add a terminator to the ntlmssp_message_types list.
[obnox/wireshark/wip.git] / packet-ntlmssp.c
1 /* packet-ntlmssp.c
2  * Routines for NTLM Secure Service Provider
3  * Devin Heitmueller <dheitmueller@netilla.com>
4  *
5  * $Id: packet-ntlmssp.c,v 1.6 2002/08/10 23:16:37 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <glib.h>
31 #include <epan/packet.h>
32
33 #include "packet-smb-common.h"
34
35 /* Message types */
36
37 #define NTLMSSP_NEGOTIATE 1
38 #define NTLMSSP_CHALLENGE 2
39 #define NTLMSSP_AUTH      3
40 #define NTLMSSP_UNKNOWN   4
41
42 static const value_string ntlmssp_message_types[] = {
43   { NTLMSSP_NEGOTIATE, "NTLMSSP_NEGOTIATE" },
44   { NTLMSSP_CHALLENGE, "NTLMSSP_CHALLENGE" },
45   { NTLMSSP_AUTH, "NTLMSSP_AUTH" },
46   { NTLMSSP_UNKNOWN, "NTLMSSP_UNKNOWN" },
47   { 0, NULL }
48 };
49
50 static const true_false_string flags_set_truth = {
51   "Set",
52   "Not set"
53 };
54
55 /* 
56  * NTLMSSP negotiation flags 
57  * Taken from Samba
58  */
59 #define NTLMSSP_NEGOTIATE_UNICODE          0x00000001
60 #define NTLMSSP_NEGOTIATE_OEM              0x00000002
61 #define NTLMSSP_REQUEST_TARGET             0x00000004
62 #define NTLMSSP_NEGOTIATE_00000008         0x00000008
63 #define NTLMSSP_NEGOTIATE_SIGN             0x00000010
64 #define NTLMSSP_NEGOTIATE_SEAL             0x00000020
65 #define NTLMSSP_NEGOTIATE_DATAGRAM_STYLE   0x00000040
66 #define NTLMSSP_NEGOTIATE_LM_KEY           0x00000080
67 #define NTLMSSP_NEGOTIATE_NETWARE          0x00000100
68 #define NTLMSSP_NEGOTIATE_NTLM             0x00000200
69 #define NTLMSSP_NEGOTIATE_00000400         0x00000400
70 #define NTLMSSP_NEGOTIATE_00000800         0x00000800
71 #define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED  0x00001000
72 #define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000
73 #define NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL  0x00004000
74 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN      0x00008000
75 #define NTLMSSP_CHAL_INIT_RESPONSE         0x00010000
76 #define NTLMSSP_CHAL_ACCEPT_RESPONSE       0x00020000
77 #define NTLMSSP_CHAL_NON_NT_SESSION_KEY    0x00040000
78 #define NTLMSSP_NEGOTIATE_NTLM2            0x00080000
79 #define NTLMSSP_NEGOTIATE_00100000         0x00100000
80 #define NTLMSSP_NEGOTIATE_00200000         0x00200000
81 #define NTLMSSP_NEGOTIATE_00400000         0x00400000
82 #define NTLMSSP_CHAL_TARGET_INFO           0x00800000
83 #define NTLMSSP_NEGOTIATE_01000000         0x01000000
84 #define NTLMSSP_NEGOTIATE_02000000         0x02000000
85 #define NTLMSSP_NEGOTIATE_04000000         0x04000000
86 #define NTLMSSP_NEGOTIATE_08000000         0x08000000
87 #define NTLMSSP_NEGOTIATE_10000000         0x10000000
88 #define NTLMSSP_NEGOTIATE_128              0x20000000
89 #define NTLMSSP_NEGOTIATE_KEY_EXCH         0x40000000
90 #define NTLMSSP_NEGOTIATE_80000000         0x80000000
91
92
93 static int proto_ntlmssp = -1;
94 static int hf_ntlmssp = -1;
95 static int hf_ntlmssp_auth = -1;
96 static int hf_ntlmssp_message_type = -1;
97 static int hf_ntlmssp_negotiate_flags = -1;
98 static int hf_ntlmssp_negotiate_flags_01 = -1;
99 static int hf_ntlmssp_negotiate_flags_02 = -1;
100 static int hf_ntlmssp_negotiate_flags_04 = -1;
101 static int hf_ntlmssp_negotiate_flags_08 = -1;
102 static int hf_ntlmssp_negotiate_flags_10 = -1;
103 static int hf_ntlmssp_negotiate_flags_20 = -1;
104 static int hf_ntlmssp_negotiate_flags_40 = -1;
105 static int hf_ntlmssp_negotiate_flags_80 = -1;
106 static int hf_ntlmssp_negotiate_flags_100 = -1;
107 static int hf_ntlmssp_negotiate_flags_200 = -1;
108 static int hf_ntlmssp_negotiate_flags_400 = -1;
109 static int hf_ntlmssp_negotiate_flags_800 = -1;
110 static int hf_ntlmssp_negotiate_flags_1000 = -1;
111 static int hf_ntlmssp_negotiate_flags_2000 = -1;
112 static int hf_ntlmssp_negotiate_flags_4000 = -1;
113 static int hf_ntlmssp_negotiate_flags_8000 = -1;
114 static int hf_ntlmssp_negotiate_flags_10000 = -1;
115 static int hf_ntlmssp_negotiate_flags_20000 = -1;
116 static int hf_ntlmssp_negotiate_flags_40000 = -1;
117 static int hf_ntlmssp_negotiate_flags_80000 = -1;
118 static int hf_ntlmssp_negotiate_flags_100000 = -1;
119 static int hf_ntlmssp_negotiate_flags_200000 = -1;
120 static int hf_ntlmssp_negotiate_flags_400000 = -1;
121 static int hf_ntlmssp_negotiate_flags_800000 = -1;
122 static int hf_ntlmssp_negotiate_flags_1000000 = -1;
123 static int hf_ntlmssp_negotiate_flags_2000000 = -1;
124 static int hf_ntlmssp_negotiate_flags_4000000 = -1;
125 static int hf_ntlmssp_negotiate_flags_8000000 = -1;
126 static int hf_ntlmssp_negotiate_flags_10000000 = -1;
127 static int hf_ntlmssp_negotiate_flags_20000000 = -1;
128 static int hf_ntlmssp_negotiate_flags_40000000 = -1;
129 static int hf_ntlmssp_negotiate_flags_80000000 = -1;
130 static int hf_ntlmssp_negotiate_workstation_strlen = -1;
131 static int hf_ntlmssp_negotiate_workstation_maxlen = -1;
132 static int hf_ntlmssp_negotiate_workstation_buffer = -1;
133 static int hf_ntlmssp_negotiate_workstation = -1;
134 static int hf_ntlmssp_negotiate_domain_strlen = -1;
135 static int hf_ntlmssp_negotiate_domain_maxlen = -1;
136 static int hf_ntlmssp_negotiate_domain_buffer = -1;
137 static int hf_ntlmssp_negotiate_domain = -1;
138 static int hf_ntlmssp_ntlm_challenge = -1;
139 static int hf_ntlmssp_reserved = -1;
140 static int hf_ntlmssp_challenge_unknown1 = -1;
141 static int hf_ntlmssp_challenge_unknown2 = -1;
142 static int hf_ntlmssp_auth_lmresponse_strlen = -1;
143 static int hf_ntlmssp_auth_lmresponse_maxlen = -1;
144 static int hf_ntlmssp_auth_lmresponse_offset = -1;
145 static int hf_ntlmssp_auth_ntresponse_strlen = -1;
146 static int hf_ntlmssp_auth_ntresponse_maxlen = -1;
147 static int hf_ntlmssp_auth_ntresponse_offset = -1;
148 static int hf_ntlmssp_auth_domain_strlen = -1;
149 static int hf_ntlmssp_auth_domain_maxlen = -1;
150 static int hf_ntlmssp_auth_domain_offset = -1;
151 static int hf_ntlmssp_auth_username_strlen = -1;
152 static int hf_ntlmssp_auth_username_maxlen = -1;
153 static int hf_ntlmssp_auth_username_offset = -1;
154 static int hf_ntlmssp_auth_hostname_strlen = -1;
155 static int hf_ntlmssp_auth_hostname_maxlen = -1;
156 static int hf_ntlmssp_auth_hostname_offset = -1;
157 static int hf_ntlmssp_auth_unknown1_strlen = -1;
158 static int hf_ntlmssp_auth_unknown1_maxlen = -1;
159 static int hf_ntlmssp_auth_unknown1_offset = -1;
160 static int hf_ntlmssp_auth_username = -1;
161 static int hf_ntlmssp_auth_domain = -1;
162 static int hf_ntlmssp_auth_hostname = -1;
163 static int hf_ntlmssp_auth_lmresponse = -1;
164 static int hf_ntlmssp_auth_ntresponse = -1;
165 static int hf_ntlmssp_auth_unknown1 = -1;
166 static gint ett_ntlmssp = -1;
167 static gint ett_ntlmssp_negotiate_flags = -1;
168
169 static int
170 dissect_ntlmssp_negotiate_flags (tvbuff_t *tvb, int offset, 
171                                  proto_tree *ntlmssp_tree,
172                                  guint32 negotiate_flags)
173 {
174   proto_tree *negotiate_flags_tree = NULL;
175   proto_item *tf = NULL;
176
177   if (ntlmssp_tree) {
178     tf = proto_tree_add_uint (ntlmssp_tree, 
179                               hf_ntlmssp_negotiate_flags, 
180                               tvb, offset, 4, negotiate_flags);
181     negotiate_flags_tree = proto_item_add_subtree (tf, ett_ntlmssp_negotiate_flags);
182   }
183
184   proto_tree_add_boolean (negotiate_flags_tree, 
185                           hf_ntlmssp_negotiate_flags_80000000, 
186                           tvb, offset, 4, negotiate_flags);
187   proto_tree_add_boolean (negotiate_flags_tree, 
188                           hf_ntlmssp_negotiate_flags_40000000, 
189                           tvb, offset, 4, negotiate_flags);
190   proto_tree_add_boolean (negotiate_flags_tree, 
191                           hf_ntlmssp_negotiate_flags_20000000, 
192                           tvb, offset, 4, negotiate_flags);
193   proto_tree_add_boolean (negotiate_flags_tree, 
194                           hf_ntlmssp_negotiate_flags_10000000, 
195                           tvb, offset, 4, negotiate_flags);
196   proto_tree_add_boolean (negotiate_flags_tree, 
197                           hf_ntlmssp_negotiate_flags_8000000, 
198                           tvb, offset, 4, negotiate_flags);
199   proto_tree_add_boolean (negotiate_flags_tree, 
200                           hf_ntlmssp_negotiate_flags_4000000, 
201                           tvb, offset, 4, negotiate_flags);
202   proto_tree_add_boolean (negotiate_flags_tree, 
203                           hf_ntlmssp_negotiate_flags_2000000, 
204                           tvb, offset, 4, negotiate_flags);
205   proto_tree_add_boolean (negotiate_flags_tree, 
206                           hf_ntlmssp_negotiate_flags_1000000, 
207                           tvb, offset, 4, negotiate_flags);
208   proto_tree_add_boolean (negotiate_flags_tree, 
209                           hf_ntlmssp_negotiate_flags_800000, 
210                           tvb, offset, 4, negotiate_flags);
211   proto_tree_add_boolean (negotiate_flags_tree, 
212                           hf_ntlmssp_negotiate_flags_400000, 
213                           tvb, offset, 4, negotiate_flags);
214   proto_tree_add_boolean (negotiate_flags_tree, 
215                           hf_ntlmssp_negotiate_flags_200000, 
216                           tvb, offset, 4, negotiate_flags);
217   proto_tree_add_boolean (negotiate_flags_tree, 
218                           hf_ntlmssp_negotiate_flags_100000, 
219                           tvb, offset, 4, negotiate_flags);
220   proto_tree_add_boolean (negotiate_flags_tree, 
221                           hf_ntlmssp_negotiate_flags_80000, 
222                           tvb, offset, 4, negotiate_flags);
223   proto_tree_add_boolean (negotiate_flags_tree, 
224                           hf_ntlmssp_negotiate_flags_40000, 
225                           tvb, offset, 4, negotiate_flags);
226   proto_tree_add_boolean (negotiate_flags_tree, 
227                           hf_ntlmssp_negotiate_flags_20000, 
228                           tvb, offset, 4, negotiate_flags);
229   proto_tree_add_boolean (negotiate_flags_tree, 
230                           hf_ntlmssp_negotiate_flags_10000, 
231                           tvb, offset, 4, negotiate_flags);
232   proto_tree_add_boolean (negotiate_flags_tree, 
233                           hf_ntlmssp_negotiate_flags_8000, 
234                           tvb, offset, 4, negotiate_flags);
235   proto_tree_add_boolean (negotiate_flags_tree, 
236                           hf_ntlmssp_negotiate_flags_4000, 
237                           tvb, offset, 4, negotiate_flags);
238   proto_tree_add_boolean (negotiate_flags_tree, 
239                           hf_ntlmssp_negotiate_flags_2000, 
240                           tvb, offset, 4, negotiate_flags);
241   proto_tree_add_boolean (negotiate_flags_tree,
242                           hf_ntlmssp_negotiate_flags_1000,
243                           tvb, offset, 4, negotiate_flags);
244   proto_tree_add_boolean (negotiate_flags_tree, 
245                           hf_ntlmssp_negotiate_flags_800, 
246                           tvb, offset, 4, negotiate_flags);
247   proto_tree_add_boolean (negotiate_flags_tree, 
248                           hf_ntlmssp_negotiate_flags_400, 
249                           tvb, offset, 4, negotiate_flags);
250   proto_tree_add_boolean (negotiate_flags_tree, 
251                           hf_ntlmssp_negotiate_flags_200, 
252                           tvb, offset, 4, negotiate_flags);
253   proto_tree_add_boolean (negotiate_flags_tree, 
254                           hf_ntlmssp_negotiate_flags_100, 
255                           tvb, offset, 4, negotiate_flags);
256   proto_tree_add_boolean (negotiate_flags_tree,
257                           hf_ntlmssp_negotiate_flags_80, 
258                           tvb, offset, 4, negotiate_flags);
259   proto_tree_add_boolean (negotiate_flags_tree, 
260                           hf_ntlmssp_negotiate_flags_40, 
261                           tvb, offset, 4, negotiate_flags);
262   proto_tree_add_boolean (negotiate_flags_tree, 
263                           hf_ntlmssp_negotiate_flags_20, 
264                           tvb, offset, 4, negotiate_flags);
265   proto_tree_add_boolean (negotiate_flags_tree, 
266                           hf_ntlmssp_negotiate_flags_10,
267                           tvb, offset, 4, negotiate_flags);
268   proto_tree_add_boolean (negotiate_flags_tree, 
269                           hf_ntlmssp_negotiate_flags_08, 
270                           tvb, offset, 4, negotiate_flags);
271   proto_tree_add_boolean (negotiate_flags_tree, 
272                           hf_ntlmssp_negotiate_flags_04, 
273                           tvb, offset, 4, negotiate_flags);
274   proto_tree_add_boolean (negotiate_flags_tree, 
275                           hf_ntlmssp_negotiate_flags_02, 
276                           tvb, offset, 4, negotiate_flags);
277   proto_tree_add_boolean (negotiate_flags_tree, 
278                           hf_ntlmssp_negotiate_flags_01, 
279                           tvb, offset, 4, negotiate_flags);  
280
281   return (offset + 4);
282 }
283
284
285 static int
286 dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, 
287                            proto_tree *ntlmssp_tree)
288 {
289   guint32 negotiate_flags;
290   guint16 workstation_length;
291   guint16 domain_length;
292
293   /* NTLMSSP Negotiate Flags */
294   negotiate_flags = tvb_get_letohl (tvb, offset);
295   offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
296                                             negotiate_flags);
297
298   /* Calling workstation domain name length */
299   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_negotiate_domain_strlen,
300                        tvb, offset, 2, TRUE);
301   domain_length = tvb_get_letohs (tvb, offset);
302   offset += 2;
303
304   /* Calling workstation domain name max length */
305   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_negotiate_domain_maxlen,
306                        tvb, offset, 2, TRUE);
307   offset += 2;
308
309
310   /* Calling workstation domain name buffer? */
311   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_negotiate_domain_buffer,
312                        tvb, offset, 4, TRUE);
313   offset += 4;
314
315   /* Calling workstation name length */
316   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_negotiate_workstation_strlen,
317                        tvb, offset, 2, TRUE);
318   workstation_length = tvb_get_letohs (tvb, offset);
319   offset += 2;
320
321   /* Calling workstation name max length */
322   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_negotiate_workstation_maxlen,
323                        tvb, offset, 2, TRUE);
324   offset += 2;
325
326   /* Calling workstation name buffer? */
327   proto_tree_add_uint(ntlmssp_tree, hf_ntlmssp_negotiate_workstation_buffer,
328                       tvb, offset, 4, TRUE);
329   offset += 4;
330
331   /* Calling workstation name */
332   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_negotiate_workstation,
333                        tvb, offset, workstation_length, FALSE);
334   offset += workstation_length;
335
336   /* Calling domain name */
337   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_negotiate_domain,
338                        tvb, offset, domain_length, FALSE);
339   offset += domain_length;
340
341   return offset;
342 }
343
344
345 static int
346 dissect_ntlmssp_challenge (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree)
347 {
348   guint32 negotiate_flags;
349
350   /* Skip over the two unknown fields */
351   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_challenge_unknown1,
352                        tvb, offset, 4, TRUE);
353   offset += 4;
354
355   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_challenge_unknown2,
356                        tvb, offset, 4, TRUE);
357   offset += 4;
358
359   /* NTLMSSP Negotiate Flags */
360   negotiate_flags = tvb_get_letohl (tvb, offset);
361   offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
362                                             negotiate_flags);
363
364   /* NTLMSSP NT Lan Manager Challenge */
365   proto_tree_add_item (ntlmssp_tree,
366                        hf_ntlmssp_ntlm_challenge,
367                        tvb, offset, 8, FALSE);
368   offset += 8;
369   
370   /* Reserved (function not completely known) */
371   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_reserved,
372                        tvb, offset, 8, FALSE);
373   offset += 8;
374
375   return offset;
376 }
377
378 static int
379 dissect_ntlmssp_auth (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree)
380 {
381   guint16 lmresponse_length;
382   guint16 ntresponse_length;
383   guint16 domain_length;
384   guint16 username_length;
385   guint16 hostname_length;
386   guint16 unknown1_length;
387   guint32 negotiate_flags;
388   const gchar *username;
389   const gchar *domain;
390   const gchar *hostname;
391   int result_length;
392   guint16 bc;
393   gboolean unicode_strings = FALSE;
394
395   /* Lan Manager response length */
396   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_lmresponse_strlen,
397                        tvb, offset, 2, TRUE);
398   lmresponse_length = tvb_get_letohs (tvb, offset);
399   offset += 2;
400
401   /* Lan Manager response max length */
402   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_lmresponse_maxlen,
403                        tvb, offset, 2, TRUE);
404   offset += 2;
405
406   /* Lan Manager response offset */
407   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_lmresponse_offset,
408                        tvb, offset, 4, TRUE);
409   offset += 4;
410
411   /* NTLM response length */
412   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_ntresponse_strlen,
413                        tvb, offset, 2, TRUE);
414   ntresponse_length = tvb_get_letohs (tvb, offset);
415   offset += 2;
416
417   /* NTLM response max length */
418   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_ntresponse_maxlen,
419                        tvb, offset, 2, TRUE);
420   offset += 2;
421
422   /* NTLM response offset */
423   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_ntresponse_offset,
424                        tvb, offset, 4, TRUE);
425   offset += 4;
426
427   /* Domain name length */
428   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_domain_strlen,
429                        tvb, offset, 2, TRUE);
430   domain_length = tvb_get_letohs (tvb, offset);
431   offset += 2;
432
433   /* Domain name max length */
434   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_domain_maxlen,
435                        tvb, offset, 2, TRUE);
436   offset += 2;
437
438   /* Domain name offset */
439   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_domain_offset,
440                        tvb, offset, 4, TRUE);
441   offset += 4;
442
443   /* Username length */
444   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_username_strlen,
445                        tvb, offset, 2, TRUE);
446   username_length = tvb_get_letohs (tvb, offset);
447   offset += 2;
448
449   /* Username max length */
450   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_username_maxlen,
451                        tvb, offset, 2, TRUE);
452   offset += 2;
453
454   /* Username offset */
455   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_username_offset,
456                        tvb, offset, 4, TRUE);
457   offset += 4;
458
459   /* Hostname length */
460   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_hostname_strlen,
461                        tvb, offset, 2, TRUE);
462   hostname_length = tvb_get_letohs (tvb, offset);
463   offset += 2;
464
465   /* Hostname max length */
466   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_hostname_maxlen,
467                        tvb, offset, 2, TRUE);
468   offset += 2;
469
470   /* Hostname offset */
471   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_hostname_offset,
472                        tvb, offset, 4, TRUE);
473   offset += 4;
474
475   /* Unknown1 length */
476   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_unknown1_strlen,
477                        tvb, offset, 2, TRUE);
478   unknown1_length = tvb_get_letohs (tvb, offset);
479   offset += 2;
480
481   /* Unknown1 max length */
482   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_unknown1_maxlen,
483                        tvb, offset, 2, TRUE);
484   offset += 2;
485
486   /* Unknown1 offset */
487   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_unknown1_offset,
488                        tvb, offset, 4, TRUE);
489   offset += 4;
490
491   /* NTLMSSP Negotiate Flags */
492   negotiate_flags = tvb_get_letohl (tvb, offset);
493   offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
494                                             negotiate_flags);
495
496   if (negotiate_flags && NTLMSSP_NEGOTIATE_UNICODE)
497     unicode_strings = TRUE;
498
499   /* Domain name */
500   bc = domain_length;
501   domain = get_unicode_or_ascii_string(tvb, &offset,
502                                        unicode_strings, &result_length,
503                                        FALSE, FALSE, &bc);
504
505   proto_tree_add_string(ntlmssp_tree, hf_ntlmssp_auth_domain, tvb, 
506                         offset, result_length, domain);
507   offset += domain_length;
508
509   /* User name */
510   bc = username_length;
511   username = get_unicode_or_ascii_string(tvb, &offset,
512                                          unicode_strings, &result_length,
513                                          FALSE, FALSE, &bc);
514
515   proto_tree_add_string(ntlmssp_tree, hf_ntlmssp_auth_username, tvb, 
516                         offset, result_length, username);
517   offset += username_length;
518
519   /* Host name */
520   bc = hostname_length;
521   hostname = get_unicode_or_ascii_string(tvb, &offset,
522                                          unicode_strings, &result_length,
523                                          FALSE, FALSE, &bc);
524
525   proto_tree_add_string(ntlmssp_tree, hf_ntlmssp_auth_hostname, tvb, 
526                         offset, result_length, hostname);
527   offset += hostname_length;
528
529   /* Lan Manager Response */
530   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_lmresponse,
531                        tvb, offset, lmresponse_length, FALSE);
532   offset += lmresponse_length;
533
534   /* NTLM Response */
535   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_ntresponse,
536                        tvb, offset, ntresponse_length, FALSE);
537   offset += ntresponse_length; 
538
539   /* Unknown1 */
540   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth_unknown1,
541                        tvb, offset, unknown1_length, FALSE);
542   offset += unknown1_length; 
543
544   return offset;
545 }
546
547 static void
548 dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
549 {
550   guint32 ntlmssp_message_type;
551   int offset = 0;
552   int payloadsize = 0;
553   proto_tree *ntlmssp_tree = NULL;
554   proto_item *tf = NULL;
555
556   /* Compute the total size of the data to be parsed */
557   payloadsize = tvb_length_remaining(tvb, 0);
558   
559   /* Setup a new tree for the NTLMSSP payload */
560   if (tree) {
561     tf = proto_tree_add_item (tree, 
562                               hf_ntlmssp,
563                               tvb, offset, payloadsize, FALSE);
564     
565     ntlmssp_tree = proto_item_add_subtree (tf, 
566                                            ett_ntlmssp);
567   }
568   
569   /* NTLMSSP constant */
570   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth, 
571                        tvb, offset, 8, FALSE);
572   offset += 8;
573
574   /* NTLMSSP Message Type */
575   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_message_type,
576                        tvb, offset, 4, TRUE);
577   ntlmssp_message_type = tvb_get_letohl (tvb, offset);
578   offset += 4;
579
580   /* Call the appropriate dissector based on the Message Type */
581   switch (ntlmssp_message_type) {
582
583   case NTLMSSP_NEGOTIATE:
584     offset = dissect_ntlmssp_negotiate (tvb, offset, ntlmssp_tree);
585     break;
586
587   case NTLMSSP_CHALLENGE:
588     offset = dissect_ntlmssp_challenge (tvb, offset, ntlmssp_tree);
589     break;
590
591   case NTLMSSP_AUTH:
592     offset = dissect_ntlmssp_auth (tvb, offset, ntlmssp_tree);
593     break;
594
595   default:
596     /* Unrecognized message type */
597     proto_tree_add_text (ntlmssp_tree, tvb, offset, 
598                          (payloadsize - 12), 
599                          "Unrecognized NTLMSSP Message");
600     break;
601   }
602 }
603
604 void
605 proto_register_ntlmssp(void)
606 {
607
608   static hf_register_info hf[] = {
609     { &hf_ntlmssp,
610       { "NTLMSSP", "ntlmssp", FT_NONE, BASE_NONE, NULL, 0x0, "NTLMSSP", HFILL }},
611     
612     { &hf_ntlmssp_auth, 
613       { "NTLMSSP identifier", "ntlmssp.identifier", FT_STRING, BASE_NONE, NULL, 0x0, "NTLMSSP Identifier", HFILL }},
614     
615     { &hf_ntlmssp_message_type,
616       { "NTLM Message Type", "ntlmssp.messagetype", FT_UINT32, BASE_HEX, VALS(ntlmssp_message_types), 0x0, "", HFILL }},
617     
618     { &hf_ntlmssp_negotiate_flags,
619       { "Flags", "dcerpc.negotiateflags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
620     { &hf_ntlmssp_negotiate_flags_01,
621       
622       { "Negotiate UNICODE", "ntlmssp.negotiateunicode", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_UNICODE, "", HFILL }},
623     { &hf_ntlmssp_negotiate_flags_02,
624       { "Negotiate OEM", "ntlmssp.negotiateoem", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_OEM, "", HFILL }},
625     { &hf_ntlmssp_negotiate_flags_04,
626       { "Request Target", "ntlmssp.requesttarget", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_REQUEST_TARGET, "", HFILL }},
627     { &hf_ntlmssp_negotiate_flags_08,
628       { "Request 0x00000008", "ntlmssp.negotiate00000008", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000008, "", HFILL }},
629     { &hf_ntlmssp_negotiate_flags_10,
630       { "Negotiate Sign", "ntlmssp.negotiatesign", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_SIGN, "", HFILL }},
631     { &hf_ntlmssp_negotiate_flags_20,
632       { "Negotiate Seal", "ntlmssp.negotiateseal", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_SEAL, "", HFILL }},
633     { &hf_ntlmssp_negotiate_flags_40,
634       { "Negotiate Datagram Style", "ntlmssp.negotiatedatagramstyle", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_DATAGRAM_STYLE, "", HFILL }},
635     { &hf_ntlmssp_negotiate_flags_80,
636       { "Negotiate Lan Manager Key", "ntlmssp.negotiatelmkey", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_LM_KEY, "", HFILL }},
637     { &hf_ntlmssp_negotiate_flags_100,
638       { "Negotiate Netware", "ntlmssp.negotiatenetware", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NETWARE, "", HFILL }},
639     { &hf_ntlmssp_negotiate_flags_200,
640       { "Negotiate NTLM key", "ntlmssp.negotiatentlm", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NTLM, "", HFILL }},
641     { &hf_ntlmssp_negotiate_flags_400,
642       { "Negotiate 0x00000400", "ntlmssp.negotiate00000400", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000400, "", HFILL }},
643     { &hf_ntlmssp_negotiate_flags_800,
644       { "Negotiate 0x00000800", "ntlmssp.negotiate00000800", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000800, "", HFILL }},
645     { &hf_ntlmssp_negotiate_flags_1000,
646       { "Negotiate Domain Supplied", "ntlmssp.negotiatedomainsupplied", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED, "", HFILL }},
647     { &hf_ntlmssp_negotiate_flags_2000,
648       { "Negotiate Workstation Supplied", "ntlmssp.negotiateworkstationsupplied", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED, "", HFILL }},
649     { &hf_ntlmssp_negotiate_flags_4000,
650       { "Negotiate This is Local Call", "ntlmssp.negotiatethisislocalcall", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL, "", HFILL }},
651     { &hf_ntlmssp_negotiate_flags_8000,
652       { "Negotiate Always Sign", "ntlmssp.negotiatealwayssign", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_ALWAYS_SIGN, "", HFILL }},
653     { &hf_ntlmssp_negotiate_flags_10000,
654       { "Negotiate Challenge Init Response", "ntlmssp.negotiatechallengeinitresponse", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_INIT_RESPONSE, "", HFILL }},
655     { &hf_ntlmssp_negotiate_flags_20000,
656       { "Negotiate Challenge Accept Response", "ntlmssp.negotiatechallengeacceptresponse", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_ACCEPT_RESPONSE, "", HFILL }},
657     { &hf_ntlmssp_negotiate_flags_40000,
658       { "Negotiate Challenge Non NT Session Key", "ntlmssp.negotiatechallengenonntsessionkey", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_NON_NT_SESSION_KEY, "", HFILL }},
659     { &hf_ntlmssp_negotiate_flags_80000,
660       { "Negotiate NTLM2 key", "ntlmssp.negotiatentlm2", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NTLM2, "", HFILL }},
661     { &hf_ntlmssp_negotiate_flags_100000,
662       { "Negotiate 0x00100000", "ntlmssp.negotiatent00100000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00100000, "", HFILL }},
663     { &hf_ntlmssp_negotiate_flags_200000,
664       { "Negotiate 0x00200000", "ntlmssp.negotiatent00200000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00200000, "", HFILL }},
665     { &hf_ntlmssp_negotiate_flags_400000,
666       { "Negotiate 0x00400000", "ntlmssp.negotiatent00400000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00400000, "", HFILL }},
667     { &hf_ntlmssp_negotiate_flags_800000,
668       { "Negotiate Target Info", "ntlmssp.negotiatetargetinfo", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_TARGET_INFO, "", HFILL }},
669     { &hf_ntlmssp_negotiate_flags_1000000,
670       { "Negotiate 0x01000000", "ntlmssp.negotiatent01000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_01000000, "", HFILL }},
671     { &hf_ntlmssp_negotiate_flags_2000000,
672       { "Negotiate 0x02000000", "ntlmssp.negotiatent02000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_02000000, "", HFILL }},
673     { &hf_ntlmssp_negotiate_flags_4000000,
674       { "Negotiate 0x04000000", "ntlmssp.negotiatent04000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_04000000, "", HFILL }},
675     { &hf_ntlmssp_negotiate_flags_8000000,
676       { "Negotiate 0x08000000", "ntlmssp.negotiatent08000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_08000000, "", HFILL }},
677     { &hf_ntlmssp_negotiate_flags_10000000,
678       { "Negotiate 0x10000000", "ntlmssp.negotiatent10000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_10000000, "", HFILL }},
679     { &hf_ntlmssp_negotiate_flags_20000000,
680       { "Negotiate 128", "ntlmssp.negotiate128", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_128, "", HFILL }},
681     { &hf_ntlmssp_negotiate_flags_40000000,
682       { "Negotiate Key Exchange", "ntlmssp.negotiatekeyexch", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_KEY_EXCH, "", HFILL }},
683     { &hf_ntlmssp_negotiate_flags_80000000,
684       { "Negotiate 0x80000000", "ntlmssp.negotiatent80000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_80000000, "", HFILL }},
685     { &hf_ntlmssp_negotiate_workstation_strlen,
686       { "Calling workstation name length", "ntlmssp.negotiate.callingworkstation.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
687     { &hf_ntlmssp_negotiate_workstation_maxlen,
688       { "Calling workstation name max length", "ntlmssp.negotiate.callingworkstation.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
689     { &hf_ntlmssp_negotiate_workstation_buffer,
690       { "Calling workstation name buffer", "ntlmssp.negotiate.callingworkstation.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
691     { &hf_ntlmssp_negotiate_workstation,
692       { "Calling workstation name", "ntlmssp.negotiate.callingworkstation", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
693     { &hf_ntlmssp_negotiate_domain_strlen,
694       { "Calling workstation domain length", "ntlmssp.negotiate.domain.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
695     { &hf_ntlmssp_negotiate_domain_maxlen,
696       { "Calling workstation domain max length", "ntlmssp.negotiate.domain.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
697     { &hf_ntlmssp_negotiate_domain_buffer,
698       { "Calling workstation domain buffer", "ntlmssp.negotiate.domain.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
699     { &hf_ntlmssp_negotiate_domain,
700       { "Calling workstation domain", "ntlmssp.negotiate.domain", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
701     { &hf_ntlmssp_ntlm_challenge,
702       { "NTLM Challenge", "ntlmssp.ntlmchallenge", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
703     { &hf_ntlmssp_reserved,
704       { "Reserved", "ntlmssp.reserved", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
705     { &hf_ntlmssp_challenge_unknown1,
706       { "Unknown1", "ntlmssp.challenge.unknown1", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
707     { &hf_ntlmssp_challenge_unknown2,
708       { "Unknown2", "ntlmssp.challenge.unknown2", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
709     { &hf_ntlmssp_auth_lmresponse_strlen,
710       { "Lan Manager response length", "ntlmssp.auth.lmresponse.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
711     { &hf_ntlmssp_auth_lmresponse_maxlen,
712       { "Lan Manager response max length", "ntlmssp.auth.lmresponse.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
713     { &hf_ntlmssp_auth_lmresponse_offset,
714       { "Lan Manager response offset", "ntlmssp.auth.lmresponse.offset", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
715     { &hf_ntlmssp_auth_ntresponse_strlen,
716       { "NTLM response length", "ntlmssp.auth.ntresponse.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
717     { &hf_ntlmssp_auth_ntresponse_maxlen,
718       { "NTLM response max length", "ntlmssp.auth.ntresponse.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
719     { &hf_ntlmssp_auth_ntresponse_offset,
720       { "NTLM response offset", "ntlmssp.auth.ntresponse.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
721     { &hf_ntlmssp_auth_domain_strlen,
722       { "Domain name length", "ntlmssp.auth.domain.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
723     { &hf_ntlmssp_auth_domain_maxlen,
724       { "Domain name max length", "ntlmssp.auth.domain.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
725     { &hf_ntlmssp_auth_domain_offset,
726       { "Domain name offset", "ntlmssp.auth.domain.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
727     { &hf_ntlmssp_auth_username_strlen,
728       { "Username length", "ntlmssp.auth.username.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
729     { &hf_ntlmssp_auth_username_maxlen,
730       { "Username max length", "ntlmssp.auth.username.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
731     { &hf_ntlmssp_auth_username_offset,
732       { "Username offset", "ntlmssp.auth.username.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
733     { &hf_ntlmssp_auth_hostname_strlen,
734       { "Hostname length", "ntlmssp.auth.hostname.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
735     { &hf_ntlmssp_auth_hostname_maxlen,
736       { "Hostname max length", "ntlmssp.auth.hostname.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
737     { &hf_ntlmssp_auth_hostname_offset,
738       { "Hostname offset", "ntlmssp.auth.hostname.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
739     { &hf_ntlmssp_auth_unknown1_strlen,
740       { "Unknown1 length", "ntlmssp.auth.unknown1.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
741     { &hf_ntlmssp_auth_unknown1_maxlen,
742       { "Unknown1 max length", "ntlmssp.auth.unknown1.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
743     { &hf_ntlmssp_auth_unknown1_offset,
744       { "Unknown1 offset", "ntlmssp.auth.unknown1.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
745     { &hf_ntlmssp_auth_domain,
746       { "Domain name", "ntlmssp.auth.domain", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
747     { &hf_ntlmssp_auth_username,
748       { "User name", "ntlmssp.auth.username", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
749     { &hf_ntlmssp_auth_hostname,
750       { "Host name", "ntlmssp.auth.hostname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
751     { &hf_ntlmssp_auth_lmresponse,
752       { "Lan Manager Response", "ntlmssp.auth.lmresponse", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
753     { &hf_ntlmssp_auth_ntresponse,
754       { "NTLM Response", "ntlmssp.auth.ntresponse", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
755     { &hf_ntlmssp_auth_unknown1,
756       { "Unknown1", "ntlmssp.auth.unknown1", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }}
757   };
758
759
760   static gint *ett[] = {
761     &ett_ntlmssp,
762     &ett_ntlmssp_negotiate_flags,
763   };
764
765   proto_ntlmssp = proto_register_protocol (
766                                            "NTLM Secure Service Provider", /* name */
767                                            "NTLMSSP",   /* short name */
768                                            "ntlmssp"    /* abbrev */
769                                            );
770   proto_register_field_array (proto_ntlmssp, hf, array_length (hf));
771   proto_register_subtree_array (ett, array_length (ett));
772   
773   register_dissector("ntlmssp", dissect_ntlmssp, proto_ntlmssp);
774 }