chap.c revision 6735
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. 196735Samurai * 206059Samurai * $Id:$ 216735Samurai * 226059Samurai * TODO: 236059Samurai */ 246059Samurai#include "fsm.h" 256059Samurai#include "chap.h" 266059Samurai#include "lcpproto.h" 276059Samurai#include "lcp.h" 286059Samurai#include "hdlc.h" 296059Samurai#include "phase.h" 306059Samurai#include "vars.h" 316735Samurai#include "auth.h" 326059Samurai 336059Samuraistatic char *chapcodes[] = { 346059Samurai "???", "CHALLENGE", "RESPONCE", "SUCCESS", "FAILURE" 356059Samurai}; 366059Samurai 376735Samuraistruct authinfo AuthChapInfo = { 386735Samurai SendChapChallenge, 396735Samurai}; 406735Samurai 416059Samuraiextern char *AuthGetSecret(); 426059Samurai 436059Samuraivoid 446059SamuraiChapOutput(code, id, ptr, count) 456059Samuraiu_int code, id; 466059Samuraiu_char *ptr; 476059Samuraiint count; 486059Samurai{ 496059Samurai int plen; 506059Samurai struct fsmheader lh; 516059Samurai struct mbuf *bp; 526059Samurai 536059Samurai plen = sizeof(struct fsmheader) + count; 546059Samurai lh.code = code; 556059Samurai lh.id = id; 566059Samurai lh.length = htons(plen); 576059Samurai bp = mballoc(plen, MB_FSM); 586059Samurai bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader)); 596059Samurai if (count) 606059Samurai bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count); 616059Samurai#ifdef DEBUG 626059Samurai DumpBp(bp); 636059Samurai#endif 646059Samurai LogPrintf(LOG_LCP, "ChapOutput: %s\n", chapcodes[code]); 656059Samurai HdlcOutput(PRI_NORMAL, PROTO_CHAP, bp); 666059Samurai} 676059Samurai 686059Samurai 696059Samuraistatic char challenge_data[80]; 706059Samuraistatic int challenge_len; 716059Samurai 726059Samuraivoid 736735SamuraiSendChapChallenge(chapid) 746735Samuraiint chapid; 756059Samurai{ 766059Samurai int keylen, len, i; 776059Samurai char *cp; 786059Samurai 796059Samurai srandom(time(NULL)); 806059Samurai 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 916059Samurai#ifdef DEBUG 926059Samuraivoid 936059SamuraiDumpDigest(mes, cp, len) 946059Samuraichar *mes; 956059Samuraichar *cp; 966735Samuraiint len; 976059Samurai{ 986059Samurai int i; 996059Samurai 1006059Samurai logprintf("%s: ", mes); 1016059Samurai for (i = 0; i < len; i++) { 1026059Samurai logprintf(" %02x", *cp++ & 0xff); 1036059Samurai } 1046059Samurai logprintf("\n"); 1056059Samurai} 1066059Samurai#endif 1076059Samurai 1086059Samuraivoid 1096059SamuraiRecvChapTalk(chp, bp) 1106059Samuraistruct fsmheader *chp; 1116059Samuraistruct mbuf *bp; 1126059Samurai{ 1136059Samurai int valsize, len; 1146059Samurai int arglen, keylen, namelen; 1156059Samurai char *cp, *argp, *ap, *name, *digest; 1166059Samurai char *keyp; 1176059Samurai MD5_CTX context; /* context */ 1186059Samurai char answer[100]; 1196059Samurai char cdigest[16]; 1206059Samurai 1216059Samurai len = ntohs(chp->length); 1226059Samurai#ifdef DEBUG 1236059Samurai logprintf("length: %d\n", len); 1246059Samurai#endif 1256059Samurai arglen = len - sizeof(struct fsmheader); 1266059Samurai cp = (char *)MBUF_CTOP(bp); 1276059Samurai valsize = *cp++ & 255; 1286059Samurai name = cp + valsize; 1296059Samurai namelen = arglen - valsize - 1; 1306059Samurai name[namelen] = 0; 1316059Samurai LogPrintf(LOG_PHASE, " Valsize = %d, Name = %s\n", valsize, name); 1326059Samurai 1336059Samurai /* 1346059Samurai * Get a secret key corresponds to the peer 1356059Samurai */ 1366059Samurai keyp = AuthGetSecret(SECRETFILE, name, namelen, chp->code == CHAP_RESPONSE); 1376059Samurai 1386059Samurai switch (chp->code) { 1396059Samurai case CHAP_CHALLENGE: 1406059Samurai if (keyp) { 1416059Samurai keylen = strlen(keyp); 1426059Samurai } else { 1436059Samurai keylen = strlen(VarAuthKey); 1446059Samurai keyp = VarAuthKey; 1456059Samurai } 1466059Samurai name = VarAuthName; 1476059Samurai namelen = strlen(VarAuthName); 1486059Samurai argp = malloc(1 + valsize + namelen); 1496059Samurai digest = argp; 1506059Samurai *digest++ = 16; /* value size */ 1516059Samurai ap = answer; 1526059Samurai *ap++ = chp->id; 1536059Samurai bcopy(keyp, ap, keylen); 1546059Samurai ap += keylen; 1556059Samurai bcopy(cp, ap, valsize); 1566059Samurai#ifdef DEBUG 1576059Samurai DumpDigest("recv", ap, valsize); 1586059Samurai#endif 1596059Samurai ap += valsize; 1606059Samurai MD5Init(&context); 1616059Samurai MD5Update(&context, answer, ap - answer); 1626059Samurai MD5Final(digest, &context); 1636059Samurai#ifdef DEBUG 1646059Samurai DumpDigest("answer", digest, 16); 1656059Samurai#endif 1666059Samurai bcopy(name, digest + 16, namelen); 1676059Samurai ap += namelen; 1686059Samurai /* Send answer to the peer */ 1696059Samurai ChapOutput(CHAP_RESPONSE, chp->id, argp, namelen + 17); 1706059Samurai break; 1716059Samurai case CHAP_RESPONSE: 1726059Samurai if (keyp) { 1736059Samurai /* 1746059Samurai * Compute correct digest value 1756059Samurai */ 1766059Samurai keylen = strlen(keyp); 1776059Samurai ap = answer; 1786059Samurai *ap++ = chp->id; 1796059Samurai bcopy(keyp, ap, keylen); 1806059Samurai ap += keylen; 1816059Samurai MD5Init(&context); 1826059Samurai MD5Update(&context, answer, ap - answer); 1836059Samurai MD5Update(&context, challenge_data+1, challenge_len); 1846059Samurai MD5Final(cdigest, &context); 1856059Samurai#ifdef DEBUG 1866059Samurai DumpDigest("got", cp, 16); 1876059Samurai DumpDigest("expect", cdigest, 16); 1886059Samurai#endif 1896059Samurai /* 1906059Samurai * Compare with the response 1916059Samurai */ 1926059Samurai if (bcmp(cp, cdigest, 16) == 0) { 1936059Samurai ChapOutput(CHAP_SUCCESS, chp->id, "Wellcome!!", 10); 1946059Samurai NewPhase(PHASE_NETWORK); 1956059Samurai break; 1966059Samurai } 1976059Samurai } 1986059Samurai /* 1996059Samurai * Peer is not registerd, or response digest is wrong. 2006059Samurai */ 2016059Samurai ChapOutput(CHAP_FAILURE, chp->id, "Invalid!!", 9); 2026059Samurai LcpClose(); 2036059Samurai break; 2046059Samurai } 2056059Samurai} 2066059Samurai 2076059Samuraivoid 2086059SamuraiRecvChapResult(chp, bp) 2096059Samuraistruct fsmheader *chp; 2106059Samuraistruct mbuf *bp; 2116059Samurai{ 2126059Samurai int len; 2136059Samurai struct lcpstate *lcp = &LcpInfo; 2146059Samurai 2156059Samurai len = ntohs(chp->length); 2166059Samurai#ifdef DEBUG 2176059Samurai logprintf("length: %d\n", len); 2186059Samurai#endif 2196059Samurai if (chp->code == CHAP_SUCCESS) { 2206059Samurai if (lcp->auth_iwait == PROTO_CHAP) { 2216059Samurai lcp->auth_iwait = 0; 2226059Samurai if (lcp->auth_ineed == 0) 2236059Samurai NewPhase(PHASE_NETWORK); 2246059Samurai } 2256059Samurai } else { 2266059Samurai /* 2276059Samurai * Maybe, we shoud close LCP. Of cause, peer may take close action, too. 2286059Samurai */ 2296059Samurai ; 2306059Samurai } 2316059Samurai} 2326059Samurai 2336059Samuraivoid 2346059SamuraiChapInput(struct mbuf *bp) 2356059Samurai{ 2366059Samurai int len = plength(bp); 2376059Samurai struct fsmheader *chp; 2386059Samurai 2396059Samurai if (len >= sizeof(struct fsmheader)) { 2406059Samurai chp = (struct fsmheader *)MBUF_CTOP(bp); 2416059Samurai if (len >= ntohs(chp->length)) { 2426059Samurai if (chp->code < 1 || chp->code > 4) 2436059Samurai chp->code = 0; 2446059Samurai LogPrintf(LOG_LCP, "ChapInput: %s\n", chapcodes[chp->code]); 2456059Samurai 2466059Samurai bp->offset += sizeof(struct fsmheader); 2476059Samurai bp->cnt -= sizeof(struct fsmheader); 2486059Samurai 2496059Samurai switch (chp->code) { 2506735Samurai case CHAP_RESPONSE: 2516735Samurai StopAuthTimer(&AuthChapInfo); 2526735Samurai /* Fall into.. */ 2536059Samurai case CHAP_CHALLENGE: 2546059Samurai RecvChapTalk(chp, bp); 2556059Samurai break; 2566059Samurai case CHAP_SUCCESS: 2576059Samurai case CHAP_FAILURE: 2586059Samurai RecvChapResult(chp, bp); 2596059Samurai break; 2606059Samurai } 2616059Samurai } 2626059Samurai } 2636059Samurai pfree(bp); 2646059Samurai} 265