summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-10-04 15:12:41 +0400
committerKozlov Dmitry <dima@server>2010-10-04 15:12:41 +0400
commita337b4af82fe30d568547aabc61df7bc67a8a835 (patch)
tree140437e3f4282abb39b17606750ba9bb4123711a
parent06858ad4c7468ac8b226b34126b68db2128877f1 (diff)
downloadaccel-ppp-a337b4af82fe30d568547aabc61df7bc67a8a835.tar.gz
accel-ppp-a337b4af82fe30d568547aabc61df7bc67a8a835.zip
ppp: implemented mppe
radius: implemented mppe support various improvements and bug fixes
-rw-r--r--accel-pptpd/CMakeLists.txt1
-rw-r--r--accel-pptpd/accel-pptpd.conf6
-rw-r--r--accel-pptpd/include/events.h2
-rw-r--r--accel-pptpd/ppp/ccp_mppe.c214
-rw-r--r--accel-pptpd/ppp/ipcp_opt_dns.c3
-rw-r--r--accel-pptpd/ppp/ipcp_opt_ipaddr.c3
-rw-r--r--accel-pptpd/ppp/lcp_opt_accomp.c8
-rw-r--r--accel-pptpd/ppp/lcp_opt_magic.c7
-rw-r--r--accel-pptpd/ppp/lcp_opt_mru.c7
-rw-r--r--accel-pptpd/ppp/lcp_opt_pcomp.c8
-rw-r--r--accel-pptpd/ppp/ppp.c2
-rw-r--r--accel-pptpd/ppp/ppp_ccp.c168
-rw-r--r--accel-pptpd/ppp/ppp_ccp.h9
-rw-r--r--accel-pptpd/radius/attr_defs.h287
-rw-r--r--accel-pptpd/radius/auth.c132
-rw-r--r--accel-pptpd/radius/dict/dictionary.microsoft6
-rw-r--r--accel-pptpd/radius/dict2c.py20
-rw-r--r--accel-pptpd/radius/radius.c30
18 files changed, 828 insertions, 85 deletions
diff --git a/accel-pptpd/CMakeLists.txt b/accel-pptpd/CMakeLists.txt
index 9254e7e9..a2c645fa 100644
--- a/accel-pptpd/CMakeLists.txt
+++ b/accel-pptpd/CMakeLists.txt
@@ -25,6 +25,7 @@ ADD_EXECUTABLE(accel-pptpd
ppp/ipcp_opt_ipaddr.c
ppp/ipcp_opt_dns.c
ppp/ppp_ccp.c
+ ppp/ccp_mppe.c
pwdb.c
ipdb.c
diff --git a/accel-pptpd/accel-pptpd.conf b/accel-pptpd/accel-pptpd.conf
index 7a48802a..22be345f 100644
--- a/accel-pptpd/accel-pptpd.conf
+++ b/accel-pptpd/accel-pptpd.conf
@@ -19,11 +19,11 @@ min-mtu=1000
mtu=1200
[lcp]
-echo-interval=10
+echo-interval=30
echo-failure=3
[pptp]
-echo-interval=3
+echo-interval=30
verbose=1
[radius]
@@ -39,7 +39,7 @@ verbose=1
[client-ip-range]
192.168.10.20-30
192.168.10.6/32
-192.168.10.1/32
+192.168.10.1/24
192.168.11.0/24
192.168.0.0/24
diff --git a/accel-pptpd/include/events.h b/accel-pptpd/include/events.h
index f3278cb2..2f4c4e5c 100644
--- a/accel-pptpd/include/events.h
+++ b/accel-pptpd/include/events.h
@@ -30,6 +30,8 @@ struct ev_mppe_keys_t
struct ppp_t *ppp;
uint8_t *recv_key;
uint8_t *send_key;
+ int policy;
+ int type;
};
#endif
diff --git a/accel-pptpd/ppp/ccp_mppe.c b/accel-pptpd/ppp/ccp_mppe.c
new file mode 100644
index 00000000..8958b520
--- /dev/null
+++ b/accel-pptpd/ppp/ccp_mppe.c
@@ -0,0 +1,214 @@
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/if_ppp.h>
+#include <net/if.h>
+
+#include "ppp.h"
+#include "ppp_ccp.h"
+#include "log.h"
+#include "events.h"
+
+#include "memdebug.h"
+
+#define MPPE_H (1 << 24)
+#define MPPE_M (1 << 7)
+#define MPPE_S (1 << 6)
+#define MPPE_L (1 << 5)
+#define MPPE_D (1 << 4)
+#define MPPE_C (1 << 0)
+
+#define MPPE_PAD 4
+
+static struct ccp_option_t *mppe_init(struct ppp_ccp_t *ccp);
+static void mppe_free(struct ppp_ccp_t *ccp, struct ccp_option_t *opt);
+static int mppe_send_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr);
+static int mppe_recv_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr);
+static void mppe_print(void (*print)(const char *fmt,...),struct ccp_option_t*, uint8_t *ptr);
+
+struct mppe_option_t
+{
+ struct ccp_option_t opt;
+ int mppe;
+ uint8_t recv_key[16];
+ uint8_t send_key[16];
+ int policy; // 1 - allowed, 2 - required
+};
+
+static struct ccp_option_handler_t mppe_opt_hnd = {
+ .init = mppe_init,
+ .send_conf_req = mppe_send_conf_req,
+ .send_conf_nak = mppe_send_conf_req,
+ .recv_conf_req = mppe_recv_conf_req,
+ .free = mppe_free,
+ .print = mppe_print,
+};
+
+static struct ccp_option_t *mppe_init(struct ppp_ccp_t *ccp)
+{
+ struct mppe_option_t *mppe_opt = _malloc(sizeof(*mppe_opt));
+ memset(mppe_opt, 0, sizeof(*mppe_opt));
+ mppe_opt->mppe = -1;
+ mppe_opt->opt.id = CI_MPPE;
+ mppe_opt->opt.len = 6;
+
+ return &mppe_opt->opt;
+}
+
+static void mppe_free(struct ppp_ccp_t *ccp, struct ccp_option_t *opt)
+{
+ struct mppe_option_t *mppe_opt = container_of(opt, typeof(*mppe_opt), opt);
+
+ _free(mppe_opt);
+}
+
+static int setup_mppe_key(int fd, int transmit, uint8_t *key)
+{
+ struct ppp_option_data data;
+ uint8_t buf[6 + 16];
+
+ memset(buf, 0, sizeof(buf));
+ buf[0] = CI_MPPE;
+ buf[1] = 6;
+ *(uint32_t*)(buf + 2) = htonl(MPPE_S | MPPE_H);
+ if (key)
+ memcpy(buf + 6, key, 16);
+
+ memset(&data, 0, sizeof(data));
+ data.ptr = buf;
+ data.length = sizeof(buf);
+ data.transmit = transmit;
+
+ if (ioctl(fd, PPPIOCSCOMPRESS, &data)) {
+ log_ppp_warn("mppe: MPPE requested but not supported by kernel\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int decrease_mtu(struct ppp_t *ppp)
+{
+ struct ifreq ifr;
+
+ strcpy(ifr.ifr_name, ppp->ifname);
+
+ if (ioctl(sock_fd, SIOCGIFMTU, &ifr)) {
+ log_ppp_error("mppe: failed to get MTU: %s\n", strerror(errno));
+ return -1;
+ }
+
+ ifr.ifr_mtu -= MPPE_PAD;
+
+ if (ioctl(sock_fd, SIOCSIFMTU, &ifr)) {
+ log_ppp_error("mppe: failed to set MTU: %s\n", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int mppe_send_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr)
+{
+ struct mppe_option_t *mppe_opt = container_of(opt,typeof(*mppe_opt),opt);
+ struct ccp_opt32_t *opt32 = (struct ccp_opt32_t*)ptr;
+
+ if (mppe_opt->policy == 2 || mppe_opt->mppe != -1) {
+ opt32->hdr.id = CI_MPPE;
+ opt32->hdr.len = 6;
+ opt32->val = mppe_opt->mppe ? htonl(MPPE_S | MPPE_H) : 0;
+
+ if (mppe_opt->mppe && setup_mppe_key(ccp->ppp->unit_fd, 0, mppe_opt->recv_key))
+ return 0;
+
+ return 6;
+ }
+ return 0;
+}
+
+static int mppe_recv_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr)
+{
+ struct mppe_option_t *mppe_opt = container_of(opt, typeof(*mppe_opt), opt);
+ struct ccp_opt32_t *opt32 = (struct ccp_opt32_t *)ptr;
+
+ /*if (!ptr) {
+ if (mppe_opt->policy == 2)
+ return CCP_OPT_NAK;
+ return CCP_OPT_ACK;
+ }*/
+
+ if (opt32->hdr.len != 6)
+ return CCP_OPT_REJ;
+
+ if (mppe_opt->policy == 2) {
+ if (ntohl(opt32->val) != (MPPE_S | MPPE_H))
+ return CCP_OPT_NAK;
+ } else if (mppe_opt->policy == 1) {
+ if (ntohl(opt32->val) == (MPPE_S | MPPE_H))
+ mppe_opt->mppe = 1;
+ else if ((ntohl(opt32->val) & (MPPE_S | MPPE_H)) == (MPPE_S | MPPE_H)) {
+ mppe_opt->mppe = 1;
+ return CCP_OPT_NAK;
+ } else if (opt32->val) {
+ mppe_opt->mppe = 0;
+ return CCP_OPT_NAK;
+ } else
+ mppe_opt->mppe = 0;
+ }
+
+ if (setup_mppe_key(ccp->ppp->unit_fd, 1, mppe_opt->send_key))
+ return CCP_OPT_REJ;
+
+ decrease_mtu(ccp->ppp);
+
+ return CCP_OPT_ACK;
+}
+
+static void mppe_print(void (*print)(const char *fmt,...),struct ccp_option_t *opt, uint8_t *ptr)
+{
+ struct mppe_option_t *mppe_opt = container_of(opt, typeof(*mppe_opt), opt);
+ struct ccp_opt32_t *opt32 = (struct ccp_opt32_t *)ptr;
+ uint32_t bits;
+
+ if (ptr)
+ bits = ntohl(opt32->val);
+ else
+ if (mppe_opt->mppe)
+ bits = MPPE_S | MPPE_H;
+ else
+ bits = 0;
+
+ print("<mppe %sH %sM %sS %sL %sD %sC>",
+ bits & MPPE_H ? "+" : "-",
+ bits & MPPE_M ? "+" : "-",
+ bits & MPPE_S ? "+" : "-",
+ bits & MPPE_L ? "+" : "-",
+ bits & MPPE_D ? "+" : "-",
+ bits & MPPE_C ? "+" : "-"
+ );
+}
+
+static void ev_mppe_keys(struct ev_mppe_keys_t *ev)
+{
+ struct mppe_option_t *mppe_opt = container_of(ccp_find_option(ev->ppp, &mppe_opt_hnd), typeof(*mppe_opt), opt);
+
+ if ((ev->type & 0x02) == 0) {
+ log_ppp_warn("mppe: 128-bit session keys not allowed, disabling mppe ...\n");
+ return;
+ }
+
+ memcpy(mppe_opt->recv_key, ev->recv_key, 16);
+ memcpy(mppe_opt->send_key, ev->send_key, 16);
+ mppe_opt->policy = ev->policy;
+
+ if (ev->policy == 2)
+ mppe_opt->mppe = 1;
+}
+
+static void __init mppe_opt_init()
+{
+ ccp_option_register(&mppe_opt_hnd);
+ triton_event_register_handler(EV_MPPE_KEYS, (triton_event_func)ev_mppe_keys);
+}
+
diff --git a/accel-pptpd/ppp/ipcp_opt_dns.c b/accel-pptpd/ppp/ipcp_opt_dns.c
index b0365da2..4c48fd4c 100644
--- a/accel-pptpd/ppp/ipcp_opt_dns.c
+++ b/accel-pptpd/ppp/ipcp_opt_dns.c
@@ -101,6 +101,9 @@ static int dns_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt,
struct dns_option_t *dns_opt=container_of(opt,typeof(*dns_opt),opt);
struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr;
+ if (opt32->hdr.len != 6)
+ return IPCP_OPT_REJ;
+
if (!dns_opt->addr)
{
if (dns_opt->opt.id == CI_DNS1 && conf_dns1) dns_opt->addr=conf_dns1;
diff --git a/accel-pptpd/ppp/ipcp_opt_ipaddr.c b/accel-pptpd/ppp/ipcp_opt_ipaddr.c
index 963d4736..108e350c 100644
--- a/accel-pptpd/ppp/ipcp_opt_ipaddr.c
+++ b/accel-pptpd/ppp/ipcp_opt_ipaddr.c
@@ -104,6 +104,9 @@ static int ipaddr_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *o
struct sockaddr_in addr;
struct npioctl np;
+ if (opt32->hdr.len != 6)
+ return IPCP_OPT_REJ;
+
if (ipaddr_opt->ip->peer_addr == opt32->val)
goto ack;
diff --git a/accel-pptpd/ppp/lcp_opt_accomp.c b/accel-pptpd/ppp/lcp_opt_accomp.c
index 94fa1281..241b0e06 100644
--- a/accel-pptpd/ppp/lcp_opt_accomp.c
+++ b/accel-pptpd/ppp/lcp_opt_accomp.c
@@ -75,13 +75,17 @@ static int accomp_send_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt,
static int accomp_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
{
struct accomp_option_t *accomp_opt=container_of(opt,typeof(*accomp_opt),opt);
+ struct lcp_opt_hdr_t *opt0=(struct lcp_opt_hdr_t*)ptr;
- if (!ptr) {
+ /*if (!ptr) {
if (accomp_opt->require)
return LCP_OPT_NAK;
accomp_opt->accomp=0;
return LCP_OPT_ACK;
- }
+ }*/
+
+ if (opt0->len != 2)
+ return LCP_OPT_REJ;
if (accomp_opt->accomp>0)
{
diff --git a/accel-pptpd/ppp/lcp_opt_magic.c b/accel-pptpd/ppp/lcp_opt_magic.c
index 166c85c4..4a61ef91 100644
--- a/accel-pptpd/ppp/lcp_opt_magic.c
+++ b/accel-pptpd/ppp/lcp_opt_magic.c
@@ -64,8 +64,11 @@ static int magic_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt,
struct magic_option_t *magic_opt=container_of(opt,typeof(*magic_opt),opt);
struct lcp_opt32_t *opt32=(struct lcp_opt32_t*)ptr;
- if (!ptr)
- return LCP_OPT_NAK;
+ /*if (!ptr)
+ return LCP_OPT_NAK;*/
+
+ if (opt32->hdr.len != 6)
+ return LCP_OPT_REJ;
if (magic_opt->magic==ntohl(opt32->val))
{
diff --git a/accel-pptpd/ppp/lcp_opt_mru.c b/accel-pptpd/ppp/lcp_opt_mru.c
index 096c0d58..9bf7af67 100644
--- a/accel-pptpd/ppp/lcp_opt_mru.c
+++ b/accel-pptpd/ppp/lcp_opt_mru.c
@@ -86,8 +86,11 @@ static int mru_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, ui
struct mru_option_t *mru_opt = container_of(opt,typeof(*mru_opt),opt);
struct lcp_opt16_t *opt16 = (struct lcp_opt16_t*)ptr;
- if (!ptr)
- return LCP_OPT_NAK;
+ /*if (!ptr)
+ return LCP_OPT_NAK;*/
+
+ if (opt16->hdr.len != 4)
+ return LCP_OPT_REJ;
if (ntohs(opt16->val) < conf_min_mtu || ntohs(opt16->val) > lcp->ppp->ctrl->max_mtu)
return LCP_OPT_NAK;
diff --git a/accel-pptpd/ppp/lcp_opt_pcomp.c b/accel-pptpd/ppp/lcp_opt_pcomp.c
index a1ceb8e8..1f8532bb 100644
--- a/accel-pptpd/ppp/lcp_opt_pcomp.c
+++ b/accel-pptpd/ppp/lcp_opt_pcomp.c
@@ -75,13 +75,17 @@ static int pcomp_send_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt,
static int pcomp_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
{
struct pcomp_option_t *pcomp_opt=container_of(opt,typeof(*pcomp_opt),opt);
+ struct lcp_opt_hdr_t *opt0=(struct lcp_opt_hdr_t*)ptr;
- if (!ptr) {
+ /*if (!ptr) {
if (pcomp_opt->require)
return LCP_OPT_NAK;
pcomp_opt->pcomp=0;
return LCP_OPT_ACK;
- }
+ }*/
+
+ if (opt0->len != 2)
+ return LCP_OPT_REJ;
if (pcomp_opt->pcomp>0)
{
diff --git a/accel-pptpd/ppp/ppp.c b/accel-pptpd/ppp/ppp.c
index 94919779..ee7e13cc 100644
--- a/accel-pptpd/ppp/ppp.c
+++ b/accel-pptpd/ppp/ppp.c
@@ -424,8 +424,8 @@ static int get_layer_order(const char *name)
{
if (!strcmp(name,"lcp")) return 0;
if (!strcmp(name,"auth")) return 1;
- if (!strcmp(name,"ipcp")) return 2;
if (!strcmp(name,"ccp")) return 2;
+ if (!strcmp(name,"ipcp")) return 3;
return -1;
}
diff --git a/accel-pptpd/ppp/ppp_ccp.c b/accel-pptpd/ppp/ppp_ccp.c
index 6deaeb18..36db6f9a 100644
--- a/accel-pptpd/ppp/ppp_ccp.c
+++ b/accel-pptpd/ppp/ppp_ccp.c
@@ -1,8 +1,9 @@
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <linux/ppp_defs.h>
#include <linux/if_ppp.h>
-#include <arpa/inet.h>
+#include <sys/ioctl.h>
#include "triton.h"
@@ -22,6 +23,7 @@ struct recv_opt_t
struct ccp_option_t *lopt;
};
+static struct ppp_layer_t ccp_layer;
static LIST_HEAD(option_handlers);
static void ccp_layer_up(struct ppp_fsm_t*);
@@ -65,6 +67,26 @@ static void ccp_options_free(struct ppp_ccp_t *ccp)
}
}
+static int ccp_set_flags(int fd, int isopen, int isup)
+{
+ int flags;
+
+ if (ioctl(fd, PPPIOCGFLAGS, &flags)) {
+ log_ppp_error("ccp: failed to get flags: %s\n", strerror(errno));
+ return -1;
+ }
+
+ flags &= ~(SC_CCP_OPEN | SC_CCP_UP);
+ flags |= (isopen ? SC_CCP_OPEN : 0) | (isup ? SC_CCP_UP : 0);
+
+ if (ioctl(fd, PPPIOCSFLAGS, &flags)) {
+ log_ppp_error("ccp: failed to set flags: %s\n", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
static struct ppp_layer_data_t *ccp_layer_init(struct ppp_t *ppp)
{
struct ppp_ccp_t *ccp=_malloc(sizeof(*ccp));
@@ -80,6 +102,11 @@ static struct ppp_layer_data_t *ccp_layer_init(struct ppp_t *ppp)
ppp_register_unit_handler(ppp,&ccp->hnd);
+ INIT_LIST_HEAD(&ccp->options);
+ ccp_options_init(ccp);
+
+ ccp->passive = 1;
+
ccp->fsm.proto = PPP_CCP;
ppp_fsm_init(&ccp->fsm);
@@ -92,7 +119,6 @@ static struct ppp_layer_data_t *ccp_layer_init(struct ppp_t *ppp)
ccp->fsm.send_term_req=send_term_req;
ccp->fsm.send_term_ack=send_term_ack;
- INIT_LIST_HEAD(&ccp->options);
INIT_LIST_HEAD(&ccp->ropt_list);
return &ccp->ld;
@@ -104,8 +130,6 @@ int ccp_layer_start(struct ppp_layer_data_t *ld)
log_ppp_debug("ccp_layer_start\n");
- ccp_options_init(ccp);
-
if (list_empty(&ccp->options)) {
ppp_layer_started(ccp->ppp, &ccp->ld);
return 0;
@@ -115,6 +139,11 @@ int ccp_layer_start(struct ppp_layer_data_t *ld)
if (ppp_fsm_open(&ccp->fsm))
return -1;
+ if (ccp_set_flags(ccp->ppp->unit_fd, 1, 0)) {
+ ppp_fsm_close(&ccp->fsm);
+ return -1;
+ }
+
return 0;
}
@@ -123,6 +152,8 @@ void ccp_layer_finish(struct ppp_layer_data_t *ld)
struct ppp_ccp_t *ccp=container_of(ld,typeof(*ccp),ld);
log_ppp_debug("ccp_layer_finish\n");
+
+ ccp_set_flags(ccp->ppp->unit_fd, 0, 0);
ccp->fsm.fsm_state = FSM_Closed;
ppp_layer_finished(ccp->ppp,&ccp->ld);
@@ -146,6 +177,10 @@ static void ccp_layer_up(struct ppp_fsm_t *fsm)
struct ppp_ccp_t *ccp=container_of(fsm,typeof(*ccp),fsm);
log_ppp_debug("ccp_layer_started\n");
ccp->started = 1;
+ if (ccp_set_flags(ccp->ppp->unit_fd, 1, 1)) {
+ ppp_terminate(ccp->ppp, 0);
+ return;
+ }
ppp_layer_started(ccp->ppp,&ccp->ld);
}
@@ -174,38 +209,45 @@ static void print_ropt(struct recv_opt_t *ropt)
static int send_conf_req(struct ppp_fsm_t *fsm)
{
- struct ppp_ccp_t *ccp=container_of(fsm,typeof(*ccp),fsm);
- uint8_t *buf=_malloc(ccp->conf_req_len), *ptr=buf;
- struct ccp_hdr_t *ccp_hdr=(struct ccp_hdr_t*)ptr;
+ struct ppp_ccp_t *ccp = container_of(fsm, typeof(*ccp), fsm);
+ uint8_t *buf, *ptr;
+ struct ccp_hdr_t *ccp_hdr;
struct ccp_option_t *lopt;
int n;
- log_ppp_debug("send [CCP ConfReq");
- ccp_hdr->proto=htons(PPP_CCP);
- ccp_hdr->code=CONFREQ;
- ccp_hdr->id=++ccp->fsm.id;
- ccp_hdr->len=0;
- log_ppp_debug(" id=%x",ccp_hdr->id);
+ ccp->need_req = 0;
+
+ if (ccp->passive)
+ return 0;
+
+ buf = _malloc(ccp->conf_req_len);
+ ccp_hdr = (struct ccp_hdr_t*)buf;
+
+ ccp_hdr->proto = htons(PPP_CCP);
+ ccp_hdr->code = CONFREQ;
+ ccp_hdr->id = ++ccp->fsm.id;
+ ccp_hdr->len = 0;
- ptr+=sizeof(*ccp_hdr);
+ ptr = (uint8_t*)(ccp_hdr + 1);
- list_for_each_entry(lopt,&ccp->options,entry)
- {
- n=lopt->h->send_conf_req(ccp,lopt,ptr);
+ log_ppp_debug("send [CCP ConfReq id=%x", ccp_hdr->id);
+
+ list_for_each_entry(lopt,&ccp->options,entry) {
+ n = lopt->h->send_conf_req(ccp,lopt,ptr);
if (n < 0)
return -1;
- if (n)
- {
+ if (n) {
log_ppp_debug(" ");
- lopt->h->print(log_ppp_debug,lopt,NULL);
- ptr+=n;
+ lopt->h->print(log_ppp_debug, lopt, NULL);
+ lopt->state = CCP_OPT_ACK;
}
+ ptr += n;
}
log_ppp_debug("]\n");
-
- ccp_hdr->len=htons((ptr-buf)-2);
- ppp_unit_send(ccp->ppp,ccp_hdr,ptr-buf);
+
+ ccp_hdr->len = htons((ptr-buf)-2);
+ ppp_unit_send(ccp->ppp, ccp_hdr, ptr-buf);
_free(buf);
@@ -298,9 +340,10 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp,uint8_t *data,int size)
struct ccp_opt_hdr_t *hdr;
struct recv_opt_t *ropt;
struct ccp_option_t *lopt;
- int r,ret=1,ack=0;
+ int r, ret = 1, ack = 0;
- ccp->ropt_len=size;
+ ccp->need_req = 0;
+ ccp->ropt_len = size;
while(size>0)
{
@@ -318,41 +361,37 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp,uint8_t *data,int size)
size-=ropt->len;
}
- list_for_each_entry(lopt,&ccp->options,entry)
- lopt->state=CCP_OPT_NONE;
-
- log_ppp_debug("recv [CCP ConfReq id=%x",ccp->fsm.recv_id);
- list_for_each_entry(ropt,&ccp->ropt_list,entry)
+ log_ppp_debug("recv [CCP ConfReq id=%x", ccp->fsm.recv_id);
+ list_for_each_entry(ropt, &ccp->ropt_list, entry)
{
- list_for_each_entry(lopt,&ccp->options,entry)
+ list_for_each_entry(lopt, &ccp->options, entry)
{
- if (lopt->id==ropt->hdr->id)
- {
+ if (lopt->id == ropt->hdr->id) {
log_ppp_debug(" ");
- lopt->h->print(log_ppp_debug,lopt,(uint8_t*)ropt->hdr);
- r=lopt->h->recv_conf_req(ccp,lopt,(uint8_t*)ropt->hdr);
- if (ack)
- {
- lopt->state=CCP_OPT_REJ;
- ropt->state=CCP_OPT_REJ;
- }else
- {
- lopt->state=r;
- ropt->state=r;
+ lopt->h->print(log_ppp_debug, lopt, (uint8_t*)ropt->hdr);
+ r = lopt->h->recv_conf_req(ccp, lopt, (uint8_t*)ropt->hdr);
+ if (ack) {
+ lopt->state = CCP_OPT_REJ;
+ ropt->state = CCP_OPT_REJ;
+ } else {
+ if (lopt->state == CCP_OPT_NAK && r == CCP_OPT_ACK)
+ ccp->need_req = 1;
+ lopt->state = r;
+ ropt->state = r;
}
- ropt->lopt=lopt;
- if (r<ret) ret=r;
+ ropt->lopt = lopt;
+ if (r < ret)
+ ret = r;
break;
}
}
- if (ropt->state==CCP_OPT_ACK || ropt->state==CCP_OPT_NAK)
- ack=1;
- else if (!ropt->lopt)
- {
+ if (ropt->state == CCP_OPT_ACK || ropt->state == CCP_OPT_NAK)
+ ack = 1;
+ else if (!ropt->lopt) {
log_ppp_debug(" ");
print_ropt(ropt);
- ropt->state=CCP_OPT_REJ;
- ret=CCP_OPT_REJ;
+ ropt->state = CCP_OPT_REJ;
+ ret = CCP_OPT_REJ;
}
}
log_ppp_debug("]\n");
@@ -570,14 +609,22 @@ static void ccp_recv(struct ppp_handler_t*h)
break;
}
ccp_free_conf_req(ccp);
- if (r==CCP_OPT_FAIL)
+
+ if (r == CCP_OPT_ACK && ccp->passive) {
+ ccp->passive = 0;
+ send_conf_req(&ccp->fsm);
+ }
+ if (r == CCP_OPT_FAIL)
ppp_terminate(ccp->ppp, 0);
break;
case CONFACK:
if (ccp_recv_conf_ack(ccp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN))
ppp_terminate(ccp->ppp, 0);
- else
+ else {
ppp_fsm_recv_conf_ack(&ccp->fsm);
+ if (ccp->need_req)
+ send_conf_req(&ccp->fsm);
+ }
break;
case CONFNAK:
ccp_recv_conf_nak(ccp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN);
@@ -625,6 +672,19 @@ int ccp_option_register(struct ccp_option_handler_t *h)
return 0;
}
+struct ccp_option_t *ccp_find_option(struct ppp_t *ppp, struct ccp_option_handler_t *h)
+{
+ struct ppp_ccp_t *ccp = container_of(ppp_find_layer_data(ppp, &ccp_layer), typeof(*ccp), ld);
+ struct ccp_option_t *opt;
+
+ list_for_each_entry(opt, &ccp->options, entry)
+ if (opt->h == h)
+ return opt;
+
+ log_emerg("ccp: BUG: option not found\n");
+ abort();
+}
+
static struct ppp_layer_t ccp_layer=
{
.init=ccp_layer_init,
diff --git a/accel-pptpd/ppp/ppp_ccp.h b/accel-pptpd/ppp/ppp_ccp.h
index 23f44f0f..27b303e6 100644
--- a/accel-pptpd/ppp/ppp_ccp.h
+++ b/accel-pptpd/ppp/ppp_ccp.h
@@ -8,10 +8,8 @@
/*
* Options.
*/
-#define CI_COMP 2 /* IP-Compress-Protocol */
-#define CI_ADDR 3 /* IP-Address */
-#define CI_DNS1 129 /* Primary-DNS-Address */
-#define CI_DNS2 131 /* Secondary-DNS-Address */
+
+#define CI_MPPE 18 /* MPPE */
struct ccp_hdr_t
{
@@ -87,9 +85,12 @@ struct ppp_ccp_t
int conf_req_len;
int started:1;
+ int passive:1;
+ int need_req:1;
};
int ccp_option_register(struct ccp_option_handler_t *h);
+struct ccp_option_t *ccp_find_option(struct ppp_t *ppp, struct ccp_option_handler_t *h);
#endif
diff --git a/accel-pptpd/radius/attr_defs.h b/accel-pptpd/radius/attr_defs.h
new file mode 100644
index 00000000..e9b617e4
--- /dev/null
+++ b/accel-pptpd/radius/attr_defs.h
@@ -0,0 +1,287 @@
+#define User_Name 1
+#define User_Password 2
+#define CHAP_Password 3
+#define NAS_IP_Address 4
+#define NAS_Port 5
+#define Service_Type 6
+#define Framed_Protocol 7
+#define Framed_IP_Address 8
+#define Framed_IP_Netmask 9
+#define Framed_Routing 10
+#define Filter_Id 11
+#define Framed_MTU 12
+#define Framed_Compression 13
+#define Login_IP_Host 14
+#define Login_Service 15
+#define Login_TCP_Port 16
+#define Reply_Message 18
+#define Callback_Number 19
+#define Callback_Id 20
+#define Framed_Route 22
+#define Framed_IPX_Network 23
+#define State 24
+#define Class 25
+#define Vendor_Specific 26
+#define Session_Timeout 27
+#define Idle_Timeout 28
+#define Termination_Action 29
+#define Called_Station_Id 30
+#define Calling_Station_Id 31
+#define NAS_Identifier 32
+#define Proxy_State 33
+#define Login_LAT_Service 34
+#define Login_LAT_Node 35
+#define Login_LAT_Group 36
+#define Framed_AppleTalk_Link 37
+#define Framed_AppleTalk_Network 38
+#define Framed_AppleTalk_Zone 39
+#define CHAP_Challenge 60
+#define NAS_Port_Type 61
+#define Port_Limit 62
+#define Login_LAT_Port 63
+#define Service_Type_Login_User 1
+#define Service_Type_Framed_User 2
+#define Service_Type_Callback_Login_User 3
+#define Service_Type_Callback_Framed_User 4
+#define Service_Type_Outbound_User 5
+#define Service_Type_Administrative_User 6
+#define Service_Type_NAS_Prompt_User 7
+#define Service_Type_Authenticate_Only 8
+#define Service_Type_Callback_NAS_Prompt 9
+#define Service_Type_Call_Check 10
+#define Service_Type_Callback_Administrative 11
+#define Framed_Protocol_PPP 1
+#define Framed_Protocol_SLIP 2
+#define Framed_Protocol_ARAP 3
+#define Framed_Protocol_Gandalf_SLML 4
+#define Framed_Protocol_Xylogics_IPX_SLIP 5
+#define Framed_Protocol_X_75_Synchronous 6
+#define Framed_Routing_None 0
+#define Framed_Routing_Broadcast 1
+#define Framed_Routing_Listen 2
+#define Framed_Routing_Broadcast_Listen 3
+#define Framed_Compression_None 0
+#define Framed_Compression_Van_Jacobson_TCP_IP 1
+#define Framed_Compression_IPX_Header_Compression 2
+#define Framed_Compression_Stac_LZS 3
+#define Login_Service_Telnet 0
+#define Login_Service_Rlogin 1
+#define Login_Service_TCP_Clear 2
+#define Login_Service_PortMaster 3
+#define Login_Service_LAT 4
+#define Login_Service_X25_PAD 5
+#define Login_Service_X25_T3POS 6
+#define Login_Service_TCP_Clear_Quiet 8
+#define Login_TCP_Port_Telnet 23
+#define Login_TCP_Port_Rlogin 513
+#define Login_TCP_Port_Rsh 514
+#define Termination_Action_Default 0
+#define Termination_Action_RADIUS_Request 1
+#define NAS_Port_Type_Async 0
+#define NAS_Port_Type_Sync 1
+#define NAS_Port_Type_ISDN 2
+#define NAS_Port_Type_ISDN_V120 3
+#define NAS_Port_Type_ISDN_V110 4
+#define NAS_Port_Type_Virtual 5
+#define NAS_Port_Type_PIAFS 6
+#define NAS_Port_Type_HDLC_Clear_Channel 7
+#define NAS_Port_Type_X_25 8
+#define NAS_Port_Type_X_75 9
+#define NAS_Port_Type_G_3_Fax 10
+#define NAS_Port_Type_SDSL 11
+#define NAS_Port_Type_ADSL_CAP 12
+#define NAS_Port_Type_ADSL_DMT 13
+#define NAS_Port_Type_IDSL 14
+#define NAS_Port_Type_Ethernet 15
+#define NAS_Port_Type_xDSL 16
+#define NAS_Port_Type_Cable 17
+#define NAS_Port_Type_Wireless_Other 18
+#define NAS_Port_Type_Wireless_802_11 19
+#define Acct_Status_Type 40
+#define Acct_Delay_Time 41
+#define Acct_Input_Octets 42
+#define Acct_Output_Octets 43
+#define Acct_Session_Id 44
+#define Acct_Authentic 45
+#define Acct_Session_Time 46
+#define Acct_Input_Packets 47
+#define Acct_Output_Packets 48
+#define Acct_Terminate_Cause 49
+#define Acct_Multi_Session_Id 50
+#define Acct_Link_Count 51
+#define Acct_Status_Type_Start 1
+#define Acct_Status_Type_Stop 2
+#define Acct_Status_Type_Alive 3
+#define Acct_Status_Type_Interim_Update 3
+#define Acct_Status_Type_Accounting_On 7
+#define Acct_Status_Type_Accounting_Off 8
+#define Acct_Status_Type_Failed 15
+#define Acct_Authentic_RADIUS 1
+#define Acct_Authentic_Local 2
+#define Acct_Authentic_Remote 3
+#define Acct_Authentic_Diameter 4
+#define Acct_Terminate_Cause_User_Request 1
+#define Acct_Terminate_Cause_Lost_Carrier 2
+#define Acct_Terminate_Cause_Lost_Service 3
+#define Acct_Terminate_Cause_Idle_Timeout 4
+#define Acct_Terminate_Cause_Session_Timeout 5
+#define Acct_Terminate_Cause_Admin_Reset 6
+#define Acct_Terminate_Cause_Admin_Reboot 7
+#define Acct_Terminate_Cause_Port_Error 8
+#define Acct_Terminate_Cause_NAS_Error 9
+#define Acct_Terminate_Cause_NAS_Request 10
+#define Acct_Terminate_Cause_NAS_Reboot 11
+#define Acct_Terminate_Cause_Port_Unneeded 12
+#define Acct_Terminate_Cause_Port_Preempted 13
+#define Acct_Terminate_Cause_Port_Suspended 14
+#define Acct_Terminate_Cause_Service_Unavailable 15
+#define Acct_Terminate_Cause_Callback 16
+#define Acct_Terminate_Cause_User_Error 17
+#define Acct_Terminate_Cause_Host_Request 18
+#define Acct_Tunnel_Connection 68
+#define Acct_Tunnel_Packets_Lost 86
+#define Acct_Status_Type_Tunnel_Start 9
+#define Acct_Status_Type_Tunnel_Stop 10
+#define Acct_Status_Type_Tunnel_Reject 11
+#define Acct_Status_Type_Tunnel_Link_Start 12
+#define Acct_Status_Type_Tunnel_Link_Stop 13
+#define Acct_Status_Type_Tunnel_Link_Reject 14
+#define Tunnel_Type 64
+#define Tunnel_Medium_Type 65
+#define Tunnel_Client_Endpoint 66
+#define Tunnel_Server_Endpoint 67
+#define Tunnel_Password 69
+#define Tunnel_Private_Group_Id 81
+#define Tunnel_Assignment_Id 82
+#define Tunnel_Preference 83
+#define Tunnel_Client_Auth_Id 90
+#define Tunnel_Server_Auth_Id 91
+#define Tunnel_Type_PPTP 1
+#define Tunnel_Type_L2F 2
+#define Tunnel_Type_L2TP 3
+#define Tunnel_Type_ATMP 4
+#define Tunnel_Type_VTP 5
+#define Tunnel_Type_AH 6
+#define Tunnel_Type_IP 7
+#define Tunnel_Type_MIN_IP 8
+#define Tunnel_Type_ESP 9
+#define Tunnel_Type_GRE 10
+#define Tunnel_Type_DVS 11
+#define Tunnel_Type_IP_in_IP 12
+#define Tunnel_Medium_Type_IP 1
+#define Tunnel_Medium_Type_IPv4 1
+#define Tunnel_Medium_Type_IPv6 2
+#define Tunnel_Medium_Type_NSAP 3
+#define Tunnel_Medium_Type_HDLC 4
+#define Tunnel_Medium_Type_BBN_1822 5
+#define Tunnel_Medium_Type_IEEE_802 6
+#define Tunnel_Medium_Type_E_163 7
+#define Tunnel_Medium_Type_E_164 8
+#define Tunnel_Medium_Type_F_69 9
+#define Tunnel_Medium_Type_X_121 10
+#define Tunnel_Medium_Type_IPX 11
+#define Tunnel_Medium_Type_Appletalk 12
+#define Tunnel_Medium_Type_DecNet_IV 13
+#define Tunnel_Medium_Type_Banyan_Vines 14
+#define Tunnel_Medium_Type_E_164_NSAP 15
+#define Acct_Input_Gigawords 52
+#define Acct_Output_Gigawords 53
+#define Event_Timestamp 55
+#define ARAP_Password 70
+#define ARAP_Features 71
+#define ARAP_Zone_Access 72
+#define ARAP_Security 73
+#define ARAP_Security_Data 74
+#define Password_Retry 75
+#define Prompt 76
+#define Connect_Info 77
+#define Configuration_Token 78
+#define EAP_Message 79
+#define Message_Authenticator 80
+#define ARAP_Challenge_Response 84
+#define Acct_Interim_Interval 85
+#define NAS_Port_Id 87
+#define Framed_Pool 88
+#define ARAP_Zone_Access_Default_Zone 1
+#define ARAP_Zone_Access_Zone_Filter_Inclusive 2
+#define ARAP_Zone_Access_Zone_Filter_Exclusive 4
+#define Prompt_No_Echo 0
+#define Prompt_Echo 1
+#define Error_Cause 101
+#define Service_Type_Authorize_Only 17
+#define Error_Cause_Residual_Context_Removed 201
+#define Error_Cause_Invalid_EAP_Packet 202
+#define Error_Cause_Unsupported_Attribute 401
+#define Error_Cause_Missing_Attribute 402
+#define Error_Cause_NAS_Identification_Mismatch 403
+#define Error_Cause_Invalid_Request 404
+#define Error_Cause_Unsupported_Service 405
+#define Error_Cause_Unsupported_Extension 406
+#define Error_Cause_Administratively_Prohibited 501
+#define Error_Cause_Proxy_Request_Not_Routable 502
+#define Error_Cause_Session_Context_Not_Found 503
+#define Error_Cause_Session_Context_Not_Removable 504
+#define Error_Cause_Proxy_Processing_Error 505
+#define Error_Cause_Resources_Unavailable 506
+#define Error_Cause_Request_Initiated 507
+#define Acct_Terminate_Cause_Supplicant_Restart 19
+#define Acct_Terminate_Cause_Reauthentication_Failure 20
+#define Acct_Terminate_Cause_Port_Reinit 21
+#define Acct_Terminate_Cause_Port_Disabled 22
+#define NAS_Port_Type_Token_Ring 20
+#define NAS_Port_Type_FDDI 21
+#define Tunnel_Type_VLAN 13
+#define EAP_Key_Name 102
+#define Chargeable_User_Identity 89
+#define Error_Cause_Invalid_Attribute_Value 407
+#define Error_Cause_Multiple_Session_Selection_Unsupported 508
+#define Vendor_Microsoft 311
+#define MS_CHAP_Response 1
+#define MS_CHAP_Error 2
+#define MS_CHAP_CPW_1 3
+#define MS_CHAP_CPW_2 4
+#define MS_CHAP_LM_Enc_PW 5
+#define MS_CHAP_NT_Enc_PW 6
+#define MS_MPPE_Encryption_Policy 7
+#define MS_MPPE_Encryption_Type 8
+#define MS_MPPE_Encryption_Types 8
+#define MS_RAS_Vendor 9
+#define MS_CHAP_Domain 10
+#define MS_CHAP_Challenge 11
+#define MS_CHAP_MPPE_Keys 12
+#define MS_BAP_Usage 13
+#define MS_Link_Utilization_Threshold 14
+#define MS_Link_Drop_Time_Limit 15
+#define MS_MPPE_Send_Key 16
+#define MS_MPPE_Recv_Key 17
+#define MS_RAS_Version 18
+#define MS_Old_ARAP_Password 19
+#define MS_New_ARAP_Password 20
+#define MS_ARAP_PW_Change_Reason 21
+#define MS_Filter 22
+#define MS_Acct_Auth_Type 23
+#define MS_Acct_EAP_Type 24
+#define MS_CHAP2_Response 25
+#define MS_CHAP2_Success 26
+#define MS_CHAP2_CPW 27
+#define MS_Primary_DNS_Server 28
+#define MS_Secondary_DNS_Server 29
+#define MS_Primary_NBNS_Server 30
+#define MS_Secondary_NBNS_Server 31
+#define MS_BAP_Usage_Not_Allowed 0
+#define MS_BAP_Usage_Allowed 1
+#define MS_BAP_Usage_Required 2
+#define MS_ARAP_PW_Change_Reason_Just_Change_Password 1
+#define MS_ARAP_PW_Change_Reason_Expired_Password 2
+#define MS_ARAP_PW_Change_Reason_Admin_Requires_Password_Change 3
+#define MS_ARAP_PW_Change_Reason_Password_Too_Short 4
+#define MS_Acct_Auth_Type_PAP 1
+#define MS_Acct_Auth_Type_CHAP 2
+#define MS_Acct_Auth_Type_MS_CHAP_1 3
+#define MS_Acct_Auth_Type_MS_CHAP_2 4
+#define MS_Acct_Auth_Type_EAP 5
+#define MS_Acct_EAP_Type_MD5 4
+#define MS_Acct_EAP_Type_OTP 5
+#define MS_Acct_EAP_Type_Generic_Token_Card 6
+#define MS_Acct_EAP_Type_TLS 13
+#define Traffic_Shape_in 231
diff --git a/accel-pptpd/radius/auth.c b/accel-pptpd/radius/auth.c
index 9b61ecc6..10fdd458 100644
--- a/accel-pptpd/radius/auth.c
+++ b/accel-pptpd/radius/auth.c
@@ -1,6 +1,7 @@
#include <stdlib.h>
#include <string.h>
#include <openssl/md5.h>
+#include <openssl/sha.h>
#include "triton.h"
#include "events.h"
@@ -8,9 +9,96 @@
#include "pwdb.h"
#include "radius_p.h"
+#include "attr_defs.h"
#include "memdebug.h"
+static int decrypt_chap_mppe_keys(struct rad_req_t *req, struct rad_attr_t *attr, const uint8_t *challenge, uint8_t *key)
+{
+ MD5_CTX md5_ctx;
+ SHA_CTX sha1_ctx;
+ uint8_t md5[16];
+ uint8_t plain[32];
+ int i;
+
+ if (attr->len != 32) {
+ log_ppp_warn("radius: %s: incorrect attribute length (%i)\n", attr->attr->name, attr->len);
+ return -1;
+ }
+
+ memcpy(plain, attr->val.octets, 32);
+
+ MD5_Init(&md5_ctx);
+ MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret));
+ MD5_Update(&md5_ctx, req->pack->buf + 4, 16);
+ MD5_Final(md5, &md5_ctx);
+
+ for (i = 0; i < 16; i++)
+ plain[i] ^= md5[i];
+
+ MD5_Init(&md5_ctx);
+ MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret));
+ MD5_Update(&md5_ctx, attr->val.octets, 16);
+ MD5_Final(md5, &md5_ctx);
+
+ for (i = 0; i < 16; i++)
+ plain[i + 16] ^= md5[i];
+
+ SHA1_Init(&sha1_ctx);
+ SHA1_Update(&sha1_ctx, plain + 8, 16);
+ SHA1_Update(&sha1_ctx, plain + 8, 16);
+ SHA1_Update(&sha1_ctx, challenge, 8);
+ SHA1_Final(key, &sha1_ctx);
+
+ return 0;
+}
+
+static int decrypt_mppe_key(struct rad_req_t *req, struct rad_attr_t *attr, uint8_t *key)
+{
+ MD5_CTX md5_ctx;
+ uint8_t md5[16];
+ uint8_t plain[32];
+ int i;
+
+ if (attr->len != 34) {
+ log_ppp_warn("radius: %s: incorrect attribute length (%i)\n", attr->attr->name, attr->len);
+ return -1;
+ }
+
+ if ((attr->val.octets[0] & 0x80) == 0) {
+ log_ppp_warn("radius: %s: incorrect salt value (%x)\n", attr->attr->name, attr->len);
+ return -1;
+ }
+
+ MD5_Init(&md5_ctx);
+ MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret));
+ MD5_Update(&md5_ctx, req->pack->buf + 4, 16);
+ MD5_Update(&md5_ctx, attr->val.octets, 2);
+ MD5_Final(md5, &md5_ctx);
+
+ memcpy(plain, attr->val.octets + 2, 32);
+
+ for (i = 0; i < 16; i++)
+ plain[i] ^= md5[i];
+
+ if (plain[0] != 16) {
+ log_ppp_warn("radius: %s: incorrect key length (%i)\n", attr->attr->name, plain[0]);
+ return -1;
+ }
+
+ MD5_Init(&md5_ctx);
+ MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret));
+ MD5_Update(&md5_ctx, attr->val.octets + 2, 16);
+ MD5_Final(md5, &md5_ctx);
+
+ plain[16] ^= md5[0];
+
+ memcpy(key, plain + 1, 16);
+
+ return 0;
+}
+
+
static uint8_t* encrypt_password(const char *passwd, const char *secret, const uint8_t *RA, int *epasswd_len)
{
uint8_t *epasswd;
@@ -160,6 +248,48 @@ out:
return r;
}
+static void setup_mppe(struct rad_req_t *req, const uint8_t *challenge)
+{
+ struct rad_attr_t *attr;
+ uint8_t mppe_recv_key[16];
+ uint8_t mppe_send_key[16];
+ struct ev_mppe_keys_t ev_mppe = {
+ .ppp = req->rpd->ppp,
+ };
+
+ list_for_each_entry(attr, &req->reply->attrs, entry) {
+ if (attr->vendor && attr->vendor->id == Vendor_Microsoft) {
+ switch (attr->attr->id) {
+ case MS_CHAP_MPPE_Keys:
+ if (decrypt_chap_mppe_keys(req, attr, challenge, mppe_recv_key))
+ continue;
+ ev_mppe.recv_key = mppe_recv_key;
+ ev_mppe.send_key = mppe_recv_key;
+ break;
+ case MS_MPPE_Recv_Key:
+ if (decrypt_mppe_key(req, attr, mppe_recv_key))
+ continue;
+ ev_mppe.recv_key = mppe_recv_key;
+ break;
+ case MS_MPPE_Send_Key:
+ if (decrypt_mppe_key(req, attr, mppe_send_key))
+ continue;
+ ev_mppe.send_key = mppe_send_key;
+ break;
+ case MS_MPPE_Encryption_Policy:
+ ev_mppe.policy = attr->val.integer;
+ break;
+ case MS_MPPE_Encryption_Type:
+ ev_mppe.type = attr->val.integer;
+ break;
+ }
+ }
+ }
+
+ if (ev_mppe.recv_key && ev_mppe.send_key)
+ triton_event_fire(EV_MPPE_KEYS, &ev_mppe);
+}
+
int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list args)
{
int r;
@@ -196,6 +326,7 @@ int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list ar
.reply = req->reply,
};
triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev);
+ setup_mppe(req, challenge);
}
out:
@@ -251,6 +382,7 @@ int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list ar
.reply = req->reply,
};
triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev);
+ setup_mppe(req, NULL);
}
out:
diff --git a/accel-pptpd/radius/dict/dictionary.microsoft b/accel-pptpd/radius/dict/dictionary.microsoft
index 6d6e71ae..9ca6b8e9 100644
--- a/accel-pptpd/radius/dict/dictionary.microsoft
+++ b/accel-pptpd/radius/dict/dictionary.microsoft
@@ -14,11 +14,11 @@ ATTRIBUTE MS-CHAP-CPW-1 3 octets
ATTRIBUTE MS-CHAP-CPW-2 4 octets
ATTRIBUTE MS-CHAP-LM-Enc-PW 5 octets
ATTRIBUTE MS-CHAP-NT-Enc-PW 6 octets
-ATTRIBUTE MS-MPPE-Encryption-Policy 7 octets
+ATTRIBUTE MS-MPPE-Encryption-Policy 7 integer
# This is referred to as both singular and plural in the RFC.
# Plural seems to make more sense.
-ATTRIBUTE MS-MPPE-Encryption-Type 8 octets
-ATTRIBUTE MS-MPPE-Encryption-Types 8 octets
+ATTRIBUTE MS-MPPE-Encryption-Type 8 integer
+ATTRIBUTE MS-MPPE-Encryption-Types 8 integer
ATTRIBUTE MS-RAS-Vendor 9 integer # content is Vendor-ID
ATTRIBUTE MS-CHAP-Domain 10 string
ATTRIBUTE MS-CHAP-Challenge 11 octets
diff --git a/accel-pptpd/radius/dict2c.py b/accel-pptpd/radius/dict2c.py
new file mode 100644
index 00000000..ff0961e7
--- /dev/null
+++ b/accel-pptpd/radius/dict2c.py
@@ -0,0 +1,20 @@
+import sys,re
+
+hdr = file(sys.argv[2],'w')
+
+def process(fname, hdr):
+ for line in file(fname):
+ if line[:-1].strip() == '':
+ continue
+ if line[0] == '#':
+ continue
+ f = re.compile('[$.a-zA-Z0-9\-]+').findall(line)
+ if f[0] == 'ATTRIBUTE' or f[0] == 'VENDOR':
+ hdr.write('#define {0} {1}\n'.format(f[1].replace('-','_').replace('.','_'), f[2]))
+ elif f[0] == 'VALUE':
+ hdr.write('#define {0}_{1} {2}\n'.format(f[1].replace('-','_').replace('.','_'), f[2].replace('-','_'),f[3]))
+ elif f[0] == '$INCLUDE':
+ process(f[1], hdr)
+
+if __name__ == '__main__':
+ process(sys.argv[1], hdr)
diff --git a/accel-pptpd/radius/radius.c b/accel-pptpd/radius/radius.c
index 42b39a5d..fb5a2ca0 100644
--- a/accel-pptpd/radius/radius.c
+++ b/accel-pptpd/radius/radius.c
@@ -13,6 +13,7 @@
#include "ipdb.h"
#include "radius_p.h"
+#include "attr_defs.h"
#include "memdebug.h"
@@ -49,18 +50,23 @@ void rad_proc_attrs(struct rad_req_t *req)
struct rad_attr_t *attr;
list_for_each_entry(attr, &req->reply->attrs, entry) {
- if (!strcmp(attr->attr->name, "Framed-IP-Address")) {
- if (!conf_gw_ip_address)
- log_ppp_warn("radius: gw-ip-address not specified, cann't assign IP address...\n");
- else {
- req->rpd->ipaddr.owner = &ipdb;
- req->rpd->ipaddr.peer_addr = attr->val.ipaddr;
- req->rpd->ipaddr.addr = inet_addr(conf_gw_ip_address);
- }
- } else if (!strcmp(attr->attr->name, "Acct-Interim-Interval"))
- req->rpd->acct_interim_interval = attr->val.integer;
- else if (!strcmp(attr->attr->name, "Session-Timeout"))
- req->rpd->session_timeout.expire_tv.tv_sec = attr->val.integer;
+ switch(attr->attr->id) {
+ case Framed_IP_Address:
+ if (!conf_gw_ip_address)
+ log_ppp_warn("radius: gw-ip-address not specified, cann't assign IP address...\n");
+ else {
+ req->rpd->ipaddr.owner = &ipdb;
+ req->rpd->ipaddr.peer_addr = attr->val.ipaddr;
+ req->rpd->ipaddr.addr = inet_addr(conf_gw_ip_address);
+ }
+ break;
+ case Acct_Interim_Interval:
+ req->rpd->acct_interim_interval = attr->val.integer;
+ break;
+ case Session_Timeout:
+ req->rpd->session_timeout.expire_tv.tv_sec = attr->val.integer;
+ break;
+ }
}
}