1 /*
2  * decode_smb.c
3  *
4  * Microsoft Server Message Block.
5  *
6  * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
7  *
8  * $Id: decode_smb.c,v 1.4 2001/03/15 08:33:02 dugsong Exp $
9  */
10 
11 #include "config.h"
12 
13 #include <sys/types.h>
14 #include <arpa/nameser.h>
15 
16 #include <stdio.h>
17 #include <string.h>
18 
19 #include "decode.h"
20 
21 struct smbhdr {
22 	u_char	proto[4];
23 	u_char	cmd;
24 	u_char	err[4];
25 	u_char	flags1;
26 	u_short	flags2;
27 	u_short	pad[6];
28 	u_short	tid, pid, uid, mid;
29 };
30 
31 int
decode_smb(u_char * buf,int len,u_char * obuf,int olen)32 decode_smb(u_char *buf, int len, u_char *obuf, int olen)
33 {
34 	struct smbhdr *smb;
35 	int i, j, k;
36 	u_char *p, *q, *end;
37 	char *user, *pass;
38 
39 	obuf[0] = '\0';
40 
41 	/* Skip NetBIOS session request. */
42 	if (len < 4 || buf[0] != 0x81) return (0);
43 	buf += 2;
44 	GETSHORT(i, buf); len -= 4;
45 	if (len < i) return (0);
46 	buf += i; len -= i;
47 	end = buf + len;
48 
49 	/* Parse SMBs. */
50 	for (p = buf; p < end; p += i) {
51 		GETLONG(i, p);
52 		if (i > end - p || i < sizeof(*smb) + 32)
53 			continue;
54 
55 		smb = (struct smbhdr *)p;
56 		if (memcmp(smb->proto, "\xffSMB", 4) != 0 || smb->cmd != 0x73)
57 			continue;
58 
59 		user = pass = NULL;
60 		q = (u_char *)(smb + 1);
61 
62 		if (*q == 10) {		/* Pre NT LM 0.12 */
63 			q += 15; j = pletohs(q); q += 2;
64 			if (j > i - (sizeof(*smb) + 15 + 6))
65 				continue;
66 			pass = q + 6;
67 			user = pass + j;
68 		}
69 		else if (*q == 13) {	/* NT LM 0.12 */
70 			q += 15; j = pletohs(q);
71 			q += 2;  k = pletohs(q);
72 			if (j > i - ((q - p) + 12) || k > i - ((q - p) + 11))
73 				continue;
74 			pass = q + 12;
75 			user = pass + j + k;
76 		}
77 		else continue;
78 
79 		/* XXX - skip null IPC sessions, etc. */
80 		if (user && pass && strlen(user) &&
81 		    is_ascii_string(pass, j - 1)) {
82 			strlcat(obuf, user, olen);
83 			strlcat(obuf, " ", olen);
84 			strlcat(obuf, pass, olen);
85 			strlcat(obuf, "\n", olen);
86 		}
87 	}
88 	return (strlen(obuf));
89 }
90 
91