Have the Etherenet and PPP dissectors register themselves, and have
[obnox/wireshark/wip.git] / 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: packet-smb-logon.c,v 1.9 2000/10/31 09:41:07 sharpe Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@zing.org>
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 static int proto_smb_logon = -1;
31
32 static int ett_smb_logon = -1;
33 static int ett_smb_account_flags = -1;
34
35
36 static void
37 dissect_account_control( const u_char *pd, int offset, frame_data *fd,
38                 proto_tree *tree){
39                 
40 /* display the Allowable Account control bits */
41
42         proto_tree  *flags_tree;
43         proto_item  *ti;
44         guint32  flags = GWORD( pd, offset);
45
46         struct flag_array_type  flag_info[] = {
47                 { 0x400, "User account ", "", "not ", "auto-locked"},
48                 { 0x200, "User password will ", "not ", "", "expire"},
49                 { 0x100, "", "", "Not a ", "Server Trust user account"},
50                 { 0x080, "", "", "Not a ", "Workstation Trust user account"},
51                 { 0x040, "", "", "Not an ", "Inter-domain Trust user account"},
52                 { 0x020, "", "", "Not a ", "MNS Logon user account"},
53                 { 0x010, "", "", "Not a ", "Normal user account"},
54                 { 0x008, "", "", "Not a ", "temp duplicate user account"},
55                 { 0x004, "", "No", "", "User password required"},
56                 { 0x002, "", "No", "", "User home directory required"},
57                 { 0x001, "User account ", "enabled", "disabled", ""},
58                 { 0, "", "", "", ""}
59         };
60
61
62         ti = proto_tree_add_text( tree, NullTVB, offset, 4,
63                 "Account control  = 0x%04x", flags);
64                 
65         flags_tree = proto_item_add_subtree( ti, ett_smb_account_flags);
66
67         display_flags( flag_info, 4, pd, offset, flags_tree);
68 }
69
70
71
72 static void
73 display_LM_token( const u_char *pd, int *offset, frame_data *fd,
74         proto_tree *tree) {
75
76 /* decode and display the LanMan token */       
77
78         guint16 Token;
79
80         if (!BYTES_ARE_IN_FRAME(*offset, 2)) {
81                 proto_tree_add_text(tree, NullTVB, *offset, 0,"****FRAME TOO SHORT***");
82                 return;
83         }
84
85         Token = GSHORT( pd, *offset);
86         
87         if ( Token && 0x01) 
88                 proto_tree_add_text( tree, NullTVB, *offset, 2,
89                         "LM20 Token: 0x%x (LanMan 2.0 or higher)", Token);
90         else
91                 proto_tree_add_text( tree, NullTVB, *offset, 2,
92                         "LM10 Token: 0x%x (WFW Networking)", Token);
93         *offset += 2;
94         
95 }
96
97 static void
98 display_NT_version( const u_char *pd, int *offset, frame_data *fd,
99         proto_tree *tree, int length) {
100
101 /* display the NT version       */      
102
103         guint32 Version;
104         
105         if (!BYTES_ARE_IN_FRAME(*offset, length)) {
106                 proto_tree_add_text(tree, NullTVB, *offset, 0, "****FRAME TOO SHORT***");
107                 return;
108         }
109
110         if ( length == 2)
111                 Version = GSHORT( pd, *offset);
112         else
113                 Version  = GWORD( pd, *offset);
114         
115         proto_tree_add_text( tree, NullTVB, *offset, length, "NT Version: 0x%x ",
116                 Version);
117
118         *offset += length;
119         
120 }
121
122
123
124 void dissect_smb_logon_request( const u_char *pd, int offset, frame_data *fd,
125                 proto_tree *tree){
126
127 /*** 0x00 (LM1.0/LM2.0 LOGON Request) ***/
128  
129         MoveAndCheckOffset( display_ms_string( "Computer Name", pd, offset, fd,
130                 tree));
131         
132         MoveAndCheckOffset( display_ms_string( "User Name", pd, offset, fd,
133                 tree));
134
135         MoveAndCheckOffset( display_ms_string( "Mailslot Name", pd, offset, fd,
136                 tree));
137
138 /*$$$$$ here add the Mailslot to the response list (if needed) */
139         
140         MoveAndCheckOffset( display_ms_value( "Request Count", 1, pd, offset,
141                 fd, tree));
142
143         display_NT_version( pd, &offset, fd, tree,2);
144         display_LM_token( pd, &offset, fd, tree);
145 }
146
147
148
149 static void
150 dissect_smb_logon_LM10_resp(const u_char *pd, int offset, frame_data *fd,
151         proto_tree *tree){
152
153 /*** 0x01 LanMan 1.0 Logon response ***/
154
155         MoveAndCheckOffset( display_ms_string( "User Name", pd, offset, fd,
156                 tree));
157         MoveAndCheckOffset( display_ms_string( "Script Name", pd, offset, fd,
158                 tree));
159 }
160
161
162
163 void dissect_smb_logon_2(const u_char *pd, int offset, frame_data *fd,
164                 proto_tree *tree) {
165
166 /*** 0x02  LM1.0 Query - Centralized Initialization ***/
167 /*** 0x03  LM1.0 Query - Distributed Initialization ***/
168 /*** 0x04  LM1.0 Query - Centralized Query Response ***/
169 /*** 0x04  LM1.0 Query - Distributed Query Response ***/
170
171         MoveAndCheckOffset( display_ms_string( "Computer Name", pd, offset, fd, tree));
172
173         MoveAndCheckOffset( display_ms_string( "Mailslot Name", pd, offset, fd, tree));
174
175         display_NT_version( pd, &offset, fd, tree, 2);
176         display_LM_token( pd, &offset, fd, tree);
177 }
178
179
180
181 void dissect_smb_logon_LM20_resp(const u_char *pd, int offset, frame_data *fd,
182                 proto_tree *tree){
183
184 /*** 0x06 (LM2.0 LOGON Response)        ***/
185
186         ++offset;               /* move to the server name */
187
188         MoveAndCheckOffset( display_ms_string( "Logon Server Name", pd, offset,
189                 fd, tree));
190
191         display_LM_token( pd, &offset, fd, tree);
192
193 }
194
195
196
197 static void
198 dissect_smb_pdc_query(const u_char *pd, int offset, frame_data *fd,
199                 proto_tree *tree){
200
201 /*** 0x07 Query for Primary PDC  ***/
202
203  
204         MoveAndCheckOffset( display_ms_string( "Computer Name", pd, offset,
205                 fd, tree));
206
207         MoveAndCheckOffset( display_ms_string( "Mailslot Name", pd, offset,
208                 fd, tree));
209
210         MoveAndCheckOffset( display_ms_string( "OEM Computer Name", pd, offset,
211                 fd, tree));
212
213         display_NT_version( pd, &offset, fd, tree, 4);
214
215         proto_tree_add_text( tree, NullTVB, offset, 2, "LMNT Token: 0x%x",
216                 GWORD(pd, offset));
217         MoveAndCheckOffset( 2);
218         
219         display_LM_token( pd, &offset, fd, tree);
220 }
221
222
223
224 void dissect_smb_pdc_startup(const u_char *pd, int offset, frame_data *fd,
225                 proto_tree *tree){
226
227 /*** 0x08  Announce startup of PDC ***/
228  
229         MoveAndCheckOffset(
230                 display_ms_string( "PDC Name", pd, offset, fd, tree));
231
232         /* A short Announce will not have the rest */
233
234         if (END_OF_FRAME > 0) { 
235
236           if (offset % 2) offset++;      /* word align ... */
237
238           MoveAndCheckOffset(
239                  display_unicode_string("Unicode PDC Name", pd, offset, fd, tree));
240
241           if (offset % 2) offset++;
242
243           MoveAndCheckOffset(
244                  display_unicode_string("Unicode Domain Name", pd, offset, fd, tree));
245
246           display_NT_version( pd, &offset, fd, tree, 4);
247
248           display_LM_token( pd, &offset, fd, tree);
249         }
250 }
251
252
253
254 static void
255 dissect_smb_pdc_failure( const u_char *pd, int offset, frame_data *fd,
256         proto_tree *tree){
257
258 /*** 0x09 Announce failure of the PDC ***/
259 /*** 0x0F LM2.0 Resp. during LOGON pause ***/
260 /*** 0x10 (LM 2.0 Unknown user response) ***/
261
262         display_NT_version( pd, &offset, fd, tree, 4);
263         display_LM_token( pd, &offset, fd, tree);
264 }
265
266
267 void dissect_announce_change( const u_char *pd, int offset,
268         frame_data *fd,proto_tree *tree) {
269         
270 /*** 0x0A ( Announce change to UAS or SAM ) ***/
271
272
273         MoveAndCheckOffset( display_ms_value( "Low serial number", 4, pd,
274                 offset, fd, tree));
275         MoveAndCheckOffset( display_ms_value( "Date/Time", 4, pd, offset, fd,
276                 tree));
277         MoveAndCheckOffset(
278                 display_ms_value( "Pulse", 4, pd, offset, fd, tree));
279         MoveAndCheckOffset(
280                 display_ms_value( "Random", 4, pd, offset, fd, tree));
281         MoveAndCheckOffset(
282                 display_ms_string( "PDC Name", pd, offset, fd, tree));
283         MoveAndCheckOffset(
284                 display_ms_string( "Domain Name", pd, offset, fd, tree));
285
286 /*???? is this needed ??? */
287         if ( !( offset & 0x1))                  /* add padding if needed */
288                 ++offset;
289
290         MoveAndCheckOffset( display_unicode_string( "Unicode PDC Name", pd,
291                 offset, fd, tree));
292
293         MoveAndCheckOffset( display_unicode_string( "Unicode Domain Name", pd,
294                 offset, fd, tree));
295
296         MoveAndCheckOffset( display_ms_value( "DB Count", 4, pd, offset, fd,
297                 tree));
298
299         MoveAndCheckOffset( display_ms_value( "NT Version ", 4, pd, offset, fd,
300                 tree));
301
302         MoveAndCheckOffset( display_ms_value( "LMNT Token ", 2, pd, offset, fd,
303                 tree));
304
305         MoveAndCheckOffset( display_ms_value( "Unknown Token ", 2, pd, offset,
306                 fd, tree));
307 }
308
309
310 static void
311 dissect_smb_sam_logon_req(const u_char *pd, int offset, frame_data *fd,
312                 proto_tree *tree){
313
314 /*** Netlogon command 0x12 - decode the SAM logon request from client ***/
315
316
317         proto_tree_add_text( tree, NullTVB, offset, 2, "Request Count  = %x",
318                 GSHORT(pd, offset));
319
320         MoveAndCheckOffset( 2);
321         
322         MoveAndCheckOffset( display_unicode_string( "Unicode Computer Name",
323                 pd, offset, fd, tree));
324         
325         MoveAndCheckOffset( display_unicode_string( "Unicode User Name",
326                 pd, offset, fd, tree));
327         
328         MoveAndCheckOffset( display_ms_string( "Mailslot Name", pd, offset, fd,
329                 tree));
330
331         dissect_account_control( pd, offset, fd, tree);
332                 
333         proto_tree_add_text( tree, NullTVB, offset, 2, "Domain SID Size = %x",
334                 GWORD(pd, offset));
335
336 }
337
338
339
340 static void
341 dissect_smb_no_user( const u_char *pd, int offset, frame_data *fd,
342                 proto_tree *tree)
343
344 {/* 0x0B (Announce no user on machine) */
345
346         display_ms_string( "Computer Name", pd, offset, fd, tree);
347 }
348
349
350
351 static void
352 dissect_smb_relogon_resp( const u_char *pd, int offset, frame_data *fd,
353         proto_tree *tree){
354
355 /*** 0x0d LanMan Response to relogon request ***/
356
357         MoveAndCheckOffset( display_ms_value( "Workstation major version", 1,
358                 pd, offset, fd, tree));
359
360         MoveAndCheckOffset( display_ms_value( "Workstation minor version", 1,
361                 pd, offset, fd, tree));
362
363         MoveAndCheckOffset( display_ms_value( "Workstation OS version", 1,
364                 pd, offset, fd, tree));
365
366         display_NT_version( pd, &offset, fd, tree, 4);
367
368         display_LM_token( pd, &offset, fd, tree);
369 }
370
371
372
373 static void
374 dissect_smb_acc_update( const u_char *pd, int offset, frame_data *fd,
375         proto_tree *tree){
376
377 /*** 0x11  LM2.1 Announce Acc updates  ***/
378
379         guint32 Temp1, Temp2;
380         
381         Temp1 = GWORD( pd, offset);
382
383         Temp2 = GWORD( pd, offset + 4);
384         
385         proto_tree_add_text( tree, NullTVB, offset, 2, "Signature: 0x%04x%04x",
386                 Temp1, Temp2);
387
388         MoveAndCheckOffset( 8);
389
390         MoveAndCheckOffset( display_ms_value( "Time/Date:", 4,
391                 pd, offset, fd, tree));
392         
393         MoveAndCheckOffset( display_ms_string( "Computer name:", 
394                 pd, offset, fd, tree));
395
396         MoveAndCheckOffset( display_ms_string( "User name:", 
397                 pd, offset, fd, tree));
398
399         MoveAndCheckOffset( display_ms_value( "Update Type:", 2,
400                 pd, offset, fd, tree));
401
402         display_NT_version( pd, &offset, fd, tree, 4);
403
404         display_LM_token( pd, &offset, fd, tree);
405 }
406
407
408
409 static void
410 dissect_smb_inter_resp( const u_char *pd, int offset, frame_data *fd,
411         proto_tree *tree){
412
413 /* 0x0e LanMan Response to interrogate request */
414
415         MoveAndCheckOffset( display_ms_value( "Workstation major version", 1,
416                 pd, offset, fd, tree));
417
418         MoveAndCheckOffset( display_ms_value( "Workstation minor version", 1,
419                 pd, offset, fd, tree));
420
421         MoveAndCheckOffset( display_ms_value( "Workstation OS version", 1, pd,
422                 offset, fd, tree));
423
424         display_NT_version( pd, &offset, fd, tree, 4);
425
426         MoveAndCheckOffset( display_ms_value( "LMNT Token ", 2, pd, offset, fd,
427                 tree));
428 }
429
430
431 void dissect_smb_sam_logon_resp(const u_char *pd, int offset, frame_data *fd,
432                 proto_tree *tree){
433
434 /* Netlogon command 0x13 - decode the SAM logon response from server */
435
436
437         MoveAndCheckOffset( display_unicode_string( "Server Name", pd, offset,
438                 fd, tree));
439         
440         MoveAndCheckOffset( display_unicode_string( "User Name", pd, offset,
441                 fd, tree));
442         
443         MoveAndCheckOffset( display_unicode_string( "Domain Name", pd, offset,
444                 fd, tree));
445
446         display_NT_version( pd, &offset, fd, tree, 4);
447
448         proto_tree_add_text( tree, NullTVB, offset, 2, "LMNT Token: 0x%x",
449                 GSHORT(pd, offset));
450         MoveAndCheckOffset( 2);
451
452         display_LM_token( pd, &offset, fd, tree);
453 }
454
455
456 guint32 
457 dissect_smb_logon(const u_char *pd, int offset, frame_data *fd,
458         proto_tree *parent, proto_tree *tree, struct smb_info si,
459         int max_data, int SMB_offset, int errcode, int dirn,
460         const u_char *command, int DataOffset, int DataCount){
461
462
463 /* decode the Microsoft netlogon protocol */
464
465 static char* CommandName[] = {
466
467         "LM1.0/LM2.0 LOGON Request",                    /* 0x00 */
468         "LM1.0 LOGON Response",                         /* 0x01 */
469         "LM1.0 Query - Centralized Initialization",     /* 0x02 */
470         "LM1.0 Query - Distributed Initialization",     /* 0x03 */
471         "LM1.0 Response - Centralized Query",           /* 0x04 */
472         "LM1.0 Response - Distributed Initialization",  /* 0x05 */
473         "LM2.0 Response to LOGON Request",              /* 0x06 */
474         "Query for PDC",                                /* 0x07 */
475         "Announce Startup of PDC",                      /* 0x08 */
476         "Announce Failed PDC",                          /* 0x09 */
477         "Announce Change to UAS or SAM",                /* 0x0A */
478         "Announce no user on machine",                  /* 0x0B */
479         "Response from PDC",                            /* 0x0C */
480         "LM1.0/LM2.0 Response to re-LOGON Request",     /* 0x0D */
481         "LM1.0/LM2.0 Response to Interrogate Request",  /* 0x0E */
482         "LM2.0 Response during LOGON pause",            /* 0x0F */
483         "LM2.0 Response - user unknown",                /* 0x10 */
484         "LM2.0 Announce account updates ",              /* 0x11 */
485         "SAM LOGON request from client ",               /* 0x12 */
486         "Response to SAM LOGON request",                /* 0x13 */
487         "SAM Response during LOGON pause",              /* 0x14 */
488         "SAM Response - user unknown",                  /* 0x15 */
489         "SAM Response to Interrogate Request",          /* 0x16 */
490         "Unknown"                                       /* 0x17 */
491         };
492
493 /* Array of functions to dissect the ms logon commands */
494                 
495 static void (*dissect_smb_logon_cmds[])(const u_char *, int, frame_data *,
496         proto_tree *) = {
497
498   dissect_smb_logon_request,    /* 0x00 (LM1.0/LM2.0 LOGON Request)     */
499   dissect_smb_logon_LM10_resp,  /* 0x01 (LM1.0 LOGON Response)          */
500   dissect_smb_logon_2,          /* 0x02 (LM1.0 Query Centralized Init.) */
501   dissect_smb_logon_2,          /* 0x03 (LM1.0 Query Distributed Init.) */
502   dissect_smb_logon_2,          /* 0x04 (LM1.0 Centralized Query Resp.) */
503   dissect_smb_logon_2,          /* 0x05 (LM1.0 Distributed Query Resp.) */
504   dissect_smb_logon_LM20_resp,  /* 0x06 (LM2.0 LOGON Response)          */
505   dissect_smb_pdc_query,        /* 0x07 (Query for PDC)                 */
506   dissect_smb_pdc_startup,      /* 0x08 (Announce PDC startup)          */
507   dissect_smb_pdc_failure,      /* 0x09 (Announce Failed PDC)           */
508   dissect_announce_change,      /* 0x0A (Announce change to UAS or SAM) */
509   dissect_smb_no_user,          /* 0x0B (Announce no user on machine)   */
510   dissect_smb_pdc_startup,      /* 0x0C (Response from PDC)             */
511   dissect_smb_relogon_resp,     /* 0x0D (Relogon response)              */
512   dissect_smb_inter_resp,       /* 0x0E (Interrogate response)          */
513   dissect_smb_pdc_failure,      /* 0x0F (LM2.0 Resp. during LOGON pause */
514   dissect_smb_pdc_failure,      /* 0x10 (LM 2.0 Unknown user response)  */
515   dissect_smb_acc_update,       /* 0x11 (LM2.1 Announce Acc updates)    */
516   dissect_smb_sam_logon_req,    /* 0x12 (SAM LOGON request )            */
517   dissect_smb_sam_logon_resp,   /* 0x13 (SAM LOGON response)            */
518   dissect_smb_unknown,          /* 0x14 (SAM Response during LOGON Pause) */
519   dissect_smb_unknown,          /* 0x15 (SAM Response User Unknown)      */
520   dissect_smb_unknown,          /* 0x16 (SAM Response to Interrogate)   */
521 };
522
523
524
525         guint8  cmd;
526         proto_tree      *smb_logon_tree;
527         proto_item      *ti;
528
529
530         if (!proto_is_protocol_enabled(proto_smb_logon))
531           return 0;
532                                            /* get the Command field */
533         cmd = MIN(  GBYTE(pd, offset), array_length(dissect_smb_logon_cmds)-1);
534
535         if (check_col(fd, COL_PROTOCOL))
536                 col_add_str(fd, COL_PROTOCOL, "NETLOGON");
537
538
539         if (check_col(fd, COL_INFO))
540                 col_add_fstr(fd, COL_INFO, "%s", CommandName[ cmd]);
541
542         if (tree) {
543                 ti = proto_tree_add_item( parent, proto_smb_logon, NullTVB, offset,
544                         END_OF_FRAME, FALSE);
545                 smb_logon_tree = proto_item_add_subtree(ti, ett_smb_logon);
546
547                 proto_tree_add_text(smb_logon_tree, NullTVB, offset, 1,
548                         "Command: %u (%s)", cmd, CommandName[ cmd]);
549                         
550                 offset += 2;                    /* skip to name field */
551
552                                                 /* vector to handle commands */
553                 (dissect_smb_logon_cmds[  cmd]) (pd, offset, fd,smb_logon_tree);
554
555         }
556    return 1;  
557 }
558
559
560
561 void
562 register_proto_smb_logon( void){
563
564 /*** Prep the logon protocol, for now, just register it */
565
566         static gint *ett[] = {
567                 &ett_smb_logon,
568                 &ett_smb_account_flags
569         };
570
571         proto_smb_logon = proto_register_protocol(
572                 "Microsoft Windows Logon Protocol", "netlogon");
573
574         proto_register_subtree_array(ett, array_length(ett));          
575 }
576
577
578
579
580