chap.c revision 19866
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 * 2019866Sphk * $Id: chap.c,v 1.7 1996/10/12 16:20:21 jkh 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(); 446059Samurai 456059Samuraivoid 466059SamuraiChapOutput(code, id, ptr, count) 476059Samuraiu_int code, id; 486059Samuraiu_char *ptr; 496059Samuraiint count; 506059Samurai{ 516059Samurai int plen; 526059Samurai struct fsmheader lh; 536059Samurai struct mbuf *bp; 546059Samurai 556059Samurai plen = sizeof(struct fsmheader) + count; 566059Samurai lh.code = code; 576059Samurai lh.id = id; 586059Samurai lh.length = htons(plen); 596059Samurai bp = mballoc(plen, MB_FSM); 606059Samurai bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader)); 616059Samurai if (count) 626059Samurai bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count); 636059Samurai#ifdef DEBUG 646059Samurai DumpBp(bp); 656059Samurai#endif 6615738Sphk LogPrintf(LOG_LCP_BIT, "ChapOutput: %s\n", chapcodes[code]); 6713733Sdfr HdlcOutput(PRI_LINK, PROTO_CHAP, bp); 686059Samurai} 696059Samurai 706059Samurai 716059Samuraistatic char challenge_data[80]; 726059Samuraistatic int challenge_len; 736059Samurai 746059Samuraivoid 756735SamuraiSendChapChallenge(chapid) 766735Samuraiint chapid; 776059Samurai{ 7813379Sphk int len, i; 796059Samurai char *cp; 806059Samurai 816059Samurai srandom(time(NULL)); 826059Samurai 836059Samurai cp = challenge_data; 846059Samurai *cp++ = challenge_len = random() % 32 + 16; 856059Samurai for (i = 0; i < challenge_len; i++) 866059Samurai *cp++ = random() & 0xff; 876059Samurai len = strlen(VarAuthName); 886059Samurai bcopy(VarAuthName, cp, len); 896059Samurai cp += len; 906059Samurai ChapOutput(CHAP_CHALLENGE, chapid, challenge_data, cp - challenge_data); 916059Samurai} 926059Samurai 936059Samurai#ifdef DEBUG 946059Samuraivoid 956059SamuraiDumpDigest(mes, cp, len) 966059Samuraichar *mes; 976059Samuraichar *cp; 986735Samuraiint len; 996059Samurai{ 1006059Samurai int i; 1016059Samurai 1026059Samurai logprintf("%s: ", mes); 1036059Samurai for (i = 0; i < len; i++) { 1046059Samurai logprintf(" %02x", *cp++ & 0xff); 1056059Samurai } 1066059Samurai logprintf("\n"); 1076059Samurai} 1086059Samurai#endif 1096059Samurai 1106059Samuraivoid 1116059SamuraiRecvChapTalk(chp, bp) 1126059Samuraistruct fsmheader *chp; 1136059Samuraistruct mbuf *bp; 1146059Samurai{ 1156059Samurai int valsize, len; 1166059Samurai int arglen, keylen, namelen; 1176059Samurai char *cp, *argp, *ap, *name, *digest; 1186059Samurai char *keyp; 1196059Samurai MD5_CTX context; /* context */ 1206059Samurai char answer[100]; 1216059Samurai char cdigest[16]; 1226059Samurai 1236059Samurai len = ntohs(chp->length); 1246059Samurai#ifdef DEBUG 1256059Samurai logprintf("length: %d\n", len); 1266059Samurai#endif 1276059Samurai arglen = len - sizeof(struct fsmheader); 1286059Samurai cp = (char *)MBUF_CTOP(bp); 1296059Samurai valsize = *cp++ & 255; 1306059Samurai name = cp + valsize; 1316059Samurai namelen = arglen - valsize - 1; 1326059Samurai name[namelen] = 0; 13315738Sphk LogPrintf(LOG_PHASE_BIT, " Valsize = %d, Name = %s\n", valsize, name); 1346059Samurai 1356059Samurai /* 1366059Samurai * Get a secret key corresponds to the peer 1376059Samurai */ 1386059Samurai keyp = AuthGetSecret(SECRETFILE, name, namelen, chp->code == CHAP_RESPONSE); 1396059Samurai 1406059Samurai switch (chp->code) { 1416059Samurai case CHAP_CHALLENGE: 1426059Samurai if (keyp) { 1436059Samurai keylen = strlen(keyp); 1446059Samurai } else { 1456059Samurai keylen = strlen(VarAuthKey); 1466059Samurai keyp = VarAuthKey; 1476059Samurai } 1486059Samurai name = VarAuthName; 1496059Samurai namelen = strlen(VarAuthName); 15018885Sjkh argp = malloc(1 + valsize + namelen + 16); 1516059Samurai digest = argp; 1526059Samurai *digest++ = 16; /* value size */ 1536059Samurai ap = answer; 1546059Samurai *ap++ = chp->id; 1556059Samurai bcopy(keyp, ap, keylen); 1566059Samurai ap += keylen; 1576059Samurai bcopy(cp, ap, valsize); 1586059Samurai#ifdef DEBUG 1596059Samurai DumpDigest("recv", ap, valsize); 1606059Samurai#endif 1616059Samurai ap += valsize; 1626059Samurai MD5Init(&context); 1636059Samurai MD5Update(&context, answer, ap - answer); 1646059Samurai MD5Final(digest, &context); 1656059Samurai#ifdef DEBUG 1666059Samurai DumpDigest("answer", digest, 16); 1676059Samurai#endif 1686059Samurai bcopy(name, digest + 16, namelen); 1696059Samurai ap += namelen; 1706059Samurai /* Send answer to the peer */ 1716059Samurai ChapOutput(CHAP_RESPONSE, chp->id, argp, namelen + 17); 17218885Sjkh free(argp); 1736059Samurai break; 1746059Samurai case CHAP_RESPONSE: 1756059Samurai if (keyp) { 1766059Samurai /* 1776059Samurai * Compute correct digest value 1786059Samurai */ 1796059Samurai keylen = strlen(keyp); 1806059Samurai ap = answer; 1816059Samurai *ap++ = chp->id; 1826059Samurai bcopy(keyp, ap, keylen); 1836059Samurai ap += keylen; 1846059Samurai MD5Init(&context); 1856059Samurai MD5Update(&context, answer, ap - answer); 1866059Samurai MD5Update(&context, challenge_data+1, challenge_len); 1876059Samurai MD5Final(cdigest, &context); 1886059Samurai#ifdef DEBUG 1896059Samurai DumpDigest("got", cp, 16); 1906059Samurai DumpDigest("expect", cdigest, 16); 1916059Samurai#endif 1926059Samurai /* 1936059Samurai * Compare with the response 1946059Samurai */ 1956059Samurai if (bcmp(cp, cdigest, 16) == 0) { 1966059Samurai ChapOutput(CHAP_SUCCESS, chp->id, "Wellcome!!", 10); 1976059Samurai NewPhase(PHASE_NETWORK); 1986059Samurai break; 1996059Samurai } 2006059Samurai } 2016059Samurai /* 2026059Samurai * Peer is not registerd, or response digest is wrong. 2036059Samurai */ 2046059Samurai ChapOutput(CHAP_FAILURE, chp->id, "Invalid!!", 9); 2056059Samurai LcpClose(); 2066059Samurai break; 2076059Samurai } 2086059Samurai} 2096059Samurai 2106059Samuraivoid 2116059SamuraiRecvChapResult(chp, bp) 2126059Samuraistruct fsmheader *chp; 2136059Samuraistruct mbuf *bp; 2146059Samurai{ 2156059Samurai int len; 2166059Samurai struct lcpstate *lcp = &LcpInfo; 2176059Samurai 2186059Samurai len = ntohs(chp->length); 2196059Samurai#ifdef DEBUG 2206059Samurai logprintf("length: %d\n", len); 2216059Samurai#endif 2226059Samurai if (chp->code == CHAP_SUCCESS) { 2236059Samurai if (lcp->auth_iwait == PROTO_CHAP) { 2246059Samurai lcp->auth_iwait = 0; 2256059Samurai if (lcp->auth_ineed == 0) 2266059Samurai NewPhase(PHASE_NETWORK); 2276059Samurai } 2286059Samurai } else { 2296059Samurai /* 2306059Samurai * Maybe, we shoud close LCP. Of cause, peer may take close action, too. 2316059Samurai */ 2326059Samurai ; 2336059Samurai } 2346059Samurai} 2356059Samurai 2366059Samuraivoid 2376059SamuraiChapInput(struct mbuf *bp) 2386059Samurai{ 2396059Samurai int len = plength(bp); 2406059Samurai struct fsmheader *chp; 2416059Samurai 2426059Samurai if (len >= sizeof(struct fsmheader)) { 2436059Samurai chp = (struct fsmheader *)MBUF_CTOP(bp); 2446059Samurai if (len >= ntohs(chp->length)) { 2456059Samurai if (chp->code < 1 || chp->code > 4) 2466059Samurai chp->code = 0; 24715738Sphk LogPrintf(LOG_LCP_BIT, "ChapInput: %s\n", chapcodes[chp->code]); 2486059Samurai 2496059Samurai bp->offset += sizeof(struct fsmheader); 2506059Samurai bp->cnt -= sizeof(struct fsmheader); 2516059Samurai 2526059Samurai switch (chp->code) { 2536735Samurai case CHAP_RESPONSE: 2546735Samurai StopAuthTimer(&AuthChapInfo); 2556735Samurai /* Fall into.. */ 2566059Samurai case CHAP_CHALLENGE: 2576059Samurai RecvChapTalk(chp, bp); 2586059Samurai break; 2596059Samurai case CHAP_SUCCESS: 2606059Samurai case CHAP_FAILURE: 2616059Samurai RecvChapResult(chp, bp); 2626059Samurai break; 2636059Samurai } 2646059Samurai } 2656059Samurai } 2666059Samurai pfree(bp); 2676059Samurai} 268