summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2010-10-28 01:02:37 +0400
committerDmitry Kozlov <xeb@mail.ru>2010-10-28 01:02:37 +0400
commite1603a51f450ad7ee52fe89ef5d78b82845fdcc2 (patch)
tree02759aee4bbb3053bbc9c1be80af33585c356bda
parent04a57e858bed078548c4c8715aa3d35ba81401ae (diff)
downloadaccel-ppp-e1603a51f450ad7ee52fe89ef5d78b82845fdcc2.tar.gz
accel-ppp-e1603a51f450ad7ee52fe89ef5d78b82845fdcc2.zip
radius: rewrited Termination-Action attribute handling so it is rfc compliant now
-rw-r--r--accel-pptpd/auth/auth_chap_md5.c44
-rw-r--r--accel-pptpd/auth/auth_mschap_v1.c43
-rw-r--r--accel-pptpd/auth/auth_mschap_v2.c43
-rw-r--r--accel-pptpd/auth/auth_pap.c6
-rw-r--r--accel-pptpd/ppp/ppp_auth.c18
-rw-r--r--accel-pptpd/ppp/ppp_auth.h6
-rw-r--r--accel-pptpd/radius/auth.c165
-rw-r--r--accel-pptpd/radius/packet.c58
-rw-r--r--accel-pptpd/radius/radius.c53
-rw-r--r--accel-pptpd/radius/radius.h4
-rw-r--r--accel-pptpd/radius/radius_p.h10
-rw-r--r--accel-pptpd/radius/req.c4
12 files changed, 339 insertions, 115 deletions
diff --git a/accel-pptpd/auth/auth_chap_md5.c b/accel-pptpd/auth/auth_chap_md5.c
index a29cedb0..89124105 100644
--- a/accel-pptpd/auth/auth_chap_md5.c
+++ b/accel-pptpd/auth/auth_chap_md5.c
@@ -81,8 +81,8 @@ struct chap_auth_data_t
static void chap_send_challenge(struct chap_auth_data_t *ad);
static void chap_recv(struct ppp_handler_t *h);
-static void chap_timeout(struct triton_timer_t *t);
-static void chap_restart(struct triton_timer_t *t);
+static void chap_timeout_timer(struct triton_timer_t *t);
+static void chap_restart_timer(struct triton_timer_t *t);
static void print_buf(const uint8_t *buf, int size)
{
@@ -112,6 +112,12 @@ static void auth_data_free(struct ppp_t *ppp, struct auth_data_t *auth)
{
struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth);
+ if (d->timeout.tpd)
+ triton_timer_del(&d->timeout);
+
+ if (d->interval.tpd)
+ triton_timer_del(&d->interval);
+
_free(d);
}
@@ -121,9 +127,9 @@ static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth)
d->h.proto = PPP_CHAP;
d->h.recv = chap_recv;
- d->timeout.expire = chap_timeout;
+ d->timeout.expire = chap_timeout_timer;
d->timeout.period = conf_timeout * 1000;
- d->interval.expire = chap_restart;
+ d->interval.expire = chap_restart_timer;
d->interval.period = conf_interval * 1000;
ppp_register_chan_handler(ppp, &d->h);
@@ -148,7 +154,7 @@ static int chap_finish(struct ppp_t *ppp, struct auth_data_t *auth)
return 0;
}
-static void chap_timeout(struct triton_timer_t *t)
+static void chap_timeout_timer(struct triton_timer_t *t)
{
struct chap_auth_data_t *d = container_of(t, typeof(*d), timeout);
@@ -159,14 +165,14 @@ static void chap_timeout(struct triton_timer_t *t)
if (d->started)
ppp_terminate(d->ppp, TERM_USER_ERROR, 0);
else
- auth_failed(d->ppp);
+ ppp_auth_failed(d->ppp);
} else {
--d->id;
chap_send_challenge(d);
}
}
-static void chap_restart(struct triton_timer_t *t)
+static void chap_restart_timer(struct triton_timer_t *t)
{
struct chap_auth_data_t *d = container_of(t, typeof(*d), interval);
@@ -305,7 +311,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
if (ad->started)
ppp_terminate(ad->ppp, TERM_USER_ERROR, 0);
else
- auth_failed(ad->ppp);
+ ppp_auth_failed(ad->ppp);
}else
{
chap_send_success(ad);
@@ -313,8 +319,9 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
ad->started = 1;
if (conf_interval)
triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0);
- auth_successed(ad->ppp, name);
- }
+ ppp_auth_successed(ad->ppp, name);
+ } else
+ _free(name);
}
_free(passwd);
} else if (r == PWDB_DENIED) {
@@ -323,15 +330,16 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
if (ad->started)
ppp_terminate(ad->ppp, TERM_USER_ERROR, 0);
else
- auth_failed(ad->ppp);
+ ppp_auth_failed(ad->ppp);
} else {
chap_send_success(ad);
if (!ad->started) {
ad->started = 1;
if (conf_interval)
triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0);
- auth_successed(ad->ppp, name);
- }
+ ppp_auth_successed(ad->ppp, name);
+ } else
+ _free(name);
}
}
@@ -340,6 +348,15 @@ static int chap_check(uint8_t *ptr)
return *ptr == CHAP_MD5;
}
+static int chap_restart(struct ppp_t *ppp, struct auth_data_t *auth)
+{
+ struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth);
+
+ chap_send_challenge(d);
+
+ return 0;
+}
+
static struct ppp_auth_handler_t chap=
{
.name = "CHAP-md5",
@@ -350,6 +367,7 @@ static struct ppp_auth_handler_t chap=
.start = chap_start,
.finish = chap_finish,
.check = chap_check,
+ .restart = chap_restart,
};
static void chap_recv(struct ppp_handler_t *h)
diff --git a/accel-pptpd/auth/auth_mschap_v1.c b/accel-pptpd/auth/auth_mschap_v1.c
index d74f8e92..8208ef22 100644
--- a/accel-pptpd/auth/auth_mschap_v1.c
+++ b/accel-pptpd/auth/auth_mschap_v1.c
@@ -95,8 +95,8 @@ struct chap_auth_data_t
static void chap_send_challenge(struct chap_auth_data_t *ad);
static void chap_recv(struct ppp_handler_t *h);
static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *res, const char *name);
-static void chap_timeout(struct triton_timer_t *t);
-static void chap_restart(struct triton_timer_t *t);
+static void chap_timeout_timer(struct triton_timer_t *t);
+static void chap_restart_timer(struct triton_timer_t *t);
static void print_buf(const uint8_t *buf,int size)
{
@@ -126,6 +126,12 @@ static void auth_data_free(struct ppp_t *ppp, struct auth_data_t *auth)
{
struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth);
+ if (d->timeout.tpd)
+ triton_timer_del(&d->timeout);
+
+ if (d->interval.tpd)
+ triton_timer_del(&d->interval);
+
_free(d);
}
@@ -135,9 +141,9 @@ static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth)
d->h.proto = PPP_CHAP;
d->h.recv = chap_recv;
- d->timeout.expire = chap_timeout;
+ d->timeout.expire = chap_timeout_timer;
d->timeout.period = conf_timeout * 1000;
- d->interval.expire = chap_restart;
+ d->interval.expire = chap_restart_timer;
d->interval.period = conf_interval * 1000;
ppp_register_chan_handler(ppp, &d->h);
@@ -162,7 +168,7 @@ static int chap_finish(struct ppp_t *ppp, struct auth_data_t *auth)
return 0;
}
-static void chap_timeout(struct triton_timer_t *t)
+static void chap_timeout_timer(struct triton_timer_t *t)
{
struct chap_auth_data_t *d = container_of(t, typeof(*d), timeout);
@@ -173,14 +179,14 @@ static void chap_timeout(struct triton_timer_t *t)
if (d->started)
ppp_terminate(d->ppp, TERM_USER_ERROR, 0);
else
- auth_failed(d->ppp);
+ ppp_auth_failed(d->ppp);
} else {
--d->id;
chap_send_challenge(d);
}
}
-static void chap_restart(struct triton_timer_t *t)
+static void chap_restart_timer(struct triton_timer_t *t)
{
struct chap_auth_data_t *d = container_of(t, typeof(*d), interval);
@@ -283,7 +289,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
if (ad->started)
ppp_terminate(ad->ppp, TERM_USER_ERROR, 0);
else
- auth_failed(ad->ppp);
+ ppp_auth_failed(ad->ppp);
}
if (msg->val_size != RESPONSE_VALUE_SIZE) {
@@ -292,7 +298,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
if (ad->started)
ppp_terminate(ad->ppp, TERM_AUTH_ERROR, 0);
else
- auth_failed(ad->ppp);
+ ppp_auth_failed(ad->ppp);
}
name = _strndup(msg->name, ntohs(msg->hdr.len) - sizeof(*msg) + 2);
@@ -301,7 +307,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
if (ad->started)
ppp_terminate(ad->ppp, TERM_NAS_ERROR, 0);
else
- auth_failed(ad->ppp);
+ ppp_auth_failed(ad->ppp);
return;
}
@@ -315,7 +321,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
if (ad->started)
ppp_terminate(ad->ppp, TERM_AUTH_ERROR, 0);
else
- auth_failed(ad->ppp);
+ ppp_auth_failed(ad->ppp);
_free(name);
} else {
chap_send_success(ad);
@@ -323,8 +329,9 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
ad->started = 1;
if (conf_interval)
triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0);
- auth_successed(ad->ppp, name);
- }
+ ppp_auth_successed(ad->ppp, name);
+ } else
+ _free(name);
}
}
@@ -400,6 +407,15 @@ static int chap_check(uint8_t *ptr)
return *ptr == MSCHAP_V1;
}
+static int chap_restart(struct ppp_t *ppp, struct auth_data_t *auth)
+{
+ struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth);
+
+ chap_send_challenge(d);
+
+ return 0;
+}
+
static struct ppp_auth_handler_t chap = {
.name = "MSCHAP-v1",
.init = auth_data_init,
@@ -409,6 +425,7 @@ static struct ppp_auth_handler_t chap = {
.start = chap_start,
.finish = chap_finish,
.check = chap_check,
+ .restart = chap_restart,
};
static void chap_recv(struct ppp_handler_t *h)
diff --git a/accel-pptpd/auth/auth_mschap_v2.c b/accel-pptpd/auth/auth_mschap_v2.c
index 8e4a7c08..08cdde93 100644
--- a/accel-pptpd/auth/auth_mschap_v2.c
+++ b/accel-pptpd/auth/auth_mschap_v2.c
@@ -109,8 +109,8 @@ struct chap_auth_data_t
static void chap_send_challenge(struct chap_auth_data_t *ad);
static void chap_recv(struct ppp_handler_t *h);
static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *msg, const char *name);
-static void chap_timeout(struct triton_timer_t *t);
-static void chap_restart(struct triton_timer_t *t);
+static void chap_timeout_timer(struct triton_timer_t *t);
+static void chap_restart_timer(struct triton_timer_t *t);
static void print_buf(const uint8_t *buf, int size)
{
@@ -141,6 +141,12 @@ static void auth_data_free(struct ppp_t *ppp, struct auth_data_t *auth)
{
struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth);
+ if (d->timeout.tpd)
+ triton_timer_del(&d->timeout);
+
+ if (d->interval.tpd)
+ triton_timer_del(&d->interval);
+
_free(d);
}
@@ -150,9 +156,9 @@ static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth)
d->h.proto = PPP_CHAP;
d->h.recv = chap_recv;
- d->timeout.expire = chap_timeout;
+ d->timeout.expire = chap_timeout_timer;
d->timeout.period = conf_timeout * 1000;
- d->interval.expire = chap_restart;
+ d->interval.expire = chap_restart_timer;
d->interval.period = conf_interval * 1000;
ppp_register_chan_handler(ppp, &d->h);
@@ -177,7 +183,7 @@ static int chap_finish(struct ppp_t *ppp, struct auth_data_t *auth)
return 0;
}
-static void chap_timeout(struct triton_timer_t *t)
+static void chap_timeout_timer(struct triton_timer_t *t)
{
struct chap_auth_data_t *d = container_of(t, typeof(*d), timeout);
@@ -188,14 +194,14 @@ static void chap_timeout(struct triton_timer_t *t)
if (d->started)
ppp_terminate(d->ppp, TERM_USER_ERROR, 0);
else
- auth_failed(d->ppp);
+ ppp_auth_failed(d->ppp);
} else {
--d->id;
chap_send_challenge(d);
}
}
-static void chap_restart(struct triton_timer_t *t)
+static void chap_restart_timer(struct triton_timer_t *t)
{
struct chap_auth_data_t *d = container_of(t, typeof(*d), interval);
@@ -358,7 +364,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
if (ad->started)
ppp_terminate(ad->ppp, TERM_USER_ERROR, 0);
else
- auth_failed(ad->ppp);
+ ppp_auth_failed(ad->ppp);
}
if (msg->val_size != RESPONSE_VALUE_SIZE) {
@@ -367,7 +373,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
if (ad->started)
ppp_terminate(ad->ppp, TERM_USER_ERROR, 0);
else
- auth_failed(ad->ppp);
+ ppp_auth_failed(ad->ppp);
}
name = _strndup(msg->name, ntohs(msg->hdr.len) - sizeof(*msg) + 2);
@@ -376,7 +382,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
if (ad->started)
ppp_terminate(ad->ppp, TERM_NAS_ERROR, 0);
else
- auth_failed(ad->ppp);
+ ppp_auth_failed(ad->ppp);
return;
}
@@ -395,7 +401,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
if (ad->started)
ppp_terminate(ad->ppp, TERM_AUTH_ERROR, 0);
else
- auth_failed(ad->ppp);
+ ppp_auth_failed(ad->ppp);
_free(name);
} else {
chap_send_success(ad, msg, authenticator);
@@ -403,8 +409,9 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
ad->started = 1;
if (conf_interval)
triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0);
- auth_successed(ad->ppp, name);
- }
+ ppp_auth_successed(ad->ppp, name);
+ } else
+ _free(name);
}
}
@@ -489,6 +496,15 @@ static int chap_check(uint8_t *ptr)
return *ptr == MSCHAP_V2;
}
+static int chap_restart(struct ppp_t *ppp, struct auth_data_t *auth)
+{
+ struct chap_auth_data_t *d = container_of(auth, typeof(*d), auth);
+
+ chap_send_challenge(d);
+
+ return 0;
+}
+
static struct ppp_auth_handler_t chap=
{
.name = "MSCHAP-v2",
@@ -499,6 +515,7 @@ static struct ppp_auth_handler_t chap=
.start = chap_start,
.finish = chap_finish,
.check = chap_check,
+ .restart = chap_restart,
};
static void chap_recv(struct ppp_handler_t *h)
diff --git a/accel-pptpd/auth/auth_pap.c b/accel-pptpd/auth/auth_pap.c
index 814d02db..96640a1a 100644
--- a/accel-pptpd/auth/auth_pap.c
+++ b/accel-pptpd/auth/auth_pap.c
@@ -118,7 +118,7 @@ static void pap_timeout(struct triton_timer_t *t)
if (conf_ppp_verbose)
log_ppp_warn("pap: timeout\n");
- auth_failed(d->ppp);
+ ppp_auth_failed(d->ppp);
}
static int lcp_send_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t *ptr)
@@ -213,14 +213,14 @@ static int pap_recv_req(struct pap_auth_data_t *p, struct pap_hdr_t *hdr)
if (p->started)
ppp_terminate(p->ppp, TERM_AUTH_ERROR, 0);
else
- auth_failed(p->ppp);
+ ppp_auth_failed(p->ppp);
ret=-1;
_free(peer_id);
} else {
pap_send_ack(p, hdr->id);
if (!p->started) {
p->started = 1;
- auth_successed(p->ppp, peer_id);
+ ppp_auth_successed(p->ppp, peer_id);
}
ret = 0;
}
diff --git a/accel-pptpd/ppp/ppp_auth.c b/accel-pptpd/ppp/ppp_auth.c
index 959dc2f9..c9934147 100644
--- a/accel-pptpd/ppp/ppp_auth.c
+++ b/accel-pptpd/ppp/ppp_auth.c
@@ -298,7 +298,7 @@ static void auth_layer_free(struct ppp_layer_data_t *ld)
_free(ad);
}
-void __export auth_successed(struct ppp_t *ppp, char *username)
+void __export ppp_auth_successed(struct ppp_t *ppp, char *username)
{
struct auth_layer_data_t *ad = container_of(ppp_find_layer_data(ppp, &auth_layer), typeof(*ad), ld);
log_ppp_debug("auth_layer_started\n");
@@ -307,7 +307,7 @@ void __export auth_successed(struct ppp_t *ppp, char *username)
triton_event_fire(EV_PPP_AUTHORIZED, ppp);
}
-void __export auth_failed(struct ppp_t *ppp)
+void __export ppp_auth_failed(struct ppp_t *ppp)
{
ppp_terminate(ppp, TERM_AUTH_ERROR, 0);
}
@@ -318,6 +318,20 @@ int __export ppp_auth_register_handler(struct ppp_auth_handler_t *h)
return 0;
}
+int __export ppp_auth_restart(struct ppp_t *ppp)
+{
+ struct auth_layer_data_t *ad = container_of(ppp_find_layer_data(ppp, &auth_layer), typeof(*ad), ld);
+ log_ppp_debug("ppp_auth_restart\n");
+
+ if (!ad->auth_opt.auth->h->restart)
+ return -1;
+
+ if (ad->auth_opt.auth->h->restart(ppp, ad->auth_opt.auth))
+ return -1;
+
+ return 0;
+}
+
static void __init ppp_auth_init()
{
ppp_register_layer("auth", &auth_layer);
diff --git a/accel-pptpd/ppp/ppp_auth.h b/accel-pptpd/ppp/ppp_auth.h
index fbd2017c..ea12d9c6 100644
--- a/accel-pptpd/ppp/ppp_auth.h
+++ b/accel-pptpd/ppp/ppp_auth.h
@@ -24,12 +24,14 @@ struct ppp_auth_handler_t
int (*finish)(struct ppp_t*, struct auth_data_t*);
void (*free)(struct ppp_t*,struct auth_data_t*);
int (*check)(uint8_t *);
+ int (*restart)(struct ppp_t*,struct auth_data_t*);
};
int ppp_auth_register_handler(struct ppp_auth_handler_t*);
-void auth_successed(struct ppp_t *ppp, char *username);
-void auth_failed(struct ppp_t *ppp);
+void ppp_auth_successed(struct ppp_t *ppp, char *username);
+void ppp_auth_failed(struct ppp_t *ppp);
+int ppp_auth_restart(struct ppp_t *ppp);
#endif
diff --git a/accel-pptpd/radius/auth.c b/accel-pptpd/radius/auth.c
index 0667075e..352da70c 100644
--- a/accel-pptpd/radius/auth.c
+++ b/accel-pptpd/radius/auth.c
@@ -210,7 +210,6 @@ out:
int rad_auth_chap_md5(struct radius_pd_t *rpd, const char *username, va_list args)
{
- struct rad_req_t *req;
int r = PWDB_DENIED;
uint8_t chap_password[17];
@@ -222,32 +221,60 @@ int rad_auth_chap_md5(struct radius_pd_t *rpd, const char *username, va_list arg
chap_password[0] = id;
memcpy(chap_password + 1, response, 16);
- req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
- if (!req)
- return PWDB_DENIED;
+ if (!rpd->auth_req) {
+ rpd->auth_req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
+ if (!rpd->auth_req)
+ return PWDB_DENIED;
- if (challenge_len == 16)
- memcpy(req->RA, challenge, 16);
- else {
- if (rad_packet_add_octets(req->pack, "CHAP-Challenge", challenge, challenge_len))
+ if (challenge_len == 16)
+ memcpy(rpd->auth_req->RA, challenge, 16);
+ else {
+ if (rad_packet_add_octets(rpd->auth_req->pack, "CHAP-Challenge", challenge, challenge_len))
goto out;
- }
+ }
- if (rad_packet_add_octets(req->pack, "CHAP-Password", chap_password, 17))
- goto out;
+ if (rad_packet_add_octets(rpd->auth_req->pack, "CHAP-Password", chap_password, 17))
+ goto out;
+ } else {
+ if (challenge_len == 16)
+ memcpy(rpd->auth_req->RA, challenge, 16);
+ else {
+ if (rad_packet_change_octets(rpd->auth_req->pack, "CHAP-Challenge", challenge, challenge_len))
+ goto out;
+ }
- r = rad_auth_send(req);
+ if (rad_packet_change_octets(rpd->auth_req->pack, "CHAP-Password", chap_password, 17))
+ goto out;
+
+ if (rpd->attr_state) {
+ if (rad_packet_find_attr(rpd->auth_req->pack, "State")) {
+ if (rad_packet_change_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len))
+ goto out;
+ } else {
+ if (rad_packet_add_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len))
+ goto out;
+ }
+ }
+
+ if (rad_packet_build(rpd->auth_req->pack, rpd->auth_req->RA))
+ return -1;
+ }
+
+ r = rad_auth_send(rpd->auth_req);
if (r == PWDB_SUCCESS) {
struct ev_radius_t ev = {
.ppp = rpd->ppp,
- .request = req->pack,
- .reply = req->reply,
+ .request = rpd->auth_req->pack,
+ .reply = rpd->auth_req->reply,
};
triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev);
+ rpd->auth_req->pack->id++;
}
+ return r;
out:
- rad_req_free(req);
+ rad_req_free(rpd->auth_req);
+ rpd->auth_req = NULL;
return r;
}
@@ -297,7 +324,6 @@ static void setup_mppe(struct rad_req_t *req, const uint8_t *challenge)
int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list args)
{
int r = PWDB_DENIED;
- struct rad_req_t *req;
uint8_t response[50];
int id = va_arg(args, int);
@@ -307,34 +333,58 @@ int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list ar
const uint8_t *nt_response = va_arg(args, const uint8_t *);
int flags = va_arg(args, int);
- req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
- if (!req)
- return PWDB_DENIED;
-
response[0] = id;
response[1] = flags;
memcpy(response + 2, lm_response, 24);
memcpy(response + 2 + 24, nt_response, 24);
- if (rad_packet_add_vendor_octets(req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, challenge_len))
- goto out;
-
- if (rad_packet_add_vendor_octets(req->pack, "Microsoft", "MS-CHAP-Response", response, sizeof(response)))
- goto out;
+ if (!rpd->auth_req) {
+ rpd->auth_req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
+ if (!rpd->auth_req)
+ return PWDB_DENIED;
+
+ if (rad_packet_add_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, challenge_len))
+ goto out;
+
+ if (rad_packet_add_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Response", response, sizeof(response)))
+ goto out;
+ } else {
+ if (rad_packet_change_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, challenge_len))
+ goto out;
+
+ if (rad_packet_change_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Response", response, sizeof(response)))
+ goto out;
- r = rad_auth_send(req);
+ if (rpd->attr_state) {
+ if (rad_packet_find_attr(rpd->auth_req->pack, "State")) {
+ if (rad_packet_change_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len))
+ goto out;
+ } else {
+ if (rad_packet_add_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len))
+ goto out;
+ }
+ }
+
+ if (rad_packet_build(rpd->auth_req->pack, rpd->auth_req->RA))
+ return -1;
+ }
+
+ r = rad_auth_send(rpd->auth_req);
if (r == PWDB_SUCCESS) {
struct ev_radius_t ev = {
.ppp = rpd->ppp,
- .request = req->pack,
- .reply = req->reply,
+ .request = rpd->auth_req->pack,
+ .reply = rpd->auth_req->reply,
};
triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev);
- setup_mppe(req, challenge);
+ setup_mppe(rpd->auth_req, challenge);
+ rpd->auth_req->pack->id++;
}
+ return r;
out:
- rad_req_free(req);
+ rad_req_free(rpd->auth_req);
+ rpd->auth_req = NULL;
return r;
}
@@ -342,7 +392,6 @@ out:
int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list args)
{
int r = PWDB_DENIED;
- struct rad_req_t *req;
struct rad_attr_t *ra;
uint8_t mschap_response[50];
@@ -354,25 +403,46 @@ int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list ar
int flags = va_arg(args, int);
uint8_t *authenticator = va_arg(args, uint8_t *);
- req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
- if (!req)
- return PWDB_DENIED;
-
mschap_response[0] = id;
mschap_response[1] = flags;
memcpy(mschap_response + 2, peer_challenge, 16);
memcpy(mschap_response + 2 + 16, reserved, 8);
memcpy(mschap_response + 2 + 16 + 8, response, 24);
- if (rad_packet_add_vendor_octets(req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, 16))
- goto out;
-
- if (rad_packet_add_vendor_octets(req->pack, "Microsoft", "MS-CHAP2-Response", mschap_response, sizeof(mschap_response)))
- goto out;
+ if (!rpd->auth_req) {
+ rpd->auth_req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
+ if (!rpd->auth_req)
+ return PWDB_DENIED;
- r = rad_auth_send(req);
+ if (rad_packet_add_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, 16))
+ goto out;
+
+ if (rad_packet_add_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP2-Response", mschap_response, sizeof(mschap_response)))
+ goto out;
+ } else {
+ if (rad_packet_change_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, 16))
+ goto out;
+
+ if (rad_packet_change_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP2-Response", mschap_response, sizeof(mschap_response)))
+ goto out;
+
+ if (rpd->attr_state) {
+ if (rad_packet_find_attr(rpd->auth_req->pack, "State")) {
+ if (rad_packet_change_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len))
+ goto out;
+ } else {
+ if (rad_packet_add_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len))
+ goto out;
+ }
+ }
+
+ if (rad_packet_build(rpd->auth_req->pack, rpd->auth_req->RA))
+ return -1;
+ }
+
+ r = rad_auth_send(rpd->auth_req);
if (r == PWDB_SUCCESS) {
- ra = rad_packet_find_vendor_attr(req->reply, "Microsoft", "MS-CHAP2-Success");
+ ra = rad_packet_find_vendor_attr(rpd->auth_req->reply, "Microsoft", "MS-CHAP2-Success");
if (!ra) {
log_error("radius:auth:mschap-v2: 'MS-CHAP-Success' not found in radius response\n");
r = PWDB_DENIED;
@@ -382,15 +452,18 @@ int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list ar
if (r == PWDB_SUCCESS) {
struct ev_radius_t ev = {
.ppp = rpd->ppp,
- .request = req->pack,
- .reply = req->reply,
+ .request = rpd->auth_req->pack,
+ .reply = rpd->auth_req->reply,
};
triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev);
- setup_mppe(req, NULL);
+ setup_mppe(rpd->auth_req, NULL);
+ rpd->auth_req->pack->id++;
}
+ return r;
out:
- rad_req_free(req);
+ rad_req_free(rpd->auth_req);
+ rpd->auth_req = NULL;
return r;
}
diff --git a/accel-pptpd/radius/packet.c b/accel-pptpd/radius/packet.c
index 543e7849..44bfc413 100644
--- a/accel-pptpd/radius/packet.c
+++ b/accel-pptpd/radius/packet.c
@@ -363,7 +363,7 @@ int rad_packet_change_int(struct rad_packet_t *pack, const char *name, int val)
return 0;
}
-int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, uint8_t *val, int len)
+int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, const uint8_t *val, int len)
{
struct rad_attr_t *ra;
struct rad_dict_attr_t *attr;
@@ -396,6 +396,35 @@ int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, uint8_t *
return 0;
}
+
+int rad_packet_change_octets(struct rad_packet_t *pack, const char *name, const uint8_t *val, int len)
+{
+ struct rad_attr_t *ra;
+
+ ra = rad_packet_find_attr(pack, name);
+ if (!ra)
+ return -1;
+
+ if (ra->len != len) {
+ if (pack->len - ra->len + len >= REQ_LENGTH_MAX)
+ return -1;
+
+ ra->val.octets = _realloc(ra->val.octets, len);
+ if (!ra->val.octets) {
+ log_emerg("radius: out of memory\n");
+ return -1;
+ }
+
+ pack->len += len - ra->len;
+ ra->len = len;
+ }
+
+ memcpy(ra->val.octets, val, len);
+
+ return 0;
+}
+
+
int rad_packet_add_str(struct rad_packet_t *pack, const char *name, const char *val, int len)
{
struct rad_attr_t *ra;
@@ -589,6 +618,33 @@ int rad_packet_add_vendor_octets(struct rad_packet_t *pack, const char *vendor_n
return 0;
}
+int rad_packet_change_vendor_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len)
+{
+ struct rad_attr_t *ra;
+
+ ra = rad_packet_find_vendor_attr(pack, vendor_name, name);
+ if (!ra)
+ return -1;
+
+ if (ra->len != len) {
+ if (pack->len - ra->len + len >= REQ_LENGTH_MAX)
+ return -1;
+
+ ra->val.octets = _realloc(ra->val.octets, len);
+ if (!ra->val.octets) {
+ log_emerg("radius: out of memory\n");
+ return -1;
+ }
+
+ pack->len += len - ra->len;
+ ra->len = len;
+ }
+
+ memcpy(ra->val.octets, val, len);
+
+ return 0;
+}
+
struct rad_attr_t *rad_packet_find_vendor_attr(struct rad_packet_t *pack, const char *vendor_name, const char *name)
{
struct rad_attr_t *ra;
diff --git a/accel-pptpd/radius/radius.c b/accel-pptpd/radius/radius.c
index 9f50dede..a07df9a6 100644
--- a/accel-pptpd/radius/radius.c
+++ b/accel-pptpd/radius/radius.c
@@ -11,6 +11,7 @@
#include "ppp.h"
#include "pwdb.h"
#include "ipdb.h"
+#include "ppp_auth.h"
#include "radius_p.h"
#include "attr_defs.h"
@@ -67,20 +68,27 @@ int rad_proc_attrs(struct rad_req_t *req)
req->rpd->acct_interim_interval = attr->val.integer;
break;
case Session_Timeout:
- req->rpd->session_timeout.expire_tv.tv_sec = attr->val.integer;
+ req->rpd->session_timeout.period = attr->val.integer * 1000;
break;
case Class:
- req->rpd->class = _malloc(attr->len);
- if (!req->rpd->class) {
- log_emerg("radius: out of memory\n");
- return -1;
- }
- memcpy(req->rpd->class, attr->val.octets, attr->len);
- req->rpd->class_len = attr->len;
+ if (!req->rpd->attr_class)
+ req->rpd->attr_class = _malloc(attr->len);
+ else if (req->rpd->attr_class_len != attr->len)
+ req->rpd->attr_class = _realloc(req->rpd->attr_class, attr->len);
+ memcpy(req->rpd->attr_class, attr->val.octets, attr->len);
+ req->rpd->attr_class_len = attr->len;
+ break;
+ case State:
+ if (!req->rpd->attr_state)
+ req->rpd->attr_state = _malloc(attr->len);
+ else if (req->rpd->attr_state_len != attr->len)
+ req->rpd->attr_state = _realloc(req->rpd->attr_state, attr->len);
+ memcpy(req->rpd->attr_state, attr->val.octets, attr->len);
+ req->rpd->attr_state_len = attr->len;
break;
case Termination_Action:
- if (attr->val.integer != 0)
- res = -1;
+ req->rpd->termination_action = attr->val.integer;
+ break;
}
}
@@ -133,9 +141,16 @@ static struct ipdb_item_t *get_ip(struct ppp_t *ppp)
static void session_timeout(struct triton_timer_t *t)
{
struct radius_pd_t *rpd = container_of(t, typeof(*rpd), session_timeout);
-
log_ppp_msg("radius: session timed out\n");
- ppp_terminate(rpd->ppp, TERM_SESSION_TIMEOUT, 0);
+
+ if (rpd->ppp->stop_time)
+ return;
+
+ if (rpd->termination_action == Termination_Action_RADIUS_Request) {
+ if (ppp_auth_restart(rpd->ppp))
+ ppp_terminate(rpd->ppp, TERM_SESSION_TIMEOUT, 0);
+ } else
+ ppp_terminate(rpd->ppp, TERM_SESSION_TIMEOUT, 0);
}
static void ppp_starting(struct ppp_t *ppp)
@@ -162,7 +177,7 @@ static void ppp_acct_start(struct ppp_t *ppp)
return;
}
- if (rpd->session_timeout.expire_tv.tv_sec) {
+ if (rpd->session_timeout.period) {
rpd->session_timeout.expire = session_timeout;
triton_timer_add(ppp->ctrl->ctx, &rpd->session_timeout, 0);
}
@@ -183,6 +198,9 @@ static void ppp_finished(struct ppp_t *ppp)
pthread_mutex_unlock(&rpd->lock);
pthread_rwlock_unlock(&sessions_lock);
+ if (rpd->auth_req)
+ rad_req_free(rpd->auth_req);
+
if (rpd->acct_req)
rad_req_free(rpd->acct_req);
@@ -192,9 +210,12 @@ static void ppp_finished(struct ppp_t *ppp)
if (rpd->session_timeout.tpd)
triton_timer_del(&rpd->session_timeout);
- if (rpd->class)
- _free(rpd->class);
-
+ if (rpd->attr_class)
+ _free(rpd->attr_class);
+
+ if (rpd->attr_state)
+ _free(rpd->attr_state);
+
list_del(&rpd->pd.entry);
mempool_free(rpd);
diff --git a/accel-pptpd/radius/radius.h b/accel-pptpd/radius/radius.h
index e202e264..95fa82b9 100644
--- a/accel-pptpd/radius/radius.h
+++ b/accel-pptpd/radius/radius.h
@@ -96,11 +96,13 @@ struct rad_attr_t *rad_packet_find_attr(struct rad_packet_t *pack, const char *n
int rad_packet_add_int(struct rad_packet_t *pack, const char *name, int val);
int rad_packet_add_val(struct rad_packet_t *pack, const char *name, const char *val);
int rad_packet_add_str(struct rad_packet_t *pack, const char *name, const char *val, int len);
-int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, uint8_t *val, int len);
+int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, const uint8_t *val, int len);
int rad_packet_change_int(struct rad_packet_t *pack, const char *name, int val);
int rad_packet_change_val(struct rad_packet_t *pack, const char *name, const char *val);
+int rad_packet_change_octets(struct rad_packet_t *pack, const char *name, const uint8_t *val, int len);
int rad_packet_add_ipaddr(struct rad_packet_t *pack, const char *name, in_addr_t ipaddr);
int rad_packet_add_vendor_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len);
+int rad_packet_change_vendor_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len);
struct rad_attr_t *rad_packet_find_vendor_attr(struct rad_packet_t *pack, const char *vendor_name, const char *name);
#endif
diff --git a/accel-pptpd/radius/radius_p.h b/accel-pptpd/radius/radius_p.h
index af7af06e..a24d6877 100644
--- a/accel-pptpd/radius/radius_p.h
+++ b/accel-pptpd/radius/radius_p.h
@@ -16,6 +16,7 @@ struct radius_pd_t
struct ppp_t *ppp;
pthread_mutex_t lock;
+ struct rad_req_t *auth_req;
struct rad_req_t *acct_req;
struct triton_timer_t acct_interim_timer;
uint32_t acct_input_octets;
@@ -31,9 +32,12 @@ struct radius_pd_t
struct ipdb_item_t ipaddr;
int acct_interim_interval;
int acct_delay_time;
-
- uint8_t *class;
- int class_len;
+
+ uint8_t *attr_class;
+ int attr_class_len;
+ uint8_t *attr_state;
+ int attr_state_len;
+ int termination_action;
};
struct rad_req_t
diff --git a/accel-pptpd/radius/req.c b/accel-pptpd/radius/req.c
index a1156c3c..f92d1224 100644
--- a/accel-pptpd/radius/req.c
+++ b/accel-pptpd/radius/req.c
@@ -70,8 +70,8 @@ struct rad_req_t *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *u
if (rpd->ppp->ctrl->called_station_id)
if (rad_packet_add_str(req->pack, "Called-Station-Id", rpd->ppp->ctrl->called_station_id, strlen(rpd->ppp->ctrl->called_station_id)))
goto out_err;
- if (rpd->class)
- if (rad_packet_add_octets(req->pack, "Class", rpd->class, rpd->class_len))
+ if (rpd->attr_class)
+ if (rad_packet_add_octets(req->pack, "Class", rpd->attr_class, rpd->attr_class_len))
goto out_err;
return req;