Decouple pap & chap output routines from the corresponding

input routines and take advantage of the new init/continue
interface in libradius.  This allows a timely response on
other links in an MP setup while RADIUS requests are in
progress as well as the ability to handle other data from
the peer in parallel.  It should also make the future addition
of PAM support trivial.

While I'm in there, validate pap & chap header IDs if
``idcheck'' is enabled (the default) for other FSM packet
types.

NOTE: This involved integrating the generation of chap
      challenges and the validation of chap responses
      (and commenting what's going on in those routines).
      I currently have no way of testing ppps ability
      to respond to M$Chap CHALLENGEs correctly, so if
      someone could do the honours, it'd be much
      appreciated (it *looks* ok!).

Sponsored by: Internet Business Solutions Ltd., Switzerland
This commit is contained in:
Brian Somers 1999-02-06 02:54:47 +00:00
parent 811d024014
commit f0cdd9c021
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=43693
19 changed files with 789 additions and 507 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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"

View File

@ -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
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);
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);
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;
auth_Init(&chap->auth, p, chap_Challenge, chap_Success, chap_Failure);
*chap->challenge = 0;
chap->using_MSChap = 0;
}
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);
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;
switch (chp->code) {
case CHAP_RESPONSE:
auth_StopTimer(&physical->dl->chap.auth);
/* Fall into.. */
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:
RecvChapTalk(bundle, chp, bp, physical);
break;
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(&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:
log_Printf(LogPHASE, "Chap Input: %s\n", chapcodes[chp->code]);
RecvChapResult(bundle, chp, bp, physical);
break;
}
/* 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:
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:
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);
}

View File

@ -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 *);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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>

View File

@ -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"

View File

@ -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)

View File

@ -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);
}

View File

@ -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);
nlen = *name++;
klen = *key;
*key++ = 0;
key[klen] = 0;
log_Printf(LogDEBUG, "PapValidate: name %s (%d), key %s (%d)\n",
name, nlen, key, klen);
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);
}
return auth_Validate(bundle, name, key, physical);
static void
pap_Failure(struct authinfo *authp)
{
SendPapCode(authp, PAP_NAK, "Login incorrect");
datalink_AuthNotOk(authp->physical->dl);
}
void
pap_Input(struct bundle *bundle, struct mbuf *bp, struct physical *physical)
pap_Init(struct authinfo *pap, struct physical *p)
{
int len = mbuf_Length(bp);
struct fsmheader *php;
u_char *cp;
auth_Init(pap, p, pap_Req, pap_Success, pap_Failure);
}
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);
void
pap_Input(struct physical *p, struct mbuf *bp)
{
struct authinfo *authp = &p->dl->pap;
u_char nlen, klen, *key;
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;
}
}
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;
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);
}

View File

@ -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 *);

View File

@ -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)
/*
* rad_continue_send_request() has given us `got' (non-zero). Deal with it.
*/
static void
radius_Process(struct radius *r, int got)
{
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)
{
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);
}
rad_close(h);
r->valid = 1;
log_Printf(LogPHASE, "radius: SUCCESS\n");
return 1;
}
/*
* 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;
}
radius_Process(r, got);
}
/*
* 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)
{

View File

@ -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 *);

View File

@ -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"