bool PPP_set_secrets ( _ppp_handle handle, /* [IN] - the PPP state structure */ uint32_t secret_number, PPP_SECRET_PTR secret_ptr ) { /* Body */ #if RTCSCFG_ENABLE_IP4 PPP_CFG_PTR ppp_ptr = handle; bool success=TRUE; switch (secret_number) { case PPP_PAP_LSECRET: PPP_SECRET(ppp_ptr, _PPP_PAP_LSECRET) = secret_ptr; break; case PPP_PAP_RSECRETS: PPP_SECRET(ppp_ptr, _PPP_PAP_RSECRETS) = secret_ptr; break; case PPP_CHAP_LSECRETS: PPP_SECRET(ppp_ptr, _PPP_CHAP_LSECRETS) = secret_ptr; break; case PPP_CHAP_RSECRETS: PPP_SECRET(ppp_ptr, _PPP_CHAP_RSECRETS) = secret_ptr; break; default: success=FALSE; } return success; #else return FALSE; #endif /* RTCSCFG_ENABLE_IP4 */ } /* Endbody */
void CHAP_challenge ( _ppp_handle handle /* [IN] - the PPP state structure */ ) { /* Body */ PPP_CFG_PTR ppp_ptr = handle; CHAP_DATA_PTR chap_ptr = &ppp_ptr->CHAP_STATE; PCB_PTR pcb; uchar_ptr outp; uint_16 len; uint_16 i, idlen; chap_ptr->SERVER_STATE = CHAP_STATE_INITIAL; chap_ptr->CURID = RTCS_rand() & 0xFF; /* Acquire a message buffer */ /* Start CR 2207 */ idlen = strlen(PPP_SECRET(ppp_ptr,_PPP_CHAP_LNAME)); /* End CR 2207 */ len = CHAP_HDR_LEN + 1 + CHAP_CHALLENGE_LEN + idlen; pcb = PPP_pcballoc(PPP_PROT_CHAP, len); if (pcb == NULL) { return; } /* Endif */ /* Build a Challenge packet */ outp = pcb->FRAG[0].FRAGMENT + 2; *outp++ = CHAP_CODE_CHALLENGE; *outp++ = chap_ptr->CURID; *outp++ = (len >> 8) & 0xFF; *outp++ = len & 0xFF; *outp++ = CHAP_CHALLENGE_LEN; for (i=0; i<CHAP_CHALLENGE_LEN; i++) { *outp++ = chap_ptr->MD5[i] = RTCS_rand() & 0xFF; } /* Endfor */ /* Start CR 2207 */ PPP_memcopy(PPP_SECRET(ppp_ptr,_PPP_CHAP_LNAME), outp, idlen); /* End CR 2207 */ /* Send the PCB */ PPP_send_rexmit(ppp_ptr, PPP_PROT_CHAP, pcb, 0, CHAP_timeout, chap_ptr); } /* Endbody */
static void LCP_resetconfreq ( PPPFSM_CFG_PTR fsm /* [IN] - State Machine */ ) { /* Body */ LCP_CFG_PTR lcp_ptr = fsm->PRIVATE; uint32_t if_type; /* Start CR 2207 */ #if PPP_SECRETS_NOT_SHARED PPP_CFG_PTR ppp_ptr = lcp_ptr->HANDLE; #endif /* End CR 2207 */ _iopcb_ioctl(lcp_ptr->DEVICE, IOPCB_IOCTL_GET_IFTYPE, &if_type); if (if_type == IPIFTYPE_ETHERNET) { lcp_ptr->SEND_OPT = PPP_DEFAULT_OPTIONS_PPPOE; lcp_ptr->RECV_OPT = PPP_DEFAULT_OPTIONS_PPPOE; lcp_ptr->RECV_NEG = LCP_DEFAULT_NEG_PPPOE; } else { lcp_ptr->SEND_OPT = PPP_DEFAULT_OPTIONS; lcp_ptr->RECV_OPT = PPP_DEFAULT_OPTIONS; lcp_ptr->RECV_NEG = LCP_DEFAULT_NEG; lcp_ptr->RECV_NEG.ACCM = _PPP_ACCM; } /* Endif */ /* Start CR 2207 */ if (PPP_SECRET(ppp_ptr,_PPP_CHAP_RSECRETS)) { /* End CR 2207 */ lcp_ptr->RECV_NEG.NEG_AP = 1; lcp_ptr->RECV_NEG.AP = PPP_PROT_CHAP; /* Start CR 2207 */ } else if (PPP_SECRET(ppp_ptr,_PPP_PAP_RSECRETS)) { /* End CR 2207 */ lcp_ptr->RECV_NEG.NEG_AP = 1; lcp_ptr->RECV_NEG.AP = PPP_PROT_PAP; } else { lcp_ptr->RECV_NEG.NEG_AP = 0; } /* Endif */ } /* Endbody */
void PAP_send ( _ppp_handle handle /* [IN] - the PPP state structure */ ) { /* Body */ #if RTCSCFG_ENABLE_IP4 PPP_CFG_PTR ppp_ptr = handle; PAP_DATA_PTR pap_ptr = &ppp_ptr->PAP_STATE; PCB_PTR pcb; unsigned char *outp; uint16_t len; pap_ptr->CLIENT_STATE = PAP_STATE_INITIAL; pap_ptr->CURID = RTCS_rand() & 0xFF; /* Acquire a PCB */ len = PAP_HDR_LEN + 2 /* Start CR 2207 */ + PPP_SECRET(ppp_ptr,_PPP_PAP_LSECRET->PPP_ID_LENGTH) + PPP_SECRET(ppp_ptr,_PPP_PAP_LSECRET->PPP_PW_LENGTH); /* End CR 2207 */ pcb = PPP_pcballoc(PPP_PROT_PAP, len); if (pcb == NULL) { return; } /* Endif */ /* Build an Authenticate-Request packet */ outp = pcb->FRAG[0].FRAGMENT + 2; *outp++ = PAP_CODE_AUTH_REQ; *outp++ = pap_ptr->CURID; *outp++ = (len >> 8) & 0xFF; *outp++ = len & 0xFF; /* Start CR 2207 */ *outp++ = len = PPP_SECRET(ppp_ptr,_PPP_PAP_LSECRET->PPP_ID_LENGTH); PPP_memcopy(PPP_SECRET(ppp_ptr,_PPP_PAP_LSECRET->PPP_ID_PTR), outp, len); outp += len; *outp++ = len = PPP_SECRET(ppp_ptr,_PPP_PAP_LSECRET->PPP_PW_LENGTH); PPP_memcopy(PPP_SECRET(ppp_ptr,_PPP_PAP_LSECRET->PPP_PW_PTR), outp, len); /* End CR 2207 */ /* Send the PCB */ PPP_send_rexmit(ppp_ptr, PPP_PROT_PAP, pcb, 0, PAP_timeout, pap_ptr); #endif /* RTCSCFG_ENABLE_IP4 */ } /* Endbody */
bool PPP_set_chap_lname ( _ppp_handle handle, /* [IN] - the PPP state structure */ char *lname ) { /* Body */ #if RTCSCFG_ENABLE_IP4 PPP_CFG_PTR ppp_ptr = handle; PPP_SECRET(ppp_ptr, _PPP_CHAP_LNAME) = lname; return TRUE; #else return FALSE; #endif /* RTCSCFG_ENABLE_IP4 */ } /* Endbody */
void PAP_input ( PCB_PTR pcb, /* [IN] - PAP packet */ _ppp_handle handle /* [IN] - the PPP state structure */ ) { /* Body */ PPP_CFG_PTR ppp_ptr = handle; PAP_DATA_PTR pap_ptr = &ppp_ptr->PAP_STATE; PPP_SECRET_PTR secret; uchar_ptr inp = pcb->FRAG[0].FRAGMENT + 2; uchar_ptr idp, pwp; uchar code, id; uchar idlen, pwlen; uint_16 len; boolean delay = FALSE; /* ** Parse header (code, id and length). ** If packet too short, drop it. */ if (pcb->FRAG[0].LENGTH < 2 + PAP_HDR_LEN) { pap_ptr->ST_PAP_SHORT++; PCB_free(pcb); return; } /* Endif */ code = *inp++; id = *inp++; len = *inp++ << 8; len += *inp++; if ((len < PAP_HDR_LEN) || (len > pcb->FRAG[0].LENGTH - 2)) { pap_ptr->ST_PAP_SHORT++; PCB_free(pcb); return; } /* Endif */ len -= PAP_HDR_LEN; switch (code) { case PAP_CODE_AUTH_REQ: switch (pap_ptr->SERVER_STATE) { case PAP_STATE_INITIAL: /* Parse the peer id and password */ idp = inp; idlen = *idp++; pwp = idp + idlen; pwlen = *pwp++; if (len < idlen + pwlen + 2) { pap_ptr->ST_PAP_SHORT++; PCB_free(pcb); break; } /* Endif */ /* Match id/password pair against the secrets table */ /* Start CR 2207 */ secret = PPP_SECRET(ppp_ptr,_PPP_PAP_RSECRETS); /* End CR 2207 */ for (;;) { if ((secret->PPP_ID_LENGTH == 0) && (secret->PPP_PW_LENGTH == 0)) { pap_ptr->SERVER_STATE = PAP_STATE_AUTH_NAK; PAP_fail(handle); delay = TRUE; break; } /* Endif */ if ((secret->PPP_ID_LENGTH == idlen) && (secret->PPP_PW_LENGTH == pwlen) && (memcmp(secret->PPP_ID_PTR, idp, idlen) == 0) && (memcmp(secret->PPP_PW_PTR, pwp, pwlen) == 0)) { pap_ptr->SERVER_STATE = PAP_STATE_AUTH_ACK; PAP_up(handle); break; } /* Endif */ secret++; } /* Endfor */ /* fall through */ case PAP_STATE_AUTH_ACK: case PAP_STATE_AUTH_NAK: /* Build an Auth-Ack or Auth-Nak reply */ inp = pcb->FRAG[0].FRAGMENT + 2; *inp++ = pap_ptr->SERVER_STATE; inp++; /* Keep same ID */ *inp++ = 0; *inp++ = 5; *inp++ = 0; pcb->FRAG[0].LENGTH = 7; if (delay) { PPP_send_rexmit(ppp_ptr, PPP_PROT_PAP, pcb, 1, PAP_close, handle); } else { PPP_send_one(ppp_ptr, PPP_PROT_PAP, pcb); } /* Endif */ break; default: pap_ptr->ST_PAP_NOAUTH++; PCB_free(pcb); break; } /* Endswitch */ break; case PAP_CODE_AUTH_ACK: pap_ptr->CLIENT_STATE = PAP_STATE_AUTH_ACK; PAP_up(handle); case PAP_CODE_AUTH_NAK: if (pap_ptr->CLIENT_STATE != PAP_STATE_AUTH_ACK) { pap_ptr->CLIENT_STATE = PAP_STATE_AUTH_NAK; } /* Endif */ if (pap_ptr->CLIENT_STATE != PAP_STATE_INITIAL && pap_ptr->CLIENT_STATE != PAP_STATE_AUTH_ACK) { pap_ptr->ST_PAP_NOREQ++; } else if (id != pap_ptr->CURID) { pap_ptr->ST_PAP_ID++; } else if (len < 1) { pap_ptr->ST_PAP_SHORT++; } else if (--len < *inp++) { pap_ptr->ST_PAP_SHORT++; } else { /* All is well -- stop send Auth-Req's */ PPP_send_stop(ppp_ptr, PPP_PROT_PAP); } /* Endif */ PCB_free(pcb); break; default: pap_ptr->ST_PAP_CODE++; PCB_free(pcb); break; } /* Endswitch */ } /* Endbody */
static uint32_t LCP_recvconfreq ( PPPFSM_CFG_PTR fsm, /* [IN] - State Machine */ bool reject /* [IN] - whether to ConfRej if we disagree */ ) { /* Body */ LCP_CFG_PTR lcp_ptr = fsm->PRIVATE; unsigned char *inp = fsm->DATA; unsigned char *nakp, *rejp; uint32_t sizeleft = fsm->LENGTH; uint32_t naklen, rejlen; bool apneg = FALSE; PPP_OPT req_opt = lcp_ptr->SEND_OPT; unsigned char code; unsigned char cicode, cilen; /* Start CR 2207 */ #if PPP_SECRETS_NOT_SHARED PPP_CFG_PTR ppp_ptr = lcp_ptr->HANDLE; #endif /* End CR 2207 */ #define CI_REJECT(n) \ inp -= n; \ code = CP_CODE_CONF_REJ; \ rejlen += cilen; \ while (cilen--) *rejp++ = *inp++ #define CI_NAK \ if (code != CP_CODE_CONF_REJ) { \ code = CP_CODE_CONF_NAK; \ if (reject) { \ inp -= cilen; \ naklen += cilen; \ while (cilen--) *nakp++ = *inp++; \ } else { \ apneg = FALSE; #define CI_ENDNAK \ } /* Endif */ \ } /* Endif */ #define CI_NAKAP(n) \ if (code != CP_CODE_CONF_REJ) { \ code = CP_CODE_CONF_NAK; \ if (reject) { \ inp -= n; \ naklen += cilen; \ while (cilen--) *nakp++ = *inp++; \ } else { \ apneg = TRUE; \ inp += cilen - n; \ } /* Endif */ \ } else { \ inp += cilen - n; \ } /* Endif */ /* ** Process all requested codes */ rejp = nakp = inp; rejlen = naklen = 0; code = CP_CODE_CONF_ACK; while (sizeleft) { /* check remaining length */ if (sizeleft < inp[1] || inp[1] < 2) { code = CP_CODE_CONF_REJ; rejlen += sizeleft; while (sizeleft--) *rejp++ = *inp++; break; } /* Endif */ cicode = *inp++; sizeleft -= cilen = *inp++; switch (cicode) { case LCP_CI_MRU: if (cilen != 4) { CI_REJECT(2); break; } /* Endif */ /* Accept any MRU no smaller than 68 bytes */ req_opt.MRU = mqx_ntohs(inp); inp += 2; if (req_opt.MRU > DEFAULT_MRU) { req_opt.MRU = DEFAULT_MRU; } else if (req_opt.MRU < MINIMUM_MRU) { CI_NAK { *nakp++ = LCP_CI_MRU; naklen += *nakp++ = 4; req_opt.MRU = MINIMUM_MRU; mqx_htons(nakp, req_opt.MRU); nakp += 2; } CI_ENDNAK; } /* Endif */ break; case LCP_CI_ACCM: if (cilen != 6) { CI_REJECT(2); break; } /* Endif */ /* If we want any characters not in their ACCM, nak it */ req_opt.ACCM = mqx_ntohl(inp); inp += 4; if ((req_opt.ACCM & _PPP_ACCM) != _PPP_ACCM) { CI_NAK { *nakp++ = LCP_CI_ACCM; naklen += *nakp++ = 6; req_opt.ACCM |= _PPP_ACCM; mqx_htonl(nakp, req_opt.ACCM); nakp += 4; } CI_ENDNAK; } /* Endif */ break; /* ** AP is unusual in that it is a variable length ** option. Thus it is possible that we may want ** to nak AP and make a suggestion longer than ** the peer's request. ** ** This is bad. ** ** It's bad because this function wants to reuse ** the incoming ConfReq to build the reply, and ** in this case, it is possible for nakp to ** overtake inp, thus overwriting an option not ** yet parsed. ** ** So we do the following: If we decide to nak ** the requested AP, we just set apneg=TRUE and ** append the nak'd AP at the end of our ConfNak ** after we've completed parsing the ConfReq. ** ** Note that we won't nak AP if we generate ** nak's for other options afterward, because ** the RFC states that nak'd options MUST be in ** the same order that they were in the ConfReq. */ case LCP_CI_AP: if (cilen < 4) { CI_REJECT(2); break; } /* Endif */ /* If we don't have any secrets, reject AP */ /* Start CR 2207 */ if (!(PPP_SECRET(ppp_ptr,_PPP_PAP_LSECRET) || PPP_SECRET(ppp_ptr,_PPP_CHAP_LSECRETS))) { /* End CR 2207 */ CI_REJECT(2); break; } /* Endif */ /* Check the desired authentication protocol */ req_opt.AP = mqx_ntohs(inp); inp += 2; switch (req_opt.AP) { /* Accept PAP only if we have a secret */ case PPP_PROT_PAP: if (cilen != 4) { CI_REJECT(4); break; /* Start CR 2207 */ } else if (PPP_SECRET(ppp_ptr,_PPP_PAP_LSECRET) == NULL) { /* End CR 2207 */ CI_NAKAP(4); break; } /* Endif */ req_opt.AP_Start = PAP_send; break; /* Accept CHAP only if we have a secrets table */ case PPP_PROT_CHAP: if (cilen != 5) { CI_REJECT(4); break; /* Start CR 2207 */ } else if (PPP_SECRET(ppp_ptr,_PPP_CHAP_LSECRETS) == NULL) { /* End CR 2207 */ CI_NAKAP(4); break; } else if (*inp++ != 5) { /* Only MD5 supported */ CI_NAKAP(5); break; } /* Endif */ req_opt.AP_Start = CHAP_open; break; default: CI_NAKAP(4); break; } /* Endswitch */ break; case LCP_CI_MAGIC: if (cilen != 6) { CI_REJECT(2); break; } /* Endif */ inp += 4; break; case LCP_CI_PFC: if (cilen != 2) { CI_REJECT(2); break; } /* Endif */ req_opt.PFC = TRUE; break; case LCP_CI_ACFC: if (cilen != 2) { CI_REJECT(2); break; } /* Endif */ req_opt.ACFC = TRUE; break; default: CI_REJECT(2); break; } /* Endswitch */
static bool LCP_recvconfnak ( PPPFSM_CFG_PTR fsm /* [IN] - State Machine */ ) { /* Body */ LCP_CFG_PTR lcp_ptr = fsm->PRIVATE; unsigned char *inp = fsm->DATA; uint32_t sizeleft = fsm->LENGTH; LCP_NEG req_neg = lcp_ptr->RECV_NEG; unsigned char code; /* Start CR 2207 */ #if PPP_SECRETS_NOT_SHARED PPP_CFG_PTR ppp_ptr = lcp_ptr->HANDLE; #endif /* End CR 2207 */ #define LCP_RNAK(len) \ if (sizeleft < len) goto badnak; \ if (*inp++ != len) goto badnak; \ sizeleft -= len /* ** Nak'd codes must be in the same order as they were in the ConfReq */ code = *inp++; if (sizeleft && req_neg.NEG_MRU && code == LCP_CI_MRU) { LCP_RNAK(4); /* We are prepared to accept maximum MRU of 1500 */ req_neg.MRU = mqx_ntohs(inp); inp += 2; if (req_neg.MRU > DEFAULT_MRU) { req_neg.MRU = DEFAULT_MRU; } /* Endif */ code = *inp++; } /* Endif */ if (sizeleft && req_neg.NEG_ACCM && code == LCP_CI_ACCM) { LCP_RNAK(6); /* Add any characters they want to our ACCM */ req_neg.ACCM |= mqx_ntohl(inp); inp += 4; code = *inp++; } /* Endif */ if (sizeleft && req_neg.NEG_AP && code == LCP_CI_AP) { if (sizeleft < *inp || *inp < 4) goto badnak; sizeleft -= *inp; /* ** If AP is nak'd, we don't care what they want -- ** we choose the next most desirable protocol. If there ** aren't any more to choose, we keep the last one we tried. */ inp += *inp - 1; if (PPP_SECRET(ppp_ptr,_PPP_CHAP_RSECRETS)) { req_neg.AP = PPP_PROT_CHAP; } else { switch (req_neg.AP) { case PPP_PROT_CHAP: /* CHAP was NAKed, try PAP */ if (PPP_SECRET(ppp_ptr,_PPP_PAP_RSECRETS)) { req_neg.AP = PPP_PROT_PAP; } /* Endif */ break; case PPP_PROT_PAP: /* no other authentication protocols known */ break; default: /* Unknown protocol NAKed, try CHAP */ if (PPP_SECRET(ppp_ptr,_PPP_CHAP_RSECRETS)) { req_neg.AP = PPP_PROT_CHAP; } break; } /* Endswitch */ } code = *inp++; } /* Endif */ /* ** If we advertised PFC and/or ACFC and the peer doesn't ** want it, they should send a ConfRej rather than a ConfNak, ** so we're not going to check for them here (if they are ** here, the switch statement below will catch it). */ #define LCP_RNAK_ADD(ci,len) \ if (req_neg.NEG_ ## ci || sizeleft < len || *inp++ != len) goto badnak; \ sizeleft -= len; \ req_neg.NEG_ ## ci = 1 /* ** There may be remaining codes if the peer wants us to ** negotiate an option we didn't include. */ while (sizeleft) { switch (code) { case LCP_CI_MRU: LCP_RNAK_ADD(MRU,4); req_neg.MRU = mqx_ntohs(inp); inp += 2; if (req_neg.MRU > DEFAULT_MRU) { req_neg.MRU = DEFAULT_MRU; } /* Endif */ break; case LCP_CI_ACCM: LCP_RNAK_ADD(ACCM,6); req_neg.ACCM |= mqx_ntohl(inp); inp += 4; break; case LCP_CI_AP: if (req_neg.NEG_AP || sizeleft < *inp || *inp < 4) goto badnak; sizeleft -= *inp; /* ** If AP is nak'd, we don't care what they want -- ** we still don't negotiate */ inp += *inp - 1; break; case LCP_CI_PFC: LCP_RNAK_ADD(PFC,2); break; case LCP_CI_ACFC: LCP_RNAK_ADD(ACFC,2); break; default: if (sizeleft < *inp || *inp < 2) goto badnak; sizeleft -= *inp; inp += *inp - 1; } /* Endswtich */ code = *inp++; } /* Endwhile */ if (fsm->STATE < PPP_STATE_OPENED) { lcp_ptr->RECV_NEG = req_neg; } /* Endif */ return TRUE; badnak: return FALSE; } /* Endbody */
void CHAP_input ( PCB_PTR pcb, /* [IN] - CHAP packet */ _ppp_handle handle /* [IN] - the PPP state structure */ ) { /* Body */ PPP_CFG_PTR ppp_ptr = handle; CHAP_DATA_PTR chap_ptr = &ppp_ptr->CHAP_STATE; PPP_SECRET_PTR secret; uchar_ptr inp = pcb->FRAG[0].FRAGMENT + 2; uchar_ptr valp, idp; uchar code, id; uchar vallen, idlen, namelen; uint_16 len; boolean delay = FALSE; /* ** Parse header (code, id and length). ** If packet too short, drop it. */ if (pcb->FRAG[0].LENGTH < 2 + CHAP_HDR_LEN) { chap_ptr->ST_CHAP_SHORT++; PCB_free(pcb); return; } /* Endif */ code = *inp++; id = *inp++; len = *inp++ << 8; len += *inp++; if ((len < CHAP_HDR_LEN) || (len > pcb->FRAG[0].LENGTH - 2)) { chap_ptr->ST_CHAP_SHORT++; PCB_free(pcb); return; } /* Endif */ len -= CHAP_HDR_LEN; /* ** For Challenge and Response packets, also parse the ** value and name fields. */ if ((code == CHAP_CODE_CHALLENGE) || (code == CHAP_CODE_RESPONSE)) { if (len < 1) { chap_ptr->ST_CHAP_SHORT++; PCB_free(pcb); return; } /* Endif */ valp = inp; vallen = *valp++; len--; if (len < vallen) { chap_ptr->ST_CHAP_SHORT++; PCB_free(pcb); return; } /* Endif */ idp = valp + vallen; idlen = len - vallen; } /* Endif */ switch (code) { case CHAP_CODE_CHALLENGE: if (chap_ptr->CLIENT_STATE != CHAP_STATE_INITIAL) { chap_ptr->ST_CHAP_NOAUTH++; PCB_free(pcb); break; } /* Endif */ /* OK -- Generate a Response packet */ /* Start CR 2207 */ secret = PPP_SECRET(ppp_ptr,_PPP_CHAP_LSECRETS); /* End CR 2207 */ inp = pcb->FRAG[0].FRAGMENT + 2; *inp++ = CHAP_CODE_RESPONSE; inp++; /* Keep same ID */ /* Start CR 2207 */ namelen = strlen(PPP_SECRET(ppp_ptr,_PPP_CHAP_LNAME)); /* End CR 2207 */ len = CHAP_HDR_LEN + 1 + 16 + namelen; *inp++ = (len >> 8) & 0xFF; *inp++ = len & 0xFF; *inp++ = 16; for (;;) { if ((secret->PPP_ID_LENGTH == 0) && (secret->PPP_PW_LENGTH == 0)) { /* Couldn't find a secret for this peer */ chap_ptr->ST_CHAP_NOPW++; PPP_MD5(inp, (uint_32)1, &id, /* id */ (uint_32)vallen, valp, /* challenge */ (uint_32)0); break; } /* Endif */ if ((secret->PPP_ID_LENGTH == idlen) && (memcmp(secret->PPP_ID_PTR, idp, idlen) == 0)) { /* Found a secret; send response */ PPP_MD5(inp, (uint_32)1, &id, /* id */ (uint_32)secret->PPP_PW_LENGTH, /* secret */ secret->PPP_PW_PTR, (uint_32)vallen, valp, /* challenge */ (uint_32)0); break; } /* Endif */ secret++; } /* Endfor */ inp += 16; /* Start CR 2207 */ PPP_memcopy(PPP_SECRET(ppp_ptr,_PPP_CHAP_LNAME), inp, namelen); /* End CR 2207 */ pcb->FRAG[0].LENGTH = len + 2; PPP_send_one(ppp_ptr, PPP_PROT_CHAP, pcb); break; case CHAP_CODE_RESPONSE: switch (chap_ptr->SERVER_STATE) { case CHAP_STATE_INITIAL: /* Check the ID against our last challenge */ if (id != chap_ptr->CURID) { chap_ptr->ST_CHAP_ID++; PCB_free(pcb); break; } /* Endif */ /* Stop the challenge, whether or not the response is correct */ PPP_send_stop(ppp_ptr, PPP_PROT_CHAP); chap_ptr->SERVER_STATE = CHAP_STATE_FAILURE; if (vallen != 16) { delay = TRUE; CHAP_fail(handle); } else { /* Search for name in the secrets table */ /* Start CR 2207 */ secret = PPP_SECRET(ppp_ptr,_PPP_CHAP_RSECRETS); /* End CR 2207 */ for (;;) { if ((secret->PPP_ID_LENGTH == 0) && (secret->PPP_PW_LENGTH == 0)) { /* Couldn't find a secret for this peer */ delay = TRUE; CHAP_fail(handle); break; } /* Endif */ if ((secret->PPP_ID_LENGTH == idlen) && (memcmp(secret->PPP_ID_PTR, idp, idlen) == 0)) { /* Found a secret; compute hash */ uchar digest[16]; PPP_MD5(digest, (uint_32)1, &id, /* id */ (uint_32)secret->PPP_PW_LENGTH, /* secret */ secret->PPP_PW_PTR, (uint_32)CHAP_CHALLENGE_LEN, /* challenge */ chap_ptr->MD5, (uint_32)0); if (memcmp(digest, valp, vallen) == 0) { chap_ptr->SERVER_STATE = CHAP_STATE_SUCCESS; CHAP_up(handle); } else { delay = TRUE; CHAP_fail(handle); } /* Endif */ break; } /* Endif */ secret++; } /* Endfor */ } /* Endif */ /* fall through */ case CHAP_STATE_SUCCESS: case CHAP_STATE_FAILURE: /* Build a Success or Failure reply */ inp = pcb->FRAG[0].FRAGMENT + 2; *inp++ = chap_ptr->SERVER_STATE; inp++; /* Keep same ID */ *inp++ = 0; *inp++ = 4; pcb->FRAG[0].LENGTH = 6; if (delay) { PPP_send_rexmit(ppp_ptr, PPP_PROT_CHAP, pcb, 1, CHAP_close, handle); } else { PPP_send_one(ppp_ptr, PPP_PROT_CHAP, pcb); } /* Endif */ break; default: chap_ptr->ST_CHAP_NOCHAL++; PCB_free(pcb); break; } /* Endswitch */ break; case CHAP_CODE_SUCCESS: /* Authentication success */ chap_ptr->CLIENT_STATE = CHAP_STATE_SUCCESS; CHAP_up(handle); case CHAP_CODE_FAILURE: /* Authentication failure */ if (chap_ptr->CLIENT_STATE != CHAP_STATE_SUCCESS) { /* Change client state when authenticate failure */ chap_ptr->CLIENT_STATE = CHAP_STATE_FAILURE; if (chap_ptr->CLIENT_STATE != CHAP_STATE_INITIAL) { chap_ptr->ST_CHAP_NOAUTH++; } CHAP_fail(handle); } /* Endif */ PCB_free(pcb); break; default: chap_ptr->ST_CHAP_CODE++; PCB_free(pcb); break; } /* Endswitch */ } /* Endbody */