diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-01-21 22:55:14 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-01-21 22:55:14 +0100 |
commit | 98b1f2a75b99f1af3c7c7cecf3735bab1793e2a2 (patch) | |
tree | 92f82fdac7c9f8643cb26453a92d2e9c54aae80b /sys | |
parent | 3004f058f69a16f09c07c58d0e60a1732190f0d3 (diff) |
ppp: mschapv2 support
Diffstat (limited to 'sys')
-rw-r--r-- | sys/src/cmd/ip/ppp/mppc.c | 38 | ||||
-rw-r--r-- | sys/src/cmd/ip/ppp/ppp.c | 273 | ||||
-rw-r--r-- | sys/src/cmd/ip/ppp/ppp.h | 10 |
3 files changed, 144 insertions, 177 deletions
diff --git a/sys/src/cmd/ip/ppp/mppc.c b/sys/src/cmd/ip/ppp/mppc.c index 52560f996..28e7f84b5 100644 --- a/sys/src/cmd/ip/ppp/mppc.c +++ b/sys/src/cmd/ip/ppp/mppc.c @@ -120,7 +120,7 @@ static void uncresetack(void*, Block*); static int ipcheck(uchar*, int); static void hischeck(Uncstate*); -static void setkey(uchar *key, uchar *startkey); +static void setkey(uchar *key, uchar *startkey); Comptype cmppc = { compinit, @@ -155,8 +155,8 @@ compinit(PPP *ppp) if(ppp->sendencrypted) { cs->encrypt = 1; - memmove(cs->startkey, ppp->key, 16); - memmove(cs->key, ppp->key, 16); + memmove(cs->startkey, ppp->sendkey, 16); + memmove(cs->key, cs->startkey, 16); setkey(cs->key, cs->startkey); setupRC4state(&cs->rc4key, cs->key, 16); } @@ -467,8 +467,8 @@ uncinit(PPP *ppp) s = mallocz(sizeof(Uncstate), 1); s->count = 0xfff; /* count of non existant last packet */ - memmove(s->startkey, ppp->key, 16); - memmove(s->key, ppp->key, 16); + memmove(s->startkey, ppp->recvkey, 16); + memmove(s->key, s->startkey, 16); setkey(s->key, s->startkey); setupRC4state(&s->rc4key, s->key, 16); @@ -577,12 +577,11 @@ netlog("******* bad count - got %ux expected %ux\n", count&0xfff, ecount); if(count & Pencrypt) { //netlog("mppc unencrypt count = %ux\n", count); rc4(&s->rc4key, p, n); +fprint(2, "plain=%.*H\n", n, p); } - if(!(count & Pcompress)) { -//netlog("uncompress blen = %d\n", BLEN(b)); - return b; - } + if(!(count & Pcompress)) + return b; bits = 0; sreg = 0; @@ -729,6 +728,27 @@ uncfini(void *as) free(s); } +void +getasymkey(uchar *key, uchar *masterkey, int send, int server) +{ + uchar digest[SHA1dlen]; + uchar pad[40]; + SHAstate *s; + char *m; + + s = sha1(masterkey, 16, nil, nil); + memset(pad, 0, 40); + sha1(pad, 40, nil, s); + if(send ^ server) + m = "On the client side, this is the send key; on the server side, it is the receive key."; + else + m = "On the client side, this is the receive key; on the server side, it is the send key."; + sha1((uchar*)m, 84, nil, s); + memset(pad, 0xf2, 40); + sha1(pad, 40, digest, s); + memmove(key, digest, 16); +} + static void setkey(uchar *key, uchar *startkey) { diff --git a/sys/src/cmd/ip/ppp/ppp.c b/sys/src/cmd/ip/ppp/ppp.c index 6e09c9c2d..45424ee5e 100644 --- a/sys/src/cmd/ip/ppp/ppp.c +++ b/sys/src/cmd/ip/ppp/ppp.c @@ -114,7 +114,6 @@ static void setphase(PPP*, int); static void terminate(PPP*, int); static int validv4(Ipaddr); static void dmppkt(char *s, uchar *a, int na); -static void getauth(PPP*); void pppopen(PPP *ppp, int mediain, int mediaout, char *net, @@ -191,7 +190,7 @@ init(PPP* ppp) ppp->chap = mallocz(sizeof(*ppp->chap), 1); if(ppp->chap == nil) abort(); - ppp->chap->proto = APmschap; + ppp->chap->proto = APmschapv2; ppp->chap->state = Cunauth; auth_freechal(ppp->chap->cs); ppp->chap->cs = nil; @@ -252,6 +251,7 @@ setphase(PPP *ppp, int phase) break; case APmd5: case APmschap: + case APmschapv2: break; default: setphase(ppp, Pnet); @@ -713,6 +713,7 @@ config(PPP *ppp, Pstate *p, int newid) syslog(0, "ppp", "requesting %I", ppp->local); putv4o(b, Oipaddr, ppp->local); } + primary = 1; if(primary && (p->optmask & Fipdns)) putv4o(b, Oipdns, ppp->dns[0]); if(primary && (p->optmask & Fipdns2)) @@ -852,15 +853,15 @@ getopts(PPP *ppp, Pstate *p, Block *b) } if(proto != Pchap) break; - if(o->data[2] != APmd5 && o->data[2] != APmschap) + if(o->data[2] != APmd5 + && o->data[2] != APmschap + && o->data[2] != APmschapv2) break; chapproto = o->data[2]; continue; } break; case Pccp: - if(nocompress) - break; switch(o->type){ case Octhwack: break; @@ -880,10 +881,6 @@ getopts(PPP *ppp, Pstate *p, Block *b) case Ocmppc: x = nhgetl(o->data); - // hack for Mac - // if(x == 0) - // continue; - /* stop ppp loops */ if((x&0x41) == 0 || ppp->ctries++ > 5) { /* @@ -895,7 +892,7 @@ getopts(PPP *ppp, Pstate *p, Block *b) } if(rejecting) continue; - if(x & 1) { + if((x & 0x01000001) == 1){ ctype = &cmppc; ppp->sendencrypted = (o->data[3]&0x40) == 0x40; continue; @@ -1965,6 +1962,20 @@ putlqm(PPP *ppp) ppp->out.reports++; } +static char* +getaproto(int proto) +{ + switch(proto){ + case APmd5: + return "chap"; + case APmschap: + return "mschap"; + case APmschapv2: + return "mschapv2"; + } + return nil; +} + /* * init challenge response dialog */ @@ -1975,24 +1986,14 @@ chapinit(PPP *ppp) Lcpmsg *m; Chap *c; int len; - char *aproto; - - getauth(ppp); c = ppp->chap; c->id++; - - switch(c->proto){ - default: - abort(); - case APmd5: - aproto = "chap"; - break; - case APmschap: - aproto = "mschap"; - break; + if(c->ai != nil){ + auth_freeAI(c->ai); + c->ai = nil; } - if((c->cs = auth_challenge("proto=%q role=server", aproto)) == nil) + if((c->cs = auth_challenge("proto=%q role=server", getaproto(c->proto))) == nil) sysfatal("auth_challenge: %r"); syslog(0, LOG, ": remote=%I: sending %d byte challenge", ppp->remote, c->cs->nchal); len = 4 + 1 + c->cs->nchal + strlen(ppp->chapname); @@ -2011,72 +2012,42 @@ chapinit(PPP *ppp) } /* - * BUG factotum should do this + * challenge response dialog */ -enum { - MShashlen = 16, - MSresplen = 24, - MSchallen = 8, -}; - -void -desencrypt(uchar data[8], uchar key[7]) -{ - ulong ekey[32]; - - key_setup(key, ekey); - block_cipher(ekey, data, 0); -} - -void -nthash(uchar hash[MShashlen], char *passwd) -{ - uchar buf[512]; - int i; - - for(i=0; *passwd && i<sizeof(buf); passwd++) { - buf[i++] = *passwd; - buf[i++] = 0; - } - memset(hash, 0, 16); - md4(buf, i, hash, 0); -} - -void -mschalresp(uchar resp[MSresplen], uchar hash[MShashlen], uchar chal[MSchallen]) +static void +setppekey(PPP *ppp, int isserver) { - int i; - uchar buf[21]; - - memset(buf, 0, sizeof(buf)); - memcpy(buf, hash, MShashlen); + Chap *c = ppp->chap; - for(i=0; i<3; i++) { - memmove(resp+i*MSchallen, chal, MSchallen); - desencrypt(resp+i*MSchallen, buf+i*7); + switch(c->proto){ + case APmschap: + if(c->ai == nil || c->ai->nsecret != 16) + sysfatal("could not get the encryption key"); + memmove(ppp->sendkey, c->ai->secret, 16); + memmove(ppp->recvkey, c->ai->secret, 16); + break; + case APmschapv2: + if(c->ai == nil || c->ai->nsecret != 16+20) + sysfatal("could not get the encryption key + authenticator"); + getasymkey(ppp->sendkey, c->ai->secret, 1, isserver); + getasymkey(ppp->recvkey, c->ai->secret, 0, isserver); + break; } + auth_freeAI(c->ai); + c->ai = nil; } -/* - * challenge response dialog - */ -extern int _asrdresp(int, uchar*, int); - static void getchap(PPP *ppp, Block *b) { - AuthInfo *ai; Lcpmsg *m; int len, vlen, i, id, n, nresp; - char md5buf[512], code; + char code; Chap *c; Chapreply cr; MSchapreply mscr; char uid[PATH]; - uchar digest[16], *p, *resp, sdigest[SHA1dlen]; - uchar mshash[MShashlen], mshash2[MShashlen]; - DigestState *s; - uchar msresp[2*MSresplen+1]; + uchar resp[256], *p; m = (Lcpmsg*)b->rptr; len = nhgets(m->len); @@ -2087,50 +2058,23 @@ getchap(PPP *ppp, Block *b) } qlock(ppp); - + c = ppp->chap; + vlen = m->data[0]; switch(m->code){ case Cchallenge: - getauth(ppp); - - vlen = m->data[0]; - if(vlen > len - 5) { - netlog("PPP: chap: bad challenge len\n"); - break; - } - id = m->id; - switch(ppp->chap->proto){ - default: - abort(); - case APmd5: - n = strlen(ppp->secret); - if(n + vlen + 1 > sizeof(md5buf)) { - netlog("PPP: chap: bad challenge len\n"); - goto end; - } - md5buf[0] = m->id; - memcpy(md5buf+1, ppp->secret, n); - memcpy(md5buf+1+n, m->data+1, vlen); - md5((uchar*)md5buf, n + vlen + 1, digest, nil); - resp = digest; - nresp = 16; - break; - case APmschap: - nthash(mshash, ppp->secret); - memset(msresp, 0, sizeof msresp); - mschalresp(msresp+MSresplen, mshash, m->data+1); - resp = msresp; - nresp = sizeof msresp; - nthash(mshash, ppp->secret); - md4(mshash, 16, mshash2, 0); - s = sha1(mshash2, 16, 0, 0); - sha1(mshash2, 16, 0, s); - sha1(m->data+1, 8, sdigest, s); - memmove(ppp->key, sdigest, 16); - break; - } - len = 4 + 1 + nresp + strlen(ppp->chapname); + memset(ppp->chapname, 0, sizeof(ppp->chapname)); + nresp = auth_respondAI(m->data+1, vlen, + ppp->chapname, sizeof(ppp->chapname), + resp, sizeof(resp), &c->ai, + auth_getkey, + "proto=%s role=client service=ppp %s", getaproto(c->proto), keyspec); + if(nresp < 0) + sysfatal("auth_respond: %r"); + if(c->proto == APmschap || c->proto == APmschapv2) + while(nresp < 49) resp[nresp++] = 0; freeb(b); + len = 4 + 1 + nresp + strlen(ppp->chapname); b = alloclcp(Cresponse, id, len, &m); *b->wptr++ = nresp; memmove(b->wptr, resp, nresp); @@ -2138,14 +2082,12 @@ getchap(PPP *ppp, Block *b) memmove(b->wptr, ppp->chapname, strlen(ppp->chapname)); b->wptr += strlen(ppp->chapname); hnputs(m->len, len); - netlog("PPP: sending response len %d\n", len); + netlog("ppp: sending response len %d\n", len); putframe(ppp, Pchap, b); break; case Cresponse: - c = ppp->chap; - vlen = m->data[0]; - if(m->id != c->id) { - netlog("PPP: chap: bad response id\n"); + if(m->id != c->id || c->cs == nil) { + netlog("ppp: chap: bad response id\n"); break; } switch(c->proto) { @@ -2153,10 +2095,9 @@ getchap(PPP *ppp, Block *b) sysfatal("unknown chap protocol: %d", c->proto); case APmd5: if(vlen > len - 5 || vlen != 16) { - netlog("PPP: chap: bad response len\n"); + netlog("ppp: chap: bad response len\n"); break; } - cr.id = m->id; memmove(cr.resp, m->data+1, 16); memset(uid, 0, sizeof(uid)); @@ -2169,8 +2110,9 @@ getchap(PPP *ppp, Block *b) c->cs->nresp = sizeof cr; break; case APmschap: - if(vlen > len - 5 || vlen != 49) { - netlog("PPP: chap: bad response len\n"); + case APmschapv2: + if(vlen > len - 5 || vlen < 48) { + netlog("ppp: chap: bad response len\n"); break; } memset(&mscr, 0, sizeof(mscr)); @@ -2196,42 +2138,53 @@ getchap(PPP *ppp, Block *b) break; } - syslog(0, LOG, ": remote=%I vlen %d proto %d response user %s nresp %d", ppp->remote, vlen, c->proto, c->cs->user, c->cs->nresp); - if((ai = auth_response(c->cs)) == nil || auth_chuid(ai, nil) < 0){ + syslog(0, LOG, ": remote=%I vlen %d proto %d response user %s nresp %d", + ppp->remote, vlen, c->proto, c->cs->user, c->cs->nresp); + + if((c->ai = auth_response(c->cs)) == nil || auth_chuid(c->ai, nil) < 0){ c->state = Cunauth; code = Cfailure; - syslog(0, LOG, ": remote=%I: auth failed: %r, uid=%s", ppp->remote, uid); + syslog(0, LOG, ": remote=%I: auth failed: %r, uid=%s", + ppp->remote, uid); }else{ c->state = Cauthok; code = Csuccess; - syslog(0, LOG, ": remote=%I: auth ok: uid=%s nsecret=%d", ppp->remote, uid, ai->nsecret); - if(c->proto == APmschap){ - if(ai->nsecret != sizeof(ppp->key)) - sysfatal("could not get the encryption key"); - memmove(ppp->key, ai->secret, sizeof(ppp->key)); - } + syslog(0, LOG, ": remote=%I: auth ok: uid=%s nsecret=%d", + ppp->remote, uid, c->ai->nsecret); } - auth_freeAI(ai); auth_freechal(c->cs); c->cs = nil; freeb(b); /* send reply */ - len = 4; - b = alloclcp(code, c->id, len, &m); - hnputs(m->len, len); + if(code == Csuccess && c->proto == APmschapv2 && c->ai->nsecret == 16+20){ + b = alloclcp(code, c->id, 4+2+2*20+1, &m); + b->wptr += sprint((char*)m->data, "S=%.20H", c->ai->secret+16); + } else { + b = alloclcp(code, c->id, 4, &m); + } + hnputs(m->len, BLEN(b)); putframe(ppp, Pchap, b); - if(c->state == Cauthok) { + if(c->state == Cauthok){ + setppekey(ppp, 1); setphase(ppp, Pnet); } else { /* restart chapp negotiation */ chapinit(ppp); } - break; case Csuccess: + if(c->proto == APmschapv2 && c->ai != nil && c->ai->nsecret == 16+20){ + n = snprint((char*)resp, sizeof(resp), "S=%.20H", c->ai->secret+16); + if(len - 4 < n || tsmemcmp(m->data, resp, n) != 0){ + netlog("ppp: chap: bad authenticator\n"); + terminate(ppp, 0); + break; + } + } netlog("ppp: chap succeeded\n"); + setppekey(ppp, 0); setphase(ppp, Pnet); break; case Cfailure: @@ -2242,7 +2195,6 @@ getchap(PPP *ppp, Block *b) syslog(0, LOG, "chap code %d?", m->code); break; } -end: qunlock(ppp); freeb(b); } @@ -2253,27 +2205,32 @@ putpaprequest(PPP *ppp) Block *b; Lcpmsg *m; Chap *c; + UserPasswd *up; int len, nlen, slen; - getauth(ppp); + up = auth_getuserpasswd(auth_getkey, "proto=pass service=ppp %s", keyspec); + if(up == nil) + sysfatal("auth_getuserpasswd: %r"); c = ppp->chap; c->id++; - netlog("PPP: pap: send authreq %d %s %s\n", c->id, ppp->chapname, "****"); + netlog("ppp: pap: send authreq %d %s %s\n", c->id, up->user, "****"); - nlen = strlen(ppp->chapname); - slen = strlen(ppp->secret); + nlen = strlen(up->user); + slen = strlen(up->passwd); len = 4 + 1 + nlen + 1 + slen; b = alloclcp(Pauthreq, c->id, len, &m); *b->wptr++ = nlen; - memmove(b->wptr, ppp->chapname, nlen); + memmove(b->wptr, up->user, nlen); b->wptr += nlen; *b->wptr++ = slen; - memmove(b->wptr, ppp->secret, slen); + memmove(b->wptr, up->passwd, slen); b->wptr += slen; hnputs(m->len, len); + free(up); + putframe(ppp, Ppasswd, b); freeb(b); } @@ -2304,13 +2261,13 @@ getpap(PPP *ppp, Block *b) qlock(ppp); switch(m->code){ case Pauthreq: - netlog("PPP: pap auth request, not supported\n"); + netlog("ppp: pap auth request, not supported\n"); break; case Pauthack: if(ppp->phase == Pauth && ppp->chap->proto == APpasswd && m->id <= ppp-> chap->id){ - netlog("PPP: pap succeeded\n"); + netlog("ppp: pap succeeded\n"); setphase(ppp, Pnet); } break; @@ -2318,13 +2275,13 @@ getpap(PPP *ppp, Block *b) if(ppp->phase == Pauth && ppp->chap->proto == APpasswd && m->id <= ppp-> chap->id){ - netlog("PPP: pap failed (%d:%.*s)\n", + netlog("ppp: pap failed (%d:%.*s)\n", m->data[0], m->data[0], (char*)m->data+1); terminate(ppp, 0); } break; default: - netlog("PPP: unknown pap messsage %d\n", m->code); + netlog("ppp: unknown pap messsage %d\n", m->code); } qunlock(ppp); freeb(b); @@ -2702,6 +2659,7 @@ main(int argc, char **argv) fmtinstall('I', eipfmt); fmtinstall('V', eipfmt); fmtinstall('E', eipfmt); + fmtinstall('H', encodefmt); dev = nil; @@ -2970,18 +2928,3 @@ putndb(PPP *ppp, char *net) close(fd); } } - -static void -getauth(PPP *ppp) -{ - UserPasswd *up; - - if(*ppp->chapname) - return; - - up = auth_getuserpasswd(auth_getkey,"proto=pass service=ppp %s", keyspec); - if(up != nil){ - strcpy(ppp->chapname, up->user); - strcpy(ppp->secret, up->passwd); - } -} diff --git a/sys/src/cmd/ip/ppp/ppp.h b/sys/src/cmd/ip/ppp/ppp.h index 56dd912d5..90ddd8002 100644 --- a/sys/src/cmd/ip/ppp/ppp.h +++ b/sys/src/cmd/ip/ppp/ppp.h @@ -113,6 +113,7 @@ enum { /* authentication protocols */ APmd5= 5, APmschap= 128, + APmschapv2= 129, APpasswd= Ppasswd, /* use Pap, not Chap */ /* lcp flags */ @@ -221,7 +222,8 @@ struct Chap int state; /* chap state */ uchar id; /* id of current message */ int timeout; /* for current state */ - Chalstate *cs; + AuthInfo *ai; + Chalstate *cs; }; struct Qualstats @@ -292,11 +294,11 @@ struct PPP void *uncstate; /* uncompression state */ /* encryption key */ - uchar key[16]; + uchar sendkey[16]; + uchar recvkey[16]; int sendencrypted; /* authentication */ - char secret[256]; /* md5 key */ char chapname[256]; /* chap system name */ /* link quality monitoring */ @@ -374,6 +376,8 @@ extern ushort ptclcsum(Block*, int, int); extern ushort ptclbsum(uchar*, int); extern ushort ipcsum(uchar*); +void getasymkey(uchar *key, uchar *masterkey, int send, int server); + extern Comptype cmppc; extern Uncomptype uncmppc; |