diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-01-21 22:32:34 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-01-21 22:32:34 +0100 |
commit | fd1e50d653c32a85086f6bd14f7e261c2683224c (patch) | |
tree | 8658c2e384a004d8e86ccc1ad62b9b5c508e4655 | |
parent | 9840c50a3e0d2392a9102484e0caf970d3153790 (diff) |
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.
-rw-r--r-- | sys/include/authsrv.h | 1 | ||||
-rw-r--r-- | sys/src/cmd/auth/authsrv.c | 87 |
2 files changed, 71 insertions, 17 deletions
diff --git a/sys/include/authsrv.h b/sys/include/authsrv.h index 4fabc3814..5c0b368e7 100644 --- a/sys/include/authsrv.h +++ b/sys/include/authsrv.h @@ -61,6 +61,7 @@ enum 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 */ diff --git a/sys/src/cmd/auth/authsrv.c b/sys/src/cmd/auth/authsrv.c index be2505d1d..5e9a7a02e 100644 --- a/sys/src/cmd/auth/authsrv.c +++ b/sys/src/cmd/auth/authsrv.c @@ -27,6 +27,7 @@ enum { MShashlen = 16, MSchallen = 8, MSresplen = 24, + MSchallenv2 = 16, }; void pak(Ticketreq*); @@ -35,7 +36,7 @@ void challengebox(Ticketreq*); 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 ntv2hash(uchar hash[MShashlen], char *passwd, char *user, char *dom); 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,7 +100,10 @@ main(int argc, char *argv[]) chap(&tr); break; case AuthMSchap: - mschap(&tr); + mschap(&tr, MSchallen); + break; + case AuthMSchapv2: + mschap(&tr, MSchallenv2); break; case AuthCram: apop(&tr, AuthCram); @@ -674,24 +679,23 @@ getname(int id, uchar *ntblob, int ntbloblen, char *buf, int nbuf) 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 @@ mschap(Ticketreq *tr) * 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 @@ mschap(Ticketreq *tr) 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 @@ mschap(Ticketreq *tr) 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,15 +1090,32 @@ mkticket(Ticketreq *tr, Ticket *t) /* * 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]; 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,12 +1123,17 @@ tickauthreply(Ticketreq *tr, Authkey *key) 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) { |