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:
parent
811d024014
commit
f0cdd9c021
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=43693
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 *);
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user