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