shithub: riscv

Download patch

ref: fd1e50d653c32a85086f6bd14f7e261c2683224c
parent: 9840c50a3e0d2392a9102484e0caf970d3153790
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jan 21 17:32:34 EST 2018

authsrv: implement mschapv2 authentication, include MPPE secret in the ticket

this adds new rpc for mschapv2 authentication (21)

deliver the MPPE secret not after the ticket/authenticator
response as cheartext, but include it in the first 128 bit
of the ticket key. and the authenticator in the first 160 bit
of the authenticator random field.

--- a/sys/include/authsrv.h
+++ b/sys/include/authsrv.h
@@ -61,6 +61,7 @@
 	AuthHttp=13,	/* http domain login */
 	AuthVNC=14,	/* VNC server login (deprecated) */
 	AuthPAK=19,	/* authenticated diffie hellman key agreement */
+	AuthMSchapv2=21,/* MS chap v2 authentication for ppp */
 	AuthTs=64,	/* ticket encrypted with server's key */
 	AuthTc,		/* ticket encrypted with client's key */
 	AuthAs,		/* server generated authenticator */
--- a/sys/src/cmd/auth/authsrv.c
+++ b/sys/src/cmd/auth/authsrv.c
@@ -27,6 +27,7 @@
 	MShashlen = 16,
 	MSchallen = 8,
 	MSresplen = 24,
+	MSchallenv2 = 16,
 };
 
 void	pak(Ticketreq*);
@@ -35,7 +36,7 @@
 void	changepasswd(Ticketreq*);
 void	apop(Ticketreq*, int);
 void	chap(Ticketreq*);
-void	mschap(Ticketreq*);
+void	mschap(Ticketreq*, int);
 void	vnc(Ticketreq*);
 int	speaksfor(char*, char*);
 void	replyerror(char*, ...);
@@ -49,6 +50,7 @@
 void	mschalresp(uchar resp[MSresplen], uchar hash[MShashlen], uchar chal[MSchallen]);
 void	desencrypt(uchar data[8], uchar key[7]);
 void	tickauthreply(Ticketreq*, Authkey*);
+void	tickauthreply2(Ticketreq*, Authkey*, uchar *, int, uchar *, int);
 void	safecpy(char*, char*, int);
 
 void
@@ -98,8 +100,11 @@
 			chap(&tr);
 			break;
 		case AuthMSchap:
-			mschap(&tr);
+			mschap(&tr, MSchallen);
 			break;
+		case AuthMSchapv2:
+			mschap(&tr, MSchallenv2);
+			break;
 		case AuthCram:
 			apop(&tr, AuthCram);
 			break;
