diff options
author | amurai <amurai@FreeBSD.org> | 1995-01-31 06:29:58 +0000 |
---|---|---|
committer | amurai <amurai@FreeBSD.org> | 1995-01-31 06:29:58 +0000 |
commit | 21ef2761fd1e5a4beb483da8bddf767d36540dce (patch) | |
tree | 3aecd1251d1647032ad1455f304eaeeaab4987d0 /usr.sbin/ppp/chap.c | |
parent | 0487956fcf018d602bfe99b0e3398c6f4d55680a (diff) | |
download | FreeBSD-src-21ef2761fd1e5a4beb483da8bddf767d36540dce.zip FreeBSD-src-21ef2761fd1e5a4beb483da8bddf767d36540dce.tar.gz |
Diffstat (limited to 'usr.sbin/ppp/chap.c')
-rw-r--r-- | usr.sbin/ppp/chap.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/usr.sbin/ppp/chap.c b/usr.sbin/ppp/chap.c new file mode 100644 index 0000000..2b86b40 --- /dev/null +++ b/usr.sbin/ppp/chap.c @@ -0,0 +1,259 @@ +/* + * PPP CHAP Module + * + * Written by Toshiharu OHNO (tony-o@iij.ad.jp) + * + * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Internet Initiative Japan, Inc. The name of the + * IIJ may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id:$ + * + * TODO: + * o Imprement retransmission timer. + */ +#include "fsm.h" +#include "chap.h" +#include "lcpproto.h" +#include "lcp.h" +#include "hdlc.h" +#include "phase.h" +#include "vars.h" + +static int chapid; + +static char *chapcodes[] = { + "???", "CHALLENGE", "RESPONCE", "SUCCESS", "FAILURE" +}; + +extern char *AuthGetSecret(); + +void +ChapOutput(code, id, ptr, count) +u_int code, id; +u_char *ptr; +int count; +{ + int plen; + struct fsmheader lh; + struct mbuf *bp; + + plen = sizeof(struct fsmheader) + count; + lh.code = code; + lh.id = id; + lh.length = htons(plen); + bp = mballoc(plen, MB_FSM); + bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader)); + if (count) + bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count); +#ifdef DEBUG + DumpBp(bp); +#endif + LogPrintf(LOG_LCP, "ChapOutput: %s\n", chapcodes[code]); + HdlcOutput(PRI_NORMAL, PROTO_CHAP, bp); +} + + +static char challenge_data[80]; +static int challenge_len; + +void +SendChapChallenge() +{ + int keylen, len, i; + char *cp; + + srandom(time(NULL)); + ++chapid; + + cp = challenge_data; + *cp++ = challenge_len = random() % 32 + 16; + for (i = 0; i < challenge_len; i++) + *cp++ = random() & 0xff; + len = strlen(VarAuthName); + bcopy(VarAuthName, cp, len); + cp += len; + ChapOutput(CHAP_CHALLENGE, chapid, challenge_data, cp - challenge_data); +} + +#ifdef DEBUG +void +DumpDigest(mes, cp, len) +char *mes; +char *cp; +{ + int i; + + logprintf("%s: ", mes); + for (i = 0; i < len; i++) { + logprintf(" %02x", *cp++ & 0xff); + } + logprintf("\n"); +} +#endif + +void +RecvChapTalk(chp, bp) +struct fsmheader *chp; +struct mbuf *bp; +{ + int valsize, len; + int arglen, keylen, namelen; + char *cp, *argp, *ap, *name, *digest; + char *keyp; + MD5_CTX context; /* context */ + char answer[100]; + char cdigest[16]; + + len = ntohs(chp->length); +#ifdef DEBUG + logprintf("length: %d\n", len); +#endif + arglen = len - sizeof(struct fsmheader); + cp = (char *)MBUF_CTOP(bp); + valsize = *cp++ & 255; + name = cp + valsize; + namelen = arglen - valsize - 1; + name[namelen] = 0; + LogPrintf(LOG_PHASE, " Valsize = %d, Name = %s\n", valsize, name); + + /* + * Get a secret key corresponds to the peer + */ + keyp = AuthGetSecret(SECRETFILE, name, namelen, chp->code == CHAP_RESPONSE); + + switch (chp->code) { + case CHAP_CHALLENGE: + if (keyp) { + keylen = strlen(keyp); + } else { + keylen = strlen(VarAuthKey); + keyp = VarAuthKey; + } + name = VarAuthName; + namelen = strlen(VarAuthName); + argp = malloc(1 + valsize + namelen); + digest = argp; + *digest++ = 16; /* value size */ + ap = answer; + *ap++ = chp->id; + bcopy(keyp, ap, keylen); + ap += keylen; + bcopy(cp, ap, valsize); +#ifdef DEBUG + DumpDigest("recv", ap, valsize); +#endif + ap += valsize; + MD5Init(&context); + MD5Update(&context, answer, ap - answer); + MD5Final(digest, &context); +#ifdef DEBUG + DumpDigest("answer", digest, 16); +#endif + bcopy(name, digest + 16, namelen); + ap += namelen; + /* Send answer to the peer */ + ChapOutput(CHAP_RESPONSE, chp->id, argp, namelen + 17); + break; + case CHAP_RESPONSE: + if (keyp) { + /* + * Compute correct digest value + */ + keylen = strlen(keyp); + ap = answer; + *ap++ = chp->id; + bcopy(keyp, ap, keylen); + ap += keylen; + MD5Init(&context); + MD5Update(&context, answer, ap - answer); + MD5Update(&context, challenge_data+1, challenge_len); + MD5Final(cdigest, &context); +#ifdef DEBUG + DumpDigest("got", cp, 16); + DumpDigest("expect", cdigest, 16); +#endif + /* + * Compare with the response + */ + if (bcmp(cp, cdigest, 16) == 0) { + ChapOutput(CHAP_SUCCESS, chp->id, "Wellcome!!", 10); + NewPhase(PHASE_NETWORK); + break; + } + } + /* + * Peer is not registerd, or response digest is wrong. + */ + ChapOutput(CHAP_FAILURE, chp->id, "Invalid!!", 9); + LcpClose(); + break; + } +} + +void +RecvChapResult(chp, bp) +struct fsmheader *chp; +struct mbuf *bp; +{ + int len; + struct lcpstate *lcp = &LcpInfo; + + len = ntohs(chp->length); +#ifdef DEBUG + logprintf("length: %d\n", len); +#endif + if (chp->code == CHAP_SUCCESS) { + if (lcp->auth_iwait == PROTO_CHAP) { + lcp->auth_iwait = 0; + if (lcp->auth_ineed == 0) + NewPhase(PHASE_NETWORK); + } + } else { + /* + * Maybe, we shoud close LCP. Of cause, peer may take close action, too. + */ + ; + } +} + +void +ChapInput(struct mbuf *bp) +{ + int len = plength(bp); + struct fsmheader *chp; + + if (len >= sizeof(struct fsmheader)) { + chp = (struct fsmheader *)MBUF_CTOP(bp); + if (len >= ntohs(chp->length)) { + if (chp->code < 1 || chp->code > 4) + chp->code = 0; + LogPrintf(LOG_LCP, "ChapInput: %s\n", chapcodes[chp->code]); + + bp->offset += sizeof(struct fsmheader); + bp->cnt -= sizeof(struct fsmheader); + + switch (chp->code) { + case CHAP_CHALLENGE: + case CHAP_RESPONSE: + RecvChapTalk(chp, bp); + break; + case CHAP_SUCCESS: + case CHAP_FAILURE: + RecvChapResult(chp, bp); + break; + } + } + } + pfree(bp); +} |