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