@@ -674,24 +679,23 @@
 static uchar ntblobsig[] = {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
 void
-mschap(Ticketreq *tr)
+mschap(Ticketreq *tr, int nchal)
 {
 	char *secret;
 	char sbuf[SECRETLEN], windom[128];
-	uchar chal[CHALLEN], ntblob[1024];
+	uchar chal[16], ntblob[1024];
 	uchar hash[MShashlen];
-	uchar hash2[MShashlen];
 	uchar resp[MSresplen];
 	OMSchapreply reply;
 	int dupe, lmok, ntok, ntbloblen;
+	uchar phash[SHA1dlen], chash[SHA1dlen], ahash[SHA1dlen];
 	DigestState *s;
-	uchar digest[SHA1dlen];
 
 	/*
 	 *  Create a challenge and send it.
 	 */
 	genrandom(chal, sizeof(chal));
-	if(write(1, chal, sizeof(chal)) != sizeof(chal))
+	if(write(1, chal, nchal) != nchal)
 		exits(0);
 
 	/*
@@ -704,7 +708,7 @@
 	 * CIFS/NTLMv2 uses variable length NT response.
 	 */
 	ntbloblen = 0;
-	if(memcmp(reply.NTresp+16, ntblobsig, sizeof(ntblobsig)) == 0){
+	if(nchal == MSchallen && memcmp(reply.NTresp+16, ntblobsig, sizeof(ntblobsig)) == 0){
 		/* Version[1], HiVision[1], Z[6] */
 		ntbloblen += 1+1+6;
 		memmove(ntblob, reply.NTresp+16, ntbloblen);
@@ -784,13 +788,24 @@
 			windom[0] = '\0';	/* try NIL domain */
 		}
 		dupe = 0;
+	} else if(nchal == MSchallenv2){
+		s = sha1((uchar*)reply.LMresp, MSchallenv2, nil, nil);
+		s = sha1(chal, MSchallenv2, nil, s);
+		sha1((uchar*)tr->uid, strlen(tr->uid), chash, s);
+
+		nthash(hash, secret);
+		mschalresp(resp, hash, chash);
+		ntok = lmok = tsmemcmp(resp, reply.NTresp, MSresplen) == 0;
+		dupe = 0;
 	} else {
 		lmhash(hash, secret);
 		mschalresp(resp, hash, chal);
 		lmok = tsmemcmp(resp, reply.LMresp, MSresplen) == 0;
+
 		nthash(hash, secret);
 		mschalresp(resp, hash, chal);
 		ntok = tsmemcmp(resp, reply.NTresp, MSresplen) == 0;
+
 		dupe = tsmemcmp(reply.LMresp, reply.NTresp, MSresplen) == 0;
 	}
 
@@ -815,21 +830,37 @@
 
 	succeed(tr->uid);
 
+	nthash(hash, secret);
+	md4(hash, 16, hash, nil);
+
 	/*
 	 *  reply with ticket & authenticator
 	 */
-	tickauthreply(tr, &hkey);
+	if(nchal == MSchallenv2){
+		s = sha1(hash, 16, nil, nil);
+		sha1((uchar*)reply.NTresp, MSresplen, nil, s);
+		sha1((uchar*)"This is the MPPE Master Key", 27, phash, s);
 
-	syslog(0, AUTHLOG, "mschap-ok %s/%s(%s)", tr->uid, tr->hostid, raddr);
+		s = sha1(hash, 16, nil, nil);
+		sha1((uchar*)reply.NTresp, MSresplen, nil, s);
+		sha1((uchar*)"Magic server to client signing constant", 39, ahash, s);
 
-	nthash(hash, secret);
-	md4(hash, 16, hash2, 0);
-	s = sha1(hash2, 16, 0, 0);
-	sha1(hash2, 16, 0, s);
-	sha1(chal, 8, digest, s);
+		s = sha1(ahash, 20, nil, nil);
+		sha1(chash, 8, nil, s);
+		sha1((uchar*)"Pad to make it do more than one iteration", 41, ahash, s);
 
-	if(write(1, digest, 16) != 16)
-		exits(0);
+		tickauthreply2(tr, &hkey, phash, 16, ahash, 20);
+	} else {
+		s = sha1(hash, 16, nil, nil);
+		sha1(hash, 16, nil, s);
+		sha1(chal, 8, phash, s);
+
+		tickauthreply2(tr, &hkey, phash, 16, nil, 0);
+	}
+
+	syslog(0, AUTHLOG, "mschap-ok %s/%s(%s)", tr->uid, tr->hostid, raddr);
+
+	exits(0);
 }
 
 void
@@ -1059,9 +1090,22 @@
 /*
  *  reply with ticket and authenticator
  */
+/*
+ *  reply with ticket and authenticator
+ */
 void
 tickauthreply(Ticketreq *tr, Authkey *key)
 {
+	tickauthreply2(tr, key, nil, 0, nil, 0);
+}
+
+/*
+ *  reply with ticket and authenticator with
+ *  secret s[ns] and authenticator data a[na].
+ */
+void
+tickauthreply2(Ticketreq *tr, Authkey *key, uchar *ps, int ns, uchar *pa, int na)
+{
 	Ticket t;
 	Authenticator a;
 	char buf[MAXTICKETLEN+MAXAUTHENTLEN+1];
@@ -1068,6 +1112,10 @@
 	int n;
 
 	mkticket(tr, &t);
+	if(t.form != 0 && ns > 0){
+		assert(ns <= NONCELEN);
+		memmove(t.key, ps, ns);
+	}
 	t.num = AuthTs;
 	n = 0;
 	buf[n++] = AuthOK;
@@ -1075,11 +1123,16 @@
 	memset(&a, 0, sizeof(a));
 	memmove(a.chal, t.chal, CHALLEN);
 	genrandom(a.rand, NONCELEN);
+	if(t.form != 0 && na > 0){
+		assert(na <= NONCELEN);
+		memmove(a.rand, pa, na);
+	}
 	a.num = AuthAc;
 	n += convA2M(&a, buf+n, sizeof(buf)-n, &t);
 	if(write(1, buf, n) != n)
 		exits(0);
 }
+
 
 void
 safecpy(char *to, char *from, int len)