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 /* 27 * References used throughout this code: 28 * 29 * [RFC1001] : PROTOCOL STANDARD FOR A NetBIOS SERVICE 30 * ON A TCP/UDP TRANSPORT: 31 * CONCEPTS AND METHODS 32 * NetBIOS Working Group, March 1987 33 * 34 * [RFC1002] : PROTOCOL STANDARD FOR A NetBIOS SERVICE 35 * ON A TCP/UDP TRANSPORT: 36 * DETAILED SPECIFICATIONS 37 * NetBIOS Working Group, March 1987 38 */ 39 40 #include <fcntl.h> 41 #include "snoop.h" 42 #include <stdio.h> 43 #include <ctype.h> 44 #include "snoop.h" 45 46 extern char *dlc_header; 47 char *show_type(); 48 49 /* See snoop_smb.c */ 50 extern void interpret_smb(int flags, uchar_t *data, int len); 51 52 /* 53 * NBT Session Packet Header 54 * [RFC 1002, Sec. 4.3.1] 55 */ 56 struct nbt_ss { 57 uchar_t type; 58 uchar_t flags; 59 ushort_t length; 60 }; 61 62 /* 63 * NBT Session Request Packet trailer 64 * [RFC 1002, Sec. 4.3.2] 65 */ 66 struct callnames { 67 uchar_t space; /* padding */ 68 uchar_t calledname[32]; 69 uchar_t nullchar; /* padding */ 70 uchar_t space2; /* padding */ 71 uchar_t callingname[32]; 72 uchar_t nullchar2; /* padding */ 73 }; 74 75 76 static void interpret_netbios_names(int flags, uchar_t *data, int len, 77 char *xtra); 78 static void netbiosname2ascii(char *asciiname, uchar_t *netbiosname); 79 80 /* 81 * Helpers to read network-order values, 82 * with NO alignment assumed. 83 */ 84 static ushort_t 85 getshort(uchar_t *p) { 86 return (p[1] + (p[0]<<8)); 87 } 88 static uint_t 89 getlong(uchar_t *p) 90 { 91 return (p[3] + (p[2]<<8) + (p[1]<<16) + (p[0]<<24)); 92 } 93 94 /* 95 * NM_FLAGS fields in the NetBIOS Name Service Packet header. 96 * [RFC 1002, Sec. 4.2.1.1] 97 */ 98 static void 99 print_flag_details(int headerflags) 100 { 101 if (headerflags & 1<<4) 102 sprintf(get_line(0, 0), " - Broadcast"); 103 if (headerflags & 1<<7) 104 sprintf(get_line(0, 0), " - Recursion Available"); 105 if (headerflags & 1<<8) 106 sprintf(get_line(0, 0), " - Recursion Desired"); 107 if (headerflags & 1<<9) 108 sprintf(get_line(0, 0), " - Truncation Flag"); 109 if (headerflags & 1<<10) 110 sprintf(get_line(0, 0), " - Authoritative Answer"); 111 } 112 113 /* 114 * Possible errors in NetBIOS name service packets. 115 * [RFC 1002, Sec. 4.2.6, 4.2.11, 4.2.14] 116 */ 117 static void 118 getrcodeerr(int headerflags, char *errortype) 119 { 120 int error = (headerflags & 0xf); 121 122 switch (error) { 123 case 0: 124 sprintf(errortype, "Success"); 125 break; 126 case 1: 127 sprintf(errortype, "Format Error"); 128 break; 129 case 2: 130 sprintf(errortype, "Server Failure"); 131 break; 132 case 3: 133 sprintf(errortype, "Name Error"); 134 break; 135 case 4: 136 sprintf(errortype, "Unsupported Request Error"); 137 break; 138 case 5: 139 sprintf(errortype, "Refused Error"); 140 break; 141 case 6: 142 sprintf(errortype, "Active Error"); 143 break; 144 case 7: 145 sprintf(errortype, "Name in Conflict Error"); 146 break; 147 default: 148 sprintf(errortype, "Unknown Error"); 149 break; 150 } 151 } 152 153 /* 154 * OPCODE fields in the NetBIOS Name Service Packet header. 155 * [RFC 1002, Sec. 4.2.1.1] 156 */ 157 static void 158 print_ns_type(int flags, int headerflags, char *xtra) 159 { 160 int opcode = (headerflags & 0x7800)>>11; 161 int response = (headerflags & 1<<15); 162 char *resptype = response ? "Response" : "Request"; 163 char *optype; 164 165 switch (opcode) { 166 case 0: 167 optype = "Query"; 168 break; 169 case 5: 170 optype = "Registration"; 171 break; 172 case 6: 173 optype = "Release"; 174 break; 175 case 7: 176 optype = "WACK"; 177 break; 178 case 8: 179 optype = "Refresh"; 180 break; 181 default: 182 optype = "Unknown"; 183 break; 184 } 185 186 if (flags & F_DTAIL) 187 sprintf(get_line(0, 0), "Type = %s %s", optype, resptype); 188 else 189 sprintf(xtra, "%s %s", optype, resptype); 190 } 191 192 193 /* 194 * Interpret Datagram Packets 195 * [RFC 1002, Sec. 4.4] 196 */ 197 void 198 interpret_netbios_datagram(int flags, uchar_t *data, int len) 199 { 200 char name[24]; 201 int packettype = data[0]; 202 int packetlen; 203 data++; 204 205 if (packettype < 0x10 || packettype > 0x11) 206 return; 207 208 if (flags & F_SUM) { 209 data += 14; 210 netbiosname2ascii(name, data); 211 sprintf(get_sum_line(), 212 "NBT Datagram Service Type=%d Source=%s", 213 packettype, name); 214 } 215 216 if (flags & F_DTAIL) { 217 show_header("NBT: ", "Netbios Datagram Service Header", len); 218 show_space(); 219 sprintf(get_line(0, 0), "Datagram Packet Type = 0x%.2x", 220 packettype); 221 sprintf(get_line(0, 0), "Datagram Flags = 0x%.2x", 222 data[0]); 223 data++; 224 sprintf(get_line(0, 0), "Datagram ID = 0x%.4x", 225 getshort(data)); 226 data += 2; 227 sprintf(get_line(0, 0), "Source IP = %d.%d.%d.%d", 228 data[0], data[1], data[2], data[3]); 229 data += 4; 230 sprintf(get_line(0, 0), "Source Port = %d", 231 getshort(data)); 232 data += 2; 233 packetlen = getshort(data); 234 sprintf(get_line(0, 0), "Datagram Length = 0x%.4x", 235 packetlen); 236 data += 2; 237 sprintf(get_line(0, 0), "Packet Offset = 0x%.4x", 238 getshort(data)); 239 data += 3; 240 netbiosname2ascii(name, data); 241 sprintf(get_line(0, 0), "Source Name = %s", name); 242 data += 34; 243 netbiosname2ascii(name, data); 244 sprintf(get_line(0, 0), "Destination Name = %s", name); 245 sprintf(get_line(0, 0), "Number of data bytes remaining = %d", 246 packetlen - 68); 247 show_trailer(); 248 } 249 } 250 251 /* 252 * Interpret NetBIOS Name Service packets. 253 * [RFC 1002, Sec. 4.2] 254 */ 255 void 256 interpret_netbios_ns(int flags, uchar_t *data, int len) 257 { 258 int headerflags, qcount, acount, nscount, arcount; 259 int transid; 260 char name[24]; 261 char extra[256]; 262 char errortype[50]; 263 int rdatalen; 264 int rrflags; 265 int nameptr; 266 int nodecode; 267 char *nodetype; 268 uchar_t *data0 = data; 269 270 transid = getshort(data); data += 2; 271 headerflags = getshort(data); data += 2; 272 qcount = getshort(data); data += 2; 273 acount = getshort(data); data += 2; 274 nscount = getshort(data); data += 2; 275 arcount = getshort(data); data += 2; 276 getrcodeerr(headerflags, errortype); 277 278 if (flags & F_SUM) { 279 print_ns_type(flags, headerflags, extra); 280 data++; 281 netbiosname2ascii(name, data); 282 sprintf(get_sum_line(), "NBT NS %s for %s, %s", 283 extra, name, errortype); 284 285 } 286 287 288 if (flags & F_DTAIL) { 289 show_header("NBT: ", "Netbios Name Service Header", len); 290 show_space(); 291 print_ns_type(flags, headerflags, 0); 292 sprintf(get_line(0, 0), "Status = %s", errortype); 293 sprintf(get_line(0, 0), "Transaction ID = 0x%.4x", transid); 294 sprintf(get_line(0, 0), "Flags Summary = 0x%.4x", 295 headerflags); 296 print_flag_details(headerflags); 297 sprintf(get_line(0, 0), "Question count = %d", qcount); 298 sprintf(get_line(0, 0), "Answer Count = %d", acount); 299 sprintf(get_line(0, 0), "Name Service Count = %d", nscount); 300 sprintf(get_line(0, 0), 301 "Additional Record Count = %d", arcount); 302 303 /* 304 * Question Section Packet Description from 305 * [RFC 1002, Sec. 4.2.1.2] 306 */ 307 308 if (qcount) { 309 data++; 310 netbiosname2ascii(name, data); 311 sprintf(get_line(0, 0), "Question Name = %s", name); 312 data += 33; 313 sprintf(get_line(0, 0), "Question Type = 0x%.4x", 314 getshort(data)); 315 data += 2; 316 sprintf(get_line(0, 0), "Question Class = 0x%.4x", 317 getshort(data)); 318 data += 2; 319 } 320 321 /* 322 * Resrouce Record Packet Description from 323 * [RFC 1002, Sec. 4.2.1.3] 324 */ 325 326 if ((acount || nscount || arcount) || 327 (qcount+acount+nscount+arcount == 0)) { 328 /* Second level encoding from RFC883 (p.31, 32) */ 329 if (data[0] & 0xc0) { 330 nameptr = getshort(data)&0x3fff; 331 netbiosname2ascii(name, (data0+nameptr+1)); 332 sprintf(get_line(0, 0), 333 "Resource Record Name = %s", name); 334 data += 2; 335 } else { 336 data++; 337 netbiosname2ascii(name, data); 338 sprintf(get_line(0, 0), 339 "Resource Record Name = %s", name); 340 data += 33; 341 } 342 sprintf(get_line(0, 0), 343 "Resource Record Type = 0x%.4x", 344 getshort(data)); 345 data += 2; 346 sprintf(get_line(0, 0), 347 "Resource Record Class = 0x%.4x", 348 getshort(data)); 349 data += 2; 350 sprintf(get_line(0, 0), 351 "Time to Live (Milliseconds) = %d", 352 getlong(data)); 353 data += 4; 354 rdatalen = getshort(data); 355 sprintf(get_line(0, 0), "RDATA Length = 0x%.4x", 356 rdatalen); 357 data += 2; 358 /* 15.4.2.1.3 */ 359 if (rdatalen == 6) { 360 rrflags = getshort(data); 361 data += 2; 362 sprintf(get_line(0, 0), 363 "Resource Record Flags = 0x%.4x", 364 rrflags); 365 nodecode = (rrflags>>13)& 0x11; 366 if (nodecode == 0) nodetype = "B"; 367 if (nodecode == 1) nodetype = "P"; 368 if (nodecode == 2) nodetype = "M"; 369 sprintf(get_line(0, 0), " - %s, %s node", 370 (rrflags & 1<<15) ? 371 "Group NetBIOS Name": 372 "Unique NetBIOS Name", nodetype); 373 sprintf(get_line(0, 0), 374 "Owner IP Address = %d.%d.%d.%d", 375 data[0], data[1], data[2], data[3]); 376 } 377 } 378 show_trailer(); 379 380 } 381 } 382 383 /* 384 * Interpret NetBIOS session packets. 385 * [RFC 1002, Sec. 4.3] 386 */ 387 void 388 interpret_netbios_ses(int flags, uchar_t *data, int len) 389 { 390 struct nbt_ss *ss; 391 uchar_t *trailer; 392 int length = len - 4; /* NBT packet length without header */ 393 char *type; 394 char extrainfo[300]; 395 396 if (len < sizeof (struct nbt_ss)) 397 return; 398 399 /* 400 * Packets that are fragments of a large NetBIOS session 401 * message will have no NetBIOS header. (Only the first 402 * TCP segment will have a NetBIOS header.) It turns out 403 * that very often, such fragments start with SMB data, so 404 * we should try to recognize and decode them. 405 */ 406 if (data[0] == 0xff && 407 data[1] == 'S' && 408 data[2] == 'M' && 409 data[3] == 'B') { 410 interpret_smb(flags, data, len); 411 return; 412 } 413 414 /* LINTED PTRALIGN */ 415 ss = (struct nbt_ss *)data; 416 trailer = data + sizeof (*ss); 417 extrainfo[0] = '\0'; 418 419 if (flags & F_SUM) { 420 switch (ss->type) { 421 case 0x00: 422 type = "SESSION MESSAGE"; 423 break; 424 case 0x81: 425 type = "SESSION REQUEST"; 426 interpret_netbios_names(flags, trailer, 427 length, extrainfo); 428 break; 429 case 0x82: 430 type = "POSITIVE SESSION RESPONSE"; 431 break; 432 case 0x83: 433 type = "NEGATIVE SESSION RESPONSE"; 434 break; 435 case 0x84: 436 type = "RETARGET SESSION RESPONSE"; 437 break; 438 case 0x85: 439 type = "SESSION KEEP ALIVE"; 440 break; 441 default: 442 type = "Unknown"; 443 break; 444 } 445 (void) sprintf(get_sum_line(), 446 "NBT Type=%s %sLength=%d", type, extrainfo, length); 447 } 448 449 if (flags & F_DTAIL) { 450 show_header("NBT: ", "NBT Header", len); 451 show_space(); 452 453 switch (ss->type) { 454 case 0x00: 455 (void) sprintf(get_line(0, 0), 456 "Type = SESSION MESSAGE"); 457 break; 458 case 0x81: 459 (void) sprintf(get_line(0, 0), 460 "Type = SESSION REQUEST"); 461 interpret_netbios_names(flags, trailer, length, 0); 462 break; 463 case 0x82: 464 (void) sprintf(get_line(0, 0), 465 "Type = POSITIVE SESSION RESPONSE"); 466 break; 467 case 0x83: 468 (void) sprintf(get_line(0, 0), 469 "Type = NEGATIVE SESSION RESPONSE"); 470 break; 471 case 0x84: 472 (void) sprintf(get_line(0, 0), 473 "Type = RETARGET SESSION RESPONSE"); 474 break; 475 case 0x85: 476 (void) sprintf(get_line(0, 0), 477 "Type = SESSION KEEP ALIVE"); 478 break; 479 default: 480 (void) sprintf(get_line(0, 0), 481 "Type = Unknown"); 482 break; 483 } 484 485 (void) sprintf(get_line(0, 0), "Length = %d bytes", length); 486 show_trailer(); 487 } 488 489 /* 490 * SMB packets have { 0xff, 'S', 'M', 'B' } 491 * in the first four bytes. If we find that, 492 * let snoop_smb.c have a look at it. 493 */ 494 if (ss->type == 0x00 && 495 length > 0 && 496 trailer[0] == 0xff && 497 trailer[1] == 'S' && 498 trailer[2] == 'M' && 499 trailer[3] == 'B') 500 interpret_smb(flags, trailer, length); 501 } 502 503 /* 504 * NetBIOS name encoding (First Level Encoding) 505 * [RFC 1001, Sec. 4.1] 506 */ 507 static void 508 netbiosname2ascii(char *aname, uchar_t *nbname) 509 { 510 int c, i, j; 511 512 i = j = 0; 513 for (;;) { 514 c = nbname[i++] - 'A'; 515 c = (c << 4) + 516 nbname[i++] - 'A'; 517 /* 16th char is the "type" */ 518 if (i >= 32) 519 break; 520 if (iscntrl(c)) 521 c = '.'; 522 if (c != ' ') 523 aname[j++] = c; 524 } 525 sprintf(&aname[j], "[%x]", c); 526 } 527 528 /* 529 * Interpret the names in a Session Request packet. 530 * [RFC 1002, Sec. 4.3.2] 531 */ 532 static void 533 interpret_netbios_names(int flags, uchar_t *data, int len, char *xtra) 534 { 535 char calledname[24]; 536 char callingname[24]; 537 struct callnames *names = (struct callnames *)data; 538 539 if (len < sizeof (*names)) 540 return; 541 542 netbiosname2ascii(calledname, names->calledname); 543 netbiosname2ascii(callingname, names->callingname); 544 545 if (flags & F_SUM) { 546 sprintf(xtra, "Dest=%s Source=%s ", calledname, callingname); 547 } 548 549 if (flags & F_DTAIL) { 550 sprintf(get_line(0, 0), "Destination = %s", calledname); 551 sprintf(get_line(0, 0), "Source = %s", callingname); 552 } 553 } 554