chap.c revision 28679
16059Samurai/* 26059Samurai * PPP CHAP Module 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 198857Srgrimes * 2028679Sbrian * $Id: chap.c,v 1.19 1997/06/14 00:21:23 ache Exp $ 218857Srgrimes * 226059Samurai * TODO: 236059Samurai */ 2413379Sphk#include <sys/types.h> 2513379Sphk#include <time.h> 266059Samurai#include "fsm.h" 276059Samurai#include "chap.h" 286059Samurai#include "lcpproto.h" 296059Samurai#include "lcp.h" 306059Samurai#include "hdlc.h" 316059Samurai#include "phase.h" 3226142Sbrian#include "loadalias.h" 336059Samurai#include "vars.h" 346735Samurai#include "auth.h" 356059Samurai 366059Samuraistatic char *chapcodes[] = { 3719866Sphk "???", "CHALLENGE", "RESPONSE", "SUCCESS", "FAILURE" 386059Samurai}; 396059Samurai 4028679Sbrianstruct authinfo AuthChapInfo = { 416735Samurai SendChapChallenge, 426735Samurai}; 436735Samurai 446059Samuraiextern char *AuthGetSecret(); 4523603Sacheextern int randinit; 466059Samurai 476059Samuraivoid 4828679SbrianChapOutput(u_int code, u_int id, u_char * ptr, int count) 496059Samurai{ 506059Samurai int plen; 516059Samurai struct fsmheader lh; 526059Samurai struct mbuf *bp; 536059Samurai 5428679Sbrian plen = sizeof(struct fsmheader) + count; 556059Samurai lh.code = code; 566059Samurai lh.id = id; 576059Samurai lh.length = htons(plen); 586059Samurai bp = mballoc(plen, MB_FSM); 596059Samurai bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader)); 606059Samurai if (count) 616059Samurai bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count); 6226516Sbrian LogDumpBp(LogDEBUG, "ChapOutput", bp); 6326516Sbrian LogPrintf(LogLCP, "ChapOutput: %s\n", chapcodes[code]); 6413733Sdfr HdlcOutput(PRI_LINK, PROTO_CHAP, bp); 656059Samurai} 666059Samurai 676059Samurai 686059Samuraistatic char challenge_data[80]; 6928679Sbrianstatic int challenge_len; 706059Samurai 716059Samuraivoid 7228679SbrianSendChapChallenge(int chapid) 736059Samurai{ 7413379Sphk int len, i; 756059Samurai char *cp; 766059Samurai 7723603Sache if (!randinit) { 7823603Sache randinit = 1; 7926626Sache srandomdev(); 8023603Sache } 816059Samurai cp = challenge_data; 826059Samurai *cp++ = challenge_len = random() % 32 + 16; 836059Samurai for (i = 0; i < challenge_len; i++) 846059Samurai *cp++ = random() & 0xff; 856059Samurai len = strlen(VarAuthName); 866059Samurai bcopy(VarAuthName, cp, len); 876059Samurai cp += len; 886059Samurai ChapOutput(CHAP_CHALLENGE, chapid, challenge_data, cp - challenge_data); 896059Samurai} 906059Samurai 916059Samuraivoid 9228679SbrianRecvChapTalk(struct fsmheader * chp, struct mbuf * bp) 936059Samurai{ 946059Samurai int valsize, len; 956059Samurai int arglen, keylen, namelen; 966059Samurai char *cp, *argp, *ap, *name, *digest; 976059Samurai char *keyp; 9828679Sbrian MD5_CTX context; /* context */ 996059Samurai char answer[100]; 1006059Samurai char cdigest[16]; 1016059Samurai 1026059Samurai len = ntohs(chp->length); 10326516Sbrian LogPrintf(LogDEBUG, "RecvChapTalk: length: %d\n", len); 1046059Samurai arglen = len - sizeof(struct fsmheader); 10528679Sbrian cp = (char *) MBUF_CTOP(bp); 1066059Samurai valsize = *cp++ & 255; 1076059Samurai name = cp + valsize; 1086059Samurai namelen = arglen - valsize - 1; 1096059Samurai name[namelen] = 0; 11026516Sbrian LogPrintf(LogPHASE, " Valsize = %d, Name = %s\n", valsize, name); 1116059Samurai 1126059Samurai /* 1136059Samurai * Get a secret key corresponds to the peer 1146059Samurai */ 1156059Samurai keyp = AuthGetSecret(SECRETFILE, name, namelen, chp->code == CHAP_RESPONSE); 1166059Samurai 1176059Samurai switch (chp->code) { 1186059Samurai case CHAP_CHALLENGE: 1196059Samurai if (keyp) { 1206059Samurai keylen = strlen(keyp); 1216059Samurai } else { 1226059Samurai keylen = strlen(VarAuthKey); 1236059Samurai keyp = VarAuthKey; 1246059Samurai } 1256059Samurai name = VarAuthName; 1266059Samurai namelen = strlen(VarAuthName); 12718885Sjkh argp = malloc(1 + valsize + namelen + 16); 12825630Sbrian if (argp == NULL) { 12925630Sbrian ChapOutput(CHAP_FAILURE, chp->id, "Out of memory!", 14); 13025630Sbrian return; 13125630Sbrian } 1326059Samurai digest = argp; 1336059Samurai *digest++ = 16; /* value size */ 1346059Samurai ap = answer; 1356059Samurai *ap++ = chp->id; 1366059Samurai bcopy(keyp, ap, keylen); 1376059Samurai ap += keylen; 1386059Samurai bcopy(cp, ap, valsize); 13926516Sbrian LogDumpBuff(LogDEBUG, "recv", ap, valsize); 1406059Samurai ap += valsize; 1416059Samurai MD5Init(&context); 1426059Samurai MD5Update(&context, answer, ap - answer); 1436059Samurai MD5Final(digest, &context); 14426516Sbrian LogDumpBuff(LogDEBUG, "answer", digest, 16); 1456059Samurai bcopy(name, digest + 16, namelen); 1466059Samurai ap += namelen; 1476059Samurai /* Send answer to the peer */ 1486059Samurai ChapOutput(CHAP_RESPONSE, chp->id, argp, namelen + 17); 14918885Sjkh free(argp); 1506059Samurai break; 1516059Samurai case CHAP_RESPONSE: 1526059Samurai if (keyp) { 15328679Sbrian 1546059Samurai /* 1556059Samurai * Compute correct digest value 1566059Samurai */ 1576059Samurai keylen = strlen(keyp); 1586059Samurai ap = answer; 1596059Samurai *ap++ = chp->id; 1606059Samurai bcopy(keyp, ap, keylen); 1616059Samurai ap += keylen; 1626059Samurai MD5Init(&context); 1636059Samurai MD5Update(&context, answer, ap - answer); 16428679Sbrian MD5Update(&context, challenge_data + 1, challenge_len); 1656059Samurai MD5Final(cdigest, &context); 16626516Sbrian LogDumpBuff(LogDEBUG, "got", cp, 16); 16726516Sbrian LogDumpBuff(LogDEBUG, "expect", cdigest, 16); 16828679Sbrian 1696059Samurai /* 1706059Samurai * Compare with the response 1716059Samurai */ 1726059Samurai if (bcmp(cp, cdigest, 16) == 0) { 1736059Samurai ChapOutput(CHAP_SUCCESS, chp->id, "Wellcome!!", 10); 1746059Samurai NewPhase(PHASE_NETWORK); 1756059Samurai break; 1766059Samurai } 1776059Samurai } 17828679Sbrian 1796059Samurai /* 1806059Samurai * Peer is not registerd, or response digest is wrong. 1816059Samurai */ 1826059Samurai ChapOutput(CHAP_FAILURE, chp->id, "Invalid!!", 9); 18326098Sbrian reconnect(RECON_FALSE); 1846059Samurai LcpClose(); 1856059Samurai break; 1866059Samurai } 1876059Samurai} 1886059Samurai 1896059Samuraivoid 19028679SbrianRecvChapResult(struct fsmheader * chp, struct mbuf * bp) 1916059Samurai{ 1926059Samurai int len; 1936059Samurai struct lcpstate *lcp = &LcpInfo; 1946059Samurai 1956059Samurai len = ntohs(chp->length); 19626516Sbrian LogPrintf(LogDEBUG, "RecvChapResult: length: %d\n", len); 1976059Samurai if (chp->code == CHAP_SUCCESS) { 1986059Samurai if (lcp->auth_iwait == PROTO_CHAP) { 1996059Samurai lcp->auth_iwait = 0; 2006059Samurai if (lcp->auth_ineed == 0) 2016059Samurai NewPhase(PHASE_NETWORK); 2026059Samurai } 2036059Samurai } else { 20428679Sbrian 2056059Samurai /* 2066059Samurai * Maybe, we shoud close LCP. Of cause, peer may take close action, too. 2076059Samurai */ 2086059Samurai ; 2096059Samurai } 2106059Samurai} 2116059Samurai 2126059Samuraivoid 21328679SbrianChapInput(struct mbuf * bp) 2146059Samurai{ 2156059Samurai int len = plength(bp); 2166059Samurai struct fsmheader *chp; 2176059Samurai 2186059Samurai if (len >= sizeof(struct fsmheader)) { 21928679Sbrian chp = (struct fsmheader *) MBUF_CTOP(bp); 2206059Samurai if (len >= ntohs(chp->length)) { 2216059Samurai if (chp->code < 1 || chp->code > 4) 2226059Samurai chp->code = 0; 22326516Sbrian LogPrintf(LogLCP, "ChapInput: %s\n", chapcodes[chp->code]); 2246059Samurai 2256059Samurai bp->offset += sizeof(struct fsmheader); 2266059Samurai bp->cnt -= sizeof(struct fsmheader); 2276059Samurai 2286059Samurai switch (chp->code) { 2296735Samurai case CHAP_RESPONSE: 2306735Samurai StopAuthTimer(&AuthChapInfo); 2316735Samurai /* Fall into.. */ 2326059Samurai case CHAP_CHALLENGE: 2336059Samurai RecvChapTalk(chp, bp); 2346059Samurai break; 2356059Samurai case CHAP_SUCCESS: 2366059Samurai case CHAP_FAILURE: 2376059Samurai RecvChapResult(chp, bp); 2386059Samurai break; 2396059Samurai } 2406059Samurai } 2416059Samurai } 2426059Samurai pfree(bp); 2436059Samurai} 244