diff options
Diffstat (limited to 'accel-pptpd/radius/dm_coa.c')
-rw-r--r-- | accel-pptpd/radius/dm_coa.c | 295 |
1 files changed, 0 insertions, 295 deletions
diff --git a/accel-pptpd/radius/dm_coa.c b/accel-pptpd/radius/dm_coa.c deleted file mode 100644 index 366bb41..0000000 --- a/accel-pptpd/radius/dm_coa.c +++ /dev/null @@ -1,295 +0,0 @@ -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> -#include <time.h> -#include <arpa/inet.h> -#include <netinet/in.h> -#include <sys/socket.h> -#include <openssl/md5.h> - -#include "triton.h" -#include "events.h" -#include "log.h" - -#include "radius_p.h" - -#include "memdebug.h" - -#define PD_COA_PORT 3799 - -struct dm_coa_serv_t -{ - struct triton_context_t ctx; - struct triton_md_handler_t hnd; -}; - -static struct dm_coa_serv_t serv; - -static int dm_coa_check_RA(struct rad_packet_t *pack, const char *secret) -{ - uint8_t RA[16]; - MD5_CTX ctx; - - memset(RA, 0, 16); - - MD5_Init(&ctx); - MD5_Update(&ctx, pack->buf, 4); - MD5_Update(&ctx, RA, 16); - MD5_Update(&ctx, pack->buf + 20, pack->len - 20); - MD5_Update(&ctx, secret, strlen(secret)); - MD5_Final(RA, &ctx); - - return memcmp(RA, pack->buf + 4, 16); -} - -static void dm_coa_set_RA(struct rad_packet_t *pack, const char *secret) -{ - MD5_CTX ctx; - - MD5_Init(&ctx); - MD5_Update(&ctx, pack->buf, pack->len); - MD5_Update(&ctx, secret, strlen(secret)); - MD5_Final(pack->buf + 4, &ctx); -} - -static int dm_coa_send_ack(int fd, struct rad_packet_t *req, struct sockaddr_in *addr) -{ - struct rad_packet_t *reply; - uint8_t RA[16]; - - memcpy(RA, req->buf + 4, sizeof(RA)); - - reply = rad_packet_alloc(req->code == CODE_COA_REQUEST ? CODE_COA_ACK : CODE_DISCONNECT_ACK); - if (!reply) - return -1; - - reply->id = req->id; - - if (rad_packet_build(reply, RA)) { - rad_packet_free(reply); - return -1; - } - - dm_coa_set_RA(reply, conf_dm_coa_secret); - - if (conf_verbose) { - log_ppp_info2("send "); - rad_packet_print(reply, log_ppp_info2); - } - - rad_packet_send(reply, fd, addr); - - rad_packet_free(reply); - - return 0; -} - -static int dm_coa_send_nak(int fd, struct rad_packet_t *req, struct sockaddr_in *addr, int err_code) -{ - struct rad_packet_t *reply; - uint8_t RA[16]; - - memcpy(RA, req->buf + 4, sizeof(RA)); - - reply = rad_packet_alloc(req->code == CODE_COA_REQUEST ? CODE_COA_NAK : CODE_DISCONNECT_NAK); - if (!reply) - return -1; - - reply->id = req->id; - - if (err_code) - rad_packet_add_int(reply, NULL, "Error-Cause", err_code); - - if (rad_packet_build(reply, RA)) { - rad_packet_free(reply); - return -1; - } - - dm_coa_set_RA(reply, conf_dm_coa_secret); - - if (conf_verbose) { - log_ppp_info2("send "); - rad_packet_print(reply, log_ppp_info2); - } - - rad_packet_send(reply, fd, addr); - - rad_packet_free(reply); - - return 0; -} - - -static void disconnect_request(struct radius_pd_t *rpd) -{ - if (conf_verbose) { - log_ppp_info2("recv "); - rad_packet_print(rpd->dm_coa_req, log_ppp_info2); - } - - dm_coa_send_ack(serv.hnd.fd, rpd->dm_coa_req, &rpd->dm_coa_addr); - - rad_packet_free(rpd->dm_coa_req); - - pthread_mutex_lock(&rpd->lock); - rpd->dm_coa_req = NULL; - pthread_mutex_unlock(&rpd->lock); - - ppp_terminate(rpd->ppp, TERM_ADMIN_RESET, 0); -} - -static void coa_request(struct radius_pd_t *rpd) -{ - struct ev_radius_t ev = { - .ppp = rpd->ppp, - .request = rpd->dm_coa_req, - }; - - if (conf_verbose) { - log_ppp_info2("recv "); - rad_packet_print(rpd->dm_coa_req, log_ppp_info2); - } - - triton_event_fire(EV_RADIUS_COA, &ev); - - if (ev.res) - dm_coa_send_nak(serv.hnd.fd, rpd->dm_coa_req, &rpd->dm_coa_addr, 0); - else - dm_coa_send_ack(serv.hnd.fd, rpd->dm_coa_req, &rpd->dm_coa_addr); - - rad_packet_free(rpd->dm_coa_req); - - pthread_mutex_lock(&rpd->lock); - rpd->dm_coa_req = NULL; - pthread_mutex_unlock(&rpd->lock); -} - -void dm_coa_cancel(struct radius_pd_t *rpd) -{ - triton_cancel_call(rpd->ppp->ctrl->ctx, (triton_event_func)disconnect_request); - triton_cancel_call(rpd->ppp->ctrl->ctx, (triton_event_func)coa_request); - rad_packet_free(rpd->dm_coa_req); -} - -static int dm_coa_read(struct triton_md_handler_t *h) -{ - struct rad_packet_t *pack; - struct radius_pd_t *rpd; - int err_code; - struct sockaddr_in addr; - - while (1) { - if (rad_packet_recv(h->fd, &pack, &addr)) - return 0; - - if (!pack) - continue; - - if (pack->code != CODE_DISCONNECT_REQUEST && pack->code != CODE_COA_REQUEST) { - log_warn("radius:dm_coa: unexpected code (%i) received\n", pack->code); - goto out_err_no_reply; - } - - if (dm_coa_check_RA(pack, conf_dm_coa_secret)) { - log_warn("radius:dm_coa: RA validation failed\n"); - goto out_err_no_reply; - } - - if (conf_verbose) { - log_debug("recv "); - rad_packet_print(pack, log_debug); - } - - if (rad_check_nas_pack(pack)) { - log_warn("radius:dm_coa: NAS identification failed\n"); - err_code = 403; - goto out_err; - } - - rpd = rad_find_session_pack(pack); - if (!rpd) { - log_warn("radius:dm_coa: session not found\n"); - err_code = 503; - goto out_err; - } - - if (rpd->dm_coa_req) { - pthread_mutex_unlock(&rpd->lock); - goto out_err_no_reply; - } - - rpd->dm_coa_req = pack; - memcpy(&rpd->dm_coa_addr, &addr, sizeof(addr)); - - if (pack->code == CODE_DISCONNECT_REQUEST) - triton_context_call(rpd->ppp->ctrl->ctx, (triton_event_func)disconnect_request, rpd); - else - triton_context_call(rpd->ppp->ctrl->ctx, (triton_event_func)coa_request, rpd); - - pthread_mutex_unlock(&rpd->lock); - - continue; - - out_err: - dm_coa_send_nak(h->fd, pack, &addr, err_code); - - out_err_no_reply: - rad_packet_free(pack); - } -} - -static void dm_coa_close(struct triton_context_t *ctx) -{ - struct dm_coa_serv_t *serv = container_of(ctx, typeof(*serv), ctx); - triton_md_unregister_handler(&serv->hnd); - close(serv->hnd.fd); - triton_context_unregister(ctx); -} - -static struct dm_coa_serv_t serv = { - .ctx.close = dm_coa_close, - .ctx.before_switch = log_switch, - .hnd.read = dm_coa_read, -}; - -static void __init init(void) -{ - struct sockaddr_in addr; - - if (!conf_dm_coa_secret) { - log_emerg("radius: no dm_coa_secret specified, DM/CoA disabled...\n"); - return; - } - - serv.hnd.fd = socket (PF_INET, SOCK_DGRAM, 0); - if (serv.hnd.fd < 0) { - log_emerg("radius:dm_coa: socket: %s\n", strerror(errno)); - return; - } - addr.sin_family = AF_INET; - addr.sin_port = htons (conf_dm_coa_port); - if (conf_dm_coa_server) - addr.sin_addr.s_addr = conf_dm_coa_server; - else - addr.sin_addr.s_addr = htonl (INADDR_ANY); - if (bind (serv.hnd.fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) { - log_emerg("radius:dm_coa: bind: %s\n", strerror(errno)); - close(serv.hnd.fd); - return; - } - - if (fcntl(serv.hnd.fd, F_SETFL, O_NONBLOCK)) { - log_emerg("radius:dm_coa: failed to set nonblocking mode: %s\n", strerror(errno)); - close(serv.hnd.fd); - return; - } - - triton_context_register(&serv.ctx, NULL); - triton_md_register_handler(&serv.ctx, &serv.hnd); - triton_md_enable_handler(&serv.hnd, MD_MODE_READ); - triton_context_wakeup(&serv.ctx); -} |