Handle MS-CHAPv2 authentication correctly via the RADIUS server (if it's

configured).
Handle internal failures in radius_Authenticate() correctly.
Bump the ppp version number.

This doesn't yet work with MPPE.  More will follow.

Sponsored by: Mozoon
This commit is contained in:
Brian Somers 2002-05-16 13:34:20 +00:00
parent d883e289b9
commit a16061b236
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=96730
5 changed files with 114 additions and 48 deletions

View File

@ -549,7 +549,13 @@ chap_Success(struct authinfo *authp)
datalink_GotAuthname(authp->physical->dl, authp->in.name);
#ifndef NODES
if (authp->physical->link.lcp.want_authtype == 0x81) {
msg = auth2chap(authp)->authresponse;
#ifndef NORADIUS
if (*bundle->radius.cfg.file && bundle->radius.msrepstr)
msg = bundle->radius.msrepstr;
else
#else
msg = auth2chap(authp)->authresponse;
#endif
MPPE_MasterKeyValid = 1; /* XXX Global ! */
} else
#endif
@ -840,13 +846,23 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
case CHAP_RESPONSE:
name = chap->auth.in.name;
nlen = strlen(name);
#ifndef NODES
if (p->link.lcp.want_authtype == 0x81) {
chap->challenge.peer[0] = CHAP81_CHALLENGE_LEN;
memcpy(chap->challenge.peer + 1, ans + 1, CHAP81_CHALLENGE_LEN);
}
#endif
#ifndef NORADIUS
if (*bundle->radius.cfg.file)
radius_Authenticate(&bundle->radius, &chap->auth,
chap->auth.in.name, ans, alen + 1,
chap->challenge.local + 1,
*chap->challenge.local);
else
if (*bundle->radius.cfg.file) {
if (!radius_Authenticate(&bundle->radius, &chap->auth,
chap->auth.in.name, ans, alen + 1,
chap->challenge.local + 1,
*chap->challenge.local,
chap->challenge.peer + 1,
*chap->challenge.peer))
chap_Failure(&chap->auth);
} else
#endif
{
key = auth_GetSecret(bundle, name, nlen, p);
@ -872,14 +888,6 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
} else
#endif
{
#ifndef NODES
/* Get peer's challenge */
if (p->link.lcp.want_authtype == 0x81) {
chap->challenge.peer[0] = CHAP81_CHALLENGE_LEN;
memcpy(chap->challenge.peer + 1, ans + 1, CHAP81_CHALLENGE_LEN);
}
#endif
myans = chap_BuildAnswer(name, key, chap->auth.id,
chap->challenge.local,
p->link.lcp.want_authtype
@ -919,7 +927,8 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
if (p->link.lcp.auth_ineed == 0) {
#ifndef NODES
if (p->link.lcp.his_authtype == 0x81) {
if (strncmp(ans, chap->authresponse, 42)) {
if (strncmp(ans, chap->authresponse, 42) &&
(*ans != 1 || strncmp(ans + 1, chap->authresponse, 41))) {
datalink_AuthNotOk(p->dl);
log_Printf(LogWARN, "CHAP81: AuthenticatorResponse: (%.42s)"
" != ans: (%.42s)\n", chap->authresponse, ans);

View File

@ -163,7 +163,7 @@
#define NEG_MPPE 54
#define NEG_CHAP81 55
const char Version[] = "3.0.4";
const char Version[] = "3.0.5";
static int ShowCommand(struct cmdargs const *);
static int TerminalCommand(struct cmdargs const *);

View File

@ -264,10 +264,11 @@ pap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
key[klen] = '\0';
#ifndef NORADIUS
if (*bundle->radius.cfg.file)
radius_Authenticate(&bundle->radius, authp, authp->in.name,
key, strlen(key), NULL, 0);
else
if (*bundle->radius.cfg.file) {
if (!radius_Authenticate(&bundle->radius, authp, authp->in.name,
key, strlen(key), NULL, 0, NULL, 0))
pap_Failure(authp);
} else
#endif
if (auth_Validate(bundle, authp->in.name, key, p))
pap_Success(authp);

View File

@ -90,12 +90,20 @@
#include "proto.h"
#ifndef NODES
struct mschap_request {
struct mschap_response {
u_char ident;
u_char flags;
u_char lm_response[24];
u_char nt_response[24];
};
struct mschap2_response {
u_char ident;
u_char flags;
u_char pchallenge[16];
u_char reserved[8];
u_char response[24];
};
#endif
/*
@ -307,6 +315,18 @@ radius_Process(struct radius *r, int got)
}
log_Printf(LogPHASE, " MS-CHAP-Error \"%s\"\n", r->errstr);
break;
case RAD_MICROSOFT_MS_CHAP2_SUCCESS:
free(r->msrepstr);
if ((r->msrepstr = rad_cvt_string(data, len)) == NULL) {
log_Printf(LogERROR, "rad_cvt_string: %s\n",
rad_strerror(r->cx.rad));
auth_Failure(r->cx.auth);
rad_close(r->cx.rad);
return;
}
log_Printf(LogPHASE, " MS-CHAP2-Success \"%s\"\n", r->msrepstr);
break;
default:
log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific "
@ -441,6 +461,7 @@ radius_Init(struct radius *r)
r->mask.s_addr = INADDR_NONE;
r->routes = NULL;
r->mtu = DEF_MTU;
r->msrepstr = NULL;
r->repstr = NULL;
r->errstr = NULL;
*r->cfg.file = '\0';;
@ -459,6 +480,8 @@ radius_Destroy(struct radius *r)
route_DeleteAll(&r->routes);
free(r->filterid);
r->filterid = NULL;
free(r->msrepstr);
r->msrepstr = NULL;
free(r->repstr);
r->repstr = NULL;
free(r->errstr);
@ -517,9 +540,10 @@ radius_put_physical_details(struct rad_handle *rad, struct physical *p)
/*
* Start an authentication request to the RADIUS server.
*/
void
int
radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
const char *key, int klen, const char *challenge, int clen)
const char *key, int klen, const char *nchallenge,
int nclen, const char *pchallenge, int pclen)
{
struct timeval tv;
int got;
@ -527,36 +551,37 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
struct hostent *hp;
struct in_addr hostaddr;
#ifndef NODES
struct mschap_request msreq;
struct mschap_response msresp;
struct mschap2_response msresp2;
#endif
if (!*r->cfg.file)
return;
return 0;
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;
return 1;
radius_Destroy(r);
if ((r->cx.rad = rad_auth_open()) == NULL) {
log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno));
return;
return 0;
}
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;
return 0;
}
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;
return 0;
}
if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 ||
@ -564,7 +589,7 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
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;
return 0;
}
switch (authp->physical->link.lcp.want_auth) {
@ -574,7 +599,7 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
log_Printf(LogERROR, "PAP: rad_put_string: %s\n",
rad_strerror(r->cx.rad));
rad_close(r->cx.rad);
return;
return 0;
}
break;
@ -582,38 +607,64 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
switch (authp->physical->link.lcp.want_authtype) {
case 0x5:
if (rad_put_attr(r->cx.rad, RAD_CHAP_PASSWORD, key, klen) != 0 ||
rad_put_attr(r->cx.rad, RAD_CHAP_CHALLENGE, challenge, clen) != 0) {
rad_put_attr(r->cx.rad, RAD_CHAP_CHALLENGE, nchallenge, nclen) != 0) {
log_Printf(LogERROR, "CHAP: rad_put_string: %s\n",
rad_strerror(r->cx.rad));
rad_close(r->cx.rad);
return;
return 0;
}
break;
#ifndef NODES
case 0x80:
if (klen != 50) {
log_Printf(LogERROR, "CHAP80: Unrecognised length %d\n", klen);
log_Printf(LogERROR, "CHAP80: Unrecognised key length %d\n", klen);
rad_close(r->cx.rad);
return;
return 0;
}
rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
RAD_MICROSOFT_MS_CHAP_CHALLENGE, challenge, clen);
msreq.ident = *key;
msreq.flags = 0x01;
memcpy(msreq.lm_response, key + 1, 24);
memcpy(msreq.nt_response, key + 25, 24);
RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen);
msresp.ident = *key;
msresp.flags = 0x01;
memcpy(msresp.lm_response, key + 1, 24);
memcpy(msresp.nt_response, key + 25, 24);
rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
RAD_MICROSOFT_MS_CHAP_RESPONSE, &msreq, 50);
RAD_MICROSOFT_MS_CHAP_RESPONSE, &msresp,
sizeof msresp);
break;
case 0x81:
if (klen != 50) {
log_Printf(LogERROR, "CHAP81: Unrecognised key length %d\n", klen);
rad_close(r->cx.rad);
return 0;
}
if (pclen != sizeof msresp2.pchallenge) {
log_Printf(LogERROR, "CHAP81: Unrecognised peer challenge length %d\n",
pclen);
rad_close(r->cx.rad);
return 0;
}
rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen);
msresp2.ident = *key;
msresp2.flags = 0x00;
memcpy(msresp2.response, key + 25, 24);
memset(msresp2.reserved, '\0', sizeof msresp2.reserved);
memcpy(msresp2.pchallenge, pchallenge, pclen);
rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
RAD_MICROSOFT_MS_CHAP2_RESPONSE, &msresp2,
sizeof msresp2);
break;
#endif
default:
log_Printf(LogERROR, "CHAP: Unrecognised type 0x%02x\n",
authp->physical->link.lcp.want_authtype);
rad_close(r->cx.rad);
return;
return 0;
}
}
@ -626,14 +677,14 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
rad_strerror(r->cx.rad));
rad_close(r->cx.rad);
return;
return 0;
}
}
if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) {
log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
rad_strerror(r->cx.rad));
rad_close(r->cx.rad);
return;
return 0;
}
}
@ -651,6 +702,8 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
r->cx.timer.arg = r;
timer_Start(&r->cx.timer);
}
return 1;
}
/*
@ -804,6 +857,8 @@ radius_Show(struct radius *r, struct prompt *p)
prompt_Printf(p, " MTU: %lu\n", r->mtu);
prompt_Printf(p, " VJ: %sabled\n", r->vj ? "en" : "dis");
prompt_Printf(p, " Message: %s\n", r->repstr ? r->repstr : "");
prompt_Printf(p, " MS-CHAP2-Response: %s\n",
r->msrepstr ? r->msrepstr : "");
prompt_Printf(p, " Error Message: %s\n", r->errstr ? r->errstr : "");
if (r->routes)
route_ShowSticky(p, r->routes, " Routes", 16);

View File

@ -42,6 +42,7 @@ struct radius {
unsigned long sessiontime; /* Session-Timeout */
char *filterid; /* FRAMED Filter Id */
struct sticky_route *routes; /* FRAMED Routes */
char *msrepstr; /* MS-CHAP2-Response */
char *repstr; /* Reply-Message */
char *errstr; /* Error-Message */
struct {
@ -68,9 +69,9 @@ extern void radius_Init(struct radius *);
extern void radius_Destroy(struct radius *);
extern void radius_Show(struct radius *, struct prompt *);
extern void radius_Authenticate(struct radius *, struct authinfo *,
const char *, const char *, int,
const char *, int);
extern int radius_Authenticate(struct radius *, struct authinfo *,
const char *, const char *, int,
const char *, int, const char *, int);
extern void radius_Account(struct radius *, struct radacct *,
struct datalink *, int, struct in_addr *,
struct in_addr *, struct pppThroughput *);