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