From e1603a51f450ad7ee52fe89ef5d78b82845fdcc2 Mon Sep 17 00:00:00 2001 From: Dmitry Kozlov Date: Thu, 28 Oct 2010 01:02:37 +0400 Subject: radius: rewrited Termination-Action attribute handling so it is rfc compliant now --- accel-pptpd/auth/auth_chap_md5.c | 44 +++++++--- accel-pptpd/auth/auth_mschap_v1.c | 43 +++++++--- accel-pptpd/auth/auth_mschap_v2.c | 43 +++++++--- accel-pptpd/auth/auth_pap.c | 6 +- accel-pptpd/ppp/ppp_auth.c | 18 ++++- accel-pptpd/ppp/ppp_auth.h | 6 +- accel-pptpd/radius/auth.c | 165 +++++++++++++++++++++++++++----------- accel-pptpd/radius/packet.c | 58 +++++++++++++- accel-pptpd/radius/radius.c | 53 ++++++++---- accel-pptpd/radius/radius.h | 4 +- accel-pptpd/radius/radius_p.h | 10 ++- accel-pptpd/radius/req.c | 4 +- 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; -- cgit v1.2.3