Added support for radius interim updates

This commit is contained in:
Nikos Mavrogiannopoulos
2014-12-10 11:10:08 +01:00
parent 35e93c6341
commit 320773e80a
9 changed files with 171 additions and 35 deletions

View File

@@ -348,7 +348,7 @@ struct pam_ctx_st * pctx = ctx;
talloc_free(pctx);
}
static int pam_auth_open_session(void* ctx)
static int pam_auth_open_session(void* ctx, const void *sid, unsigned sid_size)
{
struct pam_ctx_st * pctx = ctx;
int pret;

View File

@@ -149,7 +149,8 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
syslog(LOG_ERR,
"%s:%u: user '%s' auth error", __func__, __LINE__,
pctx->username);
return ERR_AUTH_FAIL;
ret = ERR_AUTH_FAIL;
goto cleanup;
}
service = PW_AUTHENTICATE_ONLY;
@@ -157,7 +158,8 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
syslog(LOG_ERR,
"%s:%u: user '%s' auth error", __func__, __LINE__,
pctx->username);
return ERR_AUTH_FAIL;
ret = ERR_AUTH_FAIL;
goto cleanup;
}
ret = rc_aaa(rh, 0, send, &recvd, pctx->msg, 1, PW_ACCESS_REQUEST);
@@ -207,18 +209,24 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
vp = vp->next;
}
ret = 0;
cleanup:
rc_avpair_free(send);
if (recvd != NULL)
rc_avpair_free(recvd);
return 0;
return ret;
} else {
fail:
if (send != NULL)
rc_avpair_free(send);
if (recvd != NULL)
rc_avpair_free(recvd);
if (ret == PW_ACCESS_CHALLENGE) {
pctx->pass_msg = pass_msg_second;
return ERR_AUTH_CONTINUE;
} else if ( pctx->retries++ < MAX_TRIES) {
} else if (pctx->retries++ < MAX_TRIES) {
pctx->pass_msg = pass_msg_failed;
return ERR_AUTH_CONTINUE;
} else {
@@ -245,7 +253,74 @@ static void radius_auth_deinit(void *ctx)
}
static int radius_auth_open_session(void* ctx)
static void radius_auth_session_stats(void* ctx, uint64_t bytes_in, uint64_t bytes_out)
{
struct radius_ctx_st * pctx = ctx;
int ret;
uint32_t status_type;
VALUE_PAIR *send = NULL, *recvd = NULL;
uint32_t uin, uout;
status_type = PW_STATUS_ALIVE;
syslog(LOG_DEBUG, "sending radius session interim update");
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
if (rc_avpair_add(rh, &send, PW_USER_NAME, pctx->username, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_ID, pctx->sid, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
uin = bytes_in;
uout = bytes_out;
if (rc_avpair_add(rh, &send, PW_ACCT_INPUT_OCTETS, &uin, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
if (rc_avpair_add(rh, &send, PW_ACCT_OUTPUT_OCTETS, &uout, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
uin = bytes_in / 4294967296;
if (rc_avpair_add(rh, &send, PW_ACCT_INPUT_GIGAWORDS, &uin, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
uout = bytes_in / 4294967296;
if (rc_avpair_add(rh, &send, PW_ACCT_OUTPUT_GIGAWORDS, &uout, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
ret = rc_aaa(rh, 0, send, &recvd, pctx->msg, 1, PW_ACCOUNTING_REQUEST);
if (recvd != NULL)
rc_avpair_free(recvd);
if (ret != OK_RC) {
syslog(LOG_AUTH, "radius-auth: radius_open_session: %d", ret);
goto cleanup;
}
cleanup:
rc_avpair_free(send);
return;
}
static int radius_auth_open_session(void* ctx, const void *sid, unsigned sid_size)
{
struct radius_ctx_st * pctx = ctx;
int ret;
@@ -254,20 +329,45 @@ VALUE_PAIR *send = NULL, *recvd = NULL;
status_type = PW_STATUS_START;
syslog(LOG_DEBUG, "opening session with radius");
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL)
if (sid_size != SID_SIZE) {
syslog(LOG_DEBUG, "incorrect sid size");
return -1;
}
base64_encode((char *)sid, sid_size, (char *)pctx->sid, sizeof(pctx->sid));
syslog(LOG_DEBUG, "opening session %s with radius", pctx->sid);
if (rc_avpair_add(rh, &send, PW_USER_NAME, pctx->username, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_ID, pctx->sid, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
ret = rc_aaa(rh, 0, send, &recvd, pctx->msg, 1, PW_ACCOUNTING_REQUEST);
if (recvd != NULL)
rc_avpair_free(recvd);
if (ret != OK_RC) {
syslog(LOG_AUTH, "radius-auth: radius_open_session: %d", ret);
return -1;
ret = -1;
goto cleanup;
}
return 0;
ret = 0;
cleanup:
rc_avpair_free(send);
return ret;
}
static void radius_auth_close_session(void* ctx)
@@ -283,15 +383,26 @@ VALUE_PAIR *send = NULL, *recvd = NULL;
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL)
return;
if (rc_avpair_add(rh, &send, PW_USER_NAME, pctx->username, -1, 0) == NULL) {
goto cleanup;
}
if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_ID, pctx->sid, -1, 0) == NULL) {
goto cleanup;
}
ret = rc_aaa(rh, 0, send, &recvd, pctx->msg, 1, PW_ACCOUNTING_REQUEST);
if (recvd != NULL)
rc_avpair_free(recvd);
if (ret != OK_RC) {
syslog(LOG_INFO, "radius-auth: radius_close_session: %d", ret);
return;
goto cleanup;
}
cleanup:
rc_avpair_free(send);
return;
}
@@ -307,6 +418,7 @@ const struct auth_mod_st radius_auth_funcs = {
.auth_group = radius_auth_group,
.open_session = radius_auth_open_session,
.close_session = radius_auth_close_session,
.session_stats = radius_auth_session_stats,
.group_list = NULL
};

View File

@@ -22,10 +22,13 @@
#define RADIUS_H
#include <sec-mod-auth.h>
#include <base64.h>
struct radius_ctx_st {
char username[MAX_USERNAME_SIZE*2];
char groupname[MAX_GROUPNAME_SIZE];
char sid[BASE64_LENGTH(SID_SIZE) + 1];
char msg[4096];
/* variables for configuration */

View File

@@ -56,6 +56,8 @@ static char tmp[32];
case CMD_CLI_STATS:
return "cli stats";
case SM_CMD_CLI_STATS:
return "sm: cli stats";
case SM_CMD_AUTH_INIT:
return "sm: auth init";
case SM_CMD_AUTH_CONT:

View File

@@ -327,7 +327,7 @@ int handle_sec_auth_session_cmd(sec_mod_st * sec, const SecAuthSessionMsg * req,
if (module == NULL || module->open_session == NULL)
return 0;
ret = module->open_session(e->auth_ctx);
ret = module->open_session(e->auth_ctx, req->sid.data, req->sid.len);
if (ret < 0) {
e->status = PS_AUTH_FAILED;
seclog(sec, LOG_ERR, "could not open session.");
@@ -342,6 +342,37 @@ int handle_sec_auth_session_cmd(sec_mod_st * sec, const SecAuthSessionMsg * req,
return 0;
}
int handle_sec_auth_stats_cmd(sec_mod_st * sec, const CliStatsMsg * req)
{
client_entry_st *e;
if (req->sid.len != SID_SIZE) {
seclog(sec, LOG_ERR, "auth session open/close but with illegal sid size (%d)!",
(int)req->sid.len);
return -1;
}
e = find_client_entry(sec, req->sid.data);
if (e == NULL) {
seclog(sec, LOG_INFO, "session open/close but with non-existing sid!");
return -1;
}
if (e->status != PS_AUTH_COMPLETED) {
seclog(sec, LOG_ERR, "session stats received in unauthenticated client!");
return -1;
}
e->bytes_in = req->bytes_in;
e->bytes_out = req->bytes_out;
if (module == NULL || module->session_stats == NULL)
return 0;
module->session_stats(e->auth_ctx, e->bytes_in, e->bytes_out);
return 0;
}
int handle_sec_auth_cont(sec_mod_st * sec, const SecAuthContMsg * req)
{
client_entry_st *e;

View File

@@ -36,7 +36,8 @@ struct auth_mod_st {
int (*auth_group)(void* ctx, const char *suggested, char *groupname, int groupname_size);
int (*auth_user)(void* ctx, char *groupname, int groupname_size);
int (*open_session)(void *ctx); /* optional, may be null */
int (*open_session)(void *ctx, const void *sid, unsigned sid_size); /* optional, may be null */
void (*session_stats)(void *ctx, uint64_t bytes_in, uint64_t bytes_out); /* optional, may be null */
void (*close_session)(void *ctx); /* optional */
void (*auth_deinit)(void* ctx);

View File

@@ -251,7 +251,6 @@ int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
case SM_CMD_CLI_STATS:{
CliStatsMsg *tmsg;
client_entry_st *e;
tmsg = cli_stats_msg__unpack(&pa, data.size, data.data);
if (tmsg == NULL) {
@@ -260,28 +259,9 @@ int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
return -1;
}
if (tmsg->has_sid == 0 || tmsg->sid.len != SID_SIZE) {
cli_stats_msg__free_unpacked(tmsg, &pa);
seclog(sec, LOG_INFO, "error in SID received by client (size: %d)",
(int)tmsg->sid.len);
return -1;
}
e = find_client_entry(sec, tmsg->sid.data);
if (e == NULL) {
cli_stats_msg__free_unpacked(tmsg, &pa);
seclog(sec, LOG_INFO, "session stats received with non-existing sid!");
return -1;
}
ret = handle_sec_auth_stats_cmd(sec, tmsg);
cli_stats_msg__free_unpacked(tmsg, &pa);
if (e->status != PS_AUTH_COMPLETED) {
seclog(sec, LOG_ERR, "session stats received in unauthenticated client!");
return -1;
}
e->bytes_in = tmsg->bytes_in;
e->bytes_out = tmsg->bytes_out;
return ret;
}
break;

View File

@@ -96,6 +96,7 @@ void sec_auth_init(void *pool, struct cfg_st *config);
int handle_sec_auth_init(sec_mod_st *sec, const SecAuthInitMsg * req);
int handle_sec_auth_cont(sec_mod_st *sec, const SecAuthContMsg * req);
int handle_sec_auth_session_cmd(sec_mod_st * sec, const SecAuthSessionMsg * req, unsigned cmd, client_entry_st **_e);
int handle_sec_auth_stats_cmd(sec_mod_st * sec, const CliStatsMsg * req);
void sec_auth_user_deinit(sec_mod_st * sec, client_entry_st * e);
void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_file,