2 * Beware the LM hash is easy to crack (google for l0phtCrack)
3 * and though NTLM is more secure it is still breakable.
4 * Ntlmv2 is better and seen as good enough by the windows community.
5 * For real security use kerberos.
18 #define DEF_AUTH "ntlmv2"
21 MACkeylen = 40, /* MAC key len */
22 MAClen = 8, /* signature length */
23 MACoff = 14, /* sign. offset from start of SMB (not netbios) pkt */
28 dmp(char *s, int seq, void *buf, int n)
33 print("%s %3d ", s, seq);
35 for(i = 0; i < 16 && n > 0; i++, n--)
36 print("%02x ", *p++ & 0xff);
45 auth_plain(char *windom, char *keyp, uchar *chal, int len)
52 up = auth_getuserpasswd(auth_getkey, "windom=%s proto=pass service=cifs %s",
55 sysfatal("cannot get key - %r");
57 ap = emalloc9p(sizeof(Auth));
58 memset(ap, 0, sizeof(ap));
59 ap->user = estrdup9p(up->user);
60 ap->windom = estrdup9p(windom);
62 ap->resp[0] = estrdup9p(up->passwd);
63 ap->len[0] = strlen(up->passwd);
64 memset(up->passwd, 0, strlen(up->passwd));
71 auth_proto(char *proto, char *windom, char *keyp, uchar *chal, int len)
79 mcr = (MSchapreply*)resp;
81 if(strcmp(proto, "mschap") == 0)
82 nresp = sizeof(*mcr); /* backwards compatibility with old factotum */
83 nresp = auth_respond(chal, len, user, sizeof user, resp, nresp,
84 auth_getkey, "proto=%s role=client service=cifs windom=%s %s",
87 sysfatal("cannot get response - %r");
88 if(nresp < sizeof(*mcr))
89 sysfatal("bad response size");
91 ap = emalloc9p(sizeof(Auth));
92 memset(ap, 0, sizeof(ap));
93 ap->user = estrdup9p(user);
94 ap->windom = estrdup9p(windom);
97 ap->len[0] = sizeof(mcr->LMresp);
98 ap->resp[0] = emalloc9p(ap->len[0]);
99 memcpy(ap->resp[0], mcr->LMresp, ap->len[0]);
102 ap->len[1] = nresp+sizeof(mcr->NTresp)-sizeof(*mcr);
103 ap->resp[1] = emalloc9p(ap->len[1]);
104 memcpy(ap->resp[1], mcr->NTresp, ap->len[1]);
110 auth_lm_and_ntlm(char *windom, char *keyp, uchar *chal, int len)
112 return auth_proto("mschap", windom, keyp, chal, len);
116 * NTLM response only, the LM response is a just
117 * copy of the NTLM one. we do this because the lm
118 * response is easily reversed - Google for l0pht
122 auth_ntlm(char *windom, char *keyp, uchar *chal, int len)
126 if((ap = auth_lm_and_ntlm(windom, keyp, chal, len)) == nil)
130 ap->len[0] = ap->len[1];
131 ap->resp[0] = emalloc9p(ap->len[0]);
132 memcpy(ap->resp[0], ap->resp[1], ap->len[0]);
137 auth_ntlmv2(char *windom, char *keyp, uchar *chal, int len)
139 return auth_proto("mschap2", windom, keyp, chal, len);
144 Auth *(*func)(char *, char *, uchar *, int);
146 { "plain", auth_plain },
147 { "lm+ntlm", auth_lm_and_ntlm },
148 { "ntlm", auth_ntlm },
149 { "ntlmv2", auth_ntlmv2 },
150 // { "kerberos", auth_kerberos },
158 fprint(2, "supported auth methods:\t");
159 for(i = 0; i < nelem(methods); i++)
160 fprint(2, "%s ", methods[i].name);
166 getauth(char *name, char *windom, char *keyp, int secmode, uchar *chal, int len)
173 if((secmode & SECMODE_PW_ENCRYPT) == 0)
174 sysfatal("plaintext authentication required, use '-a plain'");
178 for(i = 0; i < nelem(methods); i++)
179 if(strcmp(methods[i].name, name) == 0){
180 ap = methods[i].func(windom, keyp, chal, len);
185 fprint(2, "%s: %s - unknown auth method\n", argv0, name);
186 autherr(); /* never returns */
192 genmac(uchar *buf, int len, int seq, uchar key[MACkeylen], uchar ours[MAClen])
195 uchar *sig, digest[MD5dlen], theirs[MAClen];
198 memcpy(theirs, sig, MAClen);
200 memset(sig, 0, MAClen);
206 ds = md5(key, MACkeylen, nil, nil);
207 md5(buf, len, digest, ds);
208 memcpy(ours, digest, MAClen);
210 return memcmp(theirs, ours, MAClen);
214 macsign(Pkt *p, int seq)
217 uchar *sig, *buf, mac[MAClen];
219 sig = p->buf + NBHDRLEN + MACoff;
220 buf = p->buf + NBHDRLEN;
221 len = (p->pos - p->buf) - NBHDRLEN;
225 dmp("rx", seq, sig, MAClen);
229 memcpy(mac, "BSRSPYL ", 8); /* no idea, ask MS */
231 rc = genmac(buf, len, seq, p->s->auth->mackey[0], mac);
234 dmp("tx", seq, mac, MAClen);
236 memcpy(sig, mac, MAClen);