chap.c revision 23603
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 * 2023603Sache * $Id: chap.c,v 1.10 1997/02/22 16:10:05 peter 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" 326059Samurai#include "vars.h" 336735Samurai#include "auth.h" 346059Samurai 356059Samuraistatic char *chapcodes[] = { 3619866Sphk "???", "CHALLENGE", "RESPONSE", "SUCCESS", "FAILURE" 376059Samurai}; 386059Samurai 396735Samuraistruct authinfo AuthChapInfo = { 406735Samurai SendChapChallenge, 416735Samurai}; 426735Samurai 436059Samuraiextern char *AuthGetSecret(); 4423603Sacheextern int randinit; 456059Samurai 466059Samuraivoid 476059SamuraiChapOutput(code, id, ptr, count) 486059Samuraiu_int code, id; 496059Samuraiu_char *ptr; 506059Samuraiint count; 516059Samurai{ 526059Samurai int plen; 536059Samurai struct fsmheader lh; 546059Samurai struct mbuf *bp; 556059Samurai 566059Samurai plen = sizeof(struct fsmheader) + count; 576059Samurai lh.code = code; 586059Samurai lh.id = id; 596059Samurai lh.length = htons(plen); 606059Samurai bp = mballoc(plen, MB_FSM); 616059Samurai bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader)); 626059Samurai if (count) 636059Samurai bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count); 646059Samurai#ifdef DEBUG 656059Samurai DumpBp(bp); 666059Samurai#endif 6715738Sphk LogPrintf(LOG_LCP_BIT, "ChapOutput: %s\n", chapcodes[code]); 6813733Sdfr HdlcOutput(PRI_LINK, PROTO_CHAP, bp); 696059Samurai} 706059Samurai 716059Samurai 726059Samuraistatic char challenge_data[80]; 736059Samuraistatic int challenge_len; 746059Samurai 756059Samuraivoid 766735SamuraiSendChapChallenge(chapid) 776735Samuraiint chapid; 786059Samurai{ 7913379Sphk int len, i; 806059Samurai char *cp; 816059Samurai 8223603Sache if (!randinit) { 8323603Sache srandom((unsigned)(time(NULL) ^ getpid())); 8423603Sache randinit = 1; 8523603Sache } 866059Samurai 876059Samurai cp = challenge_data; 886059Samurai *cp++ = challenge_len = random() % 32 + 16; 896059Samurai for (i = 0; i < challenge_len; i++) 906059Samurai *cp++ = random() & 0xff; 916059Samurai len = strlen(VarAuthName); 926059Samurai bcopy(VarAuthName, cp, len); 936059Samurai cp += len; 946059Samurai ChapOutput(CHAP_CHALLENGE, chapid, challenge_data, cp - challenge_data); 956059Samurai} 966059Samurai 976059Samurai#ifdef DEBUG 986059Samuraivoid 996059SamuraiDumpDigest(mes, cp, len) 1006059Samuraichar *mes; 1016059Samuraichar *cp; 1026735Samuraiint len; 1036059Samurai{ 1046059Samurai int i; 1056059Samurai 1066059Samurai logprintf("%s: ", mes); 1076059Samurai for (i = 0; i < len; i++) { 1086059Samurai logprintf(" %02x", *cp++ & 0xff); 1096059Samurai } 1106059Samurai logprintf("\n"); 1116059Samurai} 1126059Samurai#endif 1136059Samurai 1146059Samuraivoid 1156059SamuraiRecvChapTalk(chp, bp) 1166059Samuraistruct fsmheader *chp; 1176059Samuraistruct mbuf *bp; 1186059Samurai{ 1196059Samurai int valsize, len; 1206059Samurai int arglen, keylen, namelen; 1216059Samurai char *cp, *argp, *ap, *name, *digest; 1226059Samurai char *keyp; 1236059Samurai MD5_CTX context; /* context */ 1246059Samurai char answer[100]; 1256059Samurai char cdigest[16]; 1266059Samurai 1276059Samurai len = ntohs(chp->length); 1286059Samurai#ifdef DEBUG 1296059Samurai logprintf("length: %d\n", len); 1306059Samurai#endif 1316059Samurai arglen = len - sizeof(struct fsmheader); 1326059Samurai cp = (char *)MBUF_CTOP(bp); 1336059Samurai valsize = *cp++ & 255; 1346059Samurai name = cp + valsize; 1356059Samurai namelen = arglen - valsize - 1; 1366059Samurai name[namelen] = 0; 13715738Sphk LogPrintf(LOG_PHASE_BIT, " Valsize = %d, Name = %s\n", valsize, name); 1386059Samurai 1396059Samurai /* 1406059Samurai * Get a secret key corresponds to the peer 1416059Samurai */ 1426059Samurai keyp = AuthGetSecret(SECRETFILE, name, namelen, chp->code == CHAP_RESPONSE); 1436059Samurai 1446059Samurai switch (chp->code) { 1456059Samurai case CHAP_CHALLENGE: 1466059Samurai if (keyp) { 1476059Samurai keylen = strlen(keyp); 1486059Samurai } else { 1496059Samurai keylen = strlen(VarAuthKey); 1506059Samurai keyp = VarAuthKey; 1516059Samurai } 1526059Samurai name = VarAuthName; 1536059Samurai namelen = strlen(VarAuthName); 15418885Sjkh argp = malloc(1 + valsize + namelen + 16); 1556059Samurai digest = argp; 1566059Samurai *digest++ = 16; /* value size */ 1576059Samurai ap = answer; 1586059Samurai *ap++ = chp->id; 1596059Samurai bcopy(keyp, ap, keylen); 1606059Samurai ap += keylen; 1616059Samurai bcopy(cp, ap, valsize); 1626059Samurai#ifdef DEBUG 1636059Samurai DumpDigest("recv", ap, valsize); 1646059Samurai#endif 1656059Samurai ap += valsize; 1666059Samurai MD5Init(&context); 1676059Samurai MD5Update(&context, answer, ap - answer); 1686059Samurai MD5Final(digest, &context); 1696059Samurai#ifdef DEBUG 1706059Samurai DumpDigest("answer", digest, 16); 1716059Samurai#endif 1726059Samurai bcopy(name, digest + 16, namelen); 1736059Samurai ap += namelen; 1746059Samurai /* Send answer to the peer */ 1756059Samurai ChapOutput(CHAP_RESPONSE, chp->id, argp, namelen + 17); 17618885Sjkh free(argp); 1776059Samurai break; 1786059Samurai case CHAP_RESPONSE: 1796059Samurai if (keyp) { 1806059Samurai /* 1816059Samurai * Compute correct digest value 1826059Samurai */ 1836059Samurai keylen = strlen(keyp); 1846059Samurai ap = answer; 1856059Samurai *ap++ = chp->id; 1866059Samurai bcopy(keyp, ap, keylen); 1876059Samurai ap += keylen; 1886059Samurai MD5Init(&context); 1896059Samurai MD5Update(&context, answer, ap - answer); 1906059Samurai MD5Update(&context, challenge_data+1, challenge_len); 1916059Samurai MD5Final(cdigest, &context); 1926059Samurai#ifdef DEBUG 1936059Samurai DumpDigest("got", cp, 16); 1946059Samurai DumpDigest("expect", cdigest, 16); 1956059Samurai#endif 1966059Samurai /* 1976059Samurai * Compare with the response 1986059Samurai */ 1996059Samurai if (bcmp(cp, cdigest, 16) == 0) { 2006059Samurai ChapOutput(CHAP_SUCCESS, chp->id, "Wellcome!!", 10); 2016059Samurai NewPhase(PHASE_NETWORK); 2026059Samurai break; 2036059Samurai } 2046059Samurai } 2056059Samurai /* 2066059Samurai * Peer is not registerd, or response digest is wrong. 2076059Samurai */ 2086059Samurai ChapOutput(CHAP_FAILURE, chp->id, "Invalid!!", 9); 2096059Samurai LcpClose(); 2106059Samurai break; 2116059Samurai } 2126059Samurai} 2136059Samurai 2146059Samuraivoid 2156059SamuraiRecvChapResult(chp, bp) 2166059Samuraistruct fsmheader *chp; 2176059Samuraistruct mbuf *bp; 2186059Samurai{ 2196059Samurai int len; 2206059Samurai struct lcpstate *lcp = &LcpInfo; 2216059Samurai 2226059Samurai len = ntohs(chp->length); 2236059Samurai#ifdef DEBUG 2246059Samurai logprintf("length: %d\n", len); 2256059Samurai#endif 2266059Samurai if (chp->code == CHAP_SUCCESS) { 2276059Samurai if (lcp->auth_iwait == PROTO_CHAP) { 2286059Samurai lcp->auth_iwait = 0; 2296059Samurai if (lcp->auth_ineed == 0) 2306059Samurai NewPhase(PHASE_NETWORK); 2316059Samurai } 2326059Samurai } else { 2336059Samurai /* 2346059Samurai * Maybe, we shoud close LCP. Of cause, peer may take close action, too. 2356059Samurai */ 2366059Samurai ; 2376059Samurai } 2386059Samurai} 2396059Samurai 2406059Samuraivoid 2416059SamuraiChapInput(struct mbuf *bp) 2426059Samurai{ 2436059Samurai int len = plength(bp); 2446059Samurai struct fsmheader *chp; 2456059Samurai 2466059Samurai if (len >= sizeof(struct fsmheader)) { 2476059Samurai chp = (struct fsmheader *)MBUF_CTOP(bp); 2486059Samurai if (len >= ntohs(chp->length)) { 2496059Samurai if (chp->code < 1 || chp->code > 4) 2506059Samurai chp->code = 0; 25115738Sphk LogPrintf(LOG_LCP_BIT, "ChapInput: %s\n", chapcodes[chp->code]); 2526059Samurai 2536059Samurai bp->offset += sizeof(struct fsmheader); 2546059Samurai bp->cnt -= sizeof(struct fsmheader); 2556059Samurai 2566059Samurai switch (chp->code) { 2576735Samurai case CHAP_RESPONSE: 2586735Samurai StopAuthTimer(&AuthChapInfo); 2596735Samurai /* Fall into.. */ 2606059Samurai case CHAP_CHALLENGE: 2616059Samurai RecvChapTalk(chp, bp); 2626059Samurai break; 2636059Samurai case CHAP_SUCCESS: 2646059Samurai case CHAP_FAILURE: 2656059Samurai RecvChapResult(chp, bp); 2666059Samurai break; 2676059Samurai } 2686059Samurai } 2696059Samurai } 2706059Samurai pfree(bp); 2716059Samurai} 272