summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorbrian <brian@FreeBSD.org>1999-02-11 10:14:08 +0000
committerbrian <brian@FreeBSD.org>1999-02-11 10:14:08 +0000
commit5dc50d8ed53887553c9cb516e2b7915e55171a9f (patch)
treef9ab8c0680569eb7727b37072506b8ada5abb174 /usr.sbin
parent4ef23fab94c614e2e42029a09de004d3a1613d62 (diff)
downloadFreeBSD-src-5dc50d8ed53887553c9cb516e2b7915e55171a9f.zip
FreeBSD-src-5dc50d8ed53887553c9cb516e2b7915e55171a9f.tar.gz
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.
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ppp/chap.c271
-rw-r--r--usr.sbin/ppp/chap.h16
-rw-r--r--usr.sbin/ppp/command.c14
-rw-r--r--usr.sbin/ppp/command.h4
-rw-r--r--usr.sbin/ppp/datalink.c26
-rw-r--r--usr.sbin/ppp/defs.h4
-rw-r--r--usr.sbin/ppp/descriptor.h3
-rw-r--r--usr.sbin/ppp/hdlc.c4
-rw-r--r--usr.sbin/ppp/ppp.862
-rw-r--r--usr.sbin/ppp/ppp.8.m462
10 files changed, 404 insertions, 62 deletions
diff --git a/usr.sbin/ppp/chap.c b/usr.sbin/ppp/chap.c
index 495fdde..1c937cd 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 <netinet/ip.h>
#include <sys/un.h>
+#include <errno.h>
+#include <fcntl.h>
#ifdef HAVE_DES
#include <md4.h>
#include <string.h>
#endif
#include <md5.h>
+#include <paths.h>
+#include <signal.h>
#include <stdlib.h>
+#include <sys/wait.h>
#include <termios.h>
+#include <unistd.h>
#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"
@@ -175,34 +182,230 @@ chap_BuildAnswer(char *name, char *key, u_char id, char *challenge, int MSChap)
}
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)
{
struct chap *chap = auth2chap(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,12 +435,25 @@ 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)
{
struct chap *chap = &p->dl->chap;
@@ -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 0aaea88..b5514d0 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 9245deb..00486af 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 <sys/param.h>
@@ -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 f01901d..53934c7 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 3b52c04..f5ca431 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 <sys/param.h>
@@ -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 dffc5e0..03b36de 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 a4f43a3..70a16db 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 bca157d..ff509b8 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 af102a8..a46b956 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 af102a8..a46b956 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.
OpenPOWER on IntegriCloud