diff options
-rw-r--r-- | usr.sbin/ppp/auth.c | 69 | ||||
-rw-r--r-- | usr.sbin/ppp/auth.h | 27 | ||||
-rw-r--r-- | usr.sbin/ppp/bundle.c | 17 | ||||
-rw-r--r-- | usr.sbin/ppp/ccp.c | 3 | ||||
-rw-r--r-- | usr.sbin/ppp/chap.c | 492 | ||||
-rw-r--r-- | usr.sbin/ppp/chap.h | 10 | ||||
-rw-r--r-- | usr.sbin/ppp/datalink.c | 49 | ||||
-rw-r--r-- | usr.sbin/ppp/datalink.h | 4 | ||||
-rw-r--r-- | usr.sbin/ppp/descriptor.h | 3 | ||||
-rw-r--r-- | usr.sbin/ppp/hdlc.c | 6 | ||||
-rw-r--r-- | usr.sbin/ppp/ipcp.c | 5 | ||||
-rw-r--r-- | usr.sbin/ppp/link.c | 3 | ||||
-rw-r--r-- | usr.sbin/ppp/main.c | 4 | ||||
-rw-r--r-- | usr.sbin/ppp/mbuf.c | 9 | ||||
-rw-r--r-- | usr.sbin/ppp/pap.c | 214 | ||||
-rw-r--r-- | usr.sbin/ppp/pap.h | 7 | ||||
-rw-r--r-- | usr.sbin/ppp/radius.c | 353 | ||||
-rw-r--r-- | usr.sbin/ppp/radius.h | 16 | ||||
-rw-r--r-- | usr.sbin/ppp/vjcomp.c | 3 |
19 files changed, 788 insertions, 506 deletions
diff --git a/usr.sbin/ppp/auth.c b/usr.sbin/ppp/auth.c index ceeb813..ea1a07d 100644 --- a/usr.sbin/ppp/auth.c +++ b/usr.sbin/ppp/auth.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: auth.c,v 1.36 1999/02/01 13:42:24 brian Exp $ + * $Id: auth.c,v 1.37 1999/02/02 09:35:17 brian Exp $ * * TODO: * o Implement check against with registered IP addresses. @@ -208,11 +208,6 @@ auth_Validate(struct bundle *bundle, const char *name, char *vector[5]; char buff[LINE_LEN]; -#ifndef NORADIUS - if (*bundle->radius.cfg.file) - return radius_Authenticate(&bundle->radius, bundle, name, key, NULL); -#endif - fp = OpenSecret(SECRETFILE); if (fp != NULL) { while (fgets(buff, sizeof buff, fp)) { @@ -278,8 +273,9 @@ AuthTimeout(void *vauthp) timer_Stop(&authp->authtimer); if (--authp->retry > 0) { + authp->id++; + (*authp->fn.req)(authp); timer_Start(&authp->authtimer); - (*authp->ChallengeFunc)(authp, ++authp->id, authp->physical); } else { log_Printf(LogPHASE, "Auth: No response from server\n"); datalink_AuthNotOk(authp->physical->dl); @@ -287,26 +283,28 @@ AuthTimeout(void *vauthp) } void -auth_Init(struct authinfo *authinfo) +auth_Init(struct authinfo *authp, struct physical *p, auth_func req, + auth_func success, auth_func failure) { - memset(authinfo, '\0', sizeof(struct authinfo)); - authinfo->cfg.fsmretry = DEF_FSMRETRY; + memset(authp, '\0', sizeof(struct authinfo)); + authp->cfg.fsmretry = DEF_FSMRETRY; + authp->fn.req = req; + authp->fn.success = success; + authp->fn.failure = failure; + authp->physical = p; } void -auth_StartChallenge(struct authinfo *authp, struct physical *physical, - void (*chal)(struct authinfo *, int, struct physical *)) +auth_StartReq(struct authinfo *authp) { - authp->ChallengeFunc = chal; - authp->physical = physical; timer_Stop(&authp->authtimer); authp->authtimer.func = AuthTimeout; authp->authtimer.name = "auth"; authp->authtimer.load = authp->cfg.fsmretry * SECTICKS; - authp->authtimer.arg = (void *) authp; + authp->authtimer.arg = (void *)authp; authp->retry = 3; authp->id = 1; - (*authp->ChallengeFunc)(authp, authp->id, physical); + (*authp->fn.req)(authp); timer_Start(&authp->authtimer); } @@ -314,5 +312,42 @@ void auth_StopTimer(struct authinfo *authp) { timer_Stop(&authp->authtimer); - authp->physical = NULL; +} + +struct mbuf * +auth_ReadHeader(struct authinfo *authp, struct mbuf *bp) +{ + int len; + + len = mbuf_Length(bp); + if (len >= sizeof authp->in.hdr) { + bp = mbuf_Read(bp, (u_char *)&authp->in.hdr, sizeof authp->in.hdr); + if (len >= ntohs(authp->in.hdr.length)) + return bp; + } + + mbuf_Free(bp); + return NULL; +} + +struct mbuf * +auth_ReadName(struct authinfo *authp, struct mbuf *bp, int len) +{ + if (len > sizeof authp->in.name - 1) + log_Printf(LogERROR, "auth_ReadName: Name too long (%d) !\n", len); + else { + int mlen = mbuf_Length(bp); + + if (len > mlen) + log_Printf(LogERROR, "auth_ReadName: Short packet !\n"); + else { + bp = mbuf_Read(bp, (u_char *)authp->in.name, len); + authp->in.name[len] = '\0'; + return bp; + } + } + + *authp->in.name = '\0'; + mbuf_Free(bp); + return NULL; } diff --git a/usr.sbin/ppp/auth.h b/usr.sbin/ppp/auth.h index cf4bb3e..db17ff0 100644 --- a/usr.sbin/ppp/auth.h +++ b/usr.sbin/ppp/auth.h @@ -15,16 +15,26 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: auth.h,v 1.13 1999/02/01 13:42:24 brian Exp $ + * $Id: auth.h,v 1.14 1999/02/02 09:35:17 brian Exp $ * * TODO: */ struct physical; struct bundle; +struct authinfo; +typedef void (*auth_func)(struct authinfo *); struct authinfo { - void (*ChallengeFunc)(struct authinfo *, int, struct physical *); + struct { + auth_func req; + auth_func success; + auth_func failure; + } fn; + struct { + struct fsmheader hdr; + char name[AUTHLEN]; + } in; struct pppTimer authtimer; int retry; int id; @@ -34,16 +44,19 @@ struct authinfo { } cfg; }; -extern const char *Auth2Nam(u_short); +#define auth_Failure(a) (*a->fn.failure)(a); +#define auth_Success(a) (*a->fn.success)(a); -extern void auth_Init(struct authinfo *); +extern const char *Auth2Nam(u_short); +extern void auth_Init(struct authinfo *, struct physical *, + auth_func, auth_func, auth_func); extern void auth_StopTimer(struct authinfo *); -extern void auth_StartChallenge(struct authinfo *, struct physical *, - void (*)(struct authinfo *, int, - struct physical *)); +extern void auth_StartReq(struct authinfo *); extern int auth_Validate(struct bundle *, const char *, const char *, struct physical *); extern char *auth_GetSecret(struct bundle *, const char *, int, struct physical *); extern int auth_SetPhoneList(const char *, char *, int); extern int auth_Select(struct bundle *, const char *); +extern struct mbuf *auth_ReadHeader(struct authinfo *, struct mbuf *); +extern struct mbuf *auth_ReadName(struct authinfo *, struct mbuf *, int); diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c index 681cafd..56973fd 100644 --- a/usr.sbin/ppp/bundle.c +++ b/usr.sbin/ppp/bundle.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bundle.c,v 1.43 1999/01/06 00:08:03 brian Exp $ + * $Id: bundle.c,v 1.44 1999/01/28 01:56:30 brian Exp $ */ #include <sys/param.h> @@ -32,7 +32,6 @@ #include <net/if.h> #include <arpa/inet.h> #include <net/route.h> -#include <net/if_dl.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <sys/un.h> @@ -558,6 +557,10 @@ bundle_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) } } +#ifndef NORADIUS + result += descriptor_UpdateSet(&bundle->radius.desc, r, w, e, n); +#endif + /* Which links need a select() ? */ for (dl = bundle->links; dl; dl = dl->next) result += descriptor_UpdateSet(&dl->desc, r, w, e, n); @@ -582,6 +585,11 @@ bundle_IsSet(struct descriptor *d, const fd_set *fdset) if (descriptor_IsSet(&dl->desc, fdset)) return 1; +#ifndef NORADIUS + if (descriptor_IsSet(&bundle->radius.desc, fdset)) + return 1; +#endif + if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset)) return 1; @@ -601,6 +609,11 @@ bundle_DescriptorRead(struct descriptor *d, struct bundle *bundle, if (descriptor_IsSet(&dl->desc, fdset)) descriptor_Read(&dl->desc, bundle, fdset); +#ifndef NORADIUS + if (descriptor_IsSet(&bundle->radius.desc, fdset)) + descriptor_Read(&bundle->radius.desc, bundle, fdset); +#endif + if (FD_ISSET(bundle->dev.fd, fdset)) { struct tun_data tun; int n, pri; diff --git a/usr.sbin/ppp/ccp.c b/usr.sbin/ppp/ccp.c index 4e15b1d..eabcf76 100644 --- a/usr.sbin/ppp/ccp.c +++ b/usr.sbin/ppp/ccp.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ccp.c,v 1.40 1998/08/26 18:07:56 brian Exp $ + * $Id: ccp.c,v 1.41 1999/01/28 01:56:30 brian Exp $ * * TODO: * o Support other compression protocols @@ -30,7 +30,6 @@ #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <termios.h> #include "defs.h" diff --git a/usr.sbin/ppp/chap.c b/usr.sbin/ppp/chap.c index a539155..895b34e 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.38 1999/01/28 01:56:31 brian Exp $ + * $Id: chap.c,v 1.39 1999/01/29 22:46:31 brian Exp $ * * TODO: */ @@ -29,10 +29,10 @@ #ifdef HAVE_DES #include <md4.h> +#include <string.h> #endif #include <md5.h> #include <stdlib.h> -#include <string.h> #include <termios.h> #include "mbuf.h" @@ -71,10 +71,11 @@ static const char *chapcodes[] = { "???", "CHALLENGE", "RESPONSE", "SUCCESS", "FAILURE" }; +#define MAXCHAPCODE (sizeof chapcodes / sizeof chapcodes[0] - 1) static void ChapOutput(struct physical *physical, u_int code, u_int id, - const u_char * ptr, int count, const char *text) + const u_char *ptr, int count, const char *text) { int plen; struct fsmheader lh; @@ -96,258 +97,311 @@ ChapOutput(struct physical *physical, u_int code, u_int id, hdlc_Output(&physical->link, PRI_LINK, PROTO_CHAP, bp); } -void -chap_SendChallenge(struct authinfo *auth, int chapid, struct physical *physical) +static char * +chap_BuildAnswer(char *name, char *key, u_char id, char *challenge, int MSChap) { - struct chap *chap = auth2chap(auth); + char *result, *digest; + size_t nlen, klen; + + nlen = strlen(name); + klen = strlen(key); + +#ifdef HAVE_DES + if (MSChap) { + char expkey[AUTHLEN << 2]; + MD4_CTX MD4context; + int f; + + if ((result = malloc(1 + nlen + MS_CHAP_RESPONSE_LEN)) == NULL) + return result; + + digest = result; /* this is the response */ + *digest++ = MS_CHAP_RESPONSE_LEN; /* 49 */ + memset(digest, '\0', 24); + digest += 24; + + for (f = klen; f; f--) { + expkey[2*f-2] = key[f-1]; + expkey[2*f-1] = 0; + } + + /* + * ----------- + * answer = | k\0e\0y\0 | + * ----------- + */ + MD4Init(&MD4context); + MD4Update(&MD4context, expkey, klen << 1); + MD4Final(digest, &MD4context); + memcpy(digest + 25, name, nlen); + + /* + * ``result'' is: + * ---- --------- -------------------- ------ + * result = | 49 | 24 * \0 | digest (pad to 25) | name | + * ---- --------- -------------------- ------ + */ + chap_MS(digest, challenge + 1, *challenge); + + /* + * ---- --------- ---------------- --- ---------- + * result = | 49 | 24 * \0 | 24 byte digest | 1 | authname | + * ---- --------- ---------------- --- ---------- + */ + } else +#endif + if ((result = malloc(nlen + 17)) != NULL) { + /* Normal MD5 stuff */ + MD5_CTX MD5context; + + digest = result; + *digest++ = 16; /* value size */ + + MD5Init(&MD5context); +log_Printf(LogPHASE, "Build with 0x%x, %s & %.*s\n", id, key, *challenge, challenge+1); + MD5Update(&MD5context, &id, 1); + MD5Update(&MD5context, key, klen); + MD5Update(&MD5context, challenge + 1, *challenge); + MD5Final(digest, &MD5context); + + memcpy(digest + 16, name, nlen); + /* + * ---- -------- ------ + * result = | 16 | digest | name | + * ---- -------- ------ + */ + } + + return result; +} + +static void +chap_Challenge(struct authinfo *authp) +{ + struct chap *chap = auth2chap(authp); int len, i; char *cp; randinit(); - cp = chap->challenge_data; + cp = chap->challenge; #ifndef NORADIUS - if (*physical->dl->bundle->radius.cfg.file) { + if (*authp->physical->dl->bundle->radius.cfg.file) { /* For radius, our challenge is 16 readable NUL terminated bytes :*/ - *cp++ = chap->challenge_len = 16; - for (i = 0; i < chap->challenge_len; i++) + *cp++ = 16; + for (i = 0; i < 16; i++) *cp++ = (random() % 10) + '0'; } else #endif { - *cp++ = chap->challenge_len = random() % (CHAPCHALLENGELEN-16) + 16; - for (i = 0; i < chap->challenge_len; i++) + *cp++ = random() % (CHAPCHALLENGELEN-16) + 16; + for (i = 0; i < *chap->challenge; i++) *cp++ = random() & 0xff; } - len = strlen(physical->dl->bundle->cfg.auth.name); - memcpy(cp, 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(physical, CHAP_CHALLENGE, chapid, chap->challenge_data, - cp - chap->challenge_data, NULL); + ChapOutput(authp->physical, CHAP_CHALLENGE, authp->id, chap->challenge, + cp - chap->challenge, NULL); } static void -RecvChapTalk(struct bundle *bundle, struct fsmheader *chp, struct mbuf *bp, - struct physical *physical) +chap_Success(struct authinfo *authp) { - int valsize, len, arglen, keylen, namelen, success; - char *cp, *argp, *ap, *name, *digest; - char *keyp; - MD5_CTX MD5context; /* context for MD5 */ - char answer[CHAPDIGESTLEN]; - char cdigest[16]; -#ifdef HAVE_DES - int ix; - MD4_CTX MD4context; /* context for MD4 */ -#endif - - len = ntohs(chp->length); - log_Printf(LogDEBUG, "RecvChapTalk: length: %d\n", len); - arglen = len - sizeof(struct fsmheader); - cp = (char *) MBUF_CTOP(bp); - valsize = *cp++ & 255; - name = cp + valsize; - namelen = arglen - valsize - 1; - name[namelen] = 0; - - log_Printf(LogPHASE, "Chap Input: %s (from %s)\n", - chapcodes[chp->code], name); - - switch (chp->code) { - case CHAP_CHALLENGE: - keyp = bundle->cfg.auth.key; - keylen = strlen(bundle->cfg.auth.key); - name = bundle->cfg.auth.name; - namelen = strlen(bundle->cfg.auth.name); - -#ifdef HAVE_DES - if (physical->dl->chap.using_MSChap) - argp = malloc(1 + namelen + MS_CHAP_RESPONSE_LEN); - else -#endif - argp = malloc(1 + valsize + namelen + 16); + datalink_GotAuthname(authp->physical->dl, authp->in.name); + ChapOutput(authp->physical, CHAP_SUCCESS, authp->id, "Welcome!!", 10, NULL); + authp->physical->link.lcp.auth_ineed = 0; + if (Enabled(authp->physical->dl->bundle, OPT_UTMP)) + physical_Login(authp->physical, authp->in.name); - if (argp == NULL) { - ChapOutput(physical, CHAP_FAILURE, chp->id, "Out of memory!", 14, NULL); - return; - } -#ifdef HAVE_DES - if (physical->dl->chap.using_MSChap) { - digest = argp; /* this is the response */ - *digest++ = MS_CHAP_RESPONSE_LEN; /* 49 */ - memset(digest, '\0', 24); - digest += 24; - - ap = answer; /* this is the challenge */ - memcpy(ap, keyp, keylen); - ap += 2 * keylen; - memcpy(ap, cp, valsize); - log_DumpBuff(LogDEBUG, "recv", ap, valsize); - ap += valsize; - for (ix = keylen; ix > 0 ; ix--) { - answer[2*ix-2] = answer[ix-1]; - answer[2*ix-1] = 0; - } - MD4Init(&MD4context); - MD4Update(&MD4context, answer, 2 * keylen); - MD4Final(digest, &MD4context); - memcpy(digest + 25, name, namelen); - ap += 2 * keylen; - chap_MS(digest, answer + 2 * keylen, valsize); - log_DumpBuff(LogDEBUG, "answer", digest, 24); - ChapOutput(physical, CHAP_RESPONSE, chp->id, argp, - namelen + MS_CHAP_RESPONSE_LEN + 1, name); - } else { -#endif - digest = argp; - *digest++ = 16; /* value size */ - ap = answer; - *ap++ = chp->id; - memcpy(ap, keyp, keylen); - ap += keylen; - memcpy(ap, cp, valsize); - log_DumpBuff(LogDEBUG, "recv", ap, valsize); - ap += valsize; - MD5Init(&MD5context); - MD5Update(&MD5context, answer, ap - answer); - MD5Final(digest, &MD5context); - log_DumpBuff(LogDEBUG, "answer", digest, 16); - memcpy(digest + 16, name, namelen); - ap += namelen; - /* Send answer to the peer */ - ChapOutput(physical, CHAP_RESPONSE, chp->id, argp, namelen + 17, name); -#ifdef HAVE_DES - } -#endif - free(argp); - if (*name == '\0') - log_Printf(LogWARN, "Sending empty CHAP authname!\n"); - break; - case CHAP_RESPONSE: + if (authp->physical->link.lcp.auth_iwait == 0) /* - * Get a secret key corresponds to the peer + * Either I didn't need to authenticate, or I've already been + * told that I got the answer right. */ - success = 0; -#ifndef NORADIUS - if (*bundle->radius.cfg.file) { - char chapname[AUTHLEN], chal[17]; - - if (namelen > AUTHLEN - 1) - namelen = AUTHLEN - 1; - strncpy(chapname, name, namelen); - chapname[namelen] = '\0'; - *answer = chp->id; - strncpy(answer+1, cp, 16); - answer[17] = '\0'; - strncpy(chal, physical->dl->chap.challenge_data + 1, 16); - chal[16] = '\0'; - - if (radius_Authenticate(&bundle->radius, bundle, chapname, answer, chal)) - success = 1; /* And there was much rejoicing ! */ - - } else -#endif - if ((keyp = auth_GetSecret(bundle, name, namelen, physical))) { - /* Compute correct digest value */ - keylen = strlen(keyp); - ap = answer; - *ap++ = chp->id; - memcpy(ap, keyp, keylen); - ap += keylen; - MD5Init(&MD5context); - MD5Update(&MD5context, answer, ap - answer); - MD5Update(&MD5context, physical->dl->chap.challenge_data + 1, - physical->dl->chap.challenge_len); - MD5Final(cdigest, &MD5context); - log_DumpBuff(LogDEBUG, "got", cp, 16); - log_DumpBuff(LogDEBUG, "expect", cdigest, 16); - - /* - * Compare with the response - */ - if (memcmp(cp, cdigest, 16) == 0) - success = 1; - } - - if (success) { - datalink_GotAuthname(physical->dl, name, namelen); - ChapOutput(physical, CHAP_SUCCESS, chp->id, "Welcome!!", 10, NULL); - physical->link.lcp.auth_ineed = 0; - if (Enabled(bundle, OPT_UTMP)) - physical_Login(physical, name); - - if (physical->link.lcp.auth_iwait == 0) - /* - * Either I didn't need to authenticate, or I've already been - * told that I got the answer right. - */ - datalink_AuthOk(physical->dl); - } else { - /* - * Peer is not registerd, or response digest is wrong. - */ - ChapOutput(physical, CHAP_FAILURE, chp->id, "Invalid!!", 9, NULL); - datalink_AuthNotOk(physical->dl); - break; - } - } + datalink_AuthOk(authp->physical->dl); } static void -RecvChapResult(struct bundle *bundle, struct fsmheader *chp, struct mbuf *bp, - struct physical *physical) +chap_Failure(struct authinfo *authp) { - int len; - - len = ntohs(chp->length); - log_Printf(LogDEBUG, "RecvChapResult: length: %d\n", len); - if (chp->code == CHAP_SUCCESS) { - if (physical->link.lcp.auth_iwait == PROTO_CHAP) { - physical->link.lcp.auth_iwait = 0; - if (physical->link.lcp.auth_ineed == 0) - /* - * We've succeeded in our ``login'' - * If we're not expecting the peer to authenticate (or he already - * has), proceed to network phase. - */ - datalink_AuthOk(physical->dl); - } - } else { - /* CHAP failed - it's not going to get any better */ - log_Printf(LogPHASE, "Chap Input: Giving up after name/key FAILURE\n"); - datalink_AuthNotOk(physical->dl); - } + ChapOutput(authp->physical, CHAP_FAILURE, authp->id, "Invalid!!", 9, NULL); + datalink_AuthNotOk(authp->physical->dl); } void -chap_Input(struct bundle *bundle, struct mbuf *bp, struct physical *physical) +chap_Init(struct chap *chap, struct physical *p) { - int len = mbuf_Length(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; - bp->offset += sizeof(struct fsmheader); - bp->cnt -= sizeof(struct fsmheader); - - switch (chp->code) { + auth_Init(&chap->auth, p, chap_Challenge, chap_Success, chap_Failure); + *chap->challenge = 0; + chap->using_MSChap = 0; +} + +void +chap_Input(struct physical *p, struct mbuf *bp) +{ + struct chap *chap = &p->dl->chap; + char *name, *key, *ans, *myans; + int len, nlen; + u_char alen; + + if ((bp = auth_ReadHeader(&chap->auth, bp)) == NULL) + log_Printf(LogERROR, "Chap Input: Truncated header !\n"); + else if (chap->auth.in.hdr.code == 0 || chap->auth.in.hdr.code > MAXCHAPCODE) + log_Printf(LogPHASE, "Chap Input: %d: Bad CHAP code !\n", + chap->auth.in.hdr.code); + else { + len = mbuf_Length(bp); + ans = NULL; + + if (chap->auth.in.hdr.code != CHAP_CHALLENGE && + chap->auth.id != chap->auth.in.hdr.id && + Enabled(p->dl->bundle, OPT_IDCHECK)) { + /* Wrong conversation dude ! */ + log_Printf(LogPHASE, "Chap Input: %s dropped (got id %d, not %d)\n", + chapcodes[chap->auth.in.hdr.code], chap->auth.in.hdr.id, + chap->auth.id); + mbuf_Free(bp); + return; + } + chap->auth.id = chap->auth.in.hdr.id; /* We respond with this id */ + + switch (chap->auth.in.hdr.code) { + case CHAP_CHALLENGE: + bp = mbuf_Read(bp, chap->challenge, 1); + len -= *chap->challenge + 1; + if (len < 0) { + log_Printf(LogERROR, "Chap Input: Truncated challenge !\n"); + mbuf_Free(bp); + return; + } + bp = mbuf_Read(bp, chap->challenge + 1, *chap->challenge); + bp = auth_ReadName(&chap->auth, bp, len); + break; + case CHAP_RESPONSE: - auth_StopTimer(&physical->dl->chap.auth); - /* Fall into.. */ + auth_StopTimer(&chap->auth); + bp = mbuf_Read(bp, &alen, 1); + len -= alen + 1; + if (len < 0) { + log_Printf(LogERROR, "Chap Input: Truncated response !\n"); + mbuf_Free(bp); + return; + } + if ((ans = malloc(alen + 2)) == NULL) { + log_Printf(LogERROR, "Chap Input: Out of memory !\n"); + mbuf_Free(bp); + return; + } + *ans = chap->auth.id; + bp = mbuf_Read(bp, ans + 1, alen); + ans[alen+1] = '\0'; + bp = auth_ReadName(&chap->auth, bp, len); + break; + + case CHAP_SUCCESS: + case CHAP_FAILURE: + /* chap->auth.in.name is already set up at CHALLENGE time */ + if ((ans = malloc(len + 1)) == NULL) { + log_Printf(LogERROR, "Chap Input: Out of memory !\n"); + mbuf_Free(bp); + return; + } + bp = mbuf_Read(bp, ans, len); + ans[len] = '\0'; + break; + } + + switch (chap->auth.in.hdr.code) { case CHAP_CHALLENGE: - RecvChapTalk(bundle, chp, bp, physical); - break; + case CHAP_RESPONSE: + if (*chap->auth.in.name) + log_Printf(LogPHASE, "Chap Input: %s (from %s)\n", + chapcodes[chap->auth.in.hdr.code], chap->auth.in.name); + else + log_Printf(LogPHASE, "Chap Input: %s\n", + chapcodes[chap->auth.in.hdr.code]); + break; + case CHAP_SUCCESS: case CHAP_FAILURE: - log_Printf(LogPHASE, "Chap Input: %s\n", chapcodes[chp->code]); - RecvChapResult(bundle, chp, bp, physical); - break; - } + if (*ans) + log_Printf(LogPHASE, "Chap Input: %s (%s)\n", + chapcodes[chap->auth.in.hdr.code], ans); + else + log_Printf(LogPHASE, "Chap Input: %s\n", + chapcodes[chap->auth.in.hdr.code]); + break; } + + 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); + break; + + case CHAP_RESPONSE: + name = chap->auth.in.name; + nlen = strlen(name); +#ifndef NORADIUS + if (*p->dl->bundle->radius.cfg.file) { + chap->challenge[*chap->challenge+1] = '\0'; +log_Printf(LogPHASE, "Challenge %s, answer is %d bytes starting with %d\n", chap->challenge+1, alen+1, *ans); + radius_Authenticate(&p->dl->bundle->radius, &chap->auth, + chap->auth.in.name, ans, chap->challenge + 1); + } else +#endif + { + key = auth_GetSecret(p->dl->bundle, name, nlen, p); + if (key) { + myans = chap_BuildAnswer(name, key, chap->auth.id, chap->challenge, + chap->using_MSChap); + if (myans == NULL) + key = NULL; + else { + if (memcmp(myans, ans, 1 + *myans)) + key = NULL; + free(myans); + } + } + + if (key) + chap_Success(&chap->auth); + else + chap_Failure(&chap->auth); + } + + break; + + case CHAP_SUCCESS: + if (p->link.lcp.auth_iwait == PROTO_CHAP) { + p->link.lcp.auth_iwait = 0; + if (p->link.lcp.auth_ineed == 0) + /* + * We've succeeded in our ``login'' + * If we're not expecting the peer to authenticate (or he already + * has), proceed to network phase. + */ + datalink_AuthOk(p->dl); + } + break; + + case CHAP_FAILURE: + datalink_AuthNotOk(p->dl); + break; + } + free(ans); } + mbuf_Free(bp); } diff --git a/usr.sbin/ppp/chap.h b/usr.sbin/ppp/chap.h index c504354..0aaea88 100644 --- a/usr.sbin/ppp/chap.h +++ b/usr.sbin/ppp/chap.h @@ -15,14 +15,13 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: chap.h,v 1.9.2.6 1998/05/01 19:24:05 brian Exp $ + * $Id: chap.h,v 1.10 1998/05/21 21:44:27 brian Exp $ * * TODO: */ struct mbuf; struct physical; -struct bundle; #define CHAP_CHALLENGE 1 #define CHAP_RESPONSE 2 @@ -31,12 +30,11 @@ struct bundle; struct chap { struct authinfo auth; - char challenge_data[80]; - int challenge_len; + char challenge[CHAPCHALLENGELEN + AUTHLEN]; unsigned using_MSChap : 1; /* A combination of MD4 & DES */ }; #define auth2chap(a) ((struct chap *)(a)) -extern void chap_Input(struct bundle *, struct mbuf *, struct physical *); -extern void chap_SendChallenge(struct authinfo *, int, struct physical *); +extern void chap_Init(struct chap *, struct physical *); +extern void chap_Input(struct physical *, struct mbuf *); diff --git a/usr.sbin/ppp/datalink.c b/usr.sbin/ppp/datalink.c index 7aa88cf..3b52c04 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.27 1999/02/01 13:42:24 brian Exp $ + * $Id: datalink.c,v 1.28 1999/02/02 09:35:17 brian Exp $ */ #include <sys/param.h> @@ -469,7 +469,7 @@ datalink_LayerUp(void *v, struct fsm *fp) struct datalink *dl = (struct datalink *)v; if (fp->proto == PROTO_LCP) { - datalink_GotAuthname(dl, "", 0); + datalink_GotAuthname(dl, ""); dl->physical->link.lcp.auth_ineed = dl->physical->link.lcp.want_auth; dl->physical->link.lcp.auth_iwait = dl->physical->link.lcp.his_auth; if (dl->physical->link.lcp.his_auth || dl->physical->link.lcp.want_auth) { @@ -479,21 +479,19 @@ datalink_LayerUp(void *v, struct fsm *fp) Auth2Nam(dl->physical->link.lcp.his_auth), Auth2Nam(dl->physical->link.lcp.want_auth)); if (dl->physical->link.lcp.his_auth == PROTO_PAP) - auth_StartChallenge(&dl->pap, dl->physical, pap_SendChallenge); + auth_StartReq(&dl->pap); if (dl->physical->link.lcp.want_auth == PROTO_CHAP) - auth_StartChallenge(&dl->chap.auth, dl->physical, chap_SendChallenge); + auth_StartReq(&dl->chap.auth); } else datalink_AuthOk(dl); } } void -datalink_GotAuthname(struct datalink *dl, const char *name, int len) +datalink_GotAuthname(struct datalink *dl, const char *name) { - if (len >= sizeof dl->peer.authname) - len = sizeof dl->peer.authname - 1; - strncpy(dl->peer.authname, name, len); - dl->peer.authname[len] = '\0'; + strncpy(dl->peer.authname, name, sizeof dl->peer.authname - 1); + dl->peer.authname[sizeof dl->peer.authname - 1] = '\0'; } void @@ -724,14 +722,14 @@ datalink_Create(const char *name, struct bundle *bundle, int type) dl->fsmp.LayerFinish = datalink_LayerFinish; dl->fsmp.object = dl; - auth_Init(&dl->pap); - auth_Init(&dl->chap.auth); - if ((dl->physical = modem_Create(dl, type)) == NULL) { free(dl->name); free(dl); return NULL; } + + pap_Init(&dl->pap, dl->physical); + chap_Init(&dl->chap, dl->physical); cbcp_Init(&dl->cbcp, dl->physical); chat_Init(&dl->chat, dl->physical, NULL, 1, NULL); @@ -774,17 +772,18 @@ datalink_Clone(struct datalink *odl, const char *name) dl->parent = odl->parent; memcpy(&dl->fsmp, &odl->fsmp, sizeof dl->fsmp); dl->fsmp.object = dl; - auth_Init(&dl->pap); - dl->pap.cfg.fsmretry = odl->pap.cfg.fsmretry; - - auth_Init(&dl->chap.auth); - dl->chap.auth.cfg.fsmretry = odl->chap.auth.cfg.fsmretry; if ((dl->physical = modem_Create(dl, PHYS_INTERACTIVE)) == NULL) { free(dl->name); free(dl); return NULL; } + pap_Init(&dl->pap, dl->physical); + dl->pap.cfg.fsmretry = odl->pap.cfg.fsmretry; + + chap_Init(&dl->chap, dl->physical); + dl->chap.auth.cfg.fsmretry = odl->chap.auth.cfg.fsmretry; + memcpy(&dl->physical->cfg, &odl->physical->cfg, sizeof dl->physical->cfg); memcpy(&dl->physical->link.lcp.cfg, &odl->physical->link.lcp.cfg, sizeof dl->physical->link.lcp.cfg); @@ -1180,14 +1179,6 @@ iov2datalink(struct bundle *bundle, struct iovec *iov, int *niov, int maxiov, dl->fsmp.LayerFinish = datalink_LayerFinish; dl->fsmp.object = dl; - retry = dl->pap.cfg.fsmretry; - auth_Init(&dl->pap); - dl->pap.cfg.fsmretry = retry; - - retry = dl->chap.auth.cfg.fsmretry; - auth_Init(&dl->chap.auth); - dl->chap.auth.cfg.fsmretry = retry; - dl->physical = iov2modem(dl, iov, niov, maxiov, fd); if (!dl->physical) { @@ -1195,6 +1186,14 @@ iov2datalink(struct bundle *bundle, struct iovec *iov, int *niov, int maxiov, free(dl); dl = NULL; } else { + retry = dl->pap.cfg.fsmretry; + pap_Init(&dl->pap, dl->physical); + dl->pap.cfg.fsmretry = retry; + + retry = dl->chap.auth.cfg.fsmretry; + chap_Init(&dl->chap, dl->physical); + dl->chap.auth.cfg.fsmretry = retry; + cbcp_Init(&dl->cbcp, dl->physical); chat_Init(&dl->chat, dl->physical, NULL, 1, NULL); diff --git a/usr.sbin/ppp/datalink.h b/usr.sbin/ppp/datalink.h index 4080199..e02e264 100644 --- a/usr.sbin/ppp/datalink.h +++ b/usr.sbin/ppp/datalink.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: datalink.h,v 1.4 1998/06/15 19:05:19 brian Exp $ + * $Id: datalink.h,v 1.5 1998/08/07 18:42:48 brian Exp $ */ #define DATALINK_CLOSED (0) @@ -123,7 +123,7 @@ extern struct datalink *iov2datalink(struct bundle *, struct iovec *, int *, int, int); extern int datalink2iov(struct datalink *, struct iovec *, int *, int, pid_t); extern struct datalink *datalink_Destroy(struct datalink *); -extern void datalink_GotAuthname(struct datalink *, const char *, int); +extern void datalink_GotAuthname(struct datalink *, const char *); extern void datalink_Up(struct datalink *, int, int); extern void datalink_Close(struct datalink *, int); extern void datalink_Down(struct datalink *, int); diff --git a/usr.sbin/ppp/descriptor.h b/usr.sbin/ppp/descriptor.h index 98cda53..a4f43a3 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.3 1998/05/23 22:24:34 brian Exp $ + * $Id: descriptor.h,v 1.4 1998/06/24 19:33:31 brian Exp $ */ #define PHYSICAL_DESCRIPTOR (1) @@ -33,6 +33,7 @@ #define DATALINK_DESCRIPTOR (5) #define BUNDLE_DESCRIPTOR (6) #define MPSERVER_DESCRIPTOR (7) +#define RADIUS_DESCRIPTOR (8) struct bundle; diff --git a/usr.sbin/ppp/hdlc.c b/usr.sbin/ppp/hdlc.c index ce5db46..bca157d 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.36 1998/08/07 18:42:48 brian Exp $ + * $Id: hdlc.c,v 1.37 1999/01/28 01:56:32 brian Exp $ * * TODO: */ @@ -393,7 +393,7 @@ hdlc_DecodePacket(struct bundle *bundle, u_short proto, struct mbuf * bp, break; case PROTO_PAP: if (p) - pap_Input(bundle, bp, p); + pap_Input(p, bp); else { log_Printf(LogERROR, "DecodePacket: PAP: Not a physical link !\n"); mbuf_Free(bp); @@ -418,7 +418,7 @@ hdlc_DecodePacket(struct bundle *bundle, u_short proto, struct mbuf * bp, break; case PROTO_CHAP: if (p) - chap_Input(bundle, bp, p); + chap_Input(p, bp); else { log_Printf(LogERROR, "DecodePacket: CHAP: Not a physical link !\n"); mbuf_Free(bp); diff --git a/usr.sbin/ppp/ipcp.c b/usr.sbin/ppp/ipcp.c index a2c337e..a430994 100644 --- a/usr.sbin/ppp/ipcp.c +++ b/usr.sbin/ppp/ipcp.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ipcp.c,v 1.69 1999/01/28 01:56:32 brian Exp $ + * $Id: ipcp.c,v 1.70 1999/02/02 20:27:12 brian Exp $ * * TODO: * o More RFC1772 backward compatibility @@ -30,10 +30,7 @@ #include <sys/socket.h> #include <net/route.h> #include <netdb.h> -#include <net/if.h> -#include <sys/sockio.h> #include <sys/un.h> -#include <arpa/nameser.h> #include <fcntl.h> #include <resolv.h> diff --git a/usr.sbin/ppp/link.c b/usr.sbin/ppp/link.c index 68672a5..c3a7453 100644 --- a/usr.sbin/ppp/link.c +++ b/usr.sbin/ppp/link.c @@ -23,14 +23,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: link.c,v 1.5 1998/08/25 17:48:42 brian Exp $ + * $Id: link.c,v 1.6 1998/08/26 18:07:56 brian Exp $ * */ #include <sys/types.h> #include <stdio.h> -#include <string.h> #include <termios.h> #include "defs.h" diff --git a/usr.sbin/ppp/main.c b/usr.sbin/ppp/main.c index d37c91d..de93fbb 100644 --- a/usr.sbin/ppp/main.c +++ b/usr.sbin/ppp/main.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: main.c,v 1.148 1999/01/28 01:56:33 brian Exp $ + * $Id: main.c,v 1.149 1999/02/02 09:35:29 brian Exp $ * * TODO: */ @@ -516,6 +516,8 @@ DoLoop(struct bundle *bundle) break; } + log_Printf(LogTIMER, "Select returns %d\n", i); + sig_Handle(); if (i <= 0) diff --git a/usr.sbin/ppp/mbuf.c b/usr.sbin/ppp/mbuf.c index 9601689..fa94406 100644 --- a/usr.sbin/ppp/mbuf.c +++ b/usr.sbin/ppp/mbuf.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: mbuf.c,v 1.21 1998/08/21 18:10:15 brian Exp $ + * $Id: mbuf.c,v 1.22 1998/08/25 17:48:42 brian Exp $ * */ #include <sys/types.h> @@ -114,13 +114,8 @@ mbuf_Read(struct mbuf * bp, u_char * ptr, int len) bp->cnt -= nb; len -= nb; bp->offset += nb; - if (bp->cnt == 0) { -#ifdef notdef - bp = bp->next; -#else + if (bp->cnt == 0) bp = mbuf_FreeSeg(bp); -#endif - } } return (bp); } diff --git a/usr.sbin/ppp/pap.c b/usr.sbin/ppp/pap.c index a87cc82..10be577 100644 --- a/usr.sbin/ppp/pap.c +++ b/usr.sbin/ppp/pap.c @@ -18,7 +18,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: pap.c,v 1.29 1999/02/01 13:42:25 brian Exp $ + * $Id: pap.c,v 1.30 1999/02/02 09:35:17 brian Exp $ * * TODO: */ @@ -28,7 +28,7 @@ #include <netinet/ip.h> #include <sys/un.h> -#include <string.h> +#include <stdlib.h> #include <termios.h> #include "mbuf.h" @@ -63,41 +63,41 @@ #include "datalink.h" static const char *papcodes[] = { "???", "REQUEST", "SUCCESS", "FAILURE" }; +#define MAXPAPCODE (sizeof papcodes / sizeof papcodes[0] - 1) -void -pap_SendChallenge(struct authinfo *auth, int papid, struct physical *physical) +static void +pap_Req(struct authinfo *authp) { + struct bundle *bundle = authp->physical->dl->bundle; struct fsmheader lh; struct mbuf *bp; u_char *cp; int namelen, keylen, plen; - namelen = strlen(physical->dl->bundle->cfg.auth.name); - keylen = strlen(physical->dl->bundle->cfg.auth.key); + namelen = strlen(bundle->cfg.auth.name); + keylen = strlen(bundle->cfg.auth.key); plen = namelen + keylen + 2; - log_Printf(LogDEBUG, "pap_SendChallenge: namelen = %d, keylen = %d\n", - namelen, keylen); - log_Printf(LogPHASE, "Pap Output: %s ********\n", - physical->dl->bundle->cfg.auth.name); - if (*physical->dl->bundle->cfg.auth.name == '\0') + log_Printf(LogDEBUG, "pap_Req: namelen = %d, keylen = %d\n", namelen, keylen); + log_Printf(LogPHASE, "Pap Output: %s ********\n", bundle->cfg.auth.name); + if (*bundle->cfg.auth.name == '\0') log_Printf(LogWARN, "Sending empty PAP authname!\n"); lh.code = PAP_REQUEST; - lh.id = papid; + lh.id = authp->id; lh.length = htons(plen + sizeof(struct fsmheader)); bp = mbuf_Alloc(plen + sizeof(struct fsmheader), MB_FSM); memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); cp = MBUF_CTOP(bp) + sizeof(struct fsmheader); *cp++ = namelen; - memcpy(cp, physical->dl->bundle->cfg.auth.name, namelen); + memcpy(cp, bundle->cfg.auth.name, namelen); cp += namelen; *cp++ = keylen; - memcpy(cp, physical->dl->bundle->cfg.auth.key, keylen); + memcpy(cp, bundle->cfg.auth.key, keylen); - hdlc_Output(&physical->link, PRI_LINK, PROTO_PAP, bp); + hdlc_Output(&authp->physical->link, PRI_LINK, PROTO_PAP, bp); } static void -SendPapCode(int id, int code, const char *message, struct physical *physical) +SendPapCode(struct authinfo *authp, int code, const char *message) { struct fsmheader lh; struct mbuf *bp; @@ -105,7 +105,7 @@ SendPapCode(int id, int code, const char *message, struct physical *physical) int plen, mlen; lh.code = code; - lh.id = id; + lh.id = authp->id; mlen = strlen(message); plen = mlen + 1; lh.length = htons(plen + sizeof(struct fsmheader)); @@ -115,90 +115,124 @@ SendPapCode(int id, int code, const char *message, struct physical *physical) *cp++ = mlen; memcpy(cp, message, mlen); log_Printf(LogPHASE, "Pap Output: %s\n", papcodes[code]); - hdlc_Output(&physical->link, PRI_LINK, PROTO_PAP, bp); + + hdlc_Output(&authp->physical->link, PRI_LINK, PROTO_PAP, bp); } -/* - * Validate given username and passwrd against with secret table - */ -static int -PapValidate(struct bundle *bundle, u_char *name, u_char *key, - struct physical *physical) +static void +pap_Success(struct authinfo *authp) { - int nlen, klen; + datalink_GotAuthname(authp->physical->dl, authp->in.name); + SendPapCode(authp, PAP_ACK, "Greetings!!"); + authp->physical->link.lcp.auth_ineed = 0; + if (Enabled(authp->physical->dl->bundle, OPT_UTMP)) + physical_Login(authp->physical, authp->in.name); + + if (authp->physical->link.lcp.auth_iwait == 0) + /* + * Either I didn't need to authenticate, or I've already been + * told that I got the answer right. + */ + datalink_AuthOk(authp->physical->dl); +} - nlen = *name++; - klen = *key; - *key++ = 0; - key[klen] = 0; - log_Printf(LogDEBUG, "PapValidate: name %s (%d), key %s (%d)\n", - name, nlen, key, klen); +static void +pap_Failure(struct authinfo *authp) +{ + SendPapCode(authp, PAP_NAK, "Login incorrect"); + datalink_AuthNotOk(authp->physical->dl); +} - return auth_Validate(bundle, name, key, physical); +void +pap_Init(struct authinfo *pap, struct physical *p) +{ + auth_Init(pap, p, pap_Req, pap_Success, pap_Failure); } void -pap_Input(struct bundle *bundle, struct mbuf *bp, struct physical *physical) +pap_Input(struct physical *p, struct mbuf *bp) { - int len = mbuf_Length(bp); - struct fsmheader *php; - u_char *cp; + struct authinfo *authp = &p->dl->pap; + u_char nlen, klen, *key; + + if ((bp = auth_ReadHeader(authp, bp)) == NULL) + return; + + if (authp->in.hdr.code == 0 || authp->in.hdr.code > MAXPAPCODE) { + log_Printf(LogPHASE, "Pap Input: %d: Bad PAP code !\n", authp->in.hdr.code); + mbuf_Free(bp); + return; + } + + if (authp->in.hdr.code != PAP_REQUEST && authp->id != authp->in.hdr.id && + Enabled(p->dl->bundle, OPT_IDCHECK)) { + /* Wrong conversation dude ! */ + log_Printf(LogPHASE, "Pap Input: %s dropped (got id %d, not %d)\n", + papcodes[authp->in.hdr.code], authp->in.hdr.id, authp->id); + mbuf_Free(bp); + return; + } + authp->id = authp->in.hdr.id; /* We respond with this id */ + + if (bp) { + bp = mbuf_Read(bp, &nlen, 1); + bp = auth_ReadName(authp, bp, nlen); + } + + log_Printf(LogPHASE, "Pap Input: %s (%s)\n", + papcodes[authp->in.hdr.code], authp->in.name); + + switch (authp->in.hdr.code) { + case PAP_REQUEST: + if (bp == NULL) { + log_Printf(LogPHASE, "Pap Input: No key given !\n"); + break; + } + bp = mbuf_Read(bp, &klen, 1); + if (mbuf_Length(bp) < klen) { + log_Printf(LogERROR, "Pap Input: Truncated key !\n"); + break; + } + if ((key = malloc(klen+1)) == NULL) { + log_Printf(LogERROR, "Pap Input: Out of memory !\n"); + break; + } + bp = mbuf_Read(bp, key, klen); + key[klen] = '\0'; + +#ifndef NORADIUS + if (*p->dl->bundle->radius.cfg.file) + radius_Authenticate(&p->dl->bundle->radius, authp, authp->in.name, + key, NULL); + else +#endif + if (auth_Validate(p->dl->bundle, authp->in.name, key, p)) + pap_Success(authp); + else + pap_Failure(authp); + + free(key); + break; - if (len >= sizeof(struct fsmheader)) { - php = (struct fsmheader *) MBUF_CTOP(bp); - if (len >= ntohs(php->length)) { - if (php->code < PAP_REQUEST || php->code > PAP_NAK) - php->code = 0; - switch (php->code) { - case PAP_REQUEST: - cp = (u_char *) (php + 1); - log_Printf(LogPHASE, "Pap Input: %s (%.*s)\n", - papcodes[php->code], *cp, cp + 1); - if (PapValidate(bundle, cp, cp + *cp + 1, physical)) { - datalink_GotAuthname(physical->dl, cp+1, *cp); - SendPapCode(php->id, PAP_ACK, "Greetings!!", physical); - physical->link.lcp.auth_ineed = 0; - if (Enabled(bundle, OPT_UTMP)) - physical_Login(physical, cp + 1); - - if (physical->link.lcp.auth_iwait == 0) - /* - * Either I didn't need to authenticate, or I've already been - * told that I got the answer right. - */ - datalink_AuthOk(physical->dl); - } else { - SendPapCode(php->id, PAP_NAK, "Login incorrect", physical); - datalink_AuthNotOk(physical->dl); - } - break; - case PAP_ACK: - auth_StopTimer(&physical->dl->pap); - cp = (u_char *) (php + 1); - len = *cp++; - cp[len] = 0; - log_Printf(LogPHASE, "Pap Input: %s (%s)\n", papcodes[php->code], cp); - if (physical->link.lcp.auth_iwait == PROTO_PAP) { - physical->link.lcp.auth_iwait = 0; - if (physical->link.lcp.auth_ineed == 0) - /* - * We've succeeded in our ``login'' - * If we're not expecting the peer to authenticate (or he already - * has), proceed to network phase. - */ - datalink_AuthOk(physical->dl); - } - break; - case PAP_NAK: - auth_StopTimer(&physical->dl->pap); - cp = (u_char *) (php + 1); - len = *cp++; - cp[len] = 0; - log_Printf(LogPHASE, "Pap Input: %s (%s)\n", papcodes[php->code], cp); - datalink_AuthNotOk(physical->dl); - break; + case PAP_ACK: + auth_StopTimer(authp); + if (p->link.lcp.auth_iwait == PROTO_PAP) { + p->link.lcp.auth_iwait = 0; + if (p->link.lcp.auth_ineed == 0) + /* + * We've succeeded in our ``login'' + * If we're not expecting the peer to authenticate (or he already + * has), proceed to network phase. + */ + datalink_AuthOk(p->dl); } - } + break; + + case PAP_NAK: + auth_StopTimer(authp); + datalink_AuthNotOk(p->dl); + break; } + mbuf_Free(bp); } diff --git a/usr.sbin/ppp/pap.h b/usr.sbin/ppp/pap.h index ac08b8b..bef8292 100644 --- a/usr.sbin/ppp/pap.h +++ b/usr.sbin/ppp/pap.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: pap.h,v 1.7 1999/02/01 13:42:25 brian Exp $ + * $Id: pap.h,v 1.8 1999/02/02 09:35:17 brian Exp $ * * TODO: */ @@ -27,7 +27,6 @@ struct mbuf; struct physical; struct authinfo; -struct bundle; -extern void pap_Input(struct bundle *, struct mbuf *, struct physical *); -extern void pap_SendChallenge(struct authinfo *, int, struct physical *); +extern void pap_Init(struct authinfo *, struct physical *); +extern void pap_Input(struct physical *, struct mbuf *); diff --git a/usr.sbin/ppp/radius.c b/usr.sbin/ppp/radius.c index b60605a..1228b67 100644 --- a/usr.sbin/ppp/radius.c +++ b/usr.sbin/ppp/radius.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: radius.c,v 1.1 1999/01/28 01:56:34 brian Exp $ + * $Id: radius.c,v 1.2 1999/01/29 22:46:31 brian Exp $ * */ @@ -36,10 +36,10 @@ #include <errno.h> #include <radlib.h> -#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/time.h> #include <termios.h> #include "defs.h" @@ -58,143 +58,86 @@ #include "route.h" #include "command.h" #include "filter.h" -#include "server.h" #include "lcp.h" #include "ccp.h" #include "link.h" #include "mp.h" #include "radius.h" +#include "auth.h" +#include "async.h" +#include "physical.h" +#include "chat.h" +#include "cbcp.h" +#include "chap.h" +#include "datalink.h" #include "bundle.h" -void -radius_Init(struct radius *r) -{ - r->valid = 0; - *r->cfg.file = '\0';; -} - -void -radius_Destroy(struct radius *r) -{ - r->valid = 0; - route_DeleteAll(&r->routes); -} - -int -radius_Authenticate(struct radius *r, struct bundle *bundle, const char *name, - const char *key, const char *challenge) +/* + * rad_continue_send_request() has given us `got' (non-zero). Deal with it. + */ +static void +radius_Process(struct radius *r, int got) { - struct rad_handle *h; - sigset_t alrm, prevset; - const void *data; - int got, len, argc, addrs; char *argv[MAXARGS], *nuke; + struct bundle *bundle; + int len, argc, addrs; struct in_range dest; struct in_addr gw; + const void *data; - radius_Destroy(r); - - if (!*r->cfg.file) - return 0; - - if ((h = rad_open()) == NULL) { - log_Printf(LogERROR, "rad_open: %s\n", strerror(errno)); - return 0; - } - - if (rad_config(h, r->cfg.file) != 0) { - log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(h)); - rad_close(h); - return 0; - } - - if (rad_create_request(h, RAD_ACCESS_REQUEST) != 0) { - log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(h)); - rad_close(h); - return 0; - } - - if (rad_put_string(h, RAD_USER_NAME, name) != 0 || - rad_put_int(h, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || - rad_put_int(h, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { - log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(h)); - rad_close(h); - return 0; - } - - if (challenge != NULL) { /* CHAP */ - if (rad_put_string(h, RAD_CHAP_PASSWORD, key) != 0 || - rad_put_string(h, RAD_CHAP_CHALLENGE, challenge) != 0) { - log_Printf(LogERROR, "CHAP: rad_put_string: %s\n", rad_strerror(h)); - rad_close(h); - return 0; - } - } else if (rad_put_string(h, RAD_USER_PASSWORD, key) != 0) { /* PAP */ - /* We're talking PAP */ - log_Printf(LogERROR, "PAP: rad_put_string: %s\n", rad_strerror(h)); - rad_close(h); - return 0; - } - - /* - * Having to do this is bad news. The right way is to grab the - * descriptor that rad_send_request() selects on and add it to - * our own selection list (making a full ``struct descriptor''), - * then to ``continue'' the call when the descriptor is ready. - * This requires altering libradius.... - */ - sigemptyset(&alrm); - sigaddset(&alrm, SIGALRM); - sigprocmask(SIG_BLOCK, &alrm, &prevset); - got = rad_send_request(h); - sigprocmask(SIG_SETMASK, &prevset, NULL); + r->cx.fd = -1; /* Stop select()ing */ switch (got) { case RAD_ACCESS_ACCEPT: + log_Printf(LogPHASE, "Radius: ACCEPT received\n"); break; + case RAD_ACCESS_REJECT: + log_Printf(LogPHASE, "Radius: REJECT received\n"); + auth_Failure(r->cx.auth); + rad_close(r->cx.rad); + return; + case RAD_ACCESS_CHALLENGE: /* we can't deal with this (for now) ! */ - log_Printf(LogPHASE, "Can't handle radius CHALLENGEs !\n"); - rad_close(h); - return 0; + log_Printf(LogPHASE, "Radius: CHALLENGE received (can't handle yet)\n"); + auth_Failure(r->cx.auth); + rad_close(r->cx.rad); + return; case -1: - log_Printf(LogPHASE, "radius: %s\n", rad_strerror(h)); - rad_close(h); - return 0; + log_Printf(LogPHASE, "radius: %s\n", rad_strerror(r->cx.rad)); + auth_Failure(r->cx.auth); + rad_close(r->cx.rad); + return; default: log_Printf(LogERROR, "rad_send_request: Failed %d: %s\n", - got, rad_strerror(h)); - rad_close(h); - return 0; - - case RAD_ACCESS_REJECT: - log_Printf(LogPHASE, "radius: Rejected !\n"); - rad_close(h); - return 0; + got, rad_strerror(r->cx.rad)); + auth_Failure(r->cx.auth); + rad_close(r->cx.rad); + return; } /* So we've been accepted ! Let's see what we've got in our reply :-I */ r->ip.s_addr = r->mask.s_addr = INADDR_NONE; r->mtu = 0; r->vj = 0; - while ((got = rad_get_attr(h, &data, &len)) > 0) { + while ((got = rad_get_attr(r->cx.rad, &data, &len)) > 0) { switch (got) { case RAD_FRAMED_IP_ADDRESS: r->ip = rad_cvt_addr(data); - log_Printf(LogDEBUG, "radius: Got IP %s\n", inet_ntoa(r->ip)); + log_Printf(LogPHASE, " IP %s\n", inet_ntoa(r->ip)); break; case RAD_FRAMED_IP_NETMASK: r->mask = rad_cvt_addr(data); - log_Printf(LogDEBUG, "radius: Got MASK %s\n", inet_ntoa(r->mask)); + log_Printf(LogPHASE, " Netmask %s\n", inet_ntoa(r->mask)); break; case RAD_FRAMED_MTU: r->mtu = rad_cvt_int(data); - log_Printf(LogDEBUG, "radius: Got MTU %lu\n", r->mtu); + log_Printf(LogPHASE, " MTU %lu\n", r->mtu); break; case RAD_FRAMED_ROUTING: @@ -206,7 +149,7 @@ radius_Authenticate(struct radius *r, struct bundle *bundle, const char *name, case RAD_FRAMED_COMPRESSION: r->vj = rad_cvt_int(data) == 1 ? 1 : 0; - log_Printf(LogDEBUG, "radius: Got VJ %sabled\n", r->vj ? "en" : "dis"); + log_Printf(LogPHASE, " VJ %sabled\n", r->vj ? "en" : "dis"); break; case RAD_FRAMED_ROUTE: @@ -218,11 +161,13 @@ radius_Authenticate(struct radius *r, struct bundle *bundle, const char *name, */ if ((nuke = rad_cvt_string(data, len)) == NULL) { - log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(h)); - rad_close(h); - return 0; + log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); + rad_close(r->cx.rad); + return; } + log_Printf(LogPHASE, " Route: %s\n", nuke); + bundle = r->cx.auth->physical->dl->bundle; dest.ipaddr.s_addr = dest.mask.s_addr = INADDR_ANY; dest.width = 0; argc = command_Interpret(nuke, strlen(nuke), argv); @@ -260,18 +205,208 @@ radius_Authenticate(struct radius *r, struct bundle *bundle, const char *name, } if (got == -1) { - log_Printf(LogERROR, "rad_get_attr: %s\n", rad_strerror(h)); - rad_close(h); - return 0; + log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n", + rad_strerror(r->cx.rad)); + auth_Failure(r->cx.auth); + rad_close(r->cx.rad); + } else { + r->valid = 1; + auth_Success(r->cx.auth); + rad_close(r->cx.rad); + } +} + +/* + * We've either timed out or select()ed on the read descriptor + */ +static void +radius_Continue(struct radius *r, int sel) +{ + struct timeval tv; + int got; + + timer_Stop(&r->cx.timer); + if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) { + log_Printf(LogPHASE, "Radius: Request re-sent\n"); + r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; + timer_Start(&r->cx.timer); + return; } - rad_close(h); - r->valid = 1; - log_Printf(LogPHASE, "radius: SUCCESS\n"); + radius_Process(r, got); +} - return 1; +/* + * Time to call rad_continue_send_request() - timed out. + */ +static void +radius_Timeout(void *v) +{ + radius_Continue((struct radius *)v, 0); } +/* + * Time to call rad_continue_send_request() - something to read. + */ +static void +radius_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) +{ + radius_Continue(descriptor2radius(d), 1); +} + +/* + * Behave as a struct descriptor (descriptor.h) + */ +static int +radius_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) +{ + struct radius *rad = descriptor2radius(d); + + if (r && rad->cx.fd != -1) { + FD_SET(rad->cx.fd, r); + if (*n < rad->cx.fd + 1) + *n = rad->cx.fd + 1; + log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd); + return 1; + } + + return 0; +} + +/* + * Behave as a struct descriptor (descriptor.h) + */ +static int +radius_IsSet(struct descriptor *d, const fd_set *fdset) +{ + struct radius *r = descriptor2radius(d); + + return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset); +} + +/* + * Behave as a struct descriptor (descriptor.h) + */ +static int +radius_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) +{ + /* We never want to write here ! */ + log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n"); + return 0; +} + +/* + * Initialise ourselves + */ +void +radius_Init(struct radius *r) +{ + r->valid = 0; + r->cx.fd = -1; + *r->cfg.file = '\0';; + r->desc.type = RADIUS_DESCRIPTOR; + r->desc.UpdateSet = radius_UpdateSet; + r->desc.IsSet = radius_IsSet; + r->desc.Read = radius_Read; + r->desc.Write = radius_Write; + memset(&r->cx.timer, '\0', sizeof r->cx.timer); +} + +/* + * Forget everything and go back to initialised state. + */ +void +radius_Destroy(struct radius *r) +{ + r->valid = 0; + timer_Stop(&r->cx.timer); + route_DeleteAll(&r->routes); + if (r->cx.fd != -1) { + r->cx.fd = -1; + rad_close(r->cx.rad); + } +} + +/* + * Start an authentication request to the RADIUS server. + */ +void +radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name, + const char *key, const char *challenge) +{ + struct timeval tv; + int got; + + if (!*r->cfg.file) + return; + + if (r->cx.fd != -1) + /* + * We assume that our name/key/challenge is the same as last time, + * and just continue to wait for the RADIUS server(s). + */ + return; + + radius_Destroy(r); + + if ((r->cx.rad = rad_open()) == NULL) { + log_Printf(LogERROR, "rad_open: %s\n", strerror(errno)); + return; + } + + if (rad_config(r->cx.rad, r->cfg.file) != 0) { + log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); + rad_close(r->cx.rad); + return; + } + + if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) { + log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); + rad_close(r->cx.rad); + return; + } + + if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 || + rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || + rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { + log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); + rad_close(r->cx.rad); + return; + } + + if (challenge != NULL) { + /* We're talking CHAP */ + if (rad_put_string(r->cx.rad, RAD_CHAP_PASSWORD, key) != 0 || + rad_put_string(r->cx.rad, RAD_CHAP_CHALLENGE, challenge) != 0) { + log_Printf(LogERROR, "CHAP: rad_put_string: %s\n", + rad_strerror(r->cx.rad)); + rad_close(r->cx.rad); + return; + } + } else if (rad_put_string(r->cx.rad, RAD_USER_PASSWORD, key) != 0) { + /* We're talking PAP */ + log_Printf(LogERROR, "PAP: rad_put_string: %s\n", rad_strerror(r->cx.rad)); + rad_close(r->cx.rad); + return; + } + + if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) + radius_Process(r, got); + else { + log_Printf(LogPHASE, "Radius: Request sent\n"); + log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); + r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; + r->cx.timer.func = radius_Timeout; + r->cx.timer.name = "radius"; + r->cx.timer.arg = r; + r->cx.auth = authp; + timer_Start(&r->cx.timer); + } +} + +/* + * How do things look at the moment ? + */ void radius_Show(struct radius *r, struct prompt *p) { diff --git a/usr.sbin/ppp/radius.h b/usr.sbin/ppp/radius.h index 0b02f21..37cf7b8 100644 --- a/usr.sbin/ppp/radius.h +++ b/usr.sbin/ppp/radius.h @@ -23,10 +23,17 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id:$ + * $Id: radius.h,v 1.1 1999/01/28 01:56:34 brian Exp $ */ struct radius { + struct descriptor desc; /* We're a sort of (selectable) descriptor */ + struct { + int fd; /* We're selecting on this */ + struct rad_handle *rad; /* Using this to talk to our lib */ + struct pppTimer timer; /* for this long */ + struct authinfo *auth; /* Tell this about success/failure */ + } cx; unsigned valid : 1; /* Is this structure valid ? */ unsigned vj : 1; /* FRAMED Compression */ struct in_addr ip; /* FRAMED IP */ @@ -38,11 +45,14 @@ struct radius { } cfg; }; +#define descriptor2radius(d) \ + ((d)->type == RADIUS_DESCRIPTOR ? (struct radius *)(d) : NULL) + struct bundle; extern void radius_Init(struct radius *); extern void radius_Destroy(struct radius *); extern void radius_Show(struct radius *, struct prompt *); -extern int radius_Authenticate(struct radius *, struct bundle *, const char *, - const char *, const char *); +extern void radius_Authenticate(struct radius *, struct authinfo *, + const char *, const char *, const char *); diff --git a/usr.sbin/ppp/vjcomp.c b/usr.sbin/ppp/vjcomp.c index e402c03..ee5100a 100644 --- a/usr.sbin/ppp/vjcomp.c +++ b/usr.sbin/ppp/vjcomp.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: vjcomp.c,v 1.23 1998/08/26 18:07:57 brian Exp $ + * $Id: vjcomp.c,v 1.24 1999/01/28 01:56:34 brian Exp $ * * TODO: */ @@ -28,7 +28,6 @@ #include <sys/un.h> #include <stdio.h> -#include <string.h> #include "mbuf.h" #include "log.h" |