From 58330d7bfad4d97dad6a42357ebbd436389057dd Mon Sep 17 00:00:00 2001 From: Brian Somers Date: Thu, 11 Feb 1999 10:14:08 +0000 Subject: [PATCH] When resending chap challenges, resend the same challenge each time rather than making up a new one. Increase the authname/authkey max sizes to 100 characters. Allow ``authkey'' specifications beginning with ``!''. When a challenge is received, the text following the ``!'' is executed as a program (expanding stuff in the same way that ``sh'' and ``!bg'' do). The program is passed the peer name, peer challenge and local ``authname'' on standard input and is expected to output the name/key combination that should be used to build the CHAP response. This provides support for Secure ID cards (guess what I was given at work recently!) using CHAP. Examples will follow. --- usr.sbin/ppp/chap.c | 271 +++++++++++++++++++++++++++++++++----- usr.sbin/ppp/chap.h | 16 ++- usr.sbin/ppp/command.c | 14 +- usr.sbin/ppp/command.h | 4 +- usr.sbin/ppp/datalink.c | 26 +++- usr.sbin/ppp/defs.h | 4 +- usr.sbin/ppp/descriptor.h | 3 +- usr.sbin/ppp/hdlc.c | 4 +- usr.sbin/ppp/ppp.8 | 62 ++++++++- usr.sbin/ppp/ppp.8.m4 | 62 ++++++++- 10 files changed, 404 insertions(+), 62 deletions(-) diff --git a/usr.sbin/ppp/chap.c b/usr.sbin/ppp/chap.c index 495fdded5820..1c937cdefda0 100644 --- a/usr.sbin/ppp/chap.c +++ b/usr.sbin/ppp/chap.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: chap.c,v 1.41 1999/02/07 13:48:38 brian Exp $ + * $Id: chap.c,v 1.42 1999/02/07 13:56:29 brian Exp $ * * TODO: */ @@ -27,13 +27,19 @@ #include #include +#include +#include #ifdef HAVE_DES #include #include #endif #include +#include +#include #include +#include #include +#include #include "mbuf.h" #include "log.h" @@ -45,10 +51,10 @@ #include "lqr.h" #include "hdlc.h" #include "auth.h" -#include "chap.h" #include "async.h" #include "throughput.h" #include "descriptor.h" +#include "chap.h" #include "iplist.h" #include "slcompress.h" #include "ipcp.h" @@ -63,6 +69,7 @@ #include "bundle.h" #include "chat.h" #include "cbcp.h" +#include "command.h" #include "datalink.h" #ifdef HAVE_DES #include "chap_ms.h" @@ -174,6 +181,201 @@ chap_BuildAnswer(char *name, char *key, u_char id, char *challenge, int MSChap) return result; } +static void +chap_StartChild(struct chap *chap, char *prog, const char *name) +{ + char *argv[MAXARGS], *nargv[MAXARGS]; + int argc, fd; + int in[2], out[2]; + + if (chap->child.fd != -1) { + log_Printf(LogWARN, "Chap: %s: Program already running\n", prog); + return; + } + + if (pipe(in) == -1) { + log_Printf(LogERROR, "Chap: pipe: %s\n", strerror(errno)); + return; + } + + if (pipe(out) == -1) { + log_Printf(LogERROR, "Chap: pipe: %s\n", strerror(errno)); + close(in[0]); + close(in[1]); + return; + } + + switch ((chap->child.pid = fork())) { + case -1: + log_Printf(LogERROR, "Chap: fork: %s\n", strerror(errno)); + close(in[0]); + close(in[1]); + close(out[0]); + close(out[1]); + chap->child.pid = 0; + return; + + case 0: + timer_TermService(); + close(in[1]); + close(out[0]); + if (out[1] == STDIN_FILENO) { + fd = dup(out[1]); + close(out[1]); + out[1] = fd; + } + dup2(in[0], STDIN_FILENO); + dup2(out[1], STDOUT_FILENO); + if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { + log_Printf(LogALERT, "Chap: Failed to open %s: %s\n", + _PATH_DEVNULL, strerror(errno)); + exit(1); + } + dup2(fd, STDERR_FILENO); + fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ + + setuid(geteuid()); + argc = command_Interpret(prog, strlen(prog), argv); + command_Expand(nargv, argc, (char const *const *)argv, + chap->auth.physical->dl->bundle, 0); + execvp(nargv[0], nargv); + + log_Printf(LogWARN, "exec() of %s failed: %s\n", + nargv[0], strerror(errno)); + exit(255); + + default: + close(in[0]); + close(out[1]); + chap->child.fd = out[0]; + chap->child.buf.len = 0; + write(in[1], chap->auth.in.name, strlen(chap->auth.in.name)); + write(in[1], "\n", 1); + write(in[1], chap->challenge + 1, *chap->challenge); + write(in[1], "\n", 1); + write(in[1], name, strlen(name)); + write(in[1], "\n", 1); + close(in[1]); + break; + } +} + +static void +chap_Cleanup(struct chap *chap, int sig) +{ + if (chap->child.pid) { + int status; + + close(chap->child.fd); + chap->child.fd = -1; + if (sig) + kill(chap->child.pid, SIGTERM); + chap->child.pid = 0; + chap->child.buf.len = 0; + + if (wait(&status) == -1) + log_Printf(LogERROR, "Chap: wait: %s\n", strerror(errno)); + else if (WIFSIGNALED(status)) + log_Printf(LogWARN, "Chap: Child received signal %d\n", WTERMSIG(status)); + else if (WIFEXITED(status) && WEXITSTATUS(status)) + log_Printf(LogERROR, "Chap: Child exited %d\n", WEXITSTATUS(status)); + } + *chap->challenge = 0; +} + +static void +chap_SendResponse(struct chap *chap, char *name, char *key) +{ + char *ans; + + ans = chap_BuildAnswer(name, key, chap->auth.id, chap->challenge, 0); + + if (ans) { + ChapOutput(chap->auth.physical, CHAP_RESPONSE, chap->auth.id, + ans, *ans + 1 + strlen(name), name); + free(ans); + } else + ChapOutput(chap->auth.physical, CHAP_FAILURE, chap->auth.id, + "Out of memory!", 14, NULL); +} + +static int +chap_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) +{ + struct chap *chap = descriptor2chap(d); + + if (r && chap && chap->child.fd != -1) { + FD_SET(chap->child.fd, r); + if (*n < chap->child.fd + 1) + *n = chap->child.fd + 1; + log_Printf(LogTIMER, "Chap: fdset(r) %d\n", chap->child.fd); + return 1; + } + + return 0; +} + +static int +chap_IsSet(struct descriptor *d, const fd_set *fdset) +{ + struct chap *chap = descriptor2chap(d); + + return chap && chap->child.fd != -1 && FD_ISSET(chap->child.fd, fdset); +} + +static void +chap_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) +{ + struct chap *chap = descriptor2chap(d); + int got; + + got = read(chap->child.fd, chap->child.buf.ptr + chap->child.buf.len, + sizeof chap->child.buf.ptr - chap->child.buf.len - 1); + if (got == -1) { + log_Printf(LogERROR, "Chap: Read: %s\n", strerror(errno)); + chap_Cleanup(chap, SIGTERM); + } else if (got == 0) { + log_Printf(LogWARN, "Chap: Read: Child terminated connection\n"); + chap_Cleanup(chap, SIGTERM); + } else { + char *name, *key, *end; + + chap->child.buf.len += got; + chap->child.buf.ptr[chap->child.buf.len] = '\0'; + name = chap->child.buf.ptr; + name += strspn(name, " \t"); + if ((key = strchr(name, '\n')) == NULL) + end = NULL; + else + end = strchr(++key, '\n'); + + if (end == NULL) { + if (chap->child.buf.len == sizeof chap->child.buf.ptr - 1) { + log_Printf(LogWARN, "Chap: Read: Input buffer overflow\n"); + chap_Cleanup(chap, SIGTERM); + } + } else { + while (end >= name && strchr(" \t\r\n", *end)) + *end-- = '\0'; + end = key - 1; + while (end >= name && strchr(" \t\r\n", *end)) + *end-- = '\0'; + key += strspn(key, " \t"); + + chap_SendResponse(chap, name, key); + chap_Cleanup(chap, 0); + } + } +} + +static int +chap_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) +{ + /* We never want to write here ! */ + log_Printf(LogALERT, "chap_Write: Internal error: Bad call !\n"); + return 0; +} + static void chap_Challenge(struct authinfo *authp) { @@ -181,28 +383,29 @@ chap_Challenge(struct authinfo *authp) int len, i; char *cp; - randinit(); - cp = chap->challenge; + len = strlen(authp->physical->dl->bundle->cfg.auth.name); + + if (!*chap->challenge) { + randinit(); + cp = chap->challenge; #ifndef NORADIUS - if (*authp->physical->dl->bundle->radius.cfg.file) { - /* For radius, our challenge is 16 readable NUL terminated bytes :*/ - *cp++ = 16; - for (i = 0; i < 16; i++) - *cp++ = (random() % 10) + '0'; - } else + if (*authp->physical->dl->bundle->radius.cfg.file) { + /* For radius, our challenge is 16 readable NUL terminated bytes :*/ + *cp++ = 16; + for (i = 0; i < 16; i++) + *cp++ = (random() % 10) + '0'; + } else #endif - { - *cp++ = random() % (CHAPCHALLENGELEN-16) + 16; - for (i = 0; i < *chap->challenge; i++) - *cp++ = random() & 0xff; + { + *cp++ = random() % (CHAPCHALLENGELEN-16) + 16; + for (i = 0; i < *chap->challenge; i++) + *cp++ = random() & 0xff; + } + memcpy(cp, authp->physical->dl->bundle->cfg.auth.name, len); } - - len = strlen(authp->physical->dl->bundle->cfg.auth.name); - memcpy(cp, authp->physical->dl->bundle->cfg.auth.name, len); - cp += len; ChapOutput(authp->physical, CHAP_CHALLENGE, authp->id, chap->challenge, - cp - chap->challenge, NULL); + 1 + *chap->challenge + len, NULL); } static void @@ -232,11 +435,24 @@ chap_Failure(struct authinfo *authp) void chap_Init(struct chap *chap, struct physical *p) { + chap->desc.type = CHAP_DESCRIPTOR; + chap->desc.UpdateSet = chap_UpdateSet; + chap->desc.IsSet = chap_IsSet; + chap->desc.Read = chap_Read; + chap->desc.Write = chap_Write; + chap->child.pid = 0; + chap->child.fd = -1; auth_Init(&chap->auth, p, chap_Challenge, chap_Success, chap_Failure); *chap->challenge = 0; chap->using_MSChap = 0; } +void +chap_ReInit(struct chap *chap) +{ + chap_Cleanup(chap, SIGTERM); +} + void chap_Input(struct physical *p, struct mbuf *bp) { @@ -336,17 +552,12 @@ chap_Input(struct physical *p, struct mbuf *bp) switch (chap->auth.in.hdr.code) { case CHAP_CHALLENGE: - name = p->dl->bundle->cfg.auth.name; - nlen = strlen(name); - key = p->dl->bundle->cfg.auth.key; - myans = chap_BuildAnswer(name, key, chap->auth.id, chap->challenge, 0); - if (myans) { - ChapOutput(p, CHAP_RESPONSE, chap->auth.id, myans, - *myans + 1 + nlen, name); - free(myans); - } else - ChapOutput(p, CHAP_FAILURE, chap->auth.id, "Out of memory!", - 14, NULL); + if (*p->dl->bundle->cfg.auth.key == '!') + chap_StartChild(chap, p->dl->bundle->cfg.auth.key + 1, + p->dl->bundle->cfg.auth.name); + else + chap_SendResponse(chap, p->dl->bundle->cfg.auth.name, + p->dl->bundle->cfg.auth.key); break; case CHAP_RESPONSE: diff --git a/usr.sbin/ppp/chap.h b/usr.sbin/ppp/chap.h index 0aaea8891998..b5514d0deffe 100644 --- a/usr.sbin/ppp/chap.h +++ b/usr.sbin/ppp/chap.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: chap.h,v 1.10 1998/05/21 21:44:27 brian Exp $ + * $Id: chap.h,v 1.11 1999/02/06 02:54:44 brian Exp $ * * TODO: */ @@ -29,12 +29,24 @@ struct physical; #define CHAP_FAILURE 4 struct chap { + struct descriptor desc; + struct { + pid_t pid; + int fd; + struct { + char ptr[AUTHLEN * 2 + 3]; /* Allow for \r\n at the end (- NUL) */ + int len; + } buf; + } child; struct authinfo auth; char challenge[CHAPCHALLENGELEN + AUTHLEN]; unsigned using_MSChap : 1; /* A combination of MD4 & DES */ }; -#define auth2chap(a) ((struct chap *)(a)) +#define descriptor2chap(d) \ + ((d)->type == CHAP_DESCRIPTOR ? (struct chap *)(d) : NULL) +#define auth2chap(a) (struct chap *)((char *)a - (int)&((struct chap *)0)->auth) extern void chap_Init(struct chap *, struct physical *); +extern void chap_ReInit(struct chap *); extern void chap_Input(struct physical *, struct mbuf *); diff --git a/usr.sbin/ppp/command.c b/usr.sbin/ppp/command.c index 9245deb5e0dc..00486af68625 100644 --- a/usr.sbin/ppp/command.c +++ b/usr.sbin/ppp/command.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: command.c,v 1.178 1999/01/28 01:56:31 brian Exp $ + * $Id: command.c,v 1.179 1999/01/28 09:40:15 brian Exp $ * */ #include @@ -138,7 +138,7 @@ #define NEG_DNS 50 const char Version[] = "2.1"; -const char VersionDate[] = "$Date: 1999/01/28 01:56:31 $"; +const char VersionDate[] = "$Date: 1999/01/28 09:40:15 $"; static int ShowCommand(struct cmdargs const *); static int TerminalCommand(struct cmdargs const *); @@ -388,9 +388,9 @@ subst(char *tgt, const char *oldstr, const char *newstr) return tgt; } -static void -expand(char **nargv, int argc, char const *const *oargv, struct bundle *bundle, - int inc0) +void +command_Expand(char **nargv, int argc, char const *const *oargv, + struct bundle *bundle, int inc0) { int arg; char pid[12]; @@ -484,7 +484,7 @@ ShellCommand(struct cmdargs const *arg, int bg) argc = sizeof argv / sizeof argv[0] - 1; log_Printf(LogWARN, "Truncating shell command to %d args\n", argc); } - expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0); + command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 0); if (bg) { pid_t p; @@ -2473,7 +2473,7 @@ SetProcTitle(struct cmdargs const *arg) argc = sizeof argv / sizeof argv[0] - 1; log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); } - expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1); + command_Expand(argv, argc, arg->argv + arg->argn, arg->bundle, 1); ptr = title; remaining = sizeof title - 1; diff --git a/usr.sbin/ppp/command.h b/usr.sbin/ppp/command.h index f01901d57a22..53934c7bd991 100644 --- a/usr.sbin/ppp/command.h +++ b/usr.sbin/ppp/command.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: command.h,v 1.14 1998/06/15 19:05:42 brian Exp $ + * $Id: command.h,v 1.15 1998/06/15 19:06:06 brian Exp $ * * TODO: */ @@ -54,6 +54,8 @@ struct cmdtab { extern const char Version[]; extern const char VersionDate[]; +extern void command_Expand(char **, int, char const *const *, struct bundle *, + int); extern int command_Interpret(char *, int, char *vector[MAXARGS]); extern void command_Run(struct bundle *, int, char const *const *, struct prompt *, const char *, struct datalink *); diff --git a/usr.sbin/ppp/datalink.c b/usr.sbin/ppp/datalink.c index 3b52c04ccba8..f5ca431e7f55 100644 --- a/usr.sbin/ppp/datalink.c +++ b/usr.sbin/ppp/datalink.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: datalink.c,v 1.28 1999/02/02 09:35:17 brian Exp $ + * $Id: datalink.c,v 1.29 1999/02/06 02:54:44 brian Exp $ */ #include @@ -335,7 +335,8 @@ datalink_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, case DATALINK_AUTH: case DATALINK_CBCP: case DATALINK_OPEN: - result = descriptor_UpdateSet(&dl->physical->desc, r, w, e, n); + result = descriptor_UpdateSet(&dl->chap.desc, r, w, e, n) + + descriptor_UpdateSet(&dl->physical->desc, r, w, e, n); break; } return result; @@ -367,7 +368,8 @@ datalink_IsSet(struct descriptor *d, const fd_set *fdset) case DATALINK_AUTH: case DATALINK_CBCP: case DATALINK_OPEN: - return descriptor_IsSet(&dl->physical->desc, fdset); + return descriptor_IsSet(&dl->chap.desc, fdset) ? 1 : + descriptor_IsSet(&dl->physical->desc, fdset); } return 0; } @@ -393,7 +395,10 @@ datalink_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) case DATALINK_AUTH: case DATALINK_CBCP: case DATALINK_OPEN: - descriptor_Read(&dl->physical->desc, bundle, fdset); + if (descriptor_IsSet(&dl->chap.desc, fdset)) + descriptor_Read(&dl->chap.desc, bundle, fdset); + if (descriptor_IsSet(&dl->physical->desc, fdset)) + descriptor_Read(&dl->physical->desc, bundle, fdset); break; } } @@ -420,7 +425,10 @@ datalink_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) case DATALINK_AUTH: case DATALINK_CBCP: case DATALINK_OPEN: - result = descriptor_Write(&dl->physical->desc, bundle, fdset); + if (descriptor_IsSet(&dl->chap.desc, fdset)) + result += descriptor_Write(&dl->chap.desc, bundle, fdset); + if (descriptor_IsSet(&dl->physical->desc, fdset)) + result += descriptor_Write(&dl->physical->desc, bundle, fdset); break; } @@ -541,6 +549,7 @@ void datalink_CBCPComplete(struct datalink *dl) { datalink_NewState(dl, DATALINK_LCP); + chap_ReInit(&dl->chap); fsm_Close(&dl->physical->link.lcp.fsm); } @@ -567,6 +576,7 @@ datalink_AuthOk(struct datalink *dl) /* It's not CBCP */ log_Printf(LogPHASE, "%s: Shutdown and await peer callback\n", dl->name); datalink_NewState(dl, DATALINK_LCP); + chap_ReInit(&dl->chap); fsm_Close(&dl->physical->link.lcp.fsm); } else switch (dl->physical->link.lcp.his_callback.opmask) { @@ -591,6 +601,7 @@ datalink_AuthOk(struct datalink *dl) } dl->cbcp.fsm.delay = 0; datalink_NewState(dl, DATALINK_LCP); + chap_ReInit(&dl->chap); fsm_Close(&dl->physical->link.lcp.fsm); break; @@ -603,6 +614,7 @@ datalink_AuthOk(struct datalink *dl) dl->cbcp.required = 1; dl->cbcp.fsm.delay = 0; datalink_NewState(dl, DATALINK_LCP); + chap_ReInit(&dl->chap); fsm_Close(&dl->physical->link.lcp.fsm); break; @@ -610,6 +622,7 @@ datalink_AuthOk(struct datalink *dl) log_Printf(LogPHASE, "%s: Oops - Should have NAK'd peer callback !\n", dl->name); datalink_NewState(dl, DATALINK_LCP); + chap_ReInit(&dl->chap); fsm_Close(&dl->physical->link.lcp.fsm); break; } @@ -619,6 +632,7 @@ void datalink_AuthNotOk(struct datalink *dl) { datalink_NewState(dl, DATALINK_LCP); + chap_ReInit(&dl->chap); fsm_Close(&dl->physical->link.lcp.fsm); } @@ -647,6 +661,7 @@ datalink_LayerDown(void *v, struct fsm *fp) timer_Stop(&dl->chap.auth.authtimer); } datalink_NewState(dl, DATALINK_LCP); + chap_ReInit(&dl->chap); } } @@ -877,6 +892,7 @@ datalink_Close(struct datalink *dl, int how) case DATALINK_CBCP: case DATALINK_AUTH: case DATALINK_LCP: + chap_ReInit(&dl->chap); fsm_Close(&dl->physical->link.lcp.fsm); if (how != CLOSE_NORMAL) { dl->dial_tries = -1; diff --git a/usr.sbin/ppp/defs.h b/usr.sbin/ppp/defs.h index dffc5e0d6727..03b36de473a7 100644 --- a/usr.sbin/ppp/defs.h +++ b/usr.sbin/ppp/defs.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: defs.h,v 1.36 1998/08/25 17:48:42 brian Exp $ + * $Id: defs.h,v 1.37 1999/01/28 01:56:31 brian Exp $ * * TODO: */ @@ -44,7 +44,7 @@ #define DIAL_NEXT_TIMEOUT 3 /* Default Hold time to next number redial */ #define SCRIPT_LEN 512 /* Size of login scripts */ #define LINE_LEN SCRIPT_LEN /* Size of login scripts */ -#define AUTHLEN 50 /* Size of authname/authkey */ +#define AUTHLEN 100 /* Size of authname/authkey */ #define CHAPDIGESTLEN 100 /* Maximum chap digest */ #define CHAPCHALLENGELEN 48 /* Maximum chap challenge */ #define MAXARGS 40 /* How many args per config line */ diff --git a/usr.sbin/ppp/descriptor.h b/usr.sbin/ppp/descriptor.h index a4f43a3c07f0..70a16dba07be 100644 --- a/usr.sbin/ppp/descriptor.h +++ b/usr.sbin/ppp/descriptor.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: descriptor.h,v 1.4 1998/06/24 19:33:31 brian Exp $ + * $Id: descriptor.h,v 1.5 1999/02/06 02:54:45 brian Exp $ */ #define PHYSICAL_DESCRIPTOR (1) @@ -34,6 +34,7 @@ #define BUNDLE_DESCRIPTOR (6) #define MPSERVER_DESCRIPTOR (7) #define RADIUS_DESCRIPTOR (8) +#define CHAP_DESCRIPTOR (9) struct bundle; diff --git a/usr.sbin/ppp/hdlc.c b/usr.sbin/ppp/hdlc.c index bca157db9704..ff509b8f35e2 100644 --- a/usr.sbin/ppp/hdlc.c +++ b/usr.sbin/ppp/hdlc.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: hdlc.c,v 1.37 1999/01/28 01:56:32 brian Exp $ + * $Id: hdlc.c,v 1.38 1999/02/06 02:54:45 brian Exp $ * * TODO: */ @@ -48,12 +48,12 @@ #include "vjcomp.h" #include "auth.h" #include "pap.h" -#include "chap.h" #include "lcp.h" #include "async.h" #include "ccp.h" #include "link.h" #include "descriptor.h" +#include "chap.h" #include "physical.h" #include "prompt.h" #include "chat.h" diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8 index af102a8461bb..a46b956feecd 100644 --- a/usr.sbin/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp.8 @@ -1,4 +1,4 @@ -.\" $Id: ppp.8,v 1.143 1999/01/28 01:56:33 brian Exp $ +.\" $Id: ppp.8,v 1.144 1999/01/28 22:55:08 billf Exp $ .Dd 20 September 1995 .nr XX \w'\fC00' .Os FreeBSD @@ -2854,23 +2854,73 @@ For the XON/XOFF scenario, use .Dq set accmap 000a0000 . .It set authkey|key Ar value This sets the authentication key (or password) used in client mode -PAP or CHAP negotiation to the given value. It can also be used to -specify the password to be used in the dial or login scripts in place -of the '\\P' sequence, preventing the actual password from being logged. If +PAP or CHAP negotiation to the given value. It also specifies the +password to be used in the dial or login scripts in place of the +'\\P' sequence, preventing the actual password from being logged. If .Ar command logging is in effect, .Ar value is logged as .Sq ******** for security reasons. +.Pp +If the first character of +.Ar value +is an exclaimation mark +.Pq Dq \&! , +.Nm +treats the remainder of the string as a program that must be executed +to determine the +.Dq authname +and +.Dq authkey +values. +.Pp +Ignoring the +.Dq \&! , +.Ar value +is parsed as a program to execute in the same was as the +.Dq !bg +command above, substituting special names in the same manner. Once executed, +.Nm +will feed the program three lines of input, each terminated by a newline +character: +.Bl -bullet +.It +The host name as sent in the CHAP challenge. +.It +The challenge string as sent in the CHAP challenge. +.It +The locally defined +.Dq authname . +.El +.Pp +Two lines of output are expected: +.Bl -bullet +.It +The +.Dq authname +to be sent with the CHAP response. +.It +The +.Dq authkey , +which is encrypted with the challenge and request id, the answer being sent +in the CHAP response packet. +.El +.Pp +When configuring +.Nm +in this manner, it's expected that the host challenge is a series of ascii +digits or characters. An encryption device or Secure ID card is usually +required to calculate the secret appropriate for the given challenge. .It set authname Ar id This sets the authentication id used in client mode PAP or CHAP negotiation. .Pp If used in .Fl direct -mode with PAP or CHAP enabled, +mode with CHAP enabled, .Ar id -is used in the initial authentication request and is normally set to +is used in the initial authentication challenge and should normally be set to the local machine name. .It set autoload Ar max-duration max-load [min-duration min-load] These settings apply only in multi-link mode and all default to zero. diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4 index af102a8461bb..a46b956feecd 100644 --- a/usr.sbin/ppp/ppp.8.m4 +++ b/usr.sbin/ppp/ppp.8.m4 @@ -1,4 +1,4 @@ -.\" $Id: ppp.8,v 1.143 1999/01/28 01:56:33 brian Exp $ +.\" $Id: ppp.8,v 1.144 1999/01/28 22:55:08 billf Exp $ .Dd 20 September 1995 .nr XX \w'\fC00' .Os FreeBSD @@ -2854,23 +2854,73 @@ For the XON/XOFF scenario, use .Dq set accmap 000a0000 . .It set authkey|key Ar value This sets the authentication key (or password) used in client mode -PAP or CHAP negotiation to the given value. It can also be used to -specify the password to be used in the dial or login scripts in place -of the '\\P' sequence, preventing the actual password from being logged. If +PAP or CHAP negotiation to the given value. It also specifies the +password to be used in the dial or login scripts in place of the +'\\P' sequence, preventing the actual password from being logged. If .Ar command logging is in effect, .Ar value is logged as .Sq ******** for security reasons. +.Pp +If the first character of +.Ar value +is an exclaimation mark +.Pq Dq \&! , +.Nm +treats the remainder of the string as a program that must be executed +to determine the +.Dq authname +and +.Dq authkey +values. +.Pp +Ignoring the +.Dq \&! , +.Ar value +is parsed as a program to execute in the same was as the +.Dq !bg +command above, substituting special names in the same manner. Once executed, +.Nm +will feed the program three lines of input, each terminated by a newline +character: +.Bl -bullet +.It +The host name as sent in the CHAP challenge. +.It +The challenge string as sent in the CHAP challenge. +.It +The locally defined +.Dq authname . +.El +.Pp +Two lines of output are expected: +.Bl -bullet +.It +The +.Dq authname +to be sent with the CHAP response. +.It +The +.Dq authkey , +which is encrypted with the challenge and request id, the answer being sent +in the CHAP response packet. +.El +.Pp +When configuring +.Nm +in this manner, it's expected that the host challenge is a series of ascii +digits or characters. An encryption device or Secure ID card is usually +required to calculate the secret appropriate for the given challenge. .It set authname Ar id This sets the authentication id used in client mode PAP or CHAP negotiation. .Pp If used in .Fl direct -mode with PAP or CHAP enabled, +mode with CHAP enabled, .Ar id -is used in the initial authentication request and is normally set to +is used in the initial authentication challenge and should normally be set to the local machine name. .It set autoload Ar max-duration max-load [min-duration min-load] These settings apply only in multi-link mode and all default to zero.