summaryrefslogtreecommitdiff
path: root/accel-pppd/radius/auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/radius/auth.c')
-rw-r--r--accel-pppd/radius/auth.c492
1 files changed, 204 insertions, 288 deletions
diff --git a/accel-pppd/radius/auth.c b/accel-pppd/radius/auth.c
index f4efe3b..b73f259 100644
--- a/accel-pppd/radius/auth.c
+++ b/accel-pppd/radius/auth.c
@@ -4,6 +4,7 @@
#include "crypto.h"
#include "triton.h"
+#include "mempool.h"
#include "events.h"
#include "log.h"
#include "pwdb.h"
@@ -142,193 +143,179 @@ static uint8_t* encrypt_password(const char *passwd, const char *secret, const u
return epasswd;
}
-static int rad_auth_send(struct rad_req_t *req)
+static void rad_auth_finalize(struct radius_pd_t *rpd, int r)
{
- int i;
- struct timespec tv, tv2;
+ hold_pd(rpd);
+
+ rpd->auth_ctx->cb(rpd->auth_ctx->cb_arg, r);
+
+ if (rpd->auth_ctx) {
+ rad_req_free(rpd->auth_ctx->req);
+ mempool_free(rpd->auth_ctx);
+ rpd->auth_ctx = NULL;
+ }
+
+ release_pd(rpd);
+}
+
+static void rad_auth_recv(struct rad_req_t *req)
+{
+ struct rad_packet_t *pack = req->reply;
unsigned int dt;
- int timeout;
- while (1) {
- if (rad_server_req_enter(req)) {
- if (rad_server_realloc(req)) {
- log_ppp_warn("radius: no available servers\n");
- break;
- }
- continue;
+ triton_timer_del(&req->timeout);
+
+ dt = (req->reply->tv.tv_sec - req->pack->tv.tv_sec) * 1000 + (req->reply->tv.tv_nsec - req->pack->tv.tv_nsec) / 1000000;
+ stat_accm_add(req->serv->stat_auth_query_1m, dt);
+ stat_accm_add(req->serv->stat_auth_query_5m, dt);
+
+ if (pack->code == CODE_ACCESS_ACCEPT) {
+ if (rad_proc_attrs(req)) {
+ rad_auth_finalize(req->rpd, PWDB_DENIED);
+ return;
}
+
+ struct ev_radius_t ev = {
+ .ses = req->rpd->ses,
+ .request = req->pack,
+ .reply = pack,
+ };
+ triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev);
+ }
+
+ if (req->rpd->auth_ctx->recv && req->rpd->auth_ctx->recv(req)) {
+ rad_auth_finalize(req->rpd, PWDB_DENIED);
+ return;
+ }
+
+ req->rpd->authenticated = 1;
+
+ rad_auth_finalize(req->rpd, PWDB_SUCCESS);
+}
- for(i = 0; i < conf_max_try; i++) {
- __sync_add_and_fetch(&req->serv->stat_auth_sent, 1);
- clock_gettime(CLOCK_MONOTONIC, &tv);
- if (rad_req_send(req, conf_verbose ? log_ppp_info1 : NULL))
- goto out;
+static void rad_auth_timeout(struct triton_timer_t *t)
+{
+ struct rad_req_t *req = container_of(t, typeof(*req), timeout);
+
+ __sync_add_and_fetch(&req->serv->stat_auth_lost, 1);
+ stat_accm_add(req->serv->stat_auth_lost_1m, 1);
+ stat_accm_add(req->serv->stat_auth_lost_5m, 1);
- timeout = conf_timeout;
+ if (rad_req_send(req))
+ rad_auth_finalize(req->rpd, PWDB_DENIED);
+}
- while (timeout > 0) {
+static void rad_auth_sent(struct rad_req_t *req, int res)
+{
+ if (res) {
+ rad_auth_finalize(req->rpd, PWDB_DENIED);
+ return;
+ }
+
+ __sync_add_and_fetch(&req->serv->stat_auth_sent, 1);
+
+ if (!req->hnd.tpd) {
+ triton_md_register_handler(req->rpd->ses->ctrl->ctx, &req->hnd);
+ triton_md_enable_handler(&req->hnd, MD_MODE_READ);
+ }
+
+ if (req->timeout.tpd)
+ triton_timer_mod(&req->timeout, 0);
+ else
+ triton_timer_add(req->rpd->ses->ctrl->ctx, &req->timeout, 0);
+}
+
+static struct rad_req_t *rad_auth_req_alloc(struct radius_pd_t *rpd, const char *username, int (*recv)(struct rad_req_t *))
+{
+ struct rad_req_t *req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
+
+ if (!req)
+ return NULL;
+
+ if (conf_sid_in_auth) {
+ if (rad_packet_add_str(req->pack, NULL, "Acct-Session-Id", rpd->ses->sessionid))
+ goto out;
+ }
- rad_req_wait(req, timeout);
+ if (rpd->attr_state) {
+ if (rad_packet_add_octets(req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len))
+ goto out;
+ }
- if (req->reply) {
- if (req->reply->id != req->pack->id) {
- rad_packet_free(req->reply);
- req->reply = NULL;
- clock_gettime(CLOCK_MONOTONIC, &tv2);
- timeout = conf_timeout - ((tv2.tv_sec - tv.tv_sec) * 1000 + (tv2.tv_nsec - tv.tv_nsec) / 1000000);
- } else
- break;
- } else
- break;
- }
+ req->hnd.read = rad_req_read;
+ req->timeout.expire = rad_auth_timeout;
+ req->timeout.expire_tv.tv_sec = conf_timeout;
+ req->recv = rad_auth_recv;
+ req->sent = rad_auth_sent;
+ if (conf_verbose)
+ req->log = log_ppp_info1;
- if (req->reply) {
- dt = (req->reply->tv.tv_sec - tv.tv_sec) * 1000 + (req->reply->tv.tv_nsec - tv.tv_nsec) / 1000000;
- stat_accm_add(req->serv->stat_auth_query_1m, dt);
- stat_accm_add(req->serv->stat_auth_query_5m, dt);
- break;
- } else {
- __sync_add_and_fetch(&req->serv->stat_auth_lost, 1);
- stat_accm_add(req->serv->stat_auth_lost_1m, 1);
- stat_accm_add(req->serv->stat_auth_lost_5m, 1);
- }
- }
-out:
- rad_server_req_exit(req);
+ rpd->auth_ctx->recv = recv;
+ rpd->auth_ctx->req = req;
- if (!req->reply) {
- rad_server_fail(req->serv);
- if (rad_server_realloc(req)) {
- log_ppp_warn("radius: no available servers\n");
- break;
- }
- } else {
- if (req->reply->code == CODE_ACCESS_ACCEPT) {
- if (rad_proc_attrs(req))
- return PWDB_DENIED;
- return PWDB_SUCCESS;
- } else
- break;
- }
- }
+ return req;
- return PWDB_DENIED;
+out:
+ rad_req_free(req);
+ return NULL;
}
int rad_auth_pap(struct radius_pd_t *rpd, const char *username, va_list args)
{
- struct rad_req_t *req;
- int r = PWDB_DENIED;
- //int id = va_arg(args, int);
+ struct rad_req_t *req = rad_auth_req_alloc(rpd, username, NULL);
+ int r;
const char *passwd = va_arg(args, const char *);
uint8_t *epasswd;
int epasswd_len;
- req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
if (!req)
return PWDB_DENIED;
epasswd = encrypt_password(passwd, req->serv->secret, req->RA, &epasswd_len);
if (!epasswd)
- goto out;
-
- if (rad_packet_add_octets(req->pack, NULL, "User-Password", epasswd, epasswd_len)) {
- if (epasswd_len)
- _free(epasswd);
- goto out;
- }
+ return PWDB_DENIED;
+ r = rad_packet_add_octets(req->pack, NULL, "User-Password", epasswd, epasswd_len);
if (epasswd_len)
_free(epasswd);
+
+ if (r)
+ return PWDB_DENIED;
- if (conf_sid_in_auth)
- if (rad_packet_add_str(req->pack, NULL, "Acct-Session-Id", rpd->ses->sessionid))
- return -1;
-
- r = rad_auth_send(req);
- if (r == PWDB_SUCCESS) {
- struct ev_radius_t ev = {
- .ses = rpd->ses,
- .request = req->pack,
- .reply = req->reply,
- };
- triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev);
- }
-
-out:
- rad_req_free(req);
+ if (rad_req_send(req))
+ return PWDB_DENIED;
- return r;
+ return PWDB_WAIT;
}
int rad_auth_chap_md5(struct radius_pd_t *rpd, const char *username, va_list args)
{
- int r = PWDB_DENIED;
+ struct rad_req_t *req = rad_auth_req_alloc(rpd, username, NULL);
uint8_t chap_password[17];
-
int id = va_arg(args, int);
uint8_t *challenge = va_arg(args, uint8_t *);
int challenge_len = va_arg(args, int);
uint8_t *response = va_arg(args, uint8_t *);
+
+ if (!req)
+ return PWDB_DENIED;
chap_password[0] = id;
memcpy(chap_password + 1, response, 16);
- 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(rpd->auth_req->RA, challenge, 16);
- if (rad_packet_add_octets(rpd->auth_req->pack, NULL, "CHAP-Challenge", challenge, challenge_len))
- goto out;
+ if (challenge_len == 16)
+ memcpy(req->RA, challenge, 16);
- if (rad_packet_add_octets(rpd->auth_req->pack, NULL, "CHAP-Password", chap_password, 17))
- goto out;
- } else {
- if (challenge_len == 16)
- memcpy(rpd->auth_req->RA, challenge, 16);
- if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "CHAP-Challenge", challenge, challenge_len))
- goto out;
+ if (rad_packet_add_octets(req->pack, NULL, "CHAP-Challenge", challenge, challenge_len))
+ return PWDB_DENIED;
- if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "CHAP-Password", chap_password, 17))
- goto out;
-
- if (rpd->attr_state) {
- if (rad_packet_find_attr(rpd->auth_req->pack, NULL, "State")) {
- if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len))
- goto out;
- } else {
- if (rad_packet_add_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len))
- goto out;
- }
- }
-
- if (rad_packet_build(rpd->auth_req->pack, rpd->auth_req->RA))
- return -1;
- }
+ if (rad_packet_add_octets(req->pack, NULL, "CHAP-Password", chap_password, 17))
+ return PWDB_DENIED;
- if (conf_sid_in_auth)
- if (rad_packet_add_str(rpd->auth_req->pack, NULL, "Acct-Session-Id", rpd->ses->sessionid))
- goto out;
-
- r = rad_auth_send(rpd->auth_req);
- if (r == PWDB_SUCCESS) {
- struct ev_radius_t ev = {
- .ses = rpd->ses,
- .request = rpd->auth_req->pack,
- .reply = rpd->auth_req->reply,
- };
- triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev);
- rpd->auth_req->pack->id++;
- }
-
-out:
- rad_req_free(rpd->auth_req);
- rpd->auth_req = NULL;
+ if (rad_req_send(req))
+ return PWDB_DENIED;
- return r;
+ return PWDB_WAIT;
}
static void setup_mppe(struct rad_req_t *req, const uint8_t *challenge)
@@ -376,11 +363,26 @@ static void setup_mppe(struct rad_req_t *req, const uint8_t *challenge)
triton_event_fire(EV_MPPE_KEYS, &ev_mppe);
}
+static int rad_auth_mschap_v1_recv(struct rad_req_t *req)
+{
+ if (req->reply->code == CODE_ACCESS_ACCEPT)
+ setup_mppe(req, req->rpd->auth_ctx->challenge);
+ else {
+ struct rad_attr_t *ra = rad_packet_find_attr(req->reply, "Microsoft", "MS-CHAP-Error");
+ if (ra) {
+ char **mschap_error = req->rpd->auth_ctx->mschap_error;
+ *mschap_error = _malloc(ra->len + 1);
+ memcpy(*mschap_error, ra->val.string, ra->len);
+ (*mschap_error)[ra->len] = 0;
+ }
+ }
+
+ return 0;
+}
+
int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list args)
{
- int r = PWDB_DENIED;
uint8_t response[50];
- struct rad_attr_t *ra;
int id = va_arg(args, int);
const uint8_t *challenge = va_arg(args, const uint8_t *);
@@ -388,80 +390,70 @@ int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list ar
const uint8_t *lm_response = va_arg(args, const uint8_t *);
const uint8_t *nt_response = va_arg(args, const uint8_t *);
int flags = va_arg(args, int);
- char **mschap_error = va_arg(args, char **);
+ rpd->auth_ctx->mschap_error = va_arg(args, char **);
+ struct rad_req_t *req = rad_auth_req_alloc(rpd, username, rad_auth_mschap_v1_recv);
+
+ if (!req)
+ return PWDB_DENIED;
+
+ rpd->auth_ctx->challenge = challenge;
response[0] = id;
response[1] = flags;
memcpy(response + 2, lm_response, 24);
memcpy(response + 2 + 24, nt_response, 24);
- 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_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, challenge_len))
- goto out;
-
- if (rad_packet_add_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Response", response, sizeof(response)))
- goto out;
- } else {
- if (rad_packet_change_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, challenge_len))
- goto out;
-
- if (rad_packet_change_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Response", response, sizeof(response)))
- goto out;
+ if (rad_packet_add_octets(req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, challenge_len))
+ return PWDB_DENIED;
+
+ if (rad_packet_add_octets(req->pack, "Microsoft", "MS-CHAP-Response", response, sizeof(response)))
+ return PWDB_DENIED;
+
+ if (rad_req_send(req))
+ return PWDB_DENIED;
- if (rpd->attr_state) {
- if (rad_packet_find_attr(rpd->auth_req->pack, NULL, "State")) {
- if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len))
- goto out;
- } else {
- if (rad_packet_add_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len))
- goto out;
- }
- }
-
- if (rad_packet_build(rpd->auth_req->pack, rpd->auth_req->RA))
- return -1;
- }
+ return PWDB_WAIT;
+}
- if (conf_sid_in_auth)
- if (rad_packet_add_str(rpd->auth_req->pack, NULL, "Acct-Session-Id", rpd->ses->sessionid))
- goto out;
+static int rad_auth_mschap_v2_recv(struct rad_req_t *req)
+{
+ struct radius_pd_t *rpd = req->rpd;
+ struct rad_attr_t *ra;
+ if (req->reply->code == CODE_ACCESS_ACCEPT) {
+ ra = rad_packet_find_attr(req->reply, "Microsoft", "MS-CHAP2-Success");
+ if (!ra) {
+ log_error("radius:auth:mschap-v2: 'MS-CHAP-Success' not found in radius response\n");
+ return -1;
+ } else
+ memcpy(rpd->auth_ctx->authenticator, ra->val.octets + 3, 40);
- r = rad_auth_send(rpd->auth_req);
- if (r == PWDB_SUCCESS) {
- struct ev_radius_t ev = {
- .ses = rpd->ses,
- .request = rpd->auth_req->pack,
- .reply = rpd->auth_req->reply,
- };
- triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev);
- setup_mppe(rpd->auth_req, challenge);
- rpd->auth_req->pack->id++;
- } else if (rpd->auth_req->reply) {
- ra = rad_packet_find_attr(rpd->auth_req->reply, "Microsoft", "MS-CHAP-Error");
+ setup_mppe(rpd->auth_ctx->req, NULL);
+ } else {
+ ra = rad_packet_find_attr(req->reply, "Microsoft", "MS-CHAP-Error");
if (ra) {
+ char **mschap_error = req->rpd->auth_ctx->mschap_error;
*mschap_error = _malloc(ra->len + 1);
memcpy(*mschap_error, ra->val.string, ra->len);
(*mschap_error)[ra->len] = 0;
}
- }
-out:
- rad_req_free(rpd->auth_req);
- rpd->auth_req = NULL;
+ ra = rad_packet_find_attr(req->reply, NULL, "Reply-Message");
+ if (ra) {
+ char **reply_msg = req->rpd->auth_ctx->reply_msg;
+ *reply_msg = _malloc(ra->len + 1);
+ memcpy(*reply_msg, ra->val.string, ra->len);
+ (*reply_msg)[ra->len] = 0;
+ }
+ }
- return r;
+ return 0;
}
int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list args)
{
- int r = PWDB_DENIED;
- struct rad_attr_t *ra;
uint8_t mschap_response[50];
+ struct rad_req_t *req = rad_auth_req_alloc(rpd, username, rad_auth_mschap_v2_recv);
int id = va_arg(args, int);
const uint8_t *challenge = va_arg(args, const uint8_t *);
@@ -469,9 +461,12 @@ int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list ar
const uint8_t *reserved = va_arg(args, const uint8_t *);
const uint8_t *response = va_arg(args, const uint8_t *);
int flags = va_arg(args, int);
- uint8_t *authenticator = va_arg(args, uint8_t *);
- char **mschap_error = va_arg(args, char **);
- char **reply_msg = va_arg(args, char **);
+ rpd->auth_ctx->authenticator = va_arg(args, uint8_t *);
+ rpd->auth_ctx->mschap_error = va_arg(args, char **);
+ rpd->auth_ctx->reply_msg = va_arg(args, char **);
+
+ if (!req)
+ return PWDB_DENIED;
mschap_response[0] = id;
mschap_response[1] = flags;
@@ -479,107 +474,28 @@ int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list ar
memcpy(mschap_response + 2 + 16, reserved, 8);
memcpy(mschap_response + 2 + 16 + 8, response, 24);
- 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_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, 16))
- goto out;
-
- if (rad_packet_add_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP2-Response", mschap_response, sizeof(mschap_response)))
- goto out;
- } else {
- if (rad_packet_change_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, 16))
- goto out;
+ if (rad_packet_add_octets(req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, 16))
+ return PWDB_DENIED;
- if (rad_packet_change_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, NULL, "State")) {
- if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len))
- goto out;
- } else {
- if (rad_packet_add_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len))
- goto out;
- }
- }
+ if (rad_packet_add_octets(req->pack, "Microsoft", "MS-CHAP2-Response", mschap_response, sizeof(mschap_response)))
+ return PWDB_DENIED;
- if (rad_packet_build(rpd->auth_req->pack, rpd->auth_req->RA))
- return -1;
- }
-
- if (conf_sid_in_auth)
- if (rad_packet_add_str(rpd->auth_req->pack, NULL, "Acct-Session-Id", rpd->ses->sessionid))
- goto out;
-
- r = rad_auth_send(rpd->auth_req);
- if (r == PWDB_SUCCESS) {
- ra = rad_packet_find_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;
- } else
- memcpy(authenticator, ra->val.octets + 3, 40);
- }
- if (r == PWDB_SUCCESS) {
- struct ev_radius_t ev = {
- .ses = rpd->ses,
- .request = rpd->auth_req->pack,
- .reply = rpd->auth_req->reply,
- };
- triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev);
- setup_mppe(rpd->auth_req, NULL);
- rpd->auth_req->pack->id++;
- } else if (rpd->auth_req->reply) {
- ra = rad_packet_find_attr(rpd->auth_req->reply, "Microsoft", "MS-CHAP-Error");
- if (ra) {
- *mschap_error = _malloc(ra->len + 1);
- memcpy(*mschap_error, ra->val.string, ra->len);
- (*mschap_error)[ra->len] = 0;
- }
- ra = rad_packet_find_attr(rpd->auth_req->reply, NULL, "Reply-Message");
- if (ra) {
- *reply_msg = _malloc(ra->len + 1);
- memcpy(*reply_msg, ra->val.string, ra->len);
- (*reply_msg)[ra->len] = 0;
- }
- }
-
-out:
- rad_req_free(rpd->auth_req);
- rpd->auth_req = NULL;
+ if (rad_req_send(req))
+ return PWDB_DENIED;
- return r;
+ return PWDB_WAIT;
}
-
int rad_auth_null(struct radius_pd_t *rpd, const char *username, va_list args)
{
- struct rad_req_t *req;
- int r = PWDB_DENIED;
-
- req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
+ struct rad_req_t *req = rad_auth_req_alloc(rpd, username, NULL);
+
if (!req)
return PWDB_DENIED;
-
- if (conf_sid_in_auth)
- if (rad_packet_add_str(req->pack, NULL, "Acct-Session-Id", rpd->ses->sessionid))
- return -1;
- r = rad_auth_send(req);
- if (r == PWDB_SUCCESS) {
- struct ev_radius_t ev = {
- .ses = rpd->ses,
- .request = req->pack,
- .reply = req->reply,
- };
- triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev);
- }
-
- rad_req_free(req);
+ if (rad_req_send(req))
+ return PWDB_DENIED;
- return r;
+ return PWDB_WAIT;
}