auth.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * Beware the LM hash is easy to crack (google for l0phtCrack)
  11. * and though NTLM is more secure it is still breakable.
  12. * Ntlmv2 is better and seen as good enough by the windows community.
  13. * For real security use kerberos.
  14. */
  15. #include <u.h>
  16. #include <libc.h>
  17. #include <mp.h>
  18. #include <auth.h>
  19. #include <libsec.h>
  20. #include <ctype.h>
  21. #include <fcall.h>
  22. #include <thread.h>
  23. #include <9p.h>
  24. #include "cifs.h"
  25. #define DEF_AUTH "ntlmv2"
  26. enum {
  27. MACkeylen = 40, /* MAC key len */
  28. MAClen = 8, /* signature length */
  29. MACoff = 14, /* sign. offset from start of SMB (not netbios) pkt */
  30. Bliplen = 8, /* size of LMv2 client nonce */
  31. };
  32. static Auth *
  33. auth_plain(char *windom, char *keyp, uint8_t *chal, int len)
  34. {
  35. UserPasswd *up;
  36. static Auth *ap;
  37. USED(chal); USED(len);
  38. up = auth_getuserpasswd(auth_getkey, "windom=%s proto=pass service=cifs %s",
  39. windom, keyp);
  40. if(! up)
  41. sysfatal("cannot get key - %r");
  42. ap = emalloc9p(sizeof(Auth));
  43. memset(&ap->mackey, 0, sizeof(ap->mackey));
  44. ap->user = estrdup9p(up->user);
  45. ap->windom = estrdup9p(windom);
  46. ap->resp[0] = estrdup9p(up->passwd);
  47. ap->len[0] = strlen(up->passwd);
  48. memset(up->passwd, 0, strlen(up->passwd));
  49. free(up);
  50. return ap;
  51. }
  52. static Auth *
  53. auth_lm_and_ntlm(char *windom, char *keyp, uint8_t *chal, int len)
  54. {
  55. int err;
  56. char user[64];
  57. Auth *ap;
  58. MSchapreply mcr;
  59. err = auth_respond(chal, len, user, sizeof user, &mcr, sizeof mcr,
  60. auth_getkey, "windom=%s proto=mschap role=client service=cifs %s",
  61. windom, keyp);
  62. if(err == -1)
  63. sysfatal("cannot get key - %r");
  64. ap = emalloc9p(sizeof(Auth));
  65. memset(&ap->mackey, 0, sizeof(ap->mackey));
  66. ap->user = estrdup9p(user);
  67. ap->windom = estrdup9p(windom);
  68. /* LM response */
  69. ap->len[0] = sizeof(mcr.LMresp);
  70. ap->resp[0] = emalloc9p(ap->len[0]);
  71. memcpy(ap->resp[0], mcr.LMresp, ap->len[0]);
  72. /* NTLM response */
  73. ap->len[1] = sizeof(mcr.NTresp);
  74. ap->resp[1] = emalloc9p(ap->len[1]);
  75. memcpy(ap->resp[1], mcr.NTresp, ap->len[1]);
  76. return ap;
  77. }
  78. /*
  79. * NTLM response only, the LM response is a just
  80. * copy of the NTLM one. we do this because the lm
  81. * response is easily reversed - Google for l0pht
  82. * for more info.
  83. */
  84. static Auth *
  85. auth_ntlm(char *windom, char *keyp, uint8_t *chal, int len)
  86. {
  87. Auth *ap;
  88. if((ap = auth_lm_and_ntlm(windom, keyp, chal, len)) == nil)
  89. return nil;
  90. free(ap->resp[0]);
  91. ap->len[0] = ap->len[1];
  92. ap->resp[0] = emalloc9p(ap->len[0]);
  93. memcpy(ap->resp[0], ap->resp[1], ap->len[0]);
  94. return ap;
  95. }
  96. /*
  97. * This is not really nescessary as all fields hmac_md5'ed
  98. * in the ntlmv2 protocol are less than 64 bytes long, however
  99. * I still do this for completeness
  100. */
  101. static DigestState *
  102. hmac_t64(uint8_t *data, uint32_t dlen, uint8_t *key, uint32_t klen,
  103. uint8_t *digest,
  104. DigestState *state)
  105. {
  106. if(klen > 64)
  107. klen = 64;
  108. return hmac_md5(data, dlen, key, klen, digest, state);
  109. }
  110. static int
  111. ntv2_blob(uint8_t *blob, int len, char *windom)
  112. {
  113. int n;
  114. uint64_t nttime;
  115. Rune r;
  116. char *d;
  117. uint8_t *p;
  118. enum { /* name types */
  119. Beof, /* end of name list */
  120. Bnetbios, /* Netbios machine name */
  121. Bdomain, /* Windows Domain name (NT) */
  122. Bdnsfqdn, /* DNS Fully Qualified Domain Name */
  123. Bdnsname, /* DNS machine name (win2k) */
  124. };
  125. p = blob;
  126. *p++ = 1; /* response type */
  127. *p++ = 1; /* max response type understood by client */
  128. *p++ = 0;
  129. *p++ = 0; /* 2 bytes reserved */
  130. *p++ = 0;
  131. *p++ = 0;
  132. *p++ = 0;
  133. *p++ = 0; /* 4 bytes unknown */
  134. nttime = time(nil); /* nt time now */
  135. nttime += 11644473600LL;
  136. nttime *= 10000000LL;
  137. *p++ = nttime;
  138. *p++ = nttime >> 8;
  139. *p++ = nttime >> 16;
  140. *p++ = nttime >> 24;
  141. *p++ = nttime >> 32;
  142. *p++ = nttime >> 40;
  143. *p++ = nttime >> 48;
  144. *p++ = nttime >> 56;
  145. genrandom(p, 8);
  146. p += 8; /* client nonce */
  147. *p++ = 0x6f;
  148. *p++ = 0;
  149. *p++ = 0x6e;
  150. *p++ = 0; /* unknown data */
  151. *p++ = Bdomain;
  152. *p++ = 0; /* name type */
  153. n = utflen(windom) * 2;
  154. *p++ = n;
  155. *p++ = n >> 8; /* name length */
  156. d = windom;
  157. while(*d && p-blob < (len-8)){
  158. d += chartorune(&r, d);
  159. r = toupperrune(r);
  160. *p++ = r;
  161. *p++ = r >> 8;
  162. }
  163. *p++ = 0;
  164. *p++ = Beof; /* name type */
  165. *p++ = 0;
  166. *p++ = 0; /* name length */
  167. *p++ = 0x65;
  168. *p++ = 0;
  169. *p++ = 0;
  170. *p++ = 0; /* unknown data */
  171. return p - blob;
  172. }
  173. static Auth *
  174. auth_ntlmv2(char *windom, char *keyp, uint8_t *chal, int len)
  175. {
  176. int i, n;
  177. Rune r;
  178. char *p, *u;
  179. uint8_t v1hash[MD5dlen], blip[Bliplen], blob[1024], v2hash[MD5dlen];
  180. uint8_t c, lm_hmac[MD5dlen], nt_hmac[MD5dlen], nt_sesskey[MD5dlen],
  181. lm_sesskey[MD5dlen];
  182. DigestState *ds;
  183. UserPasswd *up;
  184. static Auth *ap;
  185. up = auth_getuserpasswd(auth_getkey, "windom=%s proto=pass service=cifs-ntlmv2 %s",
  186. windom, keyp);
  187. if(!up)
  188. sysfatal("cannot get key - %r");
  189. ap = emalloc9p(sizeof(Auth));
  190. memset(&ap->mackey, 0, sizeof(ap->mackey));
  191. /* Standard says unlimited length, experience says 128 max */
  192. if((n = strlen(up->passwd)) > 128)
  193. n = 128;
  194. ds = md4(nil, 0, nil, nil);
  195. for(i=0, p=up->passwd; i < n; i++) {
  196. p += chartorune(&r, p);
  197. c = r;
  198. md4(&c, 1, nil, ds);
  199. c = r >> 8;
  200. md4(&c, 1, nil, ds);
  201. }
  202. md4(nil, 0, v1hash, ds);
  203. /*
  204. * Some documentation insists that the username must be forced to
  205. * uppercase, but the domain name should not be. Other shows both
  206. * being forced to uppercase. I am pretty sure this is irrevevant as the
  207. * domain name passed from the remote server always seems to be in
  208. * uppercase already.
  209. */
  210. ds = hmac_t64(nil, 0, v1hash, MD5dlen, nil, nil);
  211. u = up->user;
  212. while(*u){
  213. u += chartorune(&r, u);
  214. r = toupperrune(r);
  215. c = r;
  216. hmac_t64(&c, 1, v1hash, MD5dlen, nil, ds);
  217. c = r >> 8;
  218. hmac_t64(&c, 1, v1hash, MD5dlen, nil, ds);
  219. }
  220. u = windom;
  221. while(*u){
  222. u += chartorune(&r, u);
  223. c = r;
  224. hmac_t64(&c, 1, v1hash, MD5dlen, nil, ds);
  225. c = r >> 8;
  226. hmac_t64(&c, 1, v1hash, MD5dlen, nil, ds);
  227. }
  228. hmac_t64(nil, 0, v1hash, MD5dlen, v2hash, ds);
  229. ap->user = estrdup9p(up->user);
  230. ap->windom = estrdup9p(windom);
  231. /* LM v2 */
  232. genrandom(blip, Bliplen);
  233. ds = hmac_t64(chal, len, v2hash, MD5dlen, nil, nil);
  234. hmac_t64(blip, Bliplen, v2hash, MD5dlen, lm_hmac, ds);
  235. ap->len[0] = MD5dlen+Bliplen;
  236. ap->resp[0] = emalloc9p(ap->len[0]);
  237. memcpy(ap->resp[0], lm_hmac, MD5dlen);
  238. memcpy(ap->resp[0]+MD5dlen, blip, Bliplen);
  239. /* LM v2 session key */
  240. hmac_t64(lm_hmac, MD5dlen, v2hash, MD5dlen, lm_sesskey, nil);
  241. /* LM v2 MAC key */
  242. ap->mackey[0] = emalloc9p(MACkeylen);
  243. memcpy(ap->mackey[0], lm_sesskey, MD5dlen);
  244. memcpy(ap->mackey[0]+MD5dlen, ap->resp[0], MACkeylen-MD5dlen);
  245. /* NTLM v2 */
  246. n = ntv2_blob(blob, sizeof(blob), windom);
  247. ds = hmac_t64(chal, len, v2hash, MD5dlen, nil, nil);
  248. hmac_t64(blob, n, v2hash, MD5dlen, nt_hmac, ds);
  249. ap->len[1] = MD5dlen+n;
  250. ap->resp[1] = emalloc9p(ap->len[1]);
  251. memcpy(ap->resp[1], nt_hmac, MD5dlen);
  252. memcpy(ap->resp[1]+MD5dlen, blob, n);
  253. /*
  254. * v2hash definitely OK by
  255. * the time we get here.
  256. */
  257. /* NTLM v2 session key */
  258. hmac_t64(nt_hmac, MD5dlen, v2hash, MD5dlen, nt_sesskey, nil);
  259. /* NTLM v2 MAC key */
  260. ap->mackey[1] = emalloc9p(MACkeylen);
  261. memcpy(ap->mackey[1], nt_sesskey, MD5dlen);
  262. memcpy(ap->mackey[1]+MD5dlen, ap->resp[1], MACkeylen-MD5dlen);
  263. free(up);
  264. return ap;
  265. }
  266. struct {
  267. char *name;
  268. Auth *(*func)(char *, char *, uint8_t *, int);
  269. } methods[] = {
  270. { "plain", auth_plain },
  271. { "lm+ntlm", auth_lm_and_ntlm },
  272. { "ntlm", auth_ntlm },
  273. { "ntlmv2", auth_ntlmv2 },
  274. // { "kerberos", auth_kerberos },
  275. };
  276. void
  277. autherr(void)
  278. {
  279. int i;
  280. fprint(2, "supported auth methods:\t");
  281. for(i = 0; i < nelem(methods); i++)
  282. fprint(2, "%s ", methods[i].name);
  283. fprint(2, "\n");
  284. exits("usage");
  285. }
  286. Auth *
  287. getauth(char *name, char *windom, char *keyp, int secmode,
  288. uint8_t *chal,
  289. int len)
  290. {
  291. int i;
  292. Auth *ap;
  293. if(name == nil){
  294. name = DEF_AUTH;
  295. if((secmode & SECMODE_PW_ENCRYPT) == 0)
  296. sysfatal("plaintext authentication required, use '-a plain'");
  297. }
  298. ap = nil;
  299. for(i = 0; i < nelem(methods); i++)
  300. if(strcmp(methods[i].name, name) == 0){
  301. ap = methods[i].func(windom, keyp, chal, len);
  302. break;
  303. }
  304. if(! ap){
  305. fprint(2, "%s: %s - unknown auth method\n", argv0, name);
  306. autherr(); /* never returns */
  307. }
  308. return ap;
  309. }
  310. static int
  311. genmac(uint8_t *buf, int len, int seq, uint8_t key[MACkeylen],
  312. uint8_t ours[MAClen])
  313. {
  314. DigestState *ds;
  315. uint8_t *sig, digest[MD5dlen], theirs[MAClen];
  316. sig = buf+MACoff;
  317. memcpy(theirs, sig, MAClen);
  318. memset(sig, 0, MAClen);
  319. sig[0] = seq;
  320. sig[1] = seq >> 8;
  321. sig[2] = seq >> 16;
  322. sig[3] = seq >> 24;
  323. ds = md5(key, MACkeylen, nil, nil);
  324. md5(buf, len, digest, ds);
  325. memcpy(ours, digest, MAClen);
  326. return memcmp(theirs, ours, MAClen);
  327. }
  328. int
  329. macsign(Pkt *p, int seq)
  330. {
  331. int rc, len;
  332. uint8_t *sig, *buf, mac[MAClen];
  333. sig = p->buf + NBHDRLEN + MACoff;
  334. buf = p->buf + NBHDRLEN;
  335. len = (p->pos - p->buf) - NBHDRLEN;
  336. #ifdef DEBUG_MAC
  337. if(seq & 1)
  338. dmp("rx", seq, sig, MAClen);
  339. #endif
  340. rc = 0;
  341. if(! p->s->seqrun)
  342. memcpy(mac, "BSRSPYL ", 8); /* no idea, ask MS */
  343. else
  344. rc = genmac(buf, len, seq, p->s->auth->mackey[0], mac);
  345. #ifdef DEBUG_MAC
  346. if(!(seq & 1))
  347. dmp("tx", seq, mac, MAClen);
  348. #endif
  349. memcpy(sig, mac, MAClen);
  350. return rc;
  351. }