removed some gcc warnings (hopefully)
[obnox/wireshark/wip.git] / epan / dissectors / packet-smb-logon.c
1 /* packet-smb-logon.c
2  * Routines for SMB net logon packet dissection
3  * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
4  *
5  * $Id$
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 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <glib.h>
33
34 #include <epan/packet.h>
35 #include "packet-windows-common.h"
36 #include "packet-smb-common.h"
37
38 static int proto_smb_logon = -1;
39 static int hf_command = -1;
40 static int hf_computer_name = -1;
41 static int hf_unicode_computer_name = -1;
42 static int hf_server_name = -1;
43 static int hf_user_name = -1;
44 static int hf_domain_name = -1;
45 static int hf_mailslot_name = -1;
46 static int hf_pdc_name = -1;
47 static int hf_unicode_pdc_name = -1;
48 static int hf_script_name = -1;
49 static int hf_nt_version = -1;
50 static int hf_lmnt_token = -1;
51 static int hf_lm_token = -1;
52 static int hf_major_version = -1;
53 static int hf_minor_version = -1;
54 static int hf_os_version = -1;
55 static int hf_date_time = -1;
56 static int hf_update_type = -1;
57 static int hf_request_count = -1;
58 static int hf_flags_autolock = -1;
59 static int hf_flags_expire = -1;
60 static int hf_flags_server_trust = -1;
61 static int hf_flags_workstation_trust = -1;
62 static int hf_flags_interdomain_trust = -1;
63 static int hf_flags_mns_user = -1;
64 static int hf_flags_normal_user = -1;
65 static int hf_flags_temp_dup_user = -1;
66 static int hf_flags_password_required = -1;
67 static int hf_flags_homedir_required = -1;
68 static int hf_flags_enabled = -1;
69 static int hf_domain_sid_size = -1;
70 static int hf_low_serial = -1;
71 static int hf_pulse = -1;
72 static int hf_random = -1;
73 static int hf_db_count = -1;
74 static int hf_db_index = -1;
75 static int hf_large_serial = -1;
76 static int hf_nt_date_time = -1;
77
78 static int ett_smb_logon = -1;
79 static int ett_smb_account_flags = -1;
80 static int ett_smb_db_info = -1;
81
82 #define ACC_FLAG_AUTO_LOCKED                    0x0400
83 #define ACC_FLAG_EXPIRE                         0x0200
84 #define ACC_FLAG_SERVER_TRUST                   0x0100
85 #define ACC_FLAG_WORKSTATION_TRUST              0x0080
86 #define ACC_FLAG_INTERDOMAIN_TRUST              0x0040
87 #define ACC_FLAG_MNS_USER                       0x0020
88 #define ACC_FLAG_NORMAL_USER                    0x0010
89 #define ACC_FLAG_TEMP_DUP_USER                  0x0008
90 #define ACC_FLAG_PASSWORD_REQUIRED              0x0004
91 #define ACC_FLAG_HOMEDIR_REQUIRED               0x0002
92 #define ACC_FLAG_ENABLED                        0x0001
93
94 static const true_false_string tfs_flags_autolock = {
95         "User account auto-locked",
96         "User account NOT auto-locked"
97 };
98 static const true_false_string tfs_flags_expire = {
99         "User password will NOT expire",
100         "User password will expire"
101 };
102 static const true_false_string tfs_flags_server_trust = {
103         "Server Trust user account",
104         "NOT a Server Trust user account"
105 };
106 static const true_false_string tfs_flags_workstation_trust = {
107         "Workstation Trust user account",
108         "NOT a Workstation Trust user account"
109 };
110 static const true_false_string tfs_flags_interdomain_trust = {
111         "Inter-domain Trust user account",
112         "NOT a Inter-domain Trust user account"
113 };
114 static const true_false_string tfs_flags_mns_user = {
115         "MNS Logon user account",
116         "NOT a MNS Logon user account"
117 };
118 static const true_false_string tfs_flags_normal_user = {
119         "Normal user account",
120         "NOT a normal user account"
121 };
122 static const true_false_string tfs_flags_temp_dup_user = {
123         "Temp duplicate user account",
124         "NOT a temp duplicate user account"
125 };
126 static const true_false_string tfs_flags_password_required = {
127         "NO password required",
128         "Password required"
129 };
130 static const true_false_string tfs_flags_homedir_required = {
131         "NO homedir required",
132         "Homedir required"
133 };
134 static const true_false_string tfs_flags_enabled = {
135         "User account enabled",
136         "User account disabled"
137 };
138
139
140
141 static int
142 dissect_account_control(tvbuff_t *tvb, proto_tree *tree, int offset)
143 {
144         /* display the Allowable Account control bits */
145
146         proto_item *ti = NULL;
147         proto_tree *flags_tree = NULL;
148         guint32 flags;
149
150         flags = tvb_get_letohl(tvb, offset);
151
152         if (tree) {
153                 ti = proto_tree_add_text(tree, tvb, offset, 4,
154                         "Account control  = 0x%04x", flags);
155
156                 flags_tree = proto_item_add_subtree(ti, ett_smb_account_flags);
157         }
158
159         proto_tree_add_boolean(flags_tree, hf_flags_autolock, tvb, offset, 4, flags);
160         proto_tree_add_boolean(flags_tree, hf_flags_expire, tvb, offset, 4, flags);
161         proto_tree_add_boolean(flags_tree, hf_flags_server_trust, tvb, offset, 4, flags);
162         proto_tree_add_boolean(flags_tree, hf_flags_workstation_trust, tvb, offset, 4, flags);
163         proto_tree_add_boolean(flags_tree, hf_flags_interdomain_trust, tvb, offset, 4, flags);
164         proto_tree_add_boolean(flags_tree, hf_flags_mns_user, tvb, offset, 4, flags);
165         proto_tree_add_boolean(flags_tree, hf_flags_normal_user, tvb, offset, 4, flags);
166         proto_tree_add_boolean(flags_tree, hf_flags_temp_dup_user, tvb, offset, 4, flags);
167         proto_tree_add_boolean(flags_tree, hf_flags_password_required, tvb, offset, 4, flags);
168         proto_tree_add_boolean(flags_tree, hf_flags_homedir_required, tvb, offset, 4, flags);
169         proto_tree_add_boolean(flags_tree, hf_flags_enabled, tvb, offset, 4, flags);
170
171         offset += 4;
172
173         return offset;
174 }
175
176 static int
177 display_LM_token(tvbuff_t *tvb, int offset, proto_tree *tree)
178 {
179         guint16 Token;
180
181         Token = tvb_get_letohs(tvb, offset);
182
183         if (Token & 0x01) {
184                 proto_tree_add_uint_format(tree, hf_lm_token, tvb, offset, 2,
185                         Token,
186                         "LM20 Token: 0x%04x (LanMan 2.0 or higher)", Token);
187         } else {
188                 /*
189                  * XXX - are all values with the lower bit set LM 2.0,
190                  * and all values with it not set LM 1.0?
191                  * What do the other bits mean, if anything?
192                  */
193                 proto_tree_add_uint_format(tree, hf_lm_token, tvb, offset, 2,
194                         Token,
195                         "LM10 Token: 0x%04x (WFW Networking)", Token);
196         }
197
198         offset += 2;
199
200         return offset;
201 }
202
203 static int
204 display_LMNT_token(tvbuff_t *tvb, int offset, proto_tree *tree)
205 {
206         guint16 Token;
207
208         Token = tvb_get_letohs(tvb, offset);
209
210         if (Token == 0xffff) {
211                 proto_tree_add_uint_format(tree, hf_lmnt_token, tvb, offset, 2,
212                         Token,
213                         "LMNT Token: 0x%04x (Windows NT Networking)", Token);
214         } else {
215                 /*
216                  * XXX - what is it if it's not 0xffff?
217                  */
218                 proto_tree_add_uint_format(tree, hf_lm_token, tvb, offset, 2,
219                         Token,
220                         "LMNT Token: 0x%04x (Unknown)", Token);
221         }
222
223         offset += 2;
224
225         return offset;
226 }
227
228 static int
229 dissect_smb_logon_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
230 {
231         /*** 0x00 (LM1.0/LM2.0 LOGON Request) ***/
232
233         /* computer name */
234         offset = display_ms_string(tvb, tree, offset, hf_computer_name, NULL);
235
236         /* user name */
237         offset = display_ms_string(tvb, tree, offset, hf_user_name, NULL);
238
239         /* mailslot name */
240         offset = display_ms_string(tvb, tree, offset, hf_mailslot_name, NULL);
241
242         /*$$$$$ here add the Mailslot to the response list (if needed) */
243
244         /* Request count */
245         proto_tree_add_item(tree, hf_request_count, tvb, offset, 1, TRUE);
246         offset += 1;
247
248         /* NT version */
249         proto_tree_add_item(tree, hf_nt_version, tvb, offset, 2, TRUE);
250         offset += 2;
251
252         /* LM token */
253         offset = display_LM_token(tvb, offset, tree);
254
255         return offset;
256 }
257
258
259
260 static int
261 dissect_smb_logon_LM10_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
262 {
263         /*** 0x01 LanMan 1.0 Logon response ***/
264
265         /* user name */
266         offset = display_ms_string(tvb, tree, offset, hf_user_name, NULL);
267
268         /* script name */
269         offset = display_ms_string(tvb, tree, offset, hf_script_name, NULL);
270
271         return offset;
272 }
273
274
275 static int
276 dissect_smb_logon_2(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
277 {
278         /*** 0x02  LM1.0 Query - Centralized Initialization ***/
279         /*** 0x03  LM1.0 Query - Distributed Initialization ***/
280         /*** 0x04  LM1.0 Query - Centralized Query Response ***/
281         /*** 0x04  LM1.0 Query - Distributed Query Response ***/
282
283         /* computer name */
284         offset = display_ms_string(tvb, tree, offset, hf_computer_name, NULL);
285
286         /* mailslot name */
287         offset = display_ms_string(tvb, tree, offset, hf_mailslot_name, NULL);
288
289         /* NT version */
290         proto_tree_add_item(tree, hf_nt_version, tvb, offset, 2, TRUE);
291         offset += 2;
292
293         /* LM token */
294         offset = display_LM_token(tvb, offset, tree);
295
296         return offset;
297 }
298
299
300
301 static int
302 dissect_smb_logon_LM20_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
303 {
304         /*** 0x06 (LM2.0 LOGON Response)        ***/
305
306         /* server name */
307         offset = display_ms_string(tvb, tree, offset, hf_server_name, NULL);
308
309         /* LM token */
310         offset = display_LM_token(tvb, offset, tree);
311
312         return offset;
313 }
314
315
316
317 static int
318 dissect_smb_pdc_query(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
319 {
320         char *name;
321
322         /*** 0x07 Query for Primary PDC  ***/
323
324         /* computer name */
325         offset = display_ms_string(tvb, tree, offset, hf_computer_name, &name);
326
327         if (check_col(pinfo->cinfo, COL_INFO))
328                 col_append_fstr(pinfo->cinfo, COL_INFO, " from %s", name);
329
330         g_free(name);
331
332         /* mailslot name */
333         offset = display_ms_string(tvb, tree, offset, hf_mailslot_name, NULL);
334
335         if (tvb_reported_length_remaining(tvb, offset) > 2) {
336                 /*
337                  * NT-style Query for PDC?
338                  * If only 2 bytes remain, it's probably a Windows 95-style
339                  * query, which has only an LM token after the mailslot
340                  * name.
341                  *
342                  * XXX - base this on flags in the SMB header, e.g.
343                  * the ASCII/Unicode strings flag?
344                  */
345                 if (offset % 2) offset++;      /* word align ... */
346
347                 /* Unicode computer name */
348                 offset = display_unicode_string(tvb, tree, offset, hf_unicode_computer_name, NULL);
349
350                 /* NT version */
351                 proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
352                 offset += 4;
353
354                 /* LMNT token */
355                 offset = display_LMNT_token(tvb, offset, tree);
356         }
357
358         /* LM token */
359         offset = display_LM_token(tvb, offset, tree);
360
361         return offset;
362 }
363
364
365
366 static int
367 dissect_smb_pdc_startup(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
368 {
369         /*** 0x08  Announce startup of PDC ***/
370
371         /* pdc name */
372         offset = display_ms_string(tvb, tree, offset, hf_pdc_name, NULL);
373
374         /* A short Announce will not have the rest */
375
376         if (tvb_reported_length_remaining(tvb, offset) != 0) {
377           char *name = NULL;
378
379           if (offset % 2) offset++;      /* word align ... */
380
381           /* pdc name */
382           offset = display_unicode_string(tvb, tree, offset, hf_unicode_pdc_name, &name);
383
384           if (name && check_col(pinfo->cinfo, COL_INFO)) {
385                   col_append_fstr(pinfo->cinfo, COL_INFO, ": host %s", name);
386                   g_free(name);
387                   name = NULL;
388           }
389
390           if (offset % 2) offset++;
391
392           /* domain name */
393           offset = display_unicode_string(tvb, tree, offset, hf_domain_name, &name);
394
395           if (name && check_col(pinfo->cinfo, COL_INFO)) {
396                   col_append_fstr(pinfo->cinfo, COL_INFO, ", domain %s", name);
397                   g_free(name);
398                   name = NULL;
399           }
400
401           /* NT version */
402           proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
403           offset += 4;
404
405           /* LMNT token */
406           offset = display_LMNT_token(tvb, offset, tree);
407
408           /* LM token */
409           offset = display_LM_token(tvb, offset, tree);
410         }
411
412         return offset;
413 }
414
415
416
417 static int
418 dissect_smb_pdc_failure(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
419 {
420         /*** 0x09 Announce failure of the PDC ***/
421         /*** 0x0F LM2.0 Resp. during LOGON pause ***/
422         /*** 0x10 (LM 2.0 Unknown user response) ***/
423
424         /* NT version */
425         proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
426         offset += 4;
427
428         /* LM token */
429         offset = display_LM_token(tvb, offset, tree);
430
431         return offset;
432 }
433
434
435 static int
436 dissect_announce_change(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
437 {
438         /*** 0x0A ( Announce change to UAS or SAM ) ***/
439         guint32 info_count;
440         proto_item *ti = NULL;
441         proto_tree *info_tree = NULL;
442         guint32 db_index;
443         guint32 domain_sid_size;
444
445         /* low serial number */
446         proto_tree_add_item(tree, hf_low_serial, tvb, offset, 4, TRUE);
447         offset += 4;
448
449         /* date/time */
450         /* XXX - what format is this?  Neither SMB_Date/SMB_Time nor
451            "time_t but in the local time zone" appear to be correct. */
452         proto_tree_add_item(tree, hf_date_time, tvb, offset, 4, TRUE);
453         offset += 4;
454
455         /* pulse */
456         proto_tree_add_item(tree, hf_pulse, tvb, offset, 4, TRUE);
457         offset += 4;
458
459         /* random */
460         proto_tree_add_item(tree, hf_random, tvb, offset, 4, TRUE);
461         offset += 4;
462
463         /* pdc name */
464         offset = display_ms_string(tvb, tree, offset, hf_pdc_name, NULL);
465
466         /* domain name */
467         offset = display_ms_string(tvb, tree, offset, hf_domain_name, NULL);
468
469         if (offset % 2) offset++;      /* word align ... */
470
471         if (tvb_reported_length_remaining(tvb, offset) > 2) {
472                 /*
473                  * XXX - older protocol versions don't have this stuff?
474                  */
475                 /* pdc name */
476                 offset = display_unicode_string(tvb, tree, offset, hf_unicode_pdc_name, NULL);
477
478                 /* domain name */
479                 offset = display_unicode_string(tvb, tree, offset, hf_domain_name, NULL);
480
481                 /* DB count */
482                 info_count = tvb_get_letohl(tvb, offset);
483                 proto_tree_add_uint(tree, hf_db_count, tvb, offset, 4, info_count);
484                 offset += 4;
485
486                 while (info_count != 0) {
487                         db_index = tvb_get_letohl(tvb, offset);
488                         if (tree) {
489                                 ti = proto_tree_add_text(tree, tvb, offset, 20,
490                                     "DBChange Info Structure: index %u", db_index);
491                                 info_tree = proto_item_add_subtree(ti, ett_smb_db_info);
492                         }
493
494                         proto_tree_add_uint(info_tree, hf_db_index, tvb, offset, 4,
495                             db_index);
496                         offset += 4;
497
498                         proto_tree_add_item(info_tree, hf_large_serial, tvb, offset, 8,
499                             TRUE);
500                         offset += 8;
501
502                         offset = dissect_nt_64bit_time(tvb, info_tree, offset,
503                             hf_nt_date_time);
504
505                         info_count--;
506                 }
507
508                 /* Domain SID Size */
509                 domain_sid_size = tvb_get_letohl(tvb, offset);
510                 proto_tree_add_uint(tree, hf_domain_sid_size, tvb, offset, 4,
511                     domain_sid_size);
512                 offset += 4;
513
514                 if (domain_sid_size != 0) {
515                         /* Align to four-byte boundary */
516                         offset = ((offset + 3)/4)*4;
517
518                         /* Domain SID */
519                         offset = dissect_nt_sid(
520                                 tvb, offset, tree, "Domain", NULL, -1);
521                 }
522
523                 /* NT version */
524                 proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
525                 offset += 4;
526
527                 /* LMNT token */
528                 offset = display_LMNT_token(tvb, offset, tree);
529         }
530
531         /* LM token */
532         offset = display_LM_token(tvb, offset, tree);
533
534         return offset;
535 }
536
537
538
539 static int
540 dissect_smb_sam_logon_req(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
541 {
542         /* Netlogon command 0x12 - decode the SAM logon request from client */
543
544         guint32 domain_sid_size;
545
546         /* Request count */
547         proto_tree_add_item(tree, hf_request_count, tvb, offset, 2, TRUE);
548         offset += 2;
549
550         /* computer name */
551         offset = display_unicode_string(tvb, tree, offset, hf_unicode_computer_name, NULL);
552
553         /* user name */
554         offset = display_unicode_string(tvb, tree, offset, hf_user_name, NULL);
555
556         /* mailslot name */
557         offset = display_ms_string(tvb, tree, offset, hf_mailslot_name, NULL);
558
559         /* account control */
560         offset = dissect_account_control(tvb, tree, offset);
561
562         /* Domain SID Size */
563         domain_sid_size = tvb_get_letohl(tvb, offset);
564         proto_tree_add_uint(tree, hf_domain_sid_size, tvb, offset, 4,
565             domain_sid_size);
566         offset += 4;
567
568         if (domain_sid_size != 0) {
569                 /* Align to four-byte boundary */
570                 offset = ((offset + 3)/4)*4;
571
572                 /* Domain SID */
573                 offset = dissect_nt_sid(tvb, offset, tree, "Domain", NULL, -1);
574         }
575
576         /* NT version */
577         proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
578         offset += 4;
579
580         /* LMNT token */
581         offset = display_LMNT_token(tvb, offset, tree);
582
583         /* LM token */
584         offset = display_LM_token(tvb, offset, tree);
585
586         return offset;
587 }
588
589
590
591 static int
592 dissect_smb_no_user(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
593 {
594         /* 0x0B (Announce no user on machine) */
595
596         /* computer name */
597         offset = display_ms_string(tvb, tree, offset, hf_computer_name, NULL);
598
599         return offset;
600 }
601
602
603
604 static int
605 dissect_smb_relogon_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
606 {
607         /*** 0x0d LanMan Response to relogon request ***/
608
609         /* Major version */
610         proto_tree_add_item(tree, hf_major_version, tvb, offset, 1, TRUE);
611         offset += 1;
612
613         /* Minor version */
614         proto_tree_add_item(tree, hf_minor_version, tvb, offset, 1, TRUE);
615         offset += 1;
616
617         /* OS version */
618         proto_tree_add_item(tree, hf_os_version, tvb, offset, 1, TRUE);
619         offset += 1;
620
621         /* NT version */
622         proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
623         offset += 4;
624
625         /* LM token */
626         offset = display_LM_token(tvb, offset, tree);
627
628         return offset;
629 }
630
631
632
633 static int
634 dissect_smb_acc_update(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
635 {
636         /*** 0x11  LM2.1 Announce Acc updates  ***/
637
638         guint32 Temp1, Temp2;
639
640         Temp1 = tvb_get_letohl(tvb, offset);
641         Temp2 = tvb_get_letohl(tvb, offset + 4);
642
643         /* signature */
644         proto_tree_add_text(tree, tvb, offset, 8, "Signature: 0x%08x%08x",
645                 Temp1, Temp2);
646         offset += 8;
647
648         /* date/time */
649         /* XXX - what format is this?  Neither SMB_Date/SMB_Time nor
650            "time_t but in the local time zone" appear to be correct. */
651         proto_tree_add_item(tree, hf_date_time, tvb, offset, 4, TRUE);
652         offset += 4;
653
654         /* computer name */
655         offset = display_ms_string(tvb, tree, offset, hf_computer_name, NULL);
656
657         /* user name */
658         offset = display_ms_string(tvb, tree, offset, hf_user_name, NULL);
659
660         /* update type */
661         proto_tree_add_item(tree, hf_update_type, tvb, offset, 2, TRUE);
662         offset += 2;
663
664         /* NT version */
665         proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
666         offset += 4;
667
668         /* LM token */
669         offset = display_LM_token(tvb, offset, tree);
670
671         return offset;
672 }
673
674
675
676 static int
677 dissect_smb_inter_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
678 {
679         /* 0x0e LanMan Response to interrogate request */
680
681         /* Major version */
682         proto_tree_add_item(tree, hf_major_version, tvb, offset, 1, TRUE);
683         offset += 1;
684
685         /* Minor version */
686         proto_tree_add_item(tree, hf_minor_version, tvb, offset, 1, TRUE);
687         offset += 1;
688
689         /* OS version */
690         proto_tree_add_item(tree, hf_os_version, tvb, offset, 1, TRUE);
691         offset += 1;
692
693         /* NT version */
694         proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
695         offset += 4;
696
697         /* LMNT token */
698         offset = display_LMNT_token(tvb, offset, tree);
699
700         /* XXX - no LM token?  Every other packet has one after the LMNT
701            token. */
702
703         return offset;
704 }
705
706
707 static int
708 dissect_smb_sam_logon_resp(tvbuff_t *tvb, packet_info *pinfo _U_,
709         proto_tree *tree, int offset)
710 {
711         /* Netlogon command 0x13 - decode the SAM logon response from server */
712
713         /* server name */
714         offset = display_unicode_string(tvb, tree, offset, hf_server_name, NULL);
715
716         /* user name */
717         offset = display_unicode_string(tvb, tree, offset, hf_user_name, NULL);
718
719         /* domain name */
720         offset = display_unicode_string(tvb, tree, offset, hf_domain_name, NULL);
721
722         /* NT version */
723         proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
724         offset += 4;
725
726         /* LMNT token */
727         offset = display_LMNT_token(tvb, offset, tree);
728
729         /* LM token */
730         offset = display_LM_token(tvb, offset, tree);
731
732         return offset;
733 }
734
735 static int
736 dissect_smb_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
737 {
738         /* display data as unknown */
739
740         proto_tree_add_text(tree, tvb, offset, -1, "Data (%u bytes)",
741             tvb_reported_length_remaining(tvb, offset));
742
743         return offset+tvb_length_remaining(tvb, offset);
744 }
745
746 #define LOGON_LM10_LOGON_REQUEST                0x00
747 #define LOGON_LM10_LOGON_RESPONSE               0x01
748 #define LOGON_LM10_QUERY_CI                     0x02
749 #define LOGON_LM10_QUERY_DI                     0x03
750 #define LOGON_LM10_RESPONSE_CI                  0x04
751 #define LOGON_LM10_RESPONSE_DI                  0x05
752 #define LOGON_LM20_LOGON_RESPONSE               0x06
753 #define LOGON_PDC_QUERY                         0x07
754 #define LOGON_PDC_STARTUP                       0x08
755 #define LOGON_PDC_FAILED                        0x09
756 #define LOGON_UAS_SAM                           0x0a
757 #define LOGON_NO_USER                           0x0b
758 #define LOGON_PDC_RESPONSE                      0x0c
759 #define LOGON_RELOGON_RESPONSE                  0x0d
760 #define LOGON_INTERROGATE_RESPONSE              0x0e
761 #define LOGON_LM20_RESPONSE_DURING_LOGON        0x0f
762 #define LOGON_LM20_USER_UNKNOWN                 0x10
763 #define LOGON_LM20_ACCOUNT_UPDATE               0x11
764 #define LOGON_SAM_LOGON_REQUEST                 0x12
765 #define LOGON_SAM_LOGON_RESPONSE                0x13
766 #define LOGON_SAM_RESPONSE_DURING_LOGON         0x14
767 #define LOGON_SAM_USER_UNKNOWN                  0x15
768 #define LOGON_SAM_INTERROGATE_RESPONSE          0x16
769 #define LOGON_SAM_AD_USER_UNKNOWN               0x17
770 #define LOGON_SAM_UNKNOWN_18                    0x18
771 #define LOGON_SAM_AD_LOGON_RESPONSE             0x19
772 #define LOGON_LAST_CMD                          0x20
773
774 static const value_string commands[] = {
775         {LOGON_LM10_LOGON_REQUEST,      "LM1.0/LM2.0 LOGON Request"},
776         {LOGON_LM10_LOGON_RESPONSE,     "LM1.0 LOGON Response"},
777         {LOGON_LM10_QUERY_CI,           "LM1.0 Query - Centralized Initialization"},
778         {LOGON_LM10_QUERY_DI,           "LM1.0 Query - Distributed Initialization"},
779         {LOGON_LM10_RESPONSE_CI,        "LM1.0 Response - Centralized Query"},
780         {LOGON_LM10_RESPONSE_DI,        "LM1.0 Response - Distributed Initialization"},
781         {LOGON_LM20_LOGON_RESPONSE,     "LM2.0 Response to LOGON Request"},
782         {LOGON_PDC_QUERY,               "Query for PDC"},
783         {LOGON_PDC_STARTUP,             "Announce Startup of PDC"},
784         {LOGON_PDC_FAILED,              "Announce Failed PDC"},
785         {LOGON_UAS_SAM,                 "Announce Change to UAS or SAM"},
786         {LOGON_NO_USER,                 "Announce no user on machine"},
787         {LOGON_PDC_RESPONSE,            "Response from PDC"},
788         {LOGON_RELOGON_RESPONSE,        "LM1.0/LM2.0 Response to re-LOGON Request"},
789         {LOGON_INTERROGATE_RESPONSE,    "LM1.0/LM2.0 Response to Interrogate Request"},
790         {LOGON_LM20_RESPONSE_DURING_LOGON,"LM2.0 Response during LOGON pause"},
791         {LOGON_LM20_USER_UNKNOWN,       "LM2.0 Response - user unknown"},
792         {LOGON_LM20_ACCOUNT_UPDATE,     "LM2.0 Announce account updates"},
793         {LOGON_SAM_LOGON_REQUEST,       "SAM LOGON request from client"},
794         {LOGON_SAM_LOGON_RESPONSE,      "Response to SAM LOGON request"},
795         {LOGON_SAM_RESPONSE_DURING_LOGON,"SAM Response during LOGON pause"},
796         {LOGON_SAM_USER_UNKNOWN,        "SAM Response - user unknown"},
797         {LOGON_SAM_INTERROGATE_RESPONSE,"SAM Response to Interrogate Request"},
798         {LOGON_SAM_AD_USER_UNKNOWN,     "SAM Active Directory Response - user unknown"},
799         {LOGON_SAM_UNKNOWN_18,          "SAM unknown command 0x18"},
800         {LOGON_SAM_AD_LOGON_RESPONSE,   "Active Directory Response to SAM LOGON request"},
801         {0,     NULL}
802 };
803
804 static int (*dissect_smb_logon_cmds[])(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) = {
805         dissect_smb_logon_request,  /* 0x00 (LM1.0/LM2.0 LOGON Request) */
806         dissect_smb_logon_LM10_resp,/* 0x01 (LM1.0 LOGON Response)      */
807         dissect_smb_logon_2,        /* 0x02 (LM1.0 Query Centralized Init.)*/
808         dissect_smb_logon_2,        /* 0x03 (LM1.0 Query Distributed Init.)*/
809         dissect_smb_logon_2,        /* 0x04 (LM1.0 Centralized Query Resp.)*/
810         dissect_smb_logon_2,        /* 0x05 (LM1.0 Distributed Query Resp.) */
811         dissect_smb_logon_LM20_resp,/* 0x06 (LM2.0 LOGON Response)      */
812         dissect_smb_pdc_query,      /* 0x07 (Query for PDC)             */
813         dissect_smb_pdc_startup,    /* 0x08 (Announce PDC startup)      */
814         dissect_smb_pdc_failure,    /* 0x09 (Announce Failed PDC)       */
815         dissect_announce_change,    /* 0x0A (Announce Change to UAS or SAM)*/
816         dissect_smb_no_user,        /* 0x0B (Announce no user on machine)*/
817         dissect_smb_pdc_startup,    /* 0x0C (Response from PDC)         */
818         dissect_smb_relogon_resp,   /* 0x0D (Relogon response)          */
819         dissect_smb_inter_resp,     /* 0x0E (Interrogate response)      */
820         dissect_smb_pdc_failure,    /* 0x0F (LM2.0 Resp. during LOGON pause*/
821         dissect_smb_pdc_failure,    /* 0x10 (LM 2.0 Unknown user response)*/
822         dissect_smb_acc_update,     /* 0x11 (LM2.1 Announce Acc updates)*/
823         dissect_smb_sam_logon_req,  /* 0x12 (SAM LOGON request )        */
824         dissect_smb_sam_logon_resp, /* 0x13 (SAM LOGON response)        */
825         dissect_smb_unknown,        /* 0x14 (SAM Response during LOGON Pause) */
826         dissect_smb_unknown,        /* 0x15 (SAM Response User Unknown) */
827         dissect_smb_unknown,        /* 0x16 (SAM Response to Interrogate)*/
828         dissect_smb_unknown,        /* 0x17 (SAM AD response User Unknown*/
829         dissect_smb_unknown,        /* 0x18 (Unknown command)           */
830         dissect_smb_unknown         /* 0x19 (SAM LOGON AD response)     */
831 };
832
833
834 static void
835 dissect_smb_logon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
836 {
837         int        offset = 0;
838         guint8     cmd;
839         proto_tree *smb_logon_tree = NULL;
840         proto_item *item = NULL;
841
842         if (check_col(pinfo->cinfo, COL_PROTOCOL))
843                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NETLOGON");
844         if (check_col(pinfo->cinfo, COL_INFO))
845                 col_clear(pinfo->cinfo, COL_INFO);
846
847         /* get the Command field */
848         cmd = tvb_get_guint8(tvb, offset);
849
850         if (check_col(pinfo->cinfo, COL_INFO))
851                 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, commands, "Unknown Command:%02x") );
852
853         if (tree) {
854                 item = proto_tree_add_item(tree, proto_smb_logon, tvb,
855                         offset, -1, FALSE);
856
857                 smb_logon_tree = proto_item_add_subtree(item, ett_smb_logon);
858         }
859
860         /* command */
861         proto_tree_add_uint(smb_logon_tree, hf_command, tvb, offset, 1, cmd);
862         offset += 1;
863
864         /* skip next byte */
865         offset += 1;
866
867         if (cmd<LOGON_LAST_CMD) {
868                 offset = (dissect_smb_logon_cmds[cmd])(tvb, pinfo,
869                     smb_logon_tree, offset);
870         } else {
871                 /* unknown command */
872                 offset = dissect_smb_unknown(tvb, pinfo, smb_logon_tree,
873                     offset);
874         }
875 }
876
877 void
878 proto_register_smb_logon( void)
879 {
880         static hf_register_info hf[] = {
881                 { &hf_command,
882                         { "Command", "netlogon.command", FT_UINT8, BASE_HEX,
883                           VALS(commands), 0, "NETLOGON Command", HFILL }},
884
885                 { &hf_computer_name,
886                         { "Computer Name", "netlogon.computer_name", FT_STRING, BASE_NONE,
887                           NULL, 0, "NETLOGON Computer Name", HFILL }},
888
889                 { &hf_unicode_computer_name,
890                         { "Unicode Computer Name", "netlogon.unicode_computer_name", FT_STRING, BASE_NONE,
891                           NULL, 0, "NETLOGON Unicode Computer Name", HFILL }},
892
893                 { &hf_server_name,
894                         { "Server Name", "netlogon.server_name", FT_STRING, BASE_NONE,
895                           NULL, 0, "NETLOGON Server Name", HFILL }},
896
897                 { &hf_user_name,
898                         { "User Name", "netlogon.user_name", FT_STRING, BASE_NONE,
899                           NULL, 0, "NETLOGON User Name", HFILL }},
900
901                 { &hf_domain_name,
902                         { "Domain Name", "netlogon.domain_name", FT_STRING, BASE_NONE,
903                           NULL, 0, "NETLOGON Domain Name", HFILL }},
904
905                 { &hf_mailslot_name,
906                         { "Mailslot Name", "netlogon.mailslot_name", FT_STRING, BASE_NONE,
907                           NULL, 0, "NETLOGON Mailslot Name", HFILL }},
908
909                 { &hf_pdc_name,
910                         { "PDC Name", "netlogon.pdc_name", FT_STRING, BASE_NONE,
911                           NULL, 0, "NETLOGON PDC Name", HFILL }},
912
913                 { &hf_unicode_pdc_name,
914                         { "Unicode PDC Name", "netlogon.unicode_pdc_name", FT_STRING, BASE_NONE,
915                           NULL, 0, "NETLOGON Unicode PDC Name", HFILL }},
916
917                 { &hf_script_name,
918                         { "Script Name", "netlogon.script_name", FT_STRING, BASE_NONE,
919                           NULL, 0, "NETLOGON Script Name", HFILL }},
920
921                 { &hf_nt_version,
922                         { "NT Version", "netlogon.nt_version", FT_UINT32, BASE_DEC,
923                           NULL, 0, "NETLOGON NT Version", HFILL }},
924
925                 /* An LMNT Token, if 0xffff, is "WindowsNT Networking";
926                    what is it otherwise? */
927                 { &hf_lmnt_token,
928                         { "LMNT Token", "netlogon.lmnt_token", FT_UINT16, BASE_HEX,
929                           NULL, 0, "NETLOGON LMNT Token", HFILL }},
930
931                 { &hf_lm_token,
932                         { "LM Token", "netlogon.lm_token", FT_UINT16, BASE_HEX,
933                           NULL, 0, "NETLOGON LM Token", HFILL }},
934
935                 { &hf_major_version,
936                         { "Workstation Major Version", "netlogon.major_version", FT_UINT8, BASE_DEC,
937                           NULL, 0, "NETLOGON Workstation Major Version", HFILL }},
938
939                 { &hf_minor_version,
940                         { "Workstation Minor Version", "netlogon.minor_version", FT_UINT8, BASE_DEC,
941                           NULL, 0, "NETLOGON Workstation Minor Version", HFILL }},
942
943                 { &hf_os_version,
944                         { "Workstation OS Version", "netlogon.os_version", FT_UINT8, BASE_DEC,
945                           NULL, 0, "NETLOGON Workstation OS Version", HFILL }},
946
947                 { &hf_date_time,
948                         { "Date/Time", "netlogon.date_time", FT_UINT32, BASE_DEC,
949                           NULL, 0, "NETLOGON Date/Time", HFILL }},
950
951                 { &hf_update_type,
952                         { "Update Type", "netlogon.update", FT_UINT16, BASE_DEC,
953                           NULL, 0, "NETLOGON Update Type", HFILL }},
954
955                 { &hf_request_count,
956                         { "Request Count", "netlogon.request_count", FT_UINT16, BASE_DEC,
957                           NULL, 0, "NETLOGON Request Count", HFILL }},
958
959                 { &hf_flags_autolock,
960                         { "Autolock", "netlogon.flags.autolock", FT_BOOLEAN, 32,
961                         TFS(&tfs_flags_autolock), ACC_FLAG_AUTO_LOCKED, "NETLOGON Account Autolock", HFILL}},
962
963                 { &hf_flags_expire,
964                         { "Expire", "netlogon.flags.expire", FT_BOOLEAN, 32,
965                         TFS(&tfs_flags_expire), ACC_FLAG_EXPIRE, "NETLOGON Will Account Expire", HFILL}},
966
967                 { &hf_flags_server_trust,
968                         { "Server Trust", "netlogon.flags.server", FT_BOOLEAN, 32,
969                         TFS(&tfs_flags_server_trust), ACC_FLAG_SERVER_TRUST, "NETLOGON Server Trust Account", HFILL}},
970
971                 { &hf_flags_workstation_trust,
972                         { "Workstation Trust", "netlogon.flags.workstation", FT_BOOLEAN, 32,
973                         TFS(&tfs_flags_workstation_trust), ACC_FLAG_WORKSTATION_TRUST, "NETLOGON Workstation Trust Account", HFILL}},
974
975                 { &hf_flags_interdomain_trust,
976                         { "Interdomain Trust", "netlogon.flags.interdomain", FT_BOOLEAN, 32,
977                         TFS(&tfs_flags_interdomain_trust), ACC_FLAG_INTERDOMAIN_TRUST, "NETLOGON Inter-domain Trust Account", HFILL}},
978
979                 { &hf_flags_mns_user,
980                         { "MNS User", "netlogon.flags.mns", FT_BOOLEAN, 32,
981                         TFS(&tfs_flags_mns_user), ACC_FLAG_MNS_USER, "NETLOGON MNS User Account", HFILL}},
982
983                 { &hf_flags_normal_user,
984                         { "Normal User", "netlogon.flags.normal", FT_BOOLEAN, 32,
985                         TFS(&tfs_flags_normal_user), ACC_FLAG_NORMAL_USER, "NETLOGON Normal User Account", HFILL}},
986
987                 { &hf_flags_temp_dup_user,
988                         { "Temp Duplicate User", "netlogon.flags.temp_dup", FT_BOOLEAN, 32,
989                         TFS(&tfs_flags_temp_dup_user), ACC_FLAG_TEMP_DUP_USER, "NETLOGON Temp Duplicate User Account", HFILL}},
990
991                 { &hf_flags_password_required,
992                         { "Password", "netlogon.flags.password", FT_BOOLEAN, 32,
993                         TFS(&tfs_flags_password_required), ACC_FLAG_PASSWORD_REQUIRED, "NETLOGON Password Required", HFILL}},
994
995                 { &hf_flags_homedir_required,
996                         { "Homedir", "netlogon.flags.homedir", FT_BOOLEAN, 32,
997                         TFS(&tfs_flags_homedir_required), ACC_FLAG_HOMEDIR_REQUIRED, "NETLOGON Homedir Required", HFILL}},
998
999                 { &hf_flags_enabled,
1000                         { "Enabled", "netlogon.flags.enabled", FT_BOOLEAN, 32,
1001                         TFS(&tfs_flags_enabled), ACC_FLAG_ENABLED, "NETLOGON Is This Account Enabled", HFILL}},
1002
1003                 { &hf_domain_sid_size,
1004                         { "Domain SID Size", "netlogon.domain_sid_size", FT_UINT32, BASE_DEC,
1005                           NULL, 0, "NETLOGON Domain SID Size", HFILL }},
1006
1007                 { &hf_low_serial,
1008                         { "Low Serial Number", "netlogon.low_serial", FT_UINT32, BASE_DEC,
1009                           NULL, 0, "NETLOGON Low Serial Number", HFILL }},
1010
1011                 { &hf_pulse,
1012                         { "Pulse", "netlogon.pulse", FT_UINT32, BASE_DEC,
1013                           NULL, 0, "NETLOGON Pulse", HFILL }},
1014
1015                 { &hf_random,
1016                         { "Random", "netlogon.random", FT_UINT32, BASE_DEC,
1017                           NULL, 0, "NETLOGON Random", HFILL }},
1018
1019                 { &hf_db_count,
1020                         { "DB Count", "netlogon.db_count", FT_UINT32, BASE_DEC,
1021                           NULL, 0, "NETLOGON DB Count", HFILL }},
1022
1023                 { &hf_db_index,
1024                         { "Database Index", "netlogon.db_index", FT_UINT32, BASE_DEC,
1025                           NULL, 0, "NETLOGON Database Index", HFILL }},
1026
1027                 { &hf_large_serial,
1028                         { "Large Serial Number", "netlogon.large_serial", FT_UINT64, BASE_DEC,
1029                           NULL, 0, "NETLOGON Large Serial Number", HFILL }},
1030
1031                 { &hf_nt_date_time,
1032                         { "NT Date/Time", "netlogon.nt_date_time", FT_ABSOLUTE_TIME, BASE_NONE,
1033                           NULL, 0, "NETLOGON NT Date/Time", HFILL }},
1034         };
1035
1036         static gint *ett[] = {
1037                 &ett_smb_logon,
1038                 &ett_smb_account_flags,
1039                 &ett_smb_db_info
1040         };
1041
1042         proto_smb_logon = proto_register_protocol(
1043                 "Microsoft Windows Logon Protocol", "NETLOGON", "netlogon");
1044
1045         proto_register_field_array(proto_smb_logon, hf, array_length(hf));
1046         proto_register_subtree_array(ett, array_length(ett));
1047
1048         register_dissector("netlogon", dissect_smb_logon, proto_smb_logon);
1049 }