1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * References used throughout this code: 30 * 31 * [CIFS/1.0] : A Common Internet File System (CIFS/1.0) Protocol 32 * Internet Engineering Task Force (IETF) draft 33 * Paul J. Leach, Microsoft, Dec. 1997 34 * 35 * [X/Open-SMB] : X/Open CAE Specification; 36 * Protocols for X/Open PC Interworking: SMB, Version 2 37 * X/Open Document Number: C209 38 */ 39 40 #include <fcntl.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 45 #include "snoop.h" 46 47 /* some macros just for compactness */ 48 #define GETLINE get_line(0, 0) 49 #define DECARGS int flags, uchar_t *data, int len, char *extrainfo 50 51 /* 52 * SMB Format (header) 53 * [X/Open-SMB, Sec. 5.1] 54 */ 55 struct smb { 56 uchar_t idf[4]; /* identifier, contains 0xff, 'SMB' */ 57 uchar_t com; /* command code */ 58 uchar_t rcls; /* error class */ 59 uchar_t res; 60 uchar_t err[2]; /* error code */ 61 uchar_t flags; 62 uchar_t flags2[2]; 63 uchar_t re[12]; 64 uchar_t tid[2]; 65 uchar_t pid[2]; 66 uchar_t uid[2]; 67 uchar_t mid[2]; 68 /* 69 * immediately after the above 32 byte header: 70 * unsigned char WordCount; 71 * unsigned short ParameterWords[ WordCount ]; 72 * unsigned short ByteCount; 73 * unsigned char ParameterBytes[ ByteCount ]; 74 */ 75 }; 76 77 /* smb flags */ 78 #define SERVER_RESPONSE 0x80 79 80 static void interpret_sesssetupX(DECARGS); 81 static void interpret_tconX(DECARGS); 82 static void interpret_trans(DECARGS); 83 static void interpret_trans2(DECARGS); 84 static void interpret_negprot(DECARGS); 85 static void interpret_default(DECARGS); 86 87 /* 88 * Trans2 subcommand codes 89 * [X/Open-SMB, Sec. 16.1.7] 90 */ 91 #define TRANS2_OPEN 0x00 92 #define TRANS2_FIND_FIRST 0x01 93 #define TRANS2_FIND_NEXT2 0x02 94 #define TRANS2_QUERY_FS_INFORMATION 0x03 95 #define TRANS2_QUERY_PATH_INFORMATION 0x05 96 #define TRANS2_SET_PATH_INFORMATION 0x06 97 #define TRANS2_QUERY_FILE_INFORMATION 0x07 98 #define TRANS2_SET_FILE_INFORMATION 0x08 99 #define TRANS2_CREATE_DIRECTORY 0x0D 100 101 102 struct decode { 103 char *name; 104 void (*func)(DECARGS); 105 char *callfmt; 106 char *replyfmt; 107 }; 108 109 /* 110 * SMB command codes (function names) 111 * [X/Open-SMB, Sec. 5.2] 112 */ 113 static struct decode SMBtable[256] = { 114 /* 0x00 */ 115 { "mkdir", 0, 0, 0 }, 116 { "rmdir", 0, 0, 0 }, 117 { "open", 0, 0, 0 }, 118 { "create", 0, 0, 0 }, 119 120 { 121 "close", 0, 122 /* [X/Open-SMB, Sec. 7.10] */ 123 "WFileID\0lLastModTime\0wByteCount\0\0", 124 "wByteCount\0\0" 125 }, 126 127 { "flush", 0, 0, 0 }, 128 { "unlink", 0, 0, 0 }, 129 130 { 131 "mv", 0, 132 /* [X/Open-SMB, Sec. 7.11] */ 133 "wFileAttributes\0wByteCount\0" 134 "r\0UFileName\0r\0UNewPath\0\0", 135 "wByteCount\0\0" 136 }, 137 138 { 139 "getatr", 0, 140 /* [X/Open-SMB, Sec. 8.4] */ 141 "dBytecount\0r\0UFileName\0\0", 142 "wFileAttributes\0lTime\0lSize\0R\0R\0R\0" 143 "R\0R\0wByteCount\0\0" 144 }, 145 146 { "setatr", 0, 0, 0 }, 147 148 { 149 "read", 0, 150 /* [X/Open-SMB, Sec. 7.4] */ 151 "WFileID\0wI/0 Bytes\0LFileOffset\0" 152 "WBytesLeft\0wByteCount\0\0", 153 "WDataLength\0R\0R\0R\0R\0wByteCount\0\0" 154 }, 155 156 { 157 "write", 0, 158 /* [X/Open-SMB, Sec. 7.5] */ 159 "WFileID\0wI/0 Bytes\0LFileOffset\0WBytesLeft\0" 160 "wByteCount\0\0", 161 "WDataLength\0wByteCount\0\0" 162 }, 163 164 { "lock", 0, 0, 0 }, 165 { "unlock", 0, 0, 0 }, 166 { "ctemp", 0, 0, 0 }, 167 { "mknew", 0, 0, 0 }, 168 169 /* 0x10 */ 170 { 171 "chkpth", 0, 172 /* [X/Open-SMB, Sec. 8.7] */ 173 "wByteCount\0r\0UFile\0\0", 174 "wByteCount\0\0" 175 }, 176 177 { "exit", 0, 0, 0 }, 178 { "lseek", 0, 0, 0 }, 179 { "lockread", 0, 0, 0 }, 180 { "writeunlock", 0, 0, 0 }, 181 { 0, 0, 0, 0 }, 182 { 0, 0, 0, 0 }, 183 { 0, 0, 0, 0 }, 184 { 0, 0, 0, 0 }, 185 { 0, 0, 0, 0 }, 186 187 { 188 "readbraw", 0, 189 /* [X/Open-SMB, Sec. 10.1] */ 190 "WFileID\0LFileOffset\0wMaxCount\0" 191 "wMinCount\0lTimeout\0R\0wByteCount\0\0", 0 192 }, 193 194 { "readbmpx", 0, 0, 0 }, 195 { "readbs", 0, 0, 0 }, 196 { "writebraw", 0, 0, 0 }, 197 { "writebmpx", 0, 0, 0 }, 198 { "writebs", 0, 0, 0 }, 199 200 /* 0x20 */ 201 { "writec", 0, 0, 0 }, 202 { "qrysrv", 0, 0, 0 }, 203 { "setattrE", 0, 0, 0 }, 204 { "getattrE", 0, 0, 0 }, 205 206 { 207 "lockingX", 0, 208 /* [X/Open-SMB, Sec. 12.2] */ 209 "wChainedCommand\0wNextOffset\0WFileID\0" 210 "wLockType\0lOpenTimeout\0" 211 "W#Unlocks\0W#Locks\0wByteCount\0\0", 0 212 }, 213 214 { "trans", interpret_trans, 0, 0 }, 215 { "transs", 0, 0, 0 }, 216 { "ioctl", 0, 0, 0 }, 217 { "ioctls", 0, 0, 0 }, 218 { "copy", 0, 0, 0 }, 219 { "move", 0, 0, 0 }, 220 { "echo", 0, 0, 0 }, 221 { "writeclose", 0, 0, 0 }, 222 223 { 224 "openX", 0, 225 /* [X/Open-SMB, Sec. 12.1] */ 226 "wChainedCommand\0wNextOffset\0wFlags\0" 227 "wMode\0wSearchAttributes\0wFileAttributes\0" 228 "lTime\0wOpenFunction\0lFileSize\0lOpenTimeout\0" 229 "R\0R\0wByteCount\0r\0UFileName\0\0", 230 "wChainedCommand\0wNextOffset\0WFileID\0" 231 "wAttributes\0lTime\0LSize\0wOpenMode\0" 232 "wFileType\0wDeviceState\0wActionTaken\0" 233 "lUniqueFileID\0R\0wBytecount\0\0" 234 }, 235 236 { "readX", 0, 0, 0 }, 237 { "writeX", 0, 0, 0 }, 238 239 /* 0x30 */ 240 { 0, 0, 0, 0 }, 241 { "closeTD", 0, 0, 0 }, 242 { "trans2", interpret_trans2, 0, 0 }, 243 { "trans2s", 0, 0, 0 }, 244 { 245 "findclose", 0, 246 /* [X/Open-SMB, Sec. 15.4 ] */ 247 "WFileID\0wByteCount\0\0", 248 "wByteCount\0\0" 249 }, 250 { 0, 0, 0, 0 }, 251 { 0, 0, 0, 0 }, 252 { 0, 0, 0, 0 }, 253 { 0, 0, 0, 0 }, 254 { 0, 0, 0, 0 }, 255 { 0, 0, 0, 0 }, 256 { 0, 0, 0, 0 }, 257 { 0, 0, 0, 0 }, 258 { 0, 0, 0, 0 }, 259 { 0, 0, 0, 0 }, 260 { 0, 0, 0, 0 }, 261 262 /* 0x40 */ 263 { 0, 0, 0, 0 }, 264 { 0, 0, 0, 0 }, 265 { 0, 0, 0, 0 }, 266 { 0, 0, 0, 0 }, 267 { 0, 0, 0, 0 }, 268 { 0, 0, 0, 0 }, 269 { 0, 0, 0, 0 }, 270 { 0, 0, 0, 0 }, 271 { 0, 0, 0, 0 }, 272 { 0, 0, 0, 0 }, 273 { 0, 0, 0, 0 }, 274 { 0, 0, 0, 0 }, 275 { 0, 0, 0, 0 }, 276 { 0, 0, 0, 0 }, 277 { 0, 0, 0, 0 }, 278 { 0, 0, 0, 0 }, 279 280 /* 0x50 */ 281 { 0, 0, 0, 0 }, 282 { 0, 0, 0, 0 }, 283 { 0, 0, 0, 0 }, 284 { 0, 0, 0, 0 }, 285 { 0, 0, 0, 0 }, 286 { 0, 0, 0, 0 }, 287 { 0, 0, 0, 0 }, 288 { 0, 0, 0, 0 }, 289 { 0, 0, 0, 0 }, 290 { 0, 0, 0, 0 }, 291 { 0, 0, 0, 0 }, 292 { 0, 0, 0, 0 }, 293 { 0, 0, 0, 0 }, 294 { 0, 0, 0, 0 }, 295 { 0, 0, 0, 0 }, 296 { 0, 0, 0, 0 }, 297 298 /* 0x60 */ 299 { 0, 0, 0, 0 }, 300 { 0, 0, 0, 0 }, 301 { 0, 0, 0, 0 }, 302 { 0, 0, 0, 0 }, 303 { 0, 0, 0, 0 }, 304 { 0, 0, 0, 0 }, 305 { 0, 0, 0, 0 }, 306 { 0, 0, 0, 0 }, 307 { 0, 0, 0, 0 }, 308 { 0, 0, 0, 0 }, 309 { 0, 0, 0, 0 }, 310 { 0, 0, 0, 0 }, 311 { 0, 0, 0, 0 }, 312 { 0, 0, 0, 0 }, 313 { 0, 0, 0, 0 }, 314 { 0, 0, 0, 0 }, 315 316 /* 0x70 */ 317 { "tcon", 0, 0, 0 }, 318 { 319 "tdis", 0, 320 /* [X/Open-SMB, Sec. 6.3] */ 321 "wByteCount\0\0", 322 "wByteCount\0\0" 323 }, 324 { "negprot", interpret_negprot, 0, 0 }, 325 { "sesssetupX", interpret_sesssetupX, 0, 0 }, 326 { 327 "uloggoffX", 0, 328 /* [X/Open-SMB, Sec. 15.5] */ 329 "wChainedCommand\0wNextOffset\0\0", 330 "wChainedCommnad\0wNextOffset\0\0" }, 331 { "tconX", interpret_tconX, 0, 0 }, 332 { 0, 0, 0, 0 }, 333 { 0, 0, 0, 0 }, 334 { 0, 0, 0, 0 }, 335 { 0, 0, 0, 0 }, 336 { 0, 0, 0, 0 }, 337 { 0, 0, 0, 0 }, 338 { 0, 0, 0, 0 }, 339 { 0, 0, 0, 0 }, 340 { 0, 0, 0, 0 }, 341 { 0, 0, 0, 0 }, 342 343 /* 0x80 */ 344 { "dskattr", 0, 0, 0 }, 345 { "search", 0, 0, 0 }, 346 { "ffirst", 0, 0, 0 }, 347 { "funique", 0, 0, 0 }, 348 { "fclose", 0, 0, 0 }, 349 { 0, 0, 0, 0 }, 350 { 0, 0, 0, 0 }, 351 { 0, 0, 0, 0 }, 352 { 0, 0, 0, 0 }, 353 { 0, 0, 0, 0 }, 354 { 0, 0, 0, 0 }, 355 { 0, 0, 0, 0 }, 356 { 0, 0, 0, 0 }, 357 { 0, 0, 0, 0 }, 358 { 0, 0, 0, 0 }, 359 { 0, 0, 0, 0 }, 360 361 /* 0x90 */ 362 { 0, 0, 0, 0 }, 363 { 0, 0, 0, 0 }, 364 { 0, 0, 0, 0 }, 365 { 0, 0, 0, 0 }, 366 { 0, 0, 0, 0 }, 367 { 0, 0, 0, 0 }, 368 { 0, 0, 0, 0 }, 369 { 0, 0, 0, 0 }, 370 { 0, 0, 0, 0 }, 371 { 0, 0, 0, 0 }, 372 { 0, 0, 0, 0 }, 373 { 0, 0, 0, 0 }, 374 { 0, 0, 0, 0 }, 375 { 0, 0, 0, 0 }, 376 { 0, 0, 0, 0 }, 377 { 0, 0, 0, 0 }, 378 379 /* 0xa0 */ 380 /* 381 * Command codes 0xa0 to 0xa7 are from 382 * [CIFS/1.0, Sec. 5.1] 383 */ 384 { " NT_Trans", 0, 0, 0 }, 385 { " NT_Trans2", 0, 0, 0 }, 386 { 387 " NT_CreateX", 0, 388 /* [CIFS/1.0, Sec. 4.2.1] */ 389 "wChainedCommand\0wNextOffset\0r\0" 390 "wNameLength\0lCreateFlags\0lRootDirFID\0" 391 "lDesiredAccess\0R\0R\0R\0R\0" 392 "lNTFileAttributes\0lFileShareAccess\0" 393 "R\0R\0lCreateOption\0lImpersonationLevel\0" 394 "bSecurityFlags\0wByteCount\0r\0" 395 "UFileName\0\0", 396 "wChainedCommand\0wNextOffset\0" 397 "bOplockLevel\0WFileID\0lCreateAction\0\0" 398 }, 399 { 0, 0, 0, 0 }, 400 { 401 " NT_Cancel", 0, 402 /* [CIFS/1.0, Sec. 4.1.8] */ 403 "wByteCount\0", 0 404 }, 405 { 0, 0, 0, 0 }, 406 { 0, 0, 0, 0 }, 407 { 0, 0, 0, 0 }, 408 { 0, 0, 0, 0 }, 409 { 0, 0, 0, 0 }, 410 { 0, 0, 0, 0 }, 411 { 0, 0, 0, 0 }, 412 { 0, 0, 0, 0 }, 413 { 0, 0, 0, 0 }, 414 { 0, 0, 0, 0 }, 415 { 0, 0, 0, 0 }, 416 417 /* 0xb0 */ 418 { 0, 0, 0, 0 }, 419 { 0, 0, 0, 0 }, 420 { 0, 0, 0, 0 }, 421 { 0, 0, 0, 0 }, 422 { 0, 0, 0, 0 }, 423 { 0, 0, 0, 0 }, 424 { 0, 0, 0, 0 }, 425 { 0, 0, 0, 0 }, 426 { 0, 0, 0, 0 }, 427 { 0, 0, 0, 0 }, 428 { 0, 0, 0, 0 }, 429 { 0, 0, 0, 0 }, 430 { 0, 0, 0, 0 }, 431 { 0, 0, 0, 0 }, 432 { 0, 0, 0, 0 }, 433 { 0, 0, 0, 0 }, 434 435 /* 0xc0 */ 436 { "splopen", 0, 0, 0 }, 437 { "splwr", 0, 0, 0 }, 438 { "splclose", 0, 0, 0 }, 439 { "splretq", 0, 0, 0 }, 440 { 0, 0, 0, 0 }, 441 { 0, 0, 0, 0 }, 442 { 0, 0, 0, 0 }, 443 { 0, 0, 0, 0 }, 444 { 0, 0, 0, 0 }, 445 { 0, 0, 0, 0 }, 446 { 0, 0, 0, 0 }, 447 { 0, 0, 0, 0 }, 448 { 0, 0, 0, 0 }, 449 { 0, 0, 0, 0 }, 450 { 0, 0, 0, 0 }, 451 { 0, 0, 0, 0 }, 452 453 /* 0xd0 */ 454 { "sends", 0, 0, 0 }, 455 { "sendb", 0, 0, 0 }, 456 { "fwdname", 0, 0, 0 }, 457 { "cancelf", 0, 0, 0 }, 458 { "getmac", 0, 0, 0 }, 459 { "sendstrt", 0, 0, 0 }, 460 { "sendend", 0, 0, 0 }, 461 { "sendtxt", 0, 0, 0 }, 462 { 0, 0, 0, 0 }, 463 { 0, 0, 0, 0 }, 464 { 0, 0, 0, 0 }, 465 { 0, 0, 0, 0 }, 466 { 0, 0, 0, 0 }, 467 { 0, 0, 0, 0 }, 468 { 0, 0, 0, 0 }, 469 { 0, 0, 0, 0 }, 470 471 /* 0xe0 */ 472 { 0, 0, 0, 0 }, 473 { 0, 0, 0, 0 }, 474 { 0, 0, 0, 0 }, 475 { 0, 0, 0, 0 }, 476 { 0, 0, 0, 0 }, 477 { 0, 0, 0, 0 }, 478 { 0, 0, 0, 0 }, 479 { 0, 0, 0, 0 }, 480 { 0, 0, 0, 0 }, 481 { 0, 0, 0, 0 }, 482 { 0, 0, 0, 0 }, 483 { 0, 0, 0, 0 }, 484 { 0, 0, 0, 0 }, 485 { 0, 0, 0, 0 }, 486 { 0, 0, 0, 0 }, 487 { 0, 0, 0, 0 }, 488 489 /* 0xf0 */ 490 { 0, 0, 0, 0 }, 491 { 0, 0, 0, 0 }, 492 { 0, 0, 0, 0 }, 493 { 0, 0, 0, 0 }, 494 { 0, 0, 0, 0 }, 495 { 0, 0, 0, 0 }, 496 { 0, 0, 0, 0 }, 497 { 0, 0, 0, 0 }, 498 { 0, 0, 0, 0 }, 499 { 0, 0, 0, 0 }, 500 { 0, 0, 0, 0 }, 501 { 0, 0, 0, 0 }, 502 { 0, 0, 0, 0 }, 503 { 0, 0, 0, 0 }, 504 { 0, 0, 0, 0 }, 505 { 0, 0, 0, 0 } 506 }; 507 508 /* Helpers to get short and int values in Intel order. */ 509 static ushort_t 510 get2(uchar_t *p) { 511 return (p[0] + (p[1]<<8)); 512 } 513 static uint_t 514 get4(uchar_t *p) { 515 return (p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24)); 516 } 517 518 /* 519 * This is called by snoop_netbios.c. 520 * This is the external entry point. 521 */ 522 void 523 interpret_smb(int flags, uchar_t *data, int len) 524 { 525 struct smb *smb; 526 char *call_reply_detail, *call_reply_sum; 527 struct decode *decoder; 528 char xtra[300]; 529 char *line; 530 531 smb = (struct smb *)data; 532 decoder = &SMBtable[smb->com & 255]; 533 if (smb->flags & SERVER_RESPONSE) { 534 call_reply_detail = "SERVER RESPONSE"; 535 call_reply_sum = "R"; 536 } else { 537 call_reply_detail = "CLIENT REQUEST"; 538 call_reply_sum = "C"; 539 } 540 xtra[0] = '\0'; 541 542 /* 543 * SMB Header description 544 * [X/Open-SMB, Sec. 5.1] 545 */ 546 if (flags & F_DTAIL) { 547 show_header("SMB: ", "SMB Header", len); 548 show_space(); 549 sprintf(GETLINE, "%s", call_reply_detail); 550 551 (void) sprintf(GETLINE, "Command code = 0x%x", 552 smb->com); 553 if (decoder->name) 554 (void) sprintf(GETLINE, 555 "Command name = SMB%s", decoder->name); 556 557 show_space(); 558 sprintf(GETLINE, "SMB Status:"); 559 560 /* Error classes [X/Open-SMB, Sec. 5.6] */ 561 switch (smb->rcls) { 562 case 0x00: 563 sprintf(GETLINE, 564 " - Error class = No error"); 565 break; 566 case 0x01: 567 sprintf(GETLINE, 568 " - Error class = Operating System"); 569 break; 570 case 0x02: 571 sprintf(GETLINE, 572 " - Error class = LMX server"); 573 break; 574 case 0x03: 575 sprintf(GETLINE, 576 " - Error class = Hardware"); 577 break; 578 case 0xff: 579 default: 580 sprintf(GETLINE, 581 " - Error class = Incorrect format."); 582 break; 583 } 584 585 if (smb->err[0] != 0x00) { 586 sprintf(GETLINE, 587 " - Error code = %x", smb->err[0]); 588 } else 589 sprintf(GETLINE, " - Error code = No error"); 590 591 show_space(); 592 593 sprintf(GETLINE, "Header:"); 594 sprintf(GETLINE, " - Tree ID (TID) = 0x%.4x", 595 get2(smb->tid)); 596 sprintf(GETLINE, " - Process ID (PID) = 0x%.4x", 597 get2(smb->pid)); 598 sprintf(GETLINE, " - User ID (UID) = 0x%.4x", 599 get2(smb->uid)); 600 sprintf(GETLINE, " - Multiplex ID (MID) = 0x%.4x", 601 get2(smb->mid)); 602 sprintf(GETLINE, " - Flags summary = 0x%.2x", 603 smb->flags); 604 sprintf(GETLINE, " - Flags2 summary = 0x%.4x", 605 get2(smb->flags2)); 606 show_space(); 607 } 608 609 if (decoder->func) 610 (decoder->func)(flags, (uchar_t *)data, len, xtra); 611 else 612 interpret_default(flags, (uchar_t *)data, len, xtra); 613 614 if (flags & F_SUM) { 615 line = get_sum_line(); 616 if (decoder->name) 617 sprintf(line, 618 "SMB %s Code=0x%x Name=SMB%s %sError=%x ", 619 call_reply_sum, smb->com, decoder->name, xtra, 620 smb->err[0]); 621 622 else sprintf(line, "SMB %s Code=0x%x Error=%x ", 623 call_reply_sum, smb->com, smb->err[0]); 624 625 line += strlen(line); 626 } 627 628 if (flags & F_DTAIL) 629 show_trailer(); 630 } 631 632 static void 633 output_bytes(uchar_t *data, int bytecount) 634 { 635 int i; 636 char buff[80]; 637 char word[10]; 638 639 buff[0] = word[0] = '\0'; 640 sprintf(GETLINE, "Byte values (in hex):"); 641 for (i = 0; i < bytecount; i++) { 642 sprintf(word, "%.2x ", data[i]); 643 strcat(buff, word); 644 if ((i+1)%16 == 0 || i == (bytecount-1)) { 645 sprintf(GETLINE, "%s", buff); 646 strcpy(buff, ""); 647 } 648 } 649 } 650 651 /* 652 * Based on the Unicode Standard, http://www.unicode.org/ 653 * "The Unicode Standard: A Technical Introduction", June 1998 654 */ 655 static int 656 unicode2ascii(char *outstr, int outlen, uchar_t *instr, int inlen) 657 { 658 int i = 0, j = 0; 659 char c; 660 661 while (i < inlen && j < (outlen-1)) { 662 /* Show unicode chars >= 256 as '?' */ 663 if (instr[i+1]) 664 c = '?'; 665 else 666 c = instr[i]; 667 if (c == '\0') 668 break; 669 outstr[j] = c; 670 i += 2; 671 j++; 672 } 673 outstr[j] = '\0'; 674 return (j); 675 } 676 677 /* 678 * TRANS2 information levels 679 * [X/Open-SMB, Sec. 16.1.6] 680 */ 681 static void 682 get_info_level(char *outstr, int value) 683 { 684 685 switch (value) { 686 case 1: 687 sprintf(outstr, "Standard"); break; 688 case 2: 689 sprintf(outstr, "Query EA Size"); break; 690 case 3: 691 sprintf(outstr, "Query EAS from List"); break; 692 case 0x101: 693 sprintf(outstr, "Directory Info"); break; 694 case 0x102: 695 sprintf(outstr, "Full Directory Info"); break; 696 case 0x103: 697 sprintf(outstr, "Names Info"); break; 698 case 0x104: 699 sprintf(outstr, "Both Directory Info"); break; 700 default: 701 sprintf(outstr, "Unknown"); break; 702 } 703 } 704 705 /* 706 * Interpret TRANS2_QUERY_PATH subcommand 707 * [X/Open-SMB, Sec. 16.7] 708 */ 709 /* ARGSUSED */ 710 static void 711 output_trans2_querypath(int flags, uchar_t *data, char *xtra) 712 { 713 int length; 714 char filename[256]; 715 716 if (flags & F_SUM) { 717 length = sprintf(xtra, "QueryPathInfo "); 718 xtra += length; 719 data += 6; 720 (void) unicode2ascii(filename, 256, data, 512); 721 sprintf(xtra, "File=%s ", filename); 722 } 723 724 if (flags & F_DTAIL) { 725 sprintf(GETLINE, "FunctionName = QueryPathInfo"); 726 sprintf(GETLINE, "InfoLevel = 0x%.4x", 727 get2(data)); 728 data += 6; 729 (void) unicode2ascii(filename, 256, data, 512); 730 sprintf(GETLINE, "FileName = %s", 731 filename); 732 } 733 } 734 735 /* 736 * Interpret TRANS2_QUERY_FILE subcommand 737 * [X/Open-SMB, Sec. 16.9] 738 */ 739 /* ARGSUSED */ 740 static void 741 output_trans2_queryfile(int flags, uchar_t *data, char *xtra) 742 { 743 int length; 744 745 if (flags & F_SUM) { 746 length = sprintf(xtra, "QueryFileInfo "); 747 xtra += length; 748 sprintf(xtra, "FileID=0x%x ", get2(data)); 749 } 750 751 if (flags & F_DTAIL) { 752 sprintf(GETLINE, "FunctionName = QueryFileInfo"); 753 sprintf(GETLINE, "FileID = 0x%.4x", 754 get2(data)); 755 data += 2; 756 sprintf(GETLINE, "InfoLevel = 0x%.4x", 757 get2(data)); 758 } 759 } 760 761 /* 762 * Interpret TRANS2_SET_FILE subcommand 763 * [X/Open-SMB, Sec. 16.10] 764 */ 765 /* ARGSUSED */ 766 static void 767 output_trans2_setfile(int flags, uchar_t *data, char *xtra) 768 { 769 int length; 770 771 if (flags & F_SUM) { 772 length = sprintf(xtra, "SetFileInfo "); 773 xtra += length; 774 sprintf(xtra, "FileID=0x%x ", get2(data)); 775 } 776 777 if (flags & F_DTAIL) { 778 sprintf(GETLINE, "FunctionName = SetFileInfo"); 779 sprintf(GETLINE, "FileID = 0x%.4x", 780 get2(data)); 781 data += 2; 782 sprintf(GETLINE, "InfoLevel = 0x%.4x", 783 get2(data)); 784 } 785 } 786 787 /* 788 * Interpret TRANS2_FIND_FIRST subcommand 789 * [X/Open-SMB, Sec. 16.3] 790 */ 791 /* ARGSUSED */ 792 static void 793 output_trans2_findfirst(int flags, uchar_t *data, char *xtra) 794 { 795 int length; 796 char filename[256]; 797 char infolevel[100]; 798 799 if (flags & F_SUM) { 800 length = sprintf(xtra, "Findfirst "); 801 xtra += length; 802 data += 12; 803 (void) unicode2ascii(filename, 256, data, 512); 804 sprintf(xtra, "File=%s ", filename); 805 } 806 807 if (flags & F_DTAIL) { 808 sprintf(GETLINE, "FunctionName = Findfirst"); 809 sprintf(GETLINE, "SearchAttributes = 0x%.4x", 810 get2(data)); 811 data += 2; 812 sprintf(GETLINE, "FindCount = 0x%.4x", 813 get2(data)); 814 data += 2; 815 sprintf(GETLINE, "FindFlags = 0x%.4x", 816 get2(data)); 817 data += 2; 818 get_info_level(infolevel, get2(data)); 819 sprintf(GETLINE, "InfoLevel = %s", 820 infolevel); 821 data += 6; 822 (void) unicode2ascii(filename, 256, data, 512); 823 sprintf(GETLINE, "FileName = %s", 824 filename); 825 } 826 } 827 828 829 /* 830 * Interpret TRANS2_FIND_NEXT subcommand 831 * [X/Open-SMB, Sec. 16.4] 832 */ 833 /* ARGSUSED */ 834 static void 835 output_trans2_findnext(int flags, uchar_t *data, char *xtra) 836 { 837 int length; 838 char filename[256]; 839 char infolevel[100]; 840 841 if (flags & F_SUM) { 842 length = sprintf(xtra, "Findnext "); 843 xtra += length; 844 data += 12; 845 (void) unicode2ascii(filename, 256, data, 512); 846 sprintf(xtra, "File=%s ", filename); 847 } 848 849 if (flags & F_DTAIL) { 850 sprintf(GETLINE, "FunctionName = Findnext"); 851 sprintf(GETLINE, "FileID = 0x%.4x", 852 get2(data)); 853 data += 2; 854 sprintf(GETLINE, "FindCount = 0x%.4x", 855 get2(data)); 856 data += 2; 857 get_info_level(infolevel, get2(data)); 858 sprintf(GETLINE, "InfoLevel = %s", 859 infolevel); 860 data += 2; 861 sprintf(GETLINE, "FindKey = 0x%.8x", 862 get4(data)); 863 data += 4; 864 sprintf(GETLINE, "FindFlags = 0x%.4x", 865 get2(data)); 866 data += 2; 867 (void) unicode2ascii(filename, 256, data, 512); 868 sprintf(GETLINE, "FileName = %s", 869 filename); 870 } 871 } 872 873 /* 874 * Interpret a "Negprot" SMB 875 * [X/Open-SMB, Sec. 6.1] 876 */ 877 /* ARGSUSED */ 878 static void 879 interpret_negprot(int flags, uchar_t *data, int len, char *xtra) 880 { 881 int length; 882 int bytecount; 883 char dialect[256]; 884 struct smb *smbdata; 885 uchar_t *protodata; 886 887 smbdata = (struct smb *)data; 888 protodata = (uchar_t *)data + sizeof (struct smb); 889 protodata++; /* skip wordcount */ 890 891 if (smbdata->flags & SERVER_RESPONSE) { 892 if (flags & F_SUM) { 893 sprintf(xtra, "Dialect#=%d ", protodata[0]); 894 } 895 if (flags & F_DTAIL) { 896 sprintf(GETLINE, "Protocol Index = %d", 897 protodata[0]); 898 } 899 } else { 900 /* 901 * request packet: 902 * short bytecount; 903 * struct { char fmt; char name[]; } dialects 904 */ 905 bytecount = get2(protodata); 906 protodata += 2; 907 if (flags & F_SUM) { 908 while (bytecount > 1) { 909 length = snprintf(dialect, sizeof (dialect), 910 "%s", (char *)protodata+1); 911 protodata += (length+2); 912 if (protodata >= data+len) 913 break; 914 bytecount -= (length+2); 915 } 916 sprintf(xtra, "LastDialect=%s ", dialect); 917 } 918 if (flags & F_DTAIL) { 919 sprintf(GETLINE, "ByteCount = %d", bytecount); 920 while (bytecount > 1) { 921 length = snprintf(dialect, sizeof (dialect), 922 "%s", (char *)protodata+1); 923 sprintf(GETLINE, "Dialect String = %s", 924 dialect); 925 protodata += (length+2); 926 if (protodata >= data+len) 927 break; 928 bytecount -= (length+2); 929 } 930 } 931 } 932 } 933 934 /* 935 * LAN Manager remote admin function names. 936 * [X/Open-SMB, Appendix B.8] 937 */ 938 static const char *apinames[] = { 939 "RNetShareEnum", 940 "RNetShareGetInfo", 941 "NetShareSetInfo", 942 "NetShareAdd", 943 "NetShareDel", 944 "NetShareCheck", 945 "NetSessionEnum", 946 "NetSessionGetInfo", 947 "NetSessionDel", 948 "NetConnectionEnum", 949 "NetFileEnum", 950 "NetFileGetInfo", 951 "NetFileClose", 952 "RNetServerGetInfo", 953 "NetServerSetInfo", 954 "NetServerDiskEnum", 955 "NetServerAdminCommand", 956 "NetAuditOpen", 957 "NetAuditClear", 958 "NetErrorLogOpen", 959 "NetErrorLogClear", 960 "NetCharDevEnum", 961 "NetCharDevGetInfo", 962 "NetCharDevControl", 963 "NetCharDevQEnum", 964 "NetCharDevQGetInfo", 965 "NetCharDevQSetInfo", 966 "NetCharDevQPurge", 967 "RNetCharDevQPurgeSelf", 968 "NetMessageNameEnum", 969 "NetMessageNameGetInfo", 970 "NetMessageNameAdd", 971 "NetMessageNameDel", 972 "NetMessageNameFwd", 973 "NetMessageNameUnFwd", 974 "NetMessageBufferSend", 975 "NetMessageFileSend", 976 "NetMessageLogFileSet", 977 "NetMessageLogFileGet", 978 "NetServiceEnum", 979 "RNetServiceInstall", 980 "RNetServiceControl", 981 "RNetAccessEnum", 982 "RNetAccessGetInfo", 983 "RNetAccessSetInfo", 984 "RNetAccessAdd", 985 "RNetAccessDel", 986 "NetGroupEnum", 987 "NetGroupAdd", 988 "NetGroupDel", 989 "NetGroupAddUser", 990 "NetGroupDelUser", 991 "NetGroupGetUsers", 992 "NetUserEnum", 993 "RNetUserAdd", 994 "NetUserDel", 995 "NetUserGetInfo", 996 "RNetUserSetInfo", 997 "RNetUserPasswordSet", 998 "NetUserGetGroups", 999 "NetWkstaLogon", 1000 "NetWkstaLogoff", 1001 "NetWkstaSetUID", 1002 "NetWkstaGetInfo", 1003 "NetWkstaSetInfo", 1004 "NetUseEnum", 1005 "NetUseAdd", 1006 "NetUseDel", 1007 "NetUseGetInfo", 1008 "DosPrintQEnum", 1009 "DosPrintQGetInfo", 1010 "DosPrintQSetInfo", 1011 "DosPrintQAdd", 1012 "DosPrintQDel", 1013 "DosPrintQPause", 1014 "DosPrintQContinue", 1015 "DosPrintJobEnum", 1016 "DosPrintJobGetInfo", 1017 "RDosPrintJobSetInfo", 1018 "DosPrintJobAdd", 1019 "DosPrintJobSchedule", 1020 "RDosPrintJobDel", 1021 "RDosPrintJobPause", 1022 "RDosPrintJobContinue", 1023 "DosPrintDestEnum", 1024 "DosPrintDestGetInfo", 1025 "DosPrintDestControl", 1026 "NetProfileSave", 1027 "NetProfileLoad", 1028 "NetStatisticsGet", 1029 "NetStatisticsClear", 1030 "NetRemoteTOD", 1031 "NetBiosEnum", 1032 "NetBiosGetInfo", 1033 "NetServerEnum", 1034 "I_NetServerEnum", 1035 "NetServiceGetInfo", 1036 "NetSplQmAbort", 1037 "NetSplQmClose", 1038 "NetSplQmEndDoc", 1039 "NetSplQmOpen", 1040 "NetSplQmStartDoc", 1041 "NetSplQmWrite", 1042 "DosPrintQPurge", 1043 "NetServerEnum2" 1044 }; 1045 static const int apimax = ( 1046 sizeof (apinames) / 1047 sizeof (apinames[0])); 1048 1049 /* 1050 * Interpret a "trans" SMB 1051 * [X/Open-SMB, Appendix B] 1052 * 1053 * This is very much like "trans2" below. 1054 */ 1055 /* ARGSUSED */ 1056 static void 1057 interpret_trans(int flags, uchar_t *data, int len, char *xtra) 1058 { 1059 struct smb *smb; 1060 uchar_t *vwv; /* word parameters */ 1061 int wordcount; 1062 uchar_t *byteparms; 1063 int bytecount; 1064 int parambytes; 1065 int paramoffset; 1066 int setupcount; 1067 int subcode; 1068 uchar_t *setupdata; 1069 uchar_t *params; 1070 int apinum; 1071 int isunicode; 1072 char filename[256]; 1073 1074 smb = (struct smb *)data; 1075 vwv = (uchar_t *)data + sizeof (struct smb); 1076 wordcount = *vwv++; 1077 1078 byteparms = vwv + (2 * wordcount); 1079 bytecount = get2(byteparms); 1080 byteparms += 2; 1081 1082 /* 1083 * Print the lengths before we (potentially) bail out 1084 * due to lack of data (so the user knows why we did). 1085 */ 1086 if (flags & F_DTAIL) { 1087 sprintf(GETLINE, "WordCount = %d", wordcount); 1088 sprintf(GETLINE, "ByteCount = %d", bytecount); 1089 } 1090 1091 /* Get length and location of params and setup data. */ 1092 if (!(smb->flags & SERVER_RESPONSE)) { 1093 /* CALL */ 1094 if (wordcount < 14) 1095 return; 1096 parambytes = get2(vwv + (2 * 9)); 1097 paramoffset = get2(vwv + (2 * 10)); 1098 setupcount = *(vwv + (2 * 13)); 1099 setupdata = vwv + (2 * 14); 1100 } else { 1101 /* REPLY */ 1102 if (wordcount < 10) 1103 return; 1104 parambytes = get2(vwv + (2 * 3)); 1105 paramoffset = get2(vwv + (2 * 4)); 1106 setupcount = *(vwv + (2 * 9)); 1107 setupdata = vwv + (2 * 10); 1108 } 1109 if (setupcount > 0) 1110 subcode = get2(setupdata); 1111 else 1112 subcode = -1; /* invalid */ 1113 1114 /* The parameters are offset from the SMB header. */ 1115 params = data + paramoffset; 1116 if (parambytes > 0) 1117 apinum = params[0]; 1118 else 1119 apinum = -1; /* invalid */ 1120 1121 /* Is the pathname in unicode? */ 1122 isunicode = smb->flags2[1] & 0x80; 1123 1124 if (flags & F_DTAIL && !(smb->flags & SERVER_RESPONSE)) { 1125 /* This is a CALL. */ 1126 /* print the word parameters */ 1127 sprintf(GETLINE, "TotalParamBytes = %d", get2(vwv)); 1128 sprintf(GETLINE, "TotalDataBytes = %d", get2(vwv+2)); 1129 sprintf(GETLINE, "MaxParamBytes = %d", get2(vwv+4)); 1130 sprintf(GETLINE, "MaxDataBytes = %d", get2(vwv+6)); 1131 sprintf(GETLINE, "MaxSetupWords = %d", vwv[8]); 1132 sprintf(GETLINE, "TransFlags = 0x%.4x", get2(vwv+10)); 1133 sprintf(GETLINE, "Timeout = 0x%.8x", get4(vwv+12)); 1134 /* skip Reserved2 */ 1135 sprintf(GETLINE, "ParamBytes = 0x%.4x", parambytes); 1136 sprintf(GETLINE, "ParamOffset = 0x%.4x", paramoffset); 1137 sprintf(GETLINE, "DataBytes = 0x%.4x", get2(vwv+22)); 1138 sprintf(GETLINE, "DataOffset = 0x%.4x", get2(vwv+24)); 1139 sprintf(GETLINE, "SetupWords = %d", setupcount); 1140 1141 /* That finishes the VWV, now the misc. stuff. */ 1142 if (subcode >= 0) 1143 sprintf(GETLINE, "Setup[0] = %d", subcode); 1144 if (apinum >= 0) 1145 sprintf(GETLINE, "APIcode = %d", apinum); 1146 if (0 <= apinum && apinum < apimax) 1147 sprintf(GETLINE, "APIname = %s", apinames[apinum]); 1148 1149 /* Finally, print the byte parameters. */ 1150 if (isunicode) { 1151 byteparms += 1; /* alignment padding */ 1152 (void) unicode2ascii( 1153 filename, 256, byteparms, bytecount); 1154 } else { 1155 strlcpy(filename, (char *)byteparms, sizeof (filename)); 1156 } 1157 sprintf(GETLINE, "FileName = %s", filename); 1158 } 1159 1160 if (flags & F_DTAIL && smb->flags & SERVER_RESPONSE) { 1161 /* This is a REPLY. */ 1162 /* print the word parameters */ 1163 sprintf(GETLINE, "TotalParamBytes = %d", get2(vwv)); 1164 sprintf(GETLINE, "TotalDataBytes = %d", get2(vwv+2)); 1165 /* skip Reserved */ 1166 sprintf(GETLINE, "ParamBytes = 0x%.4x", parambytes); 1167 sprintf(GETLINE, "ParamOffset = 0x%.4x", paramoffset); 1168 sprintf(GETLINE, "ParamDispl. = 0x%.4x", get2(vwv+10)); 1169 sprintf(GETLINE, "DataBytes = 0x%.4x", get2(vwv+12)); 1170 sprintf(GETLINE, "DataOffset = 0x%.4x", get2(vwv+14)); 1171 sprintf(GETLINE, "DataDispl. = 0x%.4x", get2(vwv+16)); 1172 sprintf(GETLINE, "SetupWords = %d", setupcount); 1173 1174 output_bytes(byteparms, bytecount); 1175 } 1176 } 1177 1178 /* 1179 * Interpret a "TconX" SMB 1180 * [X/Open-SMB, Sec. 11.4] 1181 */ 1182 /* ARGSUSED */ 1183 static void 1184 interpret_tconX(int flags, uchar_t *data, int len, char *xtra) 1185 { 1186 int length; 1187 int bytecount; 1188 int passwordlength; 1189 int wordcount; 1190 char tempstring[256]; 1191 struct smb *smbdata; 1192 uchar_t *tcondata; 1193 1194 smbdata = (struct smb *)data; 1195 tcondata = (uchar_t *)data + sizeof (struct smb); 1196 wordcount = *tcondata++; 1197 1198 if (flags & F_SUM && !(smbdata->flags & SERVER_RESPONSE)) { 1199 tcondata += 6; 1200 passwordlength = get2(tcondata); 1201 tcondata = tcondata + 4 + passwordlength; 1202 length = snprintf(tempstring, sizeof (tempstring), "%s", 1203 (char *)tcondata); 1204 sprintf(xtra, "Share=%s ", tempstring); 1205 } 1206 1207 if (flags & F_SUM && smbdata->flags & SERVER_RESPONSE) { 1208 tcondata += 8; 1209 length = snprintf(tempstring, sizeof (tempstring), "%s", 1210 (char *)tcondata); 1211 sprintf(xtra, "Type=%s ", tempstring); 1212 } 1213 1214 if (flags & F_DTAIL && !(smbdata->flags & SERVER_RESPONSE)) { 1215 sprintf(GETLINE, "WordCount = %d", wordcount); 1216 sprintf(GETLINE, "ChainedCommand = 0x%.2x", 1217 tcondata[0]); 1218 tcondata += 2; 1219 sprintf(GETLINE, "NextOffset = 0x%.4x", 1220 get2(tcondata)); 1221 tcondata += 2; 1222 sprintf(GETLINE, "DisconnectFlag = 0x%.4x", 1223 get2(tcondata)); 1224 tcondata += 2; 1225 passwordlength = get2(tcondata); 1226 sprintf(GETLINE, "PasswordLength = 0x%.4x", 1227 passwordlength); 1228 tcondata += 2; 1229 bytecount = get2(tcondata); 1230 sprintf(GETLINE, "ByteCount = %d", bytecount); 1231 tcondata = tcondata + 2 + passwordlength; 1232 length = snprintf(tempstring, sizeof (tempstring), "%s", 1233 (char *)tcondata); 1234 tcondata += (length+1); 1235 sprintf(GETLINE, "FileName = %s", tempstring); 1236 length = snprintf(tempstring, sizeof (tempstring), "%s", 1237 (char *)tcondata); 1238 tcondata += (length+1); 1239 sprintf(GETLINE, "ServiceName = %s", tempstring); 1240 } 1241 1242 if (flags & F_DTAIL && smbdata->flags & SERVER_RESPONSE) { 1243 sprintf(GETLINE, "WordCount = %d", wordcount); 1244 sprintf(GETLINE, "ChainedCommand = 0x%.2x", 1245 tcondata[0]); 1246 tcondata += 2; 1247 sprintf(GETLINE, "NextOffset = 0x%.4x", 1248 get2(tcondata)); 1249 tcondata += 2; 1250 sprintf(GETLINE, "OptionalSupport = 0x%.4x", 1251 get2(tcondata)); 1252 tcondata += 2; 1253 bytecount = get2(tcondata); 1254 sprintf(GETLINE, "ByteCount = %d", bytecount); 1255 tcondata += 2; 1256 length = snprintf(tempstring, sizeof (tempstring), "%s", 1257 (char *)tcondata); 1258 tcondata += (length+1); 1259 sprintf(GETLINE, "ServiceName = %s", tempstring); 1260 length = snprintf(tempstring, sizeof (tempstring), "%s", 1261 (char *)tcondata); 1262 tcondata += (length+1); 1263 sprintf(GETLINE, "NativeFS = %s", tempstring); 1264 } 1265 } 1266 1267 /* 1268 * Interpret a "SesssetupX" SMB 1269 * [X/Open-SMB, Sec. 11.3] 1270 */ 1271 /* ARGSUSED */ 1272 static void 1273 interpret_sesssetupX(int flags, uchar_t *data, int len, char *xtra) 1274 { 1275 int length; 1276 int bytecount; 1277 int passwordlength; 1278 int isunicode; 1279 int upasswordlength; 1280 int wordcount; 1281 int cap; 1282 char tempstring[256]; 1283 struct smb *smbdata; 1284 uchar_t *setupdata; 1285 1286 smbdata = (struct smb *)data; 1287 setupdata = (uchar_t *)data + sizeof (struct smb); 1288 wordcount = *setupdata++; 1289 1290 isunicode = smbdata->flags2[1] & 0x80; 1291 1292 if (flags & F_SUM && !(smbdata->flags & SERVER_RESPONSE)) { 1293 if (wordcount != 13) 1294 return; 1295 setupdata += 14; 1296 passwordlength = get2(setupdata); 1297 setupdata += 2; 1298 upasswordlength = get2(setupdata); 1299 setupdata += 6; 1300 cap = get4(setupdata); 1301 setupdata = setupdata + 6 + passwordlength + upasswordlength; 1302 if (isunicode) { 1303 setupdata += 1; 1304 (void) unicode2ascii(tempstring, 256, setupdata, 256); 1305 sprintf(xtra, "Username=%s ", tempstring); 1306 } else { 1307 length = snprintf(tempstring, sizeof (tempstring), "%s", 1308 (char *)setupdata); 1309 sprintf(xtra, "Username=%s ", tempstring); 1310 } 1311 } 1312 1313 if (flags & F_DTAIL && !(smbdata->flags & SERVER_RESPONSE)) { 1314 if (wordcount != 13) 1315 return; 1316 sprintf(GETLINE, "ChainedCommand = 0x%.2x", 1317 setupdata[0]); 1318 setupdata += 2; 1319 sprintf(GETLINE, "NextOffset = 0x%.4x", 1320 get2(setupdata)); 1321 setupdata += 2; 1322 sprintf(GETLINE, "MaxBufferSize = 0x%.4x", 1323 get2(setupdata)); 1324 setupdata += 2; 1325 sprintf(GETLINE, "MaxMPXRequests = %d", 1326 get2(setupdata)); 1327 setupdata += 2; 1328 sprintf(GETLINE, "VCNumber = %d", 1329 get2(setupdata)); 1330 setupdata += 2; 1331 sprintf(GETLINE, "SessionKey = %d", 1332 get4(setupdata)); 1333 setupdata += 4; 1334 passwordlength = get2(setupdata); 1335 sprintf(GETLINE, "PasswordLength = 0x%.4x", 1336 passwordlength); 1337 setupdata += 2; 1338 upasswordlength = get2(setupdata); 1339 sprintf(GETLINE, "UnicodePasswordLength = 0x%.4x", 1340 upasswordlength); 1341 setupdata += 6; 1342 cap = get4(setupdata); 1343 sprintf(GETLINE, "Capabilities = 0x%0.8x", cap); 1344 setupdata += 4; 1345 bytecount = get2(setupdata); 1346 sprintf(GETLINE, "ByteCount = %d", bytecount); 1347 setupdata = setupdata + 2 + passwordlength + upasswordlength; 1348 if (isunicode) { 1349 setupdata++; 1350 length = 2*unicode2ascii( 1351 tempstring, 256, setupdata, 256); 1352 if (length == 2) { 1353 sprintf(GETLINE, 1354 "AccountName = %s", tempstring); 1355 sprintf(GETLINE, 1356 "DomainName = %s", tempstring); 1357 setupdata += 3; 1358 } else { 1359 setupdata += length; 1360 sprintf(GETLINE, 1361 "AccountName = %s", tempstring); 1362 length = 2*unicode2ascii( 1363 tempstring, 256, setupdata, 256); 1364 setupdata += length; 1365 sprintf(GETLINE, 1366 "DomainName = %s", tempstring); 1367 } 1368 length = 2*unicode2ascii( 1369 tempstring, 256, setupdata, 256); 1370 setupdata += (length+2); 1371 sprintf(GETLINE, 1372 "NativeOS = %s", tempstring); 1373 length = 2*unicode2ascii( 1374 tempstring, 256, setupdata, 256); 1375 sprintf(GETLINE, 1376 "NativeLanman = %s", tempstring); 1377 } else { 1378 length = snprintf(tempstring, sizeof (tempstring), "%s", 1379 (char *)setupdata); 1380 setupdata += (length+1); 1381 sprintf(GETLINE, "AccountName = %s", tempstring); 1382 length = snprintf(tempstring, sizeof (tempstring), "%s", 1383 (char *)setupdata); 1384 setupdata += (length+1); 1385 sprintf(GETLINE, "DomainName = %s", tempstring); 1386 length = snprintf(tempstring, sizeof (tempstring), "%s", 1387 (char *)setupdata); 1388 setupdata += (length+1); 1389 sprintf(GETLINE, "NativeOS = %s", tempstring); 1390 snprintf(tempstring, sizeof (tempstring), "%s", 1391 (char *)setupdata); 1392 sprintf(GETLINE, "NativeLanman = %s", tempstring); 1393 } 1394 } 1395 1396 if (flags & F_DTAIL && smbdata->flags & SERVER_RESPONSE) { 1397 if (wordcount != 3) 1398 return; 1399 sprintf(GETLINE, "ChainedCommand = 0x%.2x", 1400 setupdata[0]); 1401 setupdata += 2; 1402 sprintf(GETLINE, "NextOffset = 0x%.4x", 1403 get2(setupdata)); 1404 setupdata += 2; 1405 sprintf(GETLINE, "SetupAction = 0x%.4x", 1406 get2(setupdata)); 1407 setupdata += 2; 1408 bytecount = get2(setupdata); 1409 sprintf(GETLINE, "ByteCount = %d", bytecount); 1410 setupdata += 2; 1411 length = snprintf(tempstring, sizeof (tempstring), "%s", 1412 (char *)setupdata); 1413 setupdata += (length+1); 1414 sprintf(GETLINE, "NativeOS = %s", tempstring); 1415 length = snprintf(tempstring, sizeof (tempstring), "%s", 1416 (char *)setupdata); 1417 setupdata += (length+1); 1418 sprintf(GETLINE, "NativeLanman = %s", tempstring); 1419 length = snprintf(tempstring, sizeof (tempstring), "%s", 1420 (char *)setupdata); 1421 sprintf(GETLINE, "DomainName = %s", tempstring); 1422 } 1423 } 1424 1425 /* 1426 * Interpret "Trans2" SMB 1427 * [X/Open-SMB, Sec. 16] 1428 * 1429 * This is very much like "trans" above. 1430 */ 1431 /* ARGSUSED */ 1432 static void 1433 interpret_trans2(int flags, uchar_t *data, int len, char *xtra) 1434 { 1435 struct smb *smb; 1436 uchar_t *vwv; /* word parameters */ 1437 int wordcount; 1438 uchar_t *byteparms; 1439 int bytecount; 1440 int parambytes; 1441 int paramoffset; 1442 int setupcount; 1443 int subcode; 1444 uchar_t *setupdata; 1445 uchar_t *params; 1446 char *name; 1447 1448 smb = (struct smb *)data; 1449 vwv = (uchar_t *)data + sizeof (struct smb); 1450 wordcount = *vwv++; 1451 1452 byteparms = vwv + (2 * wordcount); 1453 bytecount = get2(byteparms); 1454 byteparms += 2; 1455 1456 /* 1457 * Print the lengths before we (potentially) bail out 1458 * due to lack of data (so the user knows why we did). 1459 */ 1460 if (flags & F_DTAIL) { 1461 sprintf(GETLINE, "WordCount = %d", wordcount); 1462 sprintf(GETLINE, "ByteCount = %d", bytecount); 1463 } 1464 1465 /* Get length and location of params and setup data. */ 1466 if (!(smb->flags & SERVER_RESPONSE)) { 1467 /* CALL */ 1468 if (wordcount < 14) 1469 return; 1470 parambytes = get2(vwv + (2 * 9)); 1471 paramoffset = get2(vwv + (2 * 10)); 1472 setupcount = *(vwv + (2 * 13)); 1473 setupdata = vwv + (2 * 14); 1474 } else { 1475 /* REPLY */ 1476 if (wordcount < 10) 1477 return; 1478 parambytes = get2(vwv + (2 * 3)); 1479 paramoffset = get2(vwv + (2 * 4)); 1480 setupcount = *(vwv + (2 * 9)); 1481 setupdata = vwv + (2 * 10); 1482 } 1483 if (setupcount > 0) 1484 subcode = get2(setupdata); 1485 else 1486 subcode = -1; /* invalid */ 1487 1488 /* The parameters are offset from the SMB header. */ 1489 params = data + paramoffset; 1490 1491 if (flags & F_DTAIL && !(smb->flags & SERVER_RESPONSE)) { 1492 /* This is a CALL. */ 1493 /* print the word parameters */ 1494 sprintf(GETLINE, "TotalParamBytes = %d", get2(vwv)); 1495 sprintf(GETLINE, "TotalDataBytes = %d", get2(vwv+2)); 1496 sprintf(GETLINE, "MaxParamBytes = %d", get2(vwv+4)); 1497 sprintf(GETLINE, "MaxDataBytes = %d", get2(vwv+6)); 1498 sprintf(GETLINE, "MaxSetupWords = %d", vwv[8]); 1499 sprintf(GETLINE, "TransFlags = 0x%.4x", get2(vwv+10)); 1500 sprintf(GETLINE, "Timeout = 0x%.8x", get4(vwv+12)); 1501 /* skip Reserved2 */ 1502 sprintf(GETLINE, "ParamBytes = 0x%.4x", parambytes); 1503 sprintf(GETLINE, "ParamOffset = 0x%.4x", paramoffset); 1504 sprintf(GETLINE, "DataBytes = 0x%.4x", get2(vwv+22)); 1505 sprintf(GETLINE, "DataOffset = 0x%.4x", get2(vwv+24)); 1506 sprintf(GETLINE, "SetupWords = %d", setupcount); 1507 1508 /* That finishes the VWV, now the misc. stuff. */ 1509 sprintf(GETLINE, "FunctionCode = %d", subcode); 1510 } 1511 1512 if (!(smb->flags & SERVER_RESPONSE)) { 1513 /* This is a CALL. Do sub-function. */ 1514 switch (subcode) { 1515 case TRANS2_OPEN: 1516 name = "Open"; 1517 goto name_only; 1518 case TRANS2_FIND_FIRST: 1519 output_trans2_findfirst(flags, params, xtra); 1520 break; 1521 case TRANS2_FIND_NEXT2: 1522 output_trans2_findnext(flags, params, xtra); 1523 break; 1524 case TRANS2_QUERY_FS_INFORMATION: 1525 name = "QueryFSInfo"; 1526 goto name_only; 1527 case TRANS2_QUERY_PATH_INFORMATION: 1528 output_trans2_querypath(flags, params, xtra); 1529 break; 1530 case TRANS2_SET_PATH_INFORMATION: 1531 name = "SetPathInfo"; 1532 goto name_only; 1533 case TRANS2_QUERY_FILE_INFORMATION: 1534 output_trans2_queryfile(flags, params, xtra); 1535 break; 1536 case TRANS2_SET_FILE_INFORMATION: 1537 output_trans2_setfile(flags, params, xtra); 1538 break; 1539 case TRANS2_CREATE_DIRECTORY: 1540 name = "CreateDir"; 1541 goto name_only; 1542 1543 default: 1544 name = "Unknown"; 1545 /* fall through */ 1546 name_only: 1547 if (flags & F_SUM) 1548 sprintf(xtra, "%s ", name); 1549 if (flags & F_DTAIL) 1550 sprintf(GETLINE, "FunctionName = %s", name); 1551 break; 1552 } 1553 } 1554 1555 if (flags & F_DTAIL && smb->flags & SERVER_RESPONSE) { 1556 /* This is a REPLY. */ 1557 /* print the word parameters */ 1558 sprintf(GETLINE, "TotalParamBytes = %d", get2(vwv)); 1559 sprintf(GETLINE, "TotalDataBytes = %d", get2(vwv+2)); 1560 /* skip Reserved */ 1561 sprintf(GETLINE, "ParamBytes = 0x%.4x", parambytes); 1562 sprintf(GETLINE, "ParamOffset = 0x%.4x", paramoffset); 1563 sprintf(GETLINE, "ParamDispl. = 0x%.4x", get2(vwv+10)); 1564 sprintf(GETLINE, "DataBytes = 0x%.4x", get2(vwv+12)); 1565 sprintf(GETLINE, "DataOffset = 0x%.4x", get2(vwv+14)); 1566 sprintf(GETLINE, "DataDispl. = 0x%.4x", get2(vwv+16)); 1567 sprintf(GETLINE, "SetupWords = %d", setupcount); 1568 1569 output_bytes(byteparms, bytecount); 1570 } 1571 } 1572 1573 1574 static void 1575 interpret_default(int flags, uchar_t *data, int len, char *xtra) 1576 { 1577 int slength; 1578 int i; 1579 int printit; 1580 int wordcount; 1581 char *outstr; 1582 char *prfmt; 1583 char *format; 1584 char valuetype; 1585 char word[10]; 1586 char *label; 1587 char tempstring[256]; 1588 uchar_t *comdata, *limit; 1589 char buff[80]; 1590 struct smb *smbdata; 1591 struct decode *decoder; 1592 1593 smbdata = (struct smb *)data; 1594 comdata = (uchar_t *)data + sizeof (struct smb); 1595 wordcount = *comdata++; 1596 limit = data + len; 1597 1598 decoder = &SMBtable[smbdata->com & 255]; 1599 1600 if (smbdata->flags & SERVER_RESPONSE) 1601 format = decoder->replyfmt; 1602 else 1603 format = decoder->callfmt; 1604 1605 if (!format || strlen(format) == 0) { 1606 if (wordcount == 0 || flags & F_SUM) 1607 return; 1608 sprintf(GETLINE, "WordCount = %d", wordcount); 1609 sprintf(GETLINE, "Word values (in hex):"); 1610 for (i = 0; i < wordcount; i++) { 1611 sprintf(word, "%.4x ", get2(comdata)); 1612 comdata += 2; 1613 if (comdata >= limit) 1614 wordcount = i+1; /* terminate */ 1615 strcat(buff, word); 1616 if (((i+1) & 7) == 0 || i == (wordcount-1)) { 1617 sprintf(GETLINE, "%s", buff); 1618 strcpy(buff, ""); 1619 } 1620 } 1621 return; 1622 } 1623 1624 1625 valuetype = format[0]; 1626 while (valuetype != '\0') { 1627 if (comdata >= limit) 1628 break; 1629 if ((flags & F_DTAIL) && valuetype != 'r' && valuetype != 'R') 1630 outstr = GETLINE; 1631 else 1632 outstr = xtra + strlen(xtra); 1633 label = format+1; 1634 printit = (flags & F_DTAIL) || (valuetype <= 'Z'); 1635 1636 switch (valuetype) { 1637 case 'W': 1638 case 'w': 1639 prfmt = (flags & F_DTAIL) ? "%s = 0x%.4x" : "%s=0x%x "; 1640 if (printit) 1641 sprintf(outstr, prfmt, label, get2(comdata)); 1642 comdata += 2; 1643 break; 1644 case 'D': 1645 case 'd': 1646 prfmt = (flags & F_DTAIL) ? "%s = %d" : "%s=%d "; 1647 if (printit) 1648 sprintf(outstr, prfmt, label, get2(comdata)); 1649 comdata += 2; 1650 break; 1651 case 'L': 1652 case 'l': 1653 prfmt = (flags & F_DTAIL) ? "%s = 0x%.8x" : "%s=0x%x "; 1654 if (printit) 1655 sprintf(outstr, prfmt, label, get4(comdata)); 1656 comdata += 4; 1657 break; 1658 case 'B': 1659 case 'b': 1660 prfmt = (flags & F_DTAIL) ? "%s = 0x%.2x" : "%s=0x%x "; 1661 if (printit) 1662 sprintf(outstr, prfmt, label, comdata[0]); 1663 comdata += 1; 1664 break; 1665 case 'r': 1666 comdata++; 1667 break; 1668 case 'R': 1669 comdata += 2; 1670 break; 1671 case 'U': 1672 case 'u': 1673 prfmt = (flags & F_DTAIL) ? "%s = %s" : "%s=%s "; 1674 slength = unicode2ascii(tempstring, 256, comdata, 256); 1675 if (printit) 1676 sprintf(outstr, prfmt, label, tempstring); 1677 comdata += (slength*2 + 1); 1678 break; 1679 case 'S': 1680 case 's': 1681 prfmt = (flags & F_DTAIL) ? "%s = %s" : "%s=%s "; 1682 slength = snprintf(tempstring, sizeof (tempstring), 1683 "%s", (char *)comdata); 1684 if (printit) 1685 sprintf(outstr, prfmt, label, tempstring); 1686 comdata += (slength+1); 1687 break; 1688 } 1689 format += (strlen(format) + 1); 1690 valuetype = format[0]; 1691 } 1692 } 1693