struct mbuf * chap_Input_old(struct bundle *bundle, struct link *l, struct mbuf *bp) { struct physical *p = link2physical(l); struct chap *chap = &p->dl->chap; char *name, *key, *ans; int len, nlen; u_char alen; #ifdef HAVE_DES int lanman; #endif if (p == NULL) { log_Printf(LogERROR, "chap_Input: Not a physical link - dropped\n"); m_freem(bp); return NULL; } if (bundle_Phase(bundle) != PHASE_NETWORK && bundle_Phase(bundle) != PHASE_AUTHENTICATE) { log_Printf(LogPHASE, "Unexpected chap input - dropped !\n"); m_freem(bp); return NULL; } m_settype(bp, MB_CHAPIN); if ((bp = auth_ReadHeader(&chap->auth, bp)) == NULL && ntohs(chap->auth.in.hdr.length) == 0) log_Printf(LogWARN, "Chap Input: Truncated header !\n"); else if (chap->auth.in.hdr.code == 0 || chap->auth.in.hdr.code > MAXCHAPCODE) log_Printf(LogPHASE, "Chap Input: %d: Bad CHAP code !\n", chap->auth.in.hdr.code); else { len = m_length(bp); ans = NULL; if (chap->auth.in.hdr.code != CHAP_CHALLENGE && chap->auth.id != chap->auth.in.hdr.id && Enabled(bundle, OPT_IDCHECK)) { /* Wrong conversation dude ! */ log_Printf(LogPHASE, "Chap Input: %s dropped (got id %d, not %d)\n", chapcodes[chap->auth.in.hdr.code], chap->auth.in.hdr.id, chap->auth.id); m_freem(bp); return NULL; } chap->auth.id = chap->auth.in.hdr.id; /* We respond with this id */ #ifdef HAVE_DES lanman = 0; #endif switch (chap->auth.in.hdr.code) { case CHAP_CHALLENGE: bp = mbuf_Read(bp, &alen, 1); len -= alen + 1; /* len -= (alen + 1); */ if (len < 0) { log_Printf(LogERROR, "Chap Input: Truncated challenge !\n"); m_freem(bp); return NULL; } *chap->challenge.peer = alen; bp = mbuf_Read(bp, chap->challenge.peer + 1, alen); bp = auth_ReadName(&chap->auth, bp, len); #ifdef HAVE_DES lanman = p->link.lcp.his_authtype == 0x80 && ((chap->NTRespSent && IsAccepted(p->link.lcp.cfg.chap80lm)) || !IsAccepted(p->link.lcp.cfg.chap80nt)); #endif break; case CHAP_RESPONSE: auth_StopTimer(&chap->auth); bp = mbuf_Read(bp, &alen, 1); /* read HASH-Size */ len -= alen + 1; /* len -= (alen + 1);, len is length of Name Field */ if (len < 0) { log_Printf(LogERROR, "Chap Input: Truncated response !\n"); m_freem(bp); return NULL; } if ((ans = malloc(alen + 2)) == 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); /* cut HASH value */ ans[alen+1] = '\0'; /* ans is (id, HASH, \0)*/ bp = auth_ReadName(&chap->auth, bp, len); #ifdef HAVE_DES lanman = alen == 49 && ans[alen] == 0; #endif break; case CHAP_SUCCESS: case CHAP_FAILURE: /* chap->auth.in.name is already set up at CHALLENGE time */ if ((ans = malloc(len + 1)) == NULL) { log_Printf(LogERROR, "Chap Input: Out of memory !\n"); m_freem(bp); return NULL; } bp = mbuf_Read(bp, ans, len); ans[len] = '\0'; break; } switch (chap->auth.in.hdr.code) { case CHAP_CHALLENGE: case CHAP_RESPONSE: if (*chap->auth.in.name) log_Printf(LogPHASE, "Chap Input: %s (%d bytes from %s%s)\n", chapcodes[chap->auth.in.hdr.code], alen, chap->auth.in.name, #ifdef HAVE_DES lanman && chap->auth.in.hdr.code == CHAP_RESPONSE ? " - lanman" : #endif ""); else log_Printf(LogPHASE, "Chap Input: %s (%d bytes%s)\n", chapcodes[chap->auth.in.hdr.code], alen, #ifdef HAVE_DES lanman && chap->auth.in.hdr.code == CHAP_RESPONSE ? " - lanman" : #endif ""); break; case CHAP_SUCCESS: case CHAP_FAILURE: if (*ans) log_Printf(LogPHASE, "Chap Input: %s (%s)\n", chapcodes[chap->auth.in.hdr.code], ans); else log_Printf(LogPHASE, "Chap Input: %s\n", chapcodes[chap->auth.in.hdr.code]); break; } switch (chap->auth.in.hdr.code) { case CHAP_CHALLENGE: if (*bundle->cfg.auth.key == '!' && bundle->cfg.auth.key[1] != '!') chap_StartChild(chap, bundle->cfg.auth.key + 1, bundle->cfg.auth.name); else chap_Respond(chap, bundle->cfg.auth.name, bundle->cfg.auth.key + (*bundle->cfg.auth.key == '!' ? 1 : 0), p->link.lcp.his_authtype #ifdef HAVE_DES , lanman #endif ); break; case CHAP_RESPONSE: name = chap->auth.in.name; nlen = strlen(name); #ifndef NORADIUS if (*bundle->radius.cfg.file) { u_char end; end = chap->challenge.local[*chap->challenge.local+1]; chap->challenge.local[*chap->challenge.local+1] = '\0'; radius_Authenticate(&bundle->radius, &chap->auth, chap->auth.in.name, ans, chap->challenge.local + 1); chap->challenge.local[*chap->challenge.local+1] = end; } else #endif { key = auth_GetSecret(bundle, name, nlen, p); if (key) { char *myans; #ifdef HAVE_DES if (lanman && !IsEnabled(p->link.lcp.cfg.chap80lm)) { log_Printf(LogPHASE, "Auth failure: LANMan not enabled\n"); if (chap_HaveAnotherGo(chap)) break; key = NULL; } else if (!lanman && !IsEnabled(p->link.lcp.cfg.chap80nt) && p->link.lcp.want_authtype == 0x80) { log_Printf(LogPHASE, "Auth failure: mschap not enabled\n"); if (chap_HaveAnotherGo(chap)) break; key = NULL; } else #endif { myans = chap_BuildAnswer(name, key, chap->auth.id, chap->challenge.local, p->link.lcp.want_authtype #ifdef HAVE_DES , lanman #endif ); if (myans == NULL) key = NULL; else { if (!chap_Cmp(p->link.lcp.want_authtype, myans + 1, *myans, ans + 1, alen #ifdef HAVE_DES , lanman #endif )) key = NULL; free(myans); } } } if (key) chap_Success(&chap->auth); else chap_Failure(&chap->auth); } break; case CHAP_SUCCESS: if (p->link.lcp.auth_iwait == PROTO_CHAP) { p->link.lcp.auth_iwait = 0; if (p->link.lcp.auth_ineed == 0) /* * We've succeeded in our ``login'' * If we're not expecting the peer to authenticate (or he already * has), proceed to network phase. */ datalink_AuthOk(p->dl); } break; case CHAP_FAILURE: datalink_AuthNotOk(p->dl); break; } free(ans); } m_freem(bp); return NULL; }
struct mbuf * chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) { struct physical *p = link2physical(l); struct chap *chap = &p->dl->chap; char *name, *key, *ans; int len, nlen; u_char alen; #ifndef NODES int lanman; #endif if (p == NULL) { log_Printf(LogERROR, "chap_Input: Not a physical link - dropped\n"); m_freem(bp); return NULL; } if (bundle_Phase(bundle) != PHASE_NETWORK && bundle_Phase(bundle) != PHASE_AUTHENTICATE) { log_Printf(LogPHASE, "Unexpected chap input - dropped !\n"); m_freem(bp); return NULL; } m_settype(bp, MB_CHAPIN); if ((bp = auth_ReadHeader(&chap->auth, bp)) == NULL && ntohs(chap->auth.in.hdr.length) == 0) log_Printf(LogWARN, "Chap Input: Truncated header !\n"); else if (chap->auth.in.hdr.code == 0 || chap->auth.in.hdr.code > MAXCHAPCODE) log_Printf(LogPHASE, "Chap Input: %d: Bad CHAP code !\n", chap->auth.in.hdr.code); else { len = m_length(bp); ans = NULL; if (chap->auth.in.hdr.code != CHAP_CHALLENGE && chap->auth.id != chap->auth.in.hdr.id && Enabled(bundle, OPT_IDCHECK)) { /* Wrong conversation dude ! */ log_Printf(LogPHASE, "Chap Input: %s dropped (got id %d, not %d)\n", chapcodes[chap->auth.in.hdr.code], chap->auth.in.hdr.id, chap->auth.id); m_freem(bp); return NULL; } chap->auth.id = chap->auth.in.hdr.id; /* We respond with this id */ #ifndef NODES lanman = 0; #endif switch (chap->auth.in.hdr.code) { case CHAP_CHALLENGE: bp = mbuf_Read(bp, &alen, 1); len -= alen + 1; if (len < 0) { log_Printf(LogERROR, "Chap Input: Truncated challenge !\n"); m_freem(bp); return NULL; } *chap->challenge.peer = alen; bp = mbuf_Read(bp, chap->challenge.peer + 1, alen); bp = auth_ReadName(&chap->auth, bp, len); #ifndef NODES lanman = p->link.lcp.his_authtype == 0x80 && ((chap->NTRespSent && IsAccepted(p->link.lcp.cfg.chap80lm)) || !IsAccepted(p->link.lcp.cfg.chap80nt)); /* Generate local challenge value */ chap_ChallengeInit(&chap->auth); #endif break; case CHAP_RESPONSE: auth_StopTimer(&chap->auth); bp = mbuf_Read(bp, &alen, 1); len -= alen + 1; if (len < 0) { log_Printf(LogERROR, "Chap Input: Truncated response !\n"); m_freem(bp); return 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); bp = auth_ReadName(&chap->auth, bp, len); #ifndef NODES lanman = p->link.lcp.want_authtype == 0x80 && alen == 49 && ans[alen] == 0; #endif break; case CHAP_SUCCESS: case CHAP_FAILURE: /* chap->auth.in.name is already set up at CHALLENGE time */ if ((ans = malloc(len + 1)) == NULL) { log_Printf(LogERROR, "Chap Input: Out of memory !\n"); m_freem(bp); return NULL; } bp = mbuf_Read(bp, ans, len); ans[len] = '\0'; break; } switch (chap->auth.in.hdr.code) { case CHAP_CHALLENGE: case CHAP_RESPONSE: if (*chap->auth.in.name) log_Printf(LogPHASE, "Chap Input: %s (%d bytes from %s%s)\n", chapcodes[chap->auth.in.hdr.code], alen, chap->auth.in.name, #ifndef NODES lanman && chap->auth.in.hdr.code == CHAP_RESPONSE ? " - lanman" : #endif ""); else log_Printf(LogPHASE, "Chap Input: %s (%d bytes%s)\n", chapcodes[chap->auth.in.hdr.code], alen, #ifndef NODES lanman && chap->auth.in.hdr.code == CHAP_RESPONSE ? " - lanman" : #endif ""); break; case CHAP_SUCCESS: case CHAP_FAILURE: if (*ans) log_Printf(LogPHASE, "Chap Input: %s (%s)\n", chapcodes[chap->auth.in.hdr.code], ans); else log_Printf(LogPHASE, "Chap Input: %s\n", chapcodes[chap->auth.in.hdr.code]); break; } switch (chap->auth.in.hdr.code) { case CHAP_CHALLENGE: if (*bundle->cfg.auth.key == '!' && bundle->cfg.auth.key[1] != '!') chap_StartChild(chap, bundle->cfg.auth.key + 1, bundle->cfg.auth.name); else chap_Respond(chap, bundle->cfg.auth.name, bundle->cfg.auth.key + (*bundle->cfg.auth.key == '!' ? 1 : 0), p->link.lcp.his_authtype #ifndef NODES , lanman #endif ); break; case CHAP_RESPONSE: name = chap->auth.in.name; nlen = strlen(name); #ifndef NODES if (p->link.lcp.want_authtype == 0x81) { 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 #ifndef NORADIUS if (*bundle->radius.cfg.file) { if (!radius_Authenticate(&bundle->radius, &chap->auth, chap->auth.in.name, ans, alen + 1, chap->challenge.local + 1, *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) { #ifndef NODES if (p->link.lcp.want_authtype == 0x80 && lanman && !IsEnabled(p->link.lcp.cfg.chap80lm)) { log_Printf(LogPHASE, "Auth failure: LANMan not enabled\n"); if (chap_HaveAnotherGo(chap)) break; key = NULL; } else if (p->link.lcp.want_authtype == 0x80 && !lanman && !IsEnabled(p->link.lcp.cfg.chap80nt)) { log_Printf(LogPHASE, "Auth failure: mschap not enabled\n"); if (chap_HaveAnotherGo(chap)) break; key = NULL; } else if (p->link.lcp.want_authtype == 0x81 && !IsEnabled(p->link.lcp.cfg.chap81)) { log_Printf(LogPHASE, "Auth failure: CHAP81 not enabled\n"); key = NULL; } else #endif { char *myans = chap_BuildAnswer(name, key, chap->auth.id, chap->challenge.local, p->link.lcp.want_authtype #ifndef NODES , chap->challenge.peer, chap->authresponse, lanman); MPPE_IsServer = 1; /* XXX Global ! */ #else ); #endif if (myans == NULL) key = NULL; else { if (!chap_Cmp(p->link.lcp.want_authtype, myans + 1, *myans, ans + 1, alen #ifndef NODES , lanman #endif )) key = NULL; free(myans); } } } if (key) chap_Success(&chap->auth); else chap_Failure(&chap->auth); } break; case CHAP_SUCCESS: if (p->link.lcp.auth_iwait == PROTO_CHAP) { p->link.lcp.auth_iwait = 0; if (p->link.lcp.auth_ineed == 0) { #ifndef NODES if (p->link.lcp.his_authtype == 0x81) { if (strncasecmp(ans, chap->authresponse, 42)) { datalink_AuthNotOk(p->dl); log_Printf(LogWARN, "CHAP81: AuthenticatorResponse: (%.42s)" " != ans: (%.42s)\n", chap->authresponse, ans); } else { /* Successful login */ MPPE_MasterKeyValid = 1; /* XXX Global ! */ datalink_AuthOk(p->dl); } } else #endif /* * We've succeeded in our ``login'' * If we're not expecting the peer to authenticate (or he already * has), proceed to network phase. */ datalink_AuthOk(p->dl); } } break; case CHAP_FAILURE: datalink_AuthNotOk(p->dl); break; } free(ans); }