From 250be50b729438a57f6ca0e1358ae4eaf8bf04f0 Mon Sep 17 00:00:00 2001 From: Brian Somers Date: Mon, 17 Jun 2002 01:12:38 +0000 Subject: Compensate for dodgy Win98/WinME MSCHAPv2 responses later in the code path... after we've talked to any RADIUS servers involved, so that we haven't touched the data before it gets to the server. Make it clearer in the code that this compensation is done by setting a flag to a value of zero, a flag which rfc2759 says *MUST* be zero. While we're here, don't bother passing the peer challenge into radius_Authenticate(). It's already part of the key we're passing in (this becomes obvious now that I've structured that data...). This ``fix'' doesn't help to authenticate Win98/WinME users in my test environment as ports/net/freeradius seems to ignore the flag completely anyway, but it may help with other RADIUS servers. --- usr.sbin/ppp/chap.c | 32 +++++++++++++++++--------------- usr.sbin/ppp/chap.h | 7 +++++++ usr.sbin/ppp/pap.c | 2 +- usr.sbin/ppp/radius.c | 20 ++++++++------------ usr.sbin/ppp/radius.h | 2 +- 5 files changed, 34 insertions(+), 29 deletions(-) diff --git a/usr.sbin/ppp/chap.c b/usr.sbin/ppp/chap.c index 33c84934146c..20ad52805215 100644 --- a/usr.sbin/ppp/chap.c +++ b/usr.sbin/ppp/chap.c @@ -761,19 +761,13 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) m_freem(bp); return NULL; } - if ((ans = malloc(alen + 2)) == NULL) { + if ((ans = malloc(alen + 1)) == NULL) { log_Printf(LogERROR, "Chap Input: Out of memory !\n"); m_freem(bp); return NULL; } *ans = chap->auth.id; bp = mbuf_Read(bp, ans + 1, alen); - if (p->link.lcp.want_authtype == 0x81 && ans[alen] != '\0') { - log_Printf(LogWARN, "%s: Compensating for corrupt (Win98/WinME?) " - "CHAP81 RESPONSE\n", l->name); - ans[alen] = '\0'; - } - ans[alen+1] = '\0'; bp = auth_ReadName(&chap->auth, bp, len); #ifndef NODES lanman = p->link.lcp.want_authtype == 0x80 && @@ -847,8 +841,11 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) nlen = strlen(name); #ifndef NODES if (p->link.lcp.want_authtype == 0x81) { - chap->challenge.peer[0] = CHAP81_CHALLENGE_LEN; - memcpy(chap->challenge.peer + 1, ans + 1, CHAP81_CHALLENGE_LEN); + struct MSCHAPv2_resp *resp = (struct MSCHAPv2_resp *)(ans + 1); + + chap->challenge.peer[0] = sizeof resp->PeerChallenge; + memcpy(chap->challenge.peer + 1, resp->PeerChallenge, + sizeof resp->PeerChallenge); } #endif @@ -857,16 +854,21 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) if (!radius_Authenticate(&bundle->radius, &chap->auth, chap->auth.in.name, ans, alen + 1, chap->challenge.local + 1, - *chap->challenge.local, - chap->challenge.peer + 1, - *chap->challenge.peer)) + *chap->challenge.local)) chap_Failure(&chap->auth); } else #endif { + if (p->link.lcp.want_authtype == 0x81 && ans[alen] != '\0' && + alen == sizeof(struct MSCHAPv2_resp)) { + struct MSCHAPv2_resp *resp = (struct MSCHAPv2_resp *)(ans + 1); + + log_Printf(LogWARN, "%s: Compensating for corrupt (Win98/WinME?) " + "CHAP81 RESPONSE\n", l->name); + resp->Flags = '\0'; /* rfc2759 says it *MUST* be zero */ + } key = auth_GetSecret(bundle, name, nlen, p); if (key) { - char *myans; #ifndef NODES if (p->link.lcp.want_authtype == 0x80 && lanman && !IsEnabled(p->link.lcp.cfg.chap80lm)) { @@ -887,8 +889,8 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) } else #endif { - myans = chap_BuildAnswer(name, key, chap->auth.id, - chap->challenge.local, + char *myans = chap_BuildAnswer(name, key, chap->auth.id, + chap->challenge.local, p->link.lcp.want_authtype #ifndef NODES , chap->challenge.peer, diff --git a/usr.sbin/ppp/chap.h b/usr.sbin/ppp/chap.h index 33a5b99097c9..617555d82d44 100644 --- a/usr.sbin/ppp/chap.h +++ b/usr.sbin/ppp/chap.h @@ -63,6 +63,13 @@ struct chap { #define auth2chap(a) \ ((struct chap *)((char *)a - (int)&((struct chap *)0)->auth)) +struct MSCHAPv2_resp { /* rfc2759 */ + char PeerChallenge[16]; + char Reserved[8]; + char NTResponse[24]; + char Flags; +}; + extern void chap_Init(struct chap *, struct physical *); extern void chap_ReInit(struct chap *); extern struct mbuf *chap_Input(struct bundle *, struct link *, struct mbuf *); diff --git a/usr.sbin/ppp/pap.c b/usr.sbin/ppp/pap.c index c604831fbe46..8a1d112d72de 100644 --- a/usr.sbin/ppp/pap.c +++ b/usr.sbin/ppp/pap.c @@ -266,7 +266,7 @@ pap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) #ifndef NORADIUS if (*bundle->radius.cfg.file) { if (!radius_Authenticate(&bundle->radius, authp, authp->in.name, - key, strlen(key), NULL, 0, NULL, 0)) + key, strlen(key), NULL, 0)) pap_Failure(authp); } else #endif diff --git a/usr.sbin/ppp/radius.c b/usr.sbin/ppp/radius.c index 99abb2a53b03..be6953a403d5 100644 --- a/usr.sbin/ppp/radius.c +++ b/usr.sbin/ppp/radius.c @@ -700,7 +700,7 @@ radius_put_physical_details(struct rad_handle *rad, struct physical *p) int radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name, const char *key, int klen, const char *nchallenge, - int nclen, const char *pchallenge, int pclen) + int nclen) { struct timeval tv; int got; @@ -712,6 +712,7 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name, #ifndef NODES struct mschap_response msresp; struct mschap2_response msresp2; + const struct MSCHAPv2_resp *keyv2; #endif if (!*r->cfg.file) @@ -794,26 +795,21 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name, break; case 0x81: - if (klen != 50) { + if (klen != sizeof(*keyv2) + 1) { log_Printf(LogERROR, "CHAP81: Unrecognised key length %d\n", klen); rad_close(r->cx.rad); return 0; } - if (pclen != sizeof msresp2.pchallenge) { - log_Printf(LogERROR, "CHAP81: Unrecognised peer challenge length %d\n", - pclen); - rad_close(r->cx.rad); - return 0; - } - + keyv2 = (const struct MSCHAPv2_resp *)(key + 1); rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen); msresp2.ident = *key; - msresp2.flags = 0x00; - memcpy(msresp2.response, key + 25, 24); + msresp2.flags = keyv2->Flags; + memcpy(msresp2.response, keyv2->NTResponse, sizeof msresp2.response); memset(msresp2.reserved, '\0', sizeof msresp2.reserved); - memcpy(msresp2.pchallenge, pchallenge, pclen); + memcpy(msresp2.pchallenge, keyv2->PeerChallenge, + sizeof msresp2.pchallenge); rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT, RAD_MICROSOFT_MS_CHAP2_RESPONSE, &msresp2, sizeof msresp2); diff --git a/usr.sbin/ppp/radius.h b/usr.sbin/ppp/radius.h index f7d6fae9f2bf..5e9586dc3d1a 100644 --- a/usr.sbin/ppp/radius.h +++ b/usr.sbin/ppp/radius.h @@ -85,7 +85,7 @@ extern void radius_Destroy(struct radius *); extern void radius_Show(struct radius *, struct prompt *); extern int radius_Authenticate(struct radius *, struct authinfo *, const char *, const char *, int, - const char *, int, const char *, int); + const char *, int); extern void radius_Account(struct radius *, struct radacct *, struct datalink *, int, struct in_addr *, struct in_addr *, struct pppThroughput *); -- cgit v1.3