summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ppp/auth.h4
-rw-r--r--usr.sbin/ppp/chap.c23
-rw-r--r--usr.sbin/ppp/pap.c11
-rw-r--r--usr.sbin/ppp/ppp.8.m48
-rw-r--r--usr.sbin/ppp/radius.c194
-rw-r--r--usr.sbin/ppp/radius.h2
6 files changed, 200 insertions, 42 deletions
diff --git a/usr.sbin/ppp/auth.h b/usr.sbin/ppp/auth.h
index 1240120..bbc257c 100644
--- a/usr.sbin/ppp/auth.h
+++ b/usr.sbin/ppp/auth.h
@@ -52,8 +52,8 @@ struct authinfo {
} cfg;
};
-#define auth_Failure(a) (*a->fn.failure)(a);
-#define auth_Success(a) (*a->fn.success)(a);
+#define auth_Failure(a) (*(a)->fn.failure)(a)
+#define auth_Success(a) (*(a)->fn.success)(a)
extern const char *Auth2Nam(u_short, u_char);
extern void auth_Init(struct authinfo *, struct physical *,
diff --git a/usr.sbin/ppp/chap.c b/usr.sbin/ppp/chap.c
index ac6a6af..1ace405 100644
--- a/usr.sbin/ppp/chap.c
+++ b/usr.sbin/ppp/chap.c
@@ -544,7 +544,9 @@ chap_Challenge(struct authinfo *authp)
static void
chap_Success(struct authinfo *authp)
{
+ struct bundle *bundle = authp->physical->dl->bundle;
const char *msg;
+
datalink_GotAuthname(authp->physical->dl, authp->in.name);
#ifndef NODES
if (authp->physical->link.lcp.want_authtype == 0x81) {
@@ -552,13 +554,18 @@ chap_Success(struct authinfo *authp)
MPPE_MasterKeyValid = 1; /* XXX Global ! */
} else
#endif
+#ifndef NORADIUS
+ if (*bundle->radius.cfg.file && bundle->radius.repstr)
+ msg = bundle->radius.repstr;
+ else
+#endif
msg = "Welcome!!";
ChapOutput(authp->physical, CHAP_SUCCESS, authp->id, msg, strlen(msg),
NULL);
authp->physical->link.lcp.auth_ineed = 0;
- if (Enabled(authp->physical->dl->bundle, OPT_UTMP))
+ if (Enabled(bundle, OPT_UTMP))
physical_Login(authp->physical, authp->in.name);
if (authp->physical->link.lcp.auth_iwait == 0)
@@ -573,13 +580,21 @@ static void
chap_Failure(struct authinfo *authp)
{
#ifndef NODES
- char buf[1024];
+ char buf[1024], *ptr;
#endif
const char *msg;
+#ifndef NORADIUS
+ struct bundle *bundle = authp->physical->link.lcp.fsm.bundle;
+ if (*bundle->radius.cfg.file && bundle->radius.errstr)
+ msg = bundle->radius.errstr;
+ else
+#endif
#ifndef NODES
- if (authp->physical->link.lcp.want_authtype == 0x81) {
- char *ptr;
+ if (authp->physical->link.lcp.want_authtype == 0x80) {
+ sprintf(buf, "E=691 R=1 M=Invalid!");
+ msg = buf;
+ } else if (authp->physical->link.lcp.want_authtype == 0x81) {
int i;
ptr = buf;
diff --git a/usr.sbin/ppp/pap.c b/usr.sbin/ppp/pap.c
index c2bbb36..d4a2a65 100644
--- a/usr.sbin/ppp/pap.c
+++ b/usr.sbin/ppp/pap.c
@@ -143,10 +143,17 @@ SendPapCode(struct authinfo *authp, int code, const char *message)
static void
pap_Success(struct authinfo *authp)
{
+ struct bundle *bundle = authp->physical->dl->bundle;
+
datalink_GotAuthname(authp->physical->dl, authp->in.name);
- SendPapCode(authp, PAP_ACK, "Greetings!!");
+#ifndef NORADIUS
+ if (*bundle->radius.cfg.file && bundle->radius.repstr)
+ SendPapCode(authp, PAP_ACK, bundle->radius.repstr);
+ else
+#endif
+ SendPapCode(authp, PAP_ACK, "Greetings!!");
authp->physical->link.lcp.auth_ineed = 0;
- if (Enabled(authp->physical->dl->bundle, OPT_UTMP))
+ if (Enabled(bundle, OPT_UTMP))
physical_Login(authp->physical, authp->in.name);
if (authp->physical->link.lcp.auth_iwait == 0)
diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4
index 26a2f99..4c1b5a8 100644
--- a/usr.sbin/ppp/ppp.8.m4
+++ b/usr.sbin/ppp/ppp.8.m4
@@ -5329,6 +5329,14 @@ keywords.
.It RAD_SESSION_TIMEOUT
If supplied, the client connection is closed after the given number of
seconds.
+.It RAD_REPLY_MESSAGE
+If supplied, this message is passed back to the peer as the authentication
+SUCCESS text.
+.It RAD_MICROSOFT_MS_CHAP_ERROR
+If this
+.Dv RAD_VENDOR_MICROSOFT
+vendor specific attribute is supplied, it is passed back to the peer as the
+authentication FAILURE text.
.El
Values received from the RADIUS server may be viewed using
.Dq show bundle .
diff --git a/usr.sbin/ppp/radius.c b/usr.sbin/ppp/radius.c
index 0d0bbae..e666165 100644
--- a/usr.sbin/ppp/radius.c
+++ b/usr.sbin/ppp/radius.c
@@ -38,8 +38,10 @@
#ifdef LOCALRAD
#include "radlib.h"
+#include "radlib_vs.h"
#else
#include <radlib.h>
+#include <radlib_vs.h>
#endif
#include <errno.h>
@@ -86,6 +88,16 @@
#include "datalink.h"
#include "ncp.h"
#include "bundle.h"
+#include "proto.h"
+
+#ifndef NODES
+struct mschap_request {
+ u_char ident;
+ u_char flags;
+ u_char lm_response[24];
+ u_char nt_response[24];
+};
+#endif
/*
* rad_continue_send_request() has given us `got' (non-zero). Deal with it.
@@ -95,13 +107,13 @@ radius_Process(struct radius *r, int got)
{
char *argv[MAXARGS], *nuke;
struct bundle *bundle;
- int argc, addrs, width;
+ int argc, addrs, res, width;
size_t len;
struct ncprange dest;
struct ncpaddr gw;
const void *data;
const char *stype;
- u_int32_t ipaddr;
+ u_int32_t ipaddr, vendor;
struct in_addr ip;
r->cx.fd = -1; /* Stop select()ing */
@@ -118,10 +130,11 @@ radius_Process(struct radius *r, int got)
case RAD_ACCESS_REJECT:
log_Printf(LogPHASE, "Radius(%s): REJECT received\n", stype);
- if (r->cx.auth)
- auth_Failure(r->cx.auth);
- rad_close(r->cx.rad);
- return;
+ if (!r->cx.auth) {
+ rad_close(r->cx.rad);
+ return;
+ }
+ break;
case RAD_ACCESS_CHALLENGE:
/* we can't deal with this (for now) ! */
@@ -156,40 +169,41 @@ radius_Process(struct radius *r, int got)
return;
}
- /* So we've been accepted ! Let's see what we've got in our reply :-I */
+ /* Let's see what we've got in our reply */
r->ip.s_addr = r->mask.s_addr = INADDR_NONE;
r->mtu = 0;
r->vj = 0;
- while ((got = rad_get_attr(r->cx.rad, &data, &len)) > 0) {
- switch (got) {
+ while ((res = rad_get_attr(r->cx.rad, &data, &len)) > 0) {
+ switch (res) {
case RAD_FRAMED_IP_ADDRESS:
r->ip = rad_cvt_addr(data);
- log_Printf(LogPHASE, " IP %s\n", inet_ntoa(r->ip));
+ log_Printf(LogPHASE, " IP %s\n", inet_ntoa(r->ip));
break;
case RAD_FILTER_ID:
free(r->filterid);
if ((r->filterid = 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, " Filter \"%s\"\n", r->filterid);
+ log_Printf(LogPHASE, " Filter \"%s\"\n", r->filterid);
break;
case RAD_SESSION_TIMEOUT:
r->sessiontime = rad_cvt_int(data);
- log_Printf(LogPHASE, " Session-Timeout %lu\n", r->sessiontime);
+ log_Printf(LogPHASE, " Session-Timeout %lu\n", r->sessiontime);
break;
case RAD_FRAMED_IP_NETMASK:
r->mask = rad_cvt_addr(data);
- log_Printf(LogPHASE, " Netmask %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(LogPHASE, " MTU %lu\n", r->mtu);
+ log_Printf(LogPHASE, " MTU %lu\n", r->mtu);
break;
case RAD_FRAMED_ROUTING:
@@ -201,7 +215,7 @@ radius_Process(struct radius *r, int got)
case RAD_FRAMED_COMPRESSION:
r->vj = rad_cvt_int(data) == 1 ? 1 : 0;
- log_Printf(LogPHASE, " VJ %sabled\n", r->vj ? "en" : "dis");
+ log_Printf(LogPHASE, " VJ %sabled\n", r->vj ? "en" : "dis");
break;
case RAD_FRAMED_ROUTE:
@@ -214,11 +228,12 @@ radius_Process(struct radius *r, int got)
if ((nuke = 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, " Route: %s\n", nuke);
+ log_Printf(LogPHASE, " Route: %s\n", nuke);
bundle = r->cx.auth->physical->dl->bundle;
ip.s_addr = INADDR_ANY;
ncprange_setip4host(&dest, ip);
@@ -258,19 +273,73 @@ radius_Process(struct radius *r, int got)
}
free(nuke);
break;
+
+ case RAD_REPLY_MESSAGE:
+ free(r->repstr);
+ if ((r->repstr = 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, " Reply-Message \"%s\"\n", r->repstr);
+ break;
+
+ case RAD_VENDOR_SPECIFIC:
+ if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) {
+ log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n",
+ rad_strerror(r->cx.rad));
+ auth_Failure(r->cx.auth);
+ rad_close(r->cx.rad);
+ return;
+ }
+
+ switch (vendor) {
+ case RAD_VENDOR_MICROSOFT:
+ switch (res) {
+ case RAD_MICROSOFT_MS_CHAP_ERROR:
+ free(r->errstr);
+ if ((r->errstr = 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-CHAP-Error \"%s\"\n", r->errstr);
+ break;
+
+ default:
+ log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific "
+ "RADIUS attribute %d\n", res);
+ break;
+ }
+ break;
+
+ default:
+ log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n",
+ (unsigned long)vendor, res);
+ break;
+ }
+ break;
+
+ default:
+ log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res);
+ break;
}
}
- if (got == -1) {
+ if (res == -1) {
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 {
+ } else if (got == RAD_ACCESS_REJECT)
+ auth_Failure(r->cx.auth);
+ else {
r->valid = 1;
auth_Success(r->cx.auth);
- rad_close(r->cx.rad);
}
+ rad_close(r->cx.rad);
}
/*
@@ -358,15 +427,24 @@ radius_Write(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset)
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;
+ r->cx.fd = -1;
+ r->cx.rad = NULL;
memset(&r->cx.timer, '\0', sizeof r->cx.timer);
+ r->cx.auth = NULL;
+ r->valid = 0;
+ r->vj = 0;
+ r->ip.s_addr = INADDR_ANY;
+ r->mask.s_addr = INADDR_NONE;
+ r->routes = NULL;
+ r->mtu = DEF_MTU;
+ r->repstr = NULL;
+ r->errstr = NULL;
+ *r->cfg.file = '\0';;
log_Printf(LogDEBUG, "Radius: radius_Init\n");
}
@@ -382,6 +460,10 @@ radius_Destroy(struct radius *r)
route_DeleteAll(&r->routes);
free(r->filterid);
r->filterid = NULL;
+ free(r->repstr);
+ r->repstr = NULL;
+ free(r->errstr);
+ r->errstr = NULL;
if (r->cx.fd != -1) {
r->cx.fd = -1;
rad_close(r->cx.rad);
@@ -401,6 +483,9 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
char hostname[MAXHOSTNAMELEN];
struct hostent *hp;
struct in_addr hostaddr;
+#ifndef NODES
+ struct mschap_request msreq;
+#endif
if (!*r->cfg.file)
return;
@@ -439,20 +524,54 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
return;
}
- if (challenge != NULL) {
- /* We're talking CHAP */
- 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) {
- log_Printf(LogERROR, "CHAP: rad_put_string: %s\n",
+ switch (authp->physical->link.lcp.want_auth) {
+ case PROTO_PAP:
+ /* We're talking PAP */
+ if (rad_put_attr(r->cx.rad, RAD_USER_PASSWORD, key, klen) != 0) {
+ log_Printf(LogERROR, "PAP: rad_put_string: %s\n",
rad_strerror(r->cx.rad));
rad_close(r->cx.rad);
return;
}
- } else if (rad_put_attr(r->cx.rad, RAD_USER_PASSWORD, key, klen) != 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;
+ break;
+
+ case PROTO_CHAP:
+ 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) {
+ log_Printf(LogERROR, "CHAP: rad_put_string: %s\n",
+ rad_strerror(r->cx.rad));
+ rad_close(r->cx.rad);
+ return;
+ }
+ break;
+
+#ifndef NODES
+ case 0x80:
+ if (klen != 50) {
+ log_Printf(LogERROR, "CHAP80: Unrecognised length %d\n", klen);
+ rad_close(r->cx.rad);
+ return;
+ }
+ 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_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
+ RAD_MICROSOFT_MS_CHAP_RESPONSE, &msreq, 50);
+ break;
+
+ case 0x81:
+#endif
+ default:
+ log_Printf(LogERROR, "CHAP: Unrecognised type 0x%02x\n",
+ authp->physical->link.lcp.want_authtype);
+ rad_close(r->cx.rad);
+ return;
+ }
}
if (gethostname(hostname, sizeof hostname) != 0)
@@ -481,7 +600,7 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
for (slot = 1; (ttyp = getttyent()); ++slot)
if (!strcmp(ttyp->ty_name, authp->physical->name.base)) {
if (rad_put_int(r->cx.rad, RAD_NAS_PORT, slot) != 0) {
- log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
+ log_Printf(LogERROR, "rad_put: rad_put_int: %s\n",
rad_strerror(r->cx.rad));
rad_close(r->cx.rad);
endttyent();
@@ -490,6 +609,11 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
break;
}
endttyent();
+ } else if (rad_put_int(r->cx.rad, RAD_NAS_PORT, 0) != 0) {
+ log_Printf(LogERROR, "rad_put: rad_put_int: %s\n",
+ rad_strerror(r->cx.rad));
+ rad_close(r->cx.rad);
+ return;
}
@@ -673,6 +797,8 @@ radius_Show(struct radius *r, struct prompt *p)
prompt_Printf(p, " Netmask: %s\n", inet_ntoa(r->mask));
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, " Error Message: %s\n", r->errstr ? r->errstr : "");
if (r->routes)
route_ShowSticky(p, r->routes, " Routes", 16);
} else
diff --git a/usr.sbin/ppp/radius.h b/usr.sbin/ppp/radius.h
index 1b3d188..d021575 100644
--- a/usr.sbin/ppp/radius.h
+++ b/usr.sbin/ppp/radius.h
@@ -42,6 +42,8 @@ struct radius {
unsigned long sessiontime; /* Session-Timeout */
char *filterid; /* FRAMED Filter Id */
struct sticky_route *routes; /* FRAMED Routes */
+ char *repstr; /* Reply-Message */
+ char *errstr; /* Error-Message */
struct {
char file[PATH_MAX]; /* Radius config file */
} cfg;
OpenPOWER on IntegriCloud