summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorbrian <brian@FreeBSD.org>2002-06-12 00:33:17 +0000
committerbrian <brian@FreeBSD.org>2002-06-12 00:33:17 +0000
commit64df5969679c3ad7b7f9452c2dcaee6a0621e26a (patch)
treed492060e826fff36baae2f94497a23630e59bb9e /usr.sbin
parent900ca326699fe7cba94c534173fd85d67cf1cef7 (diff)
downloadFreeBSD-src-64df5969679c3ad7b7f9452c2dcaee6a0621e26a.zip
FreeBSD-src-64df5969679c3ad7b7f9452c2dcaee6a0621e26a.tar.gz
Understand the following Microsoft Vendor Specific RADIUS attributes:
RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES RAD_MICROSOFT_MS_MPPE_RECV_KEY RAD_MICROSOFT_MS_MPPE_SEND_KEY These attributes may be supplied by a RADIUS server when MSCHAPv2 is used to authenticate. It *should* now be possible to build ppp with -DNODES and still support CHAP/MSCHAP/MSCHAPv2/MPPE via a RADIUS server, but the code isn't yet smart enough to do that (building with -DNODES just looses these facilities). Sponsored by: Monzoon
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ppp/ccp.c13
-rw-r--r--usr.sbin/ppp/ccp.h11
-rw-r--r--usr.sbin/ppp/deflate.c13
-rw-r--r--usr.sbin/ppp/mppe.c118
-rw-r--r--usr.sbin/ppp/ppp.8.m444
-rw-r--r--usr.sbin/ppp/pred.c10
-rw-r--r--usr.sbin/ppp/radius.c161
-rw-r--r--usr.sbin/ppp/radius.h14
8 files changed, 329 insertions, 55 deletions
diff --git a/usr.sbin/ppp/ccp.c b/usr.sbin/ppp/ccp.c
index a0f6490..aef3a51 100644
--- a/usr.sbin/ppp/ccp.c
+++ b/usr.sbin/ppp/ccp.c
@@ -369,7 +369,7 @@ CcpSendConfigReq(struct fsm *fp)
(*o)->val.hdr.len = 2;
(*o)->next = NULL;
(*o)->algorithm = f;
- (*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg);
+ (*algorithm[f]->o.OptInit)(fp->bundle, &(*o)->val, &ccp->cfg);
}
if (cp + (*o)->val.hdr.len > buff + sizeof buff) {
@@ -517,7 +517,8 @@ CcpLayerUp(struct fsm *fp)
if (ccp->in.state == NULL && ccp->in.algorithm >= 0 &&
ccp->in.algorithm < NALGORITHMS) {
- ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt);
+ ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)
+ (fp->bundle, &ccp->in.opt);
if (ccp->in.state == NULL) {
log_Printf(LogERROR, "%s: %s (in) initialisation failure\n",
fp->link->name, protoname(ccp->his_proto));
@@ -534,7 +535,8 @@ CcpLayerUp(struct fsm *fp)
if (ccp->out.state == NULL && ccp->out.algorithm >= 0 &&
ccp->out.algorithm < NALGORITHMS) {
- ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init)(&(*o)->val);
+ ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init)
+ (fp->bundle, &(*o)->val);
if (ccp->out.state == NULL) {
log_Printf(LogERROR, "%s: %s (out) initialisation failure\n",
fp->link->name, protoname(ccp->my_proto));
@@ -596,7 +598,7 @@ CcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type,
(*algorithm[f]->Usable)(fp) &&
ccp->in.algorithm == -1) {
memcpy(&ccp->in.opt, opt, opt->hdr.len);
- switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) {
+ switch ((*algorithm[f]->i.Set)(fp->bundle, &ccp->in.opt, &ccp->cfg)) {
case MODE_REJ:
fsm_rej(dec, &ccp->in.opt);
break;
@@ -622,7 +624,8 @@ CcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type,
" option\n", fp->link->name);
else {
memcpy(&o->val, opt, opt->hdr.len);
- if ((*algorithm[f]->o.Set)(&o->val, &ccp->cfg) == MODE_ACK)
+ if ((*algorithm[f]->o.Set)(fp->bundle, &o->val, &ccp->cfg) ==
+ MODE_ACK)
ccp->my_proto = algorithm[f]->id;
else {
ccp->his_reject |= (1 << opt->hdr.id);
diff --git a/usr.sbin/ppp/ccp.h b/usr.sbin/ppp/ccp.h
index 46c96db..bc867b6 100644
--- a/usr.sbin/ppp/ccp.h
+++ b/usr.sbin/ppp/ccp.h
@@ -127,8 +127,8 @@ struct ccp_algorithm {
int (*Usable)(struct fsm *); /* Ok to negotiate ? */
int (*Required)(struct fsm *); /* Must negotiate ? */
struct {
- int (*Set)(struct fsm_opt *, const struct ccp_config *);
- void *(*Init)(struct fsm_opt *);
+ int (*Set)(struct bundle *, struct fsm_opt *, const struct ccp_config *);
+ void *(*Init)(struct bundle *, struct fsm_opt *);
void (*Term)(void *);
void (*Reset)(void *);
struct mbuf *(*Read)(void *, struct ccp *, u_short *, struct mbuf *);
@@ -136,9 +136,10 @@ struct ccp_algorithm {
} i;
struct {
int MTUOverhead;
- void (*OptInit)(struct fsm_opt *, const struct ccp_config *);
- int (*Set)(struct fsm_opt *, const struct ccp_config *);
- void *(*Init)(struct fsm_opt *);
+ void (*OptInit)(struct bundle *, struct fsm_opt *,
+ const struct ccp_config *);
+ int (*Set)(struct bundle *, struct fsm_opt *, const struct ccp_config *);
+ void *(*Init)(struct bundle *, struct fsm_opt *);
void (*Term)(void *);
int (*Reset)(void *);
struct mbuf *(*Write)(void *, struct ccp *, struct link *, int, u_short *,
diff --git a/usr.sbin/ppp/deflate.c b/usr.sbin/ppp/deflate.c
index f629c5b..3e6198d 100644
--- a/usr.sbin/ppp/deflate.c
+++ b/usr.sbin/ppp/deflate.c
@@ -440,7 +440,8 @@ DeflateDispOpts(struct fsm_opt *o)
}
static void
-DeflateInitOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
+DeflateInitOptsOutput(struct bundle *bundle, struct fsm_opt *o,
+ const struct ccp_config *cfg)
{
o->hdr.len = 4;
o->data[0] = ((cfg->deflate.out.winsize - 8) << 4) + 8;
@@ -448,7 +449,8 @@ DeflateInitOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
}
static int
-DeflateSetOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
+DeflateSetOptsOutput(struct bundle *bundle, struct fsm_opt *o,
+ const struct ccp_config *cfg)
{
if (o->hdr.len != 4 || (o->data[0] & 15) != 8 || o->data[1] != '\0')
return MODE_REJ;
@@ -462,7 +464,8 @@ DeflateSetOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
}
static int
-DeflateSetOptsInput(struct fsm_opt *o, const struct ccp_config *cfg)
+DeflateSetOptsInput(struct bundle *bundle, struct fsm_opt *o,
+ const struct ccp_config *cfg)
{
int want;
@@ -483,7 +486,7 @@ DeflateSetOptsInput(struct fsm_opt *o, const struct ccp_config *cfg)
}
static void *
-DeflateInitInput(struct fsm_opt *o)
+DeflateInitInput(struct bundle *bundle, struct fsm_opt *o)
{
struct deflate_state *state;
@@ -506,7 +509,7 @@ DeflateInitInput(struct fsm_opt *o)
}
static void *
-DeflateInitOutput(struct fsm_opt *o)
+DeflateInitOutput(struct bundle *bundle, struct fsm_opt *o)
{
struct deflate_state *state;
diff --git a/usr.sbin/ppp/mppe.c b/usr.sbin/ppp/mppe.c
index 908d427..f3d8254 100644
--- a/usr.sbin/ppp/mppe.c
+++ b/usr.sbin/ppp/mppe.c
@@ -26,11 +26,13 @@
* $FreeBSD$
*/
-#include <sys/types.h>
+#include <sys/param.h>
-#ifdef __FreeBSD__
+#include <sys/socket.h>
+#include <netinet/in_systm.h>
#include <netinet/in.h>
-#endif
+#include <netinet/ip.h>
+#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
@@ -54,6 +56,19 @@
#include "proto.h"
#include "mppe.h"
#include "ua.h"
+#include "descriptor.h"
+#ifndef NORADIUS
+#include "radius.h"
+#endif
+#include "ncpaddr.h"
+#include "iplist.h"
+#include "slcompress.h"
+#include "ipcp.h"
+#include "ipv6cp.h"
+#include "filter.h"
+#include "mp.h"
+#include "ncp.h"
+#include "bundle.h"
/*
* Documentation:
@@ -427,29 +442,50 @@ MPPEUsable(struct fsm *fp)
static int
MPPERequired(struct fsm *fp)
{
+#ifndef NORADIUS
+ /*
+ * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY,
+ * use that instead of our configuration value.
+ */
+ if (*fp->bundle->radius.cfg.file && fp->bundle->radius.mppe.policy)
+ return fp->bundle->radius.mppe.policy == MPPE_POLICY_REQUIRED ? 1 : 0;
+#endif
+
return fp->link->ccp.cfg.mppe.required;
}
static u_int32_t
-MPPE_ConfigVal(const struct ccp_config *cfg)
+MPPE_ConfigVal(struct bundle *bundle, const struct ccp_config *cfg)
{
u_int32_t val;
val = cfg->mppe.state == MPPE_STATELESS ? MPPE_OPT_STATELESS : 0;
- switch(cfg->mppe.keybits) {
- case 128:
- val |= MPPE_OPT_128BIT;
- break;
- case 56:
- val |= MPPE_OPT_56BIT;
- break;
- case 40:
- val |= MPPE_OPT_40BIT;
- break;
- case 0:
- val |= MPPE_OPT_128BIT | MPPE_OPT_56BIT | MPPE_OPT_40BIT;
- break;
- }
+#ifndef NORADIUS
+ /*
+ * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES,
+ * use that instead of our configuration value.
+ */
+ if (*bundle->radius.cfg.file && bundle->radius.mppe.types) {
+ if (bundle->radius.mppe.types & MPPE_TYPE_40BIT)
+ val |= MPPE_OPT_40BIT;
+ if (bundle->radius.mppe.types & MPPE_TYPE_128BIT)
+ val |= MPPE_OPT_128BIT;
+ } else
+#endif
+ switch(cfg->mppe.keybits) {
+ case 128:
+ val |= MPPE_OPT_128BIT;
+ break;
+ case 56:
+ val |= MPPE_OPT_56BIT;
+ break;
+ case 40:
+ val |= MPPE_OPT_40BIT;
+ break;
+ case 0:
+ val |= MPPE_OPT_128BIT | MPPE_OPT_56BIT | MPPE_OPT_40BIT;
+ break;
+ }
return val;
}
@@ -458,7 +494,8 @@ MPPE_ConfigVal(const struct ccp_config *cfg)
* What options should we use for our first configure request
*/
static void
-MPPEInitOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
+MPPEInitOptsOutput(struct bundle *bundle, struct fsm_opt *o,
+ const struct ccp_config *cfg)
{
u_int32_t mval;
@@ -471,7 +508,8 @@ MPPEInitOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
return;
}
- mval = MPPE_ConfigVal(cfg);
+
+ mval = MPPE_ConfigVal(bundle, cfg);
ua_htonl(&mval, o->data);
}
@@ -479,7 +517,8 @@ MPPEInitOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
* Our CCP request was NAK'd with the given options
*/
static int
-MPPESetOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
+MPPESetOptsOutput(struct bundle *bundle, struct fsm_opt *o,
+ const struct ccp_config *cfg)
{
u_int32_t mval, peer;
@@ -489,7 +528,7 @@ MPPESetOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
/* Treat their NAK as a REJ */
return MODE_NAK;
- mval = MPPE_ConfigVal(cfg);
+ mval = MPPE_ConfigVal(bundle, cfg);
/*
* If we haven't been configured with a specific number of keybits, allow
@@ -517,7 +556,8 @@ MPPESetOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
* The peer has requested the given options
*/
static int
-MPPESetOptsInput(struct fsm_opt *o, const struct ccp_config *cfg)
+MPPESetOptsInput(struct bundle *bundle, struct fsm_opt *o,
+ const struct ccp_config *cfg)
{
u_int32_t mval, peer;
int res = MODE_ACK;
@@ -532,7 +572,7 @@ MPPESetOptsInput(struct fsm_opt *o, const struct ccp_config *cfg)
return MODE_ACK;
}
- mval = MPPE_ConfigVal(cfg);
+ mval = MPPE_ConfigVal(bundle, cfg);
if (peer & ~MPPE_OPT_MASK)
/* He's asking for bits we don't know about */
@@ -620,7 +660,7 @@ MPPE_InitState(struct fsm_opt *o)
}
static void *
-MPPEInitInput(struct fsm_opt *o)
+MPPEInitInput(struct bundle *bundle, struct fsm_opt *o)
{
struct mppe_state *mip;
@@ -636,8 +676,17 @@ MPPEInitInput(struct fsm_opt *o)
log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits);
- GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0,
- MPPE_IsServer);
+#ifndef NORADIUS
+ if (*bundle->radius.cfg.file && bundle->radius.mppe.recvkey) {
+ mip->keylen = bundle->radius.mppe.recvkeylen;
+ if (mip->keylen > sizeof mip->mastkey)
+ mip->keylen = sizeof mip->mastkey;
+ memcpy(mip->mastkey, bundle->radius.mppe.recvkey, mip->keylen);
+ } else
+#endif
+ GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0,
+ MPPE_IsServer);
+
GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey);
MPPEReduceSessionKey(mip);
@@ -666,7 +715,7 @@ MPPEInitInput(struct fsm_opt *o)
}
static void *
-MPPEInitOutput(struct fsm_opt *o)
+MPPEInitOutput(struct bundle *bundle, struct fsm_opt *o)
{
struct mppe_state *mop;
@@ -682,8 +731,17 @@ MPPEInitOutput(struct fsm_opt *o)
log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits);
- GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1,
- MPPE_IsServer);
+#ifndef NORADIUS
+ if (*bundle->radius.cfg.file && bundle->radius.mppe.sendkey) {
+ mop->keylen = bundle->radius.mppe.sendkeylen;
+ if (mop->keylen > sizeof mop->mastkey)
+ mop->keylen = sizeof mop->mastkey;
+ memcpy(mop->mastkey, bundle->radius.mppe.sendkey, mop->keylen);
+ } else
+#endif
+ GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1,
+ MPPE_IsServer);
+
GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey);
MPPEReduceSessionKey(mop);
diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4
index 9b59275..bec41d6 100644
--- a/usr.sbin/ppp/ppp.8.m4
+++ b/usr.sbin/ppp/ppp.8.m4
@@ -5081,7 +5081,8 @@ If any arguments are given,
.Nm
will
.Em insist
-on using MPPE and will close the link if it's rejected by the peer.
+on using MPPE and will close the link if it's rejected by the peer (Note;
+this behaviour can be overridden by a configured RADIUS server).
.Pp
The first argument specifies the number of bits that
.Nm
@@ -5243,7 +5244,7 @@ This command enables RADIUS support (if it's compiled in).
.Ar config-file
refers to the radius client configuration file as described in
.Xr radius.conf 5 .
-If PAP or CHAP are
+If PAP, CHAP, MSCHAP or MSCHAPv2 are
.Dq enable Ns No d ,
.Nm
behaves as a
@@ -5255,7 +5256,7 @@ authenticating from the
.Pa ppp.secret
file or from the passwd database.
.Pp
-If neither PAP or CHAP are enabled,
+If none of PAP, CHAP, MSCHAP or MSCHAPv2 are enabled,
.Dq set radius
will do nothing.
.Pp
@@ -5342,7 +5343,44 @@ If this
.Dv RAD_VENDOR_MICROSOFT
vendor specific attribute is supplied and if MS-CHAPv2 authentication is
being used, it is passed back to the peer as the authentication SUCCESS text.
+.It RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY
+If this
+.Dv RAD_VENDOR_MICROSOFT
+vendor specific attribute is supplied and has a value of 2 (Required),
+.Nm
+will insist that MPPE encryption is used (even if no
+.Dq set mppe
+configuration command has been given with arguments).
+If it is supplied with a value of 1 (Allowed), encryption is made optional
+(despite any
+.Dq set mppe
+configuration commands with arguments).
+.It RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES
+If this
+.Dv RAD_VENDOR_MICROSOFT
+vendor specific attribute is supplied, bits 1 and 2 are examined.
+If either or both are set, 40 bit and/or 128 bit (respectively) encryption
+options are set, overriding any given first argument to the
+.Dq set mppe
+command.
+Note, it is not currently possible for the RADIUS server to specify 56 bit
+encryption.
+.It RAD_MICROSOFT_MS_MPPE_RECV_KEY
+If this
+.Dv RAD_VENDOR_MICROSOFT
+vendor specific attribute is supplied, it's value is used as the master
+key for decryption of incoming data. When clients are authenticated using
+MSCHAPv2, the RADIUS server MUST provide this attribute if inbound MPPE is
+to function.
+.It RAD_MICROSOFT_MS_MPPE_SEND_KEY
+If this
+.Dv RAD_VENDOR_MICROSOFT
+vendor specific attribute is supplied, it's value is used as the master
+key for encryption of outgoing data. When clients are authenticated using
+MSCHAPv2, the RADIUS server MUST provide this attribute if outbound MPPE is
+to function.
.El
+.Pp
Values received from the RADIUS server may be viewed using
.Dq show bundle .
.It set reconnect Ar timeout ntries
diff --git a/usr.sbin/ppp/pred.c b/usr.sbin/ppp/pred.c
index d286a97..2a81381 100644
--- a/usr.sbin/ppp/pred.c
+++ b/usr.sbin/ppp/pred.c
@@ -151,7 +151,7 @@ Pred1ResetOutput(void *v)
}
static void *
-Pred1InitInput(struct fsm_opt *o)
+Pred1InitInput(struct bundle *bundle, struct fsm_opt *o)
{
struct pred1_state *state;
state = (struct pred1_state *)malloc(sizeof(struct pred1_state));
@@ -161,7 +161,7 @@ Pred1InitInput(struct fsm_opt *o)
}
static void *
-Pred1InitOutput(struct fsm_opt *o)
+Pred1InitOutput(struct bundle *bundle, struct fsm_opt *o)
{
struct pred1_state *state;
state = (struct pred1_state *)malloc(sizeof(struct pred1_state));
@@ -300,13 +300,15 @@ Pred1DispOpts(struct fsm_opt *o)
}
static void
-Pred1InitOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
+Pred1InitOptsOutput(struct bundle *bundle, struct fsm_opt *o,
+ const struct ccp_config *cfg)
{
o->hdr.len = 2;
}
static int
-Pred1SetOpts(struct fsm_opt *o, const struct ccp_config *cfg)
+Pred1SetOpts(struct bundle *bundle, struct fsm_opt *o,
+ const struct ccp_config *cfg)
{
if (o->hdr.len != 2) {
o->hdr.len = 2;
diff --git a/usr.sbin/ppp/radius.c b/usr.sbin/ppp/radius.c
index 87d5375..1f43db2 100644
--- a/usr.sbin/ppp/radius.c
+++ b/usr.sbin/ppp/radius.c
@@ -28,6 +28,7 @@
*/
#include <sys/param.h>
+
#include <sys/socket.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
@@ -45,6 +46,9 @@
#endif
#include <errno.h>
+#ifndef NODES
+#include <md5.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -104,6 +108,112 @@ struct mschap2_response {
u_char reserved[8];
u_char response[24];
};
+
+#define AUTH_LEN 16
+#define SALT_LEN 2
+#endif
+
+static const char *
+radius_policyname(int policy)
+{
+ switch(policy) {
+ case MPPE_POLICY_ALLOWED:
+ return "Allowed";
+ case MPPE_POLICY_REQUIRED:
+ return "Required";
+ }
+ return NumStr(policy, NULL, 0);
+}
+
+static const char *
+radius_typesname(int types)
+{
+ switch(types) {
+ case MPPE_TYPE_40BIT:
+ return "40 bit";
+ case MPPE_TYPE_128BIT:
+ return "128 bit";
+ case MPPE_TYPE_40BIT|MPPE_TYPE_128BIT:
+ return "40 or 128 bit";
+ }
+ return NumStr(types, NULL, 0);
+}
+
+#ifndef NODES
+static void
+demangle(struct radius *r, const void *mangled, size_t mlen,
+ char **buf, size_t *len)
+{
+ char R[AUTH_LEN]; /* variable names as per rfc2548 */
+ const char *S;
+ u_char b[16];
+ const u_char *A, *C;
+ MD5_CTX Context;
+ int Slen, i, Clen, Ppos;
+ u_char *P;
+
+ if (mlen % 16 != SALT_LEN) {
+ log_Printf(LogWARN, "Cannot interpret mangled data of length %ld\n",
+ (u_long)mlen);
+ *buf = NULL;
+ *len = 0;
+ return;
+ }
+
+ /* We need the RADIUS Request-Authenticator */
+ if (rad_request_authenticator(r->cx.rad, R, sizeof R) != AUTH_LEN) {
+ log_Printf(LogWARN, "Cannot obtain the RADIUS request authenticator\n");
+ *buf = NULL;
+ *len = 0;
+ return;
+ }
+
+ A = (const u_char *)mangled; /* Salt comes first */
+ C = (const u_char *)mangled + SALT_LEN; /* Then the ciphertext */
+ Clen = mlen - SALT_LEN;
+ S = rad_server_secret(r->cx.rad); /* We need the RADIUS secret */
+ Slen = strlen(S);
+ P = alloca(Clen); /* We derive our plaintext */
+
+ MD5Init(&Context);
+ MD5Update(&Context, S, Slen);
+ MD5Update(&Context, R, AUTH_LEN);
+ MD5Update(&Context, A, SALT_LEN);
+ MD5Final(b, &Context);
+ Ppos = 0;
+
+ while (Clen) {
+ Clen -= 16;
+
+ for (i = 0; i < 16; i++)
+ P[Ppos++] = C[i] ^ b[i];
+
+ if (Clen) {
+ MD5Init(&Context);
+ MD5Update(&Context, S, Slen);
+ MD5Update(&Context, C, 16);
+ MD5Final(b, &Context);
+ }
+
+ C += 16;
+ }
+
+ /*
+ * The resulting plain text consists of a one-byte length, the text and
+ * maybe some padding.
+ */
+ *len = *P;
+ if (*len > mlen - 1) {
+ log_Printf(LogWARN, "Mangled data seems to be garbage\n");
+ *buf = NULL;
+ *len = 0;
+ return;
+ }
+
+ *buf = malloc(*len);
+ memcpy(*buf, P + 1, *len);
+log_Printf(LogWARN, "demangled %d bytes\n", *len);
+}
#endif
/*
@@ -304,6 +414,7 @@ radius_Process(struct radius *r, int got)
switch (vendor) {
case RAD_VENDOR_MICROSOFT:
switch (res) {
+#ifndef NODES
case RAD_MICROSOFT_MS_CHAP_ERROR:
free(r->errstr);
if ((r->errstr = rad_cvt_string(data, len)) == NULL) {
@@ -328,6 +439,30 @@ radius_Process(struct radius *r, int got)
log_Printf(LogPHASE, " MS-CHAP2-Success \"%s\"\n", r->msrepstr);
break;
+ case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
+ r->mppe.policy = rad_cvt_int(data);
+ log_Printf(LogPHASE, " MS-MPPE-Encryption-Policy %s\n",
+ radius_policyname(r->mppe.policy));
+ break;
+
+ case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
+ r->mppe.types = rad_cvt_int(data);
+ log_Printf(LogPHASE, " MS-MPPE-Encryption-Types %s\n",
+ radius_typesname(r->mppe.types));
+ break;
+
+ case RAD_MICROSOFT_MS_MPPE_RECV_KEY:
+ free(r->mppe.recvkey);
+ demangle(r, data, len, &r->mppe.recvkey, &r->mppe.recvkeylen);
+ log_Printf(LogPHASE, " MS-MPPE-Recv-Key ********\n");
+ break;
+
+ case RAD_MICROSOFT_MS_MPPE_SEND_KEY:
+ demangle(r, data, len, &r->mppe.sendkey, &r->mppe.sendkeylen);
+ log_Printf(LogPHASE, " MS-MPPE-Send-Key ********\n");
+ break;
+#endif
+
default:
log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific "
"RADIUS attribute %d\n", res);
@@ -464,6 +599,12 @@ radius_Init(struct radius *r)
r->msrepstr = NULL;
r->repstr = NULL;
r->errstr = NULL;
+ r->mppe.policy = 0;
+ r->mppe.types = 0;
+ r->mppe.recvkey = NULL;
+ r->mppe.recvkeylen = 0;
+ r->mppe.sendkey = NULL;
+ r->mppe.sendkeylen = 0;
*r->cfg.file = '\0';;
log_Printf(LogDEBUG, "Radius: radius_Init\n");
}
@@ -486,6 +627,12 @@ radius_Destroy(struct radius *r)
r->repstr = NULL;
free(r->errstr);
r->errstr = NULL;
+ free(r->mppe.recvkey);
+ r->mppe.recvkey = NULL;
+ r->mppe.recvkeylen = 0;
+ free(r->mppe.sendkey);
+ r->mppe.sendkey = NULL;
+ r->mppe.sendkeylen = 0;
if (r->cx.fd != -1) {
r->cx.fd = -1;
rad_close(r->cx.rad);
@@ -550,8 +697,8 @@ radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
char hostname[MAXHOSTNAMELEN];
#if 0
struct hostent *hp;
-#endif
struct in_addr hostaddr;
+#endif
#ifndef NODES
struct mschap_response msresp;
struct mschap2_response msresp2;
@@ -723,8 +870,8 @@ radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl,
char hostname[MAXHOSTNAMELEN];
#if 0
struct hostent *hp;
-#endif
struct in_addr hostaddr;
+#endif
if (!*r->cfg.file)
return;
@@ -736,7 +883,7 @@ radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl,
*/
return;
- radius_Destroy(r);
+ timer_Stop(&r->cx.timer);
if ((r->cx.rad = rad_acct_open()) == NULL) {
log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno));
@@ -865,6 +1012,14 @@ 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, " MPPE Enc Policy: %s\n",
+ radius_policyname(r->mppe.policy));
+ prompt_Printf(p, " MPPE Enc Types: %s\n",
+ radius_typesname(r->mppe.types));
+ prompt_Printf(p, " MPPE Recv Key: %seceived\n",
+ r->mppe.recvkey ? "R" : "Not r");
+ prompt_Printf(p, " MPPE Send Key: %seceived\n",
+ r->mppe.sendkey ? "R" : "Not r");
prompt_Printf(p, " MS-CHAP2-Response: %s\n",
r->msrepstr ? r->msrepstr : "");
prompt_Printf(p, " Error Message: %s\n", r->errstr ? r->errstr : "");
diff --git a/usr.sbin/ppp/radius.h b/usr.sbin/ppp/radius.h
index 0ea6edd..0b01b23 100644
--- a/usr.sbin/ppp/radius.h
+++ b/usr.sbin/ppp/radius.h
@@ -26,6 +26,12 @@
* $FreeBSD$
*/
+#define MPPE_POLICY_ALLOWED 1
+#define MPPE_POLICY_REQUIRED 2
+
+#define MPPE_TYPE_40BIT 2
+#define MPPE_TYPE_128BIT 4
+
struct radius {
struct fdescriptor desc; /* We're a sort of (selectable) fdescriptor */
struct {
@@ -46,6 +52,14 @@ struct radius {
char *repstr; /* Reply-Message */
char *errstr; /* Error-Message */
struct {
+ int policy; /* MPPE_POLICY_* */
+ int types; /* MPPE_TYPE_*BIT bitmask */
+ char *recvkey;
+ size_t recvkeylen;
+ char *sendkey;
+ size_t sendkeylen;
+ } mppe;
+ struct {
char file[PATH_MAX]; /* Radius config file */
} cfg;
};
OpenPOWER on IntegriCloud