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