summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorbrian <brian@cvs.openbsd.org>2002-05-16 14:27:22 +0000
committerbrian <brian@cvs.openbsd.org>2002-05-16 14:27:22 +0000
commit62ab45b33182bdc923b291e42c09fd2ad091d540 (patch)
tree321abcafd4bb4a5cc28093fe706f9a5f3ea17d23 /usr.sbin
parent132ea071efb904ad03f62112b0572ef1600cc75c (diff)
Handle MS-CHAPv2 authentication correctly via the RADIUS server (if it's
configured). This doesn't yet work with MPPE. More to follow.
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ppp/ppp/chap.c42
-rw-r--r--usr.sbin/ppp/ppp/pap.c11
-rw-r--r--usr.sbin/ppp/ppp/radius.c105
-rw-r--r--usr.sbin/ppp/ppp/radius.h9
4 files changed, 116 insertions, 51 deletions
diff --git a/usr.sbin/ppp/ppp/chap.c b/usr.sbin/ppp/ppp/chap.c
index 50f62645045..15f310e05bd 100644
--- a/usr.sbin/ppp/ppp/chap.c
+++ b/usr.sbin/ppp/ppp/chap.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $OpenBSD: chap.c,v 1.32 2002/05/16 01:13:39 brian Exp $
+ * $OpenBSD: chap.c,v 1.33 2002/05/16 14:27:21 brian Exp $
*/
#include <sys/param.h>
@@ -549,7 +549,12 @@ 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
+#endif
+ msg = auth2chap(authp)->authresponse;
MPPE_MasterKeyValid = 1; /* XXX Global ! */
} else
#endif
@@ -840,13 +845,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 +887,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 +926,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);
diff --git a/usr.sbin/ppp/ppp/pap.c b/usr.sbin/ppp/ppp/pap.c
index 09e4bf3c656..145b5912dcc 100644
--- a/usr.sbin/ppp/ppp/pap.c
+++ b/usr.sbin/ppp/ppp/pap.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $OpenBSD: pap.c,v 1.18 2002/05/16 01:13:39 brian Exp $
+ * $OpenBSD: pap.c,v 1.19 2002/05/16 14:27:21 brian Exp $
*/
#include <sys/param.h>
@@ -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);
diff --git a/usr.sbin/ppp/ppp/radius.c b/usr.sbin/ppp/ppp/radius.c
index cb9b44704ca..08f7f73350c 100644
--- a/usr.sbin/ppp/ppp/radius.c
+++ b/usr.sbin/ppp/ppp/radius.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $OpenBSD: radius.c,v 1.14 2002/05/16 01:13:39 brian Exp $
+ * $OpenBSD: radius.c,v 1.15 2002/05/16 14:27:21 brian Exp $
*
*/
@@ -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);
diff --git a/usr.sbin/ppp/ppp/radius.h b/usr.sbin/ppp/ppp/radius.h
index 11f79197bb2..9eafae49332 100644
--- a/usr.sbin/ppp/ppp/radius.h
+++ b/usr.sbin/ppp/ppp/radius.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $OpenBSD: radius.h,v 1.7 2002/05/16 01:13:39 brian Exp $
+ * $OpenBSD: radius.h,v 1.8 2002/05/16 14:27:21 brian Exp $
*/
struct radius {
@@ -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 *);