summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ppp/chap.c
diff options
context:
space:
mode:
authoramurai <amurai@FreeBSD.org>1995-01-31 06:29:58 +0000
committeramurai <amurai@FreeBSD.org>1995-01-31 06:29:58 +0000
commit21ef2761fd1e5a4beb483da8bddf767d36540dce (patch)
tree3aecd1251d1647032ad1455f304eaeeaab4987d0 /usr.sbin/ppp/chap.c
parent0487956fcf018d602bfe99b0e3398c6f4d55680a (diff)
downloadFreeBSD-src-21ef2761fd1e5a4beb483da8bddf767d36540dce.zip
FreeBSD-src-21ef2761fd1e5a4beb483da8bddf767d36540dce.tar.gz
Diffstat (limited to 'usr.sbin/ppp/chap.c')
-rw-r--r--usr.sbin/ppp/chap.c259
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);
+}
OpenPOWER on IntegriCloud