chap.c revision 25908
1229997Sken/* 2229997Sken * PPP CHAP Module 3229997Sken * 4232604Strasz * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5229997Sken * 6229997Sken * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7232604Strasz * 8232604Strasz * Redistribution and use in source and binary forms are permitted 9232604Strasz * provided that the above copyright notice and this paragraph are 10229997Sken * duplicated in all such forms and that any documentation, 11229997Sken * advertising materials, and other materials related to such 12229997Sken * distribution and use acknowledge that the software was developed 13229997Sken * by the Internet Initiative Japan, Inc. The name of the 14229997Sken * IIJ may not be used to endorse or promote products derived 15229997Sken * from this software without specific prior written permission. 16229997Sken * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17229997Sken * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18229997Sken * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19229997Sken * 20229997Sken * $Id: chap.c,v 1.14 1997/05/10 01:22:06 brian Exp $ 21229997Sken * 22229997Sken * TODO: 23229997Sken */ 24229997Sken#include <sys/types.h> 25229997Sken#include <time.h> 26229997Sken#include "fsm.h" 27229997Sken#include "chap.h" 28229997Sken#include "lcpproto.h" 29229997Sken#include "lcp.h" 30229997Sken#include "hdlc.h" 31229997Sken#include "phase.h" 32229997Sken#include "vars.h" 33229997Sken#include "auth.h" 34229997Sken 35229997Skenstatic char *chapcodes[] = { 36229997Sken "???", "CHALLENGE", "RESPONSE", "SUCCESS", "FAILURE" 37229997Sken}; 38229997Sken 39229997Skenstruct authinfo AuthChapInfo = { 40229997Sken SendChapChallenge, 41229997Sken}; 42229997Sken 43229997Skenextern char *AuthGetSecret(); 44229997Skenextern int randinit; 45229997Sken 46229997Skenvoid 47229997SkenChapOutput(code, id, ptr, count) 48229997Skenu_int code, id; 49229997Skenu_char *ptr; 50229997Skenint count; 51229997Sken{ 52229997Sken int plen; 53229997Sken struct fsmheader lh; 54229997Sken struct mbuf *bp; 55229997Sken 56229997Sken plen = sizeof(struct fsmheader) + count; 57229997Sken lh.code = code; 58229997Sken lh.id = id; 59229997Sken lh.length = htons(plen); 60229997Sken bp = mballoc(plen, MB_FSM); 61229997Sken bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader)); 62229997Sken if (count) 63229997Sken bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count); 64229997Sken#ifdef DEBUG 65229997Sken DumpBp(bp); 66229997Sken#endif 67229997Sken LogPrintf(LOG_LCP_BIT, "ChapOutput: %s\n", chapcodes[code]); 68229997Sken HdlcOutput(PRI_LINK, PROTO_CHAP, bp); 69229997Sken} 70229997Sken 71229997Sken 72229997Skenstatic char challenge_data[80]; 73229997Skenstatic int challenge_len; 74229997Sken 75229997Skenvoid 76229997SkenSendChapChallenge(chapid) 77229997Skenint chapid; 78229997Sken{ 79229997Sken int len, i; 80229997Sken char *cp; 81229997Sken 82229997Sken if (!randinit) { 83229997Sken randinit = 1; 84229997Sken if (srandomdev() < 0) 85229997Sken srandom((unsigned long)(time(NULL) ^ getpid())); 86229997Sken } 87229997Sken 88229997Sken cp = challenge_data; 89229997Sken *cp++ = challenge_len = random() % 32 + 16; 90229997Sken for (i = 0; i < challenge_len; i++) 91229997Sken *cp++ = random() & 0xff; 92229997Sken len = strlen(VarAuthName); 93229997Sken bcopy(VarAuthName, cp, len); 94229997Sken cp += len; 95229997Sken ChapOutput(CHAP_CHALLENGE, chapid, challenge_data, cp - challenge_data); 96229997Sken} 97229997Sken 98229997Sken#ifdef DEBUG 99229997Skenvoid 100229997SkenDumpDigest(mes, cp, len) 101229997Skenchar *mes; 102229997Skenchar *cp; 103229997Skenint len; 104229997Sken{ 105229997Sken int i; 106229997Sken 107229997Sken logprintf("%s: ", mes); 108229997Sken for (i = 0; i < len; i++) { 109229997Sken logprintf(" %02x", *cp++ & 0xff); 110229997Sken } 111229997Sken logprintf("\n"); 112229997Sken} 113229997Sken#endif 114229997Sken 115229997Skenvoid 116229997SkenRecvChapTalk(chp, bp) 117229997Skenstruct fsmheader *chp; 118229997Skenstruct mbuf *bp; 119229997Sken{ 120229997Sken int valsize, len; 121229997Sken int arglen, keylen, namelen; 122229997Sken char *cp, *argp, *ap, *name, *digest; 123229997Sken char *keyp; 124229997Sken MD5_CTX context; /* context */ 125229997Sken char answer[100]; 126229997Sken char cdigest[16]; 127229997Sken 128229997Sken len = ntohs(chp->length); 129229997Sken#ifdef DEBUG 130229997Sken logprintf("length: %d\n", len); 131229997Sken#endif 132229997Sken arglen = len - sizeof(struct fsmheader); 133229997Sken cp = (char *)MBUF_CTOP(bp); 134229997Sken valsize = *cp++ & 255; 135229997Sken name = cp + valsize; 136229997Sken namelen = arglen - valsize - 1; 137229997Sken name[namelen] = 0; 138229997Sken LogPrintf(LOG_PHASE_BIT, " Valsize = %d, Name = %s\n", valsize, name); 139229997Sken 140229997Sken /* 141229997Sken * Get a secret key corresponds to the peer 142229997Sken */ 143229997Sken keyp = AuthGetSecret(SECRETFILE, name, namelen, chp->code == CHAP_RESPONSE); 144229997Sken 145229997Sken switch (chp->code) { 146229997Sken case CHAP_CHALLENGE: 147229997Sken if (keyp) { 148229997Sken keylen = strlen(keyp); 149229997Sken } else { 150229997Sken keylen = strlen(VarAuthKey); 151229997Sken keyp = VarAuthKey; 152229997Sken } 153229997Sken name = VarAuthName; 154229997Sken namelen = strlen(VarAuthName); 155229997Sken argp = malloc(1 + valsize + namelen + 16); 156229997Sken if (argp == NULL) { 157229997Sken ChapOutput(CHAP_FAILURE, chp->id, "Out of memory!", 14); 158229997Sken return; 159264191Smav } 160264191Smav digest = argp; 161229997Sken *digest++ = 16; /* value size */ 162229997Sken ap = answer; 163229997Sken *ap++ = chp->id; 164229997Sken bcopy(keyp, ap, keylen); 165229997Sken ap += keylen; 166229997Sken bcopy(cp, ap, valsize); 167229997Sken#ifdef DEBUG 168229997Sken DumpDigest("recv", ap, valsize); 169229997Sken#endif 170229997Sken ap += valsize; 171229997Sken MD5Init(&context); 172229997Sken MD5Update(&context, answer, ap - answer); 173229997Sken MD5Final(digest, &context); 174229997Sken#ifdef DEBUG 175229997Sken DumpDigest("answer", digest, 16); 176229997Sken#endif 177229997Sken bcopy(name, digest + 16, namelen); 178229997Sken ap += namelen; 179229997Sken /* Send answer to the peer */ 180229997Sken ChapOutput(CHAP_RESPONSE, chp->id, argp, namelen + 17); 181229997Sken free(argp); 182229997Sken break; 183229997Sken case CHAP_RESPONSE: 184229997Sken if (keyp) { 185229997Sken /* 186229997Sken * Compute correct digest value 187229997Sken */ 188229997Sken keylen = strlen(keyp); 189229997Sken ap = answer; 190229997Sken *ap++ = chp->id; 191229997Sken bcopy(keyp, ap, keylen); 192229997Sken ap += keylen; 193229997Sken MD5Init(&context); 194229997Sken MD5Update(&context, answer, ap - answer); 195229997Sken MD5Update(&context, challenge_data+1, challenge_len); 196229997Sken MD5Final(cdigest, &context); 197229997Sken#ifdef DEBUG 198229997Sken DumpDigest("got", cp, 16); 199229997Sken DumpDigest("expect", cdigest, 16); 200229997Sken#endif 201229997Sken /* 202229997Sken * Compare with the response 203229997Sken */ 204229997Sken if (bcmp(cp, cdigest, 16) == 0) { 205229997Sken ChapOutput(CHAP_SUCCESS, chp->id, "Wellcome!!", 10); 206229997Sken NewPhase(PHASE_NETWORK); 207229997Sken break; 208229997Sken } 209229997Sken } 210229997Sken /* 211229997Sken * Peer is not registerd, or response digest is wrong. 212229997Sken */ 213229997Sken ChapOutput(CHAP_FAILURE, chp->id, "Invalid!!", 9); 214229997Sken LcpClose(); 215229997Sken reconnectCount = 0; 216229997Sken break; 217229997Sken } 218229997Sken} 219229997Sken 220229997Skenvoid 221229997SkenRecvChapResult(chp, bp) 222229997Skenstruct fsmheader *chp; 223229997Skenstruct mbuf *bp; 224229997Sken{ 225229997Sken int len; 226229997Sken struct lcpstate *lcp = &LcpInfo; 227229997Sken 228229997Sken len = ntohs(chp->length); 229229997Sken#ifdef DEBUG 230229997Sken logprintf("length: %d\n", len); 231229997Sken#endif 232229997Sken if (chp->code == CHAP_SUCCESS) { 233229997Sken if (lcp->auth_iwait == PROTO_CHAP) { 234229997Sken lcp->auth_iwait = 0; 235229997Sken if (lcp->auth_ineed == 0) 236229997Sken NewPhase(PHASE_NETWORK); 237229997Sken } 238229997Sken } else { 239229997Sken /* 240229997Sken * Maybe, we shoud close LCP. Of cause, peer may take close action, too. 241229997Sken */ 242229997Sken ; 243229997Sken } 244229997Sken} 245229997Sken 246229997Skenvoid 247229997SkenChapInput(struct mbuf *bp) 248229997Sken{ 249229997Sken int len = plength(bp); 250232604Strasz struct fsmheader *chp; 251232604Strasz 252232604Strasz if (len >= sizeof(struct fsmheader)) { 253232604Strasz chp = (struct fsmheader *)MBUF_CTOP(bp); 254232604Strasz if (len >= ntohs(chp->length)) { 255232604Strasz if (chp->code < 1 || chp->code > 4) 256229997Sken chp->code = 0; 257229997Sken LogPrintf(LOG_LCP_BIT, "ChapInput: %s\n", chapcodes[chp->code]); 258229997Sken 259229997Sken bp->offset += sizeof(struct fsmheader); 260229997Sken bp->cnt -= sizeof(struct fsmheader); 261229997Sken 262229997Sken switch (chp->code) { 263229997Sken case CHAP_RESPONSE: 264229997Sken StopAuthTimer(&AuthChapInfo); 265229997Sken /* Fall into.. */ 266230334Sken case CHAP_CHALLENGE: 267230334Sken RecvChapTalk(chp, bp); 268230334Sken break; 269230334Sken case CHAP_SUCCESS: 270230334Sken case CHAP_FAILURE: 271230334Sken RecvChapResult(chp, bp); 272230334Sken break; 273230334Sken } 274230334Sken } 275229997Sken } 276229997Sken pfree(bp); 277229997Sken} 278229997Sken