From d063b0812cf85797ee9c9747df11ac1e1d14c94b Mon Sep 17 00:00:00 2001 From: Marc Huber Date: Wed, 11 Dec 2024 09:44:26 +0100 Subject: [PATCH] tac_plus-ng/packet.c et al.: support RADIUS Status-Server code --- mavis/spawnd_accepted.c | 1 + mavis/spawnd_conf.c | 18 +++++++++++++++++- mavis/spawnd_headers.h | 1 + mavis/token.pl | 2 ++ tac_plus-ng/headers.h | 1 + tac_plus-ng/main.c | 1 + tac_plus-ng/packet.c | 20 ++++++++++++++++---- tac_plus-ng/sample/tac_plus-ng-radius.cfg | 2 +- 8 files changed, 40 insertions(+), 6 deletions(-) diff --git a/mavis/spawnd_accepted.c b/mavis/spawnd_accepted.c index f50b6231..2dcf003b 100644 --- a/mavis/spawnd_accepted.c +++ b/mavis/spawnd_accepted.c @@ -142,6 +142,7 @@ void spawnd_accepted(struct spawnd_context *ctx, int cur) memcpy(sd_udp->data, buf, len); sd_udp->sock = cur; sd_udp->type = SCM_UDPDATA; + sd_udp->rad_acct = ctx->rad_acct; memcpy(sd_udp->realm, ctx->tag, SCM_REALM_SIZE); sd_udp->protocol = sa.sa.sa_family; switch (sa.sa.sa_family) { diff --git a/mavis/spawnd_conf.c b/mavis/spawnd_conf.c index 95d55b78..094374df 100644 --- a/mavis/spawnd_conf.c +++ b/mavis/spawnd_conf.c @@ -249,8 +249,24 @@ static void parse_listen(struct sym *sym) parse_error_expect(sym, S_count, S_idle, S_interval, S_unknown); } break; + case S_flag: + sym_get(sym); + parse(sym, S_equal); + switch (sym->code) { + case S_access: + ctx->rad_acct = 0; + break; + case S_accounting: + ctx->rad_acct = 1; + break; + default: + parse_error_expect(sym, S_access, S_accounting, S_unknown); + } + sym_get(sym); + break; default: - parse_error_expect(sym, S_address, S_path, S_port, S_realm, S_tls, S_userid, S_groupid, S_backlog, S_type, S_protocol, S_retry, S_tcp, S_unknown); + parse_error_expect(sym, S_address, S_path, S_port, S_realm, S_tls, S_userid, S_groupid, S_backlog, S_type, S_protocol, S_retry, S_tcp, S_flag, + S_unknown); } } if (ctx->overload_backlog > ctx->listen_backlog) diff --git a/mavis/spawnd_headers.h b/mavis/spawnd_headers.h index ec9ef3eb..bbf27a6a 100644 --- a/mavis/spawnd_headers.h +++ b/mavis/spawnd_headers.h @@ -88,6 +88,7 @@ struct spawnd_context { u_int dying:1; /* server only */ u_int logged_retry:1; /* server only */ u_int haproxy:1; /* server only */ + u_int rad_acct:1; /* radius accounting */ int socktype; /* SOCK_STREAM, SOCK_SEQPACKET */ int protocol; /* IPROTO_IP (default)/_TCP/_SCTP */ short port; /* tcp/udp port in network byte order */ diff --git a/mavis/token.pl b/mavis/token.pl index d22b9cd9..0b7642ea 100755 --- a/mavis/token.pl +++ b/mavis/token.pl @@ -548,3 +548,5 @@ # conn.protocol S_conn_protocol # +flag S_flag +# diff --git a/tac_plus-ng/headers.h b/tac_plus-ng/headers.h index e8c23ce2..2a6dcbed 100644 --- a/tac_plus-ng/headers.h +++ b/tac_plus-ng/headers.h @@ -945,6 +945,7 @@ struct context { BISTATE(use_tls); BISTATE(mavis_pending); BISTATE(mavis_tried); + BISTATE(rad_acct); enum token mavis_result; enum token aaa_protocol; u_int id; diff --git a/tac_plus-ng/main.c b/tac_plus-ng/main.c index c4100443..736d7778 100644 --- a/tac_plus-ng/main.c +++ b/tac_plus-ng/main.c @@ -1451,6 +1451,7 @@ static void accept_control_udp(int s __attribute__((unused)), struct scm_data_ac struct context *ctx = new_context(common_data.io, r); ctx->sock = sd_ext->sd_udp.sock; + ctx->rad_acct = sd_ext->sd_udp.rad_acct; context_lru_append(ctx); ctx->aaa_protocol = S_radius; diff --git a/tac_plus-ng/packet.c b/tac_plus-ng/packet.c index 9b07ea34..317f9789 100644 --- a/tac_plus-ng/packet.c +++ b/tac_plus-ng/packet.c @@ -918,6 +918,12 @@ void rad_read(struct context *ctx, int cur) case RADIUS_CODE_ACCOUNTING_REQUEST: rad_acct(session); break; + case RADIUS_CODE_STATUS_SERVER: + if (ctx->rad_acct) + rad_send_acct_reply(session); + else + rad_send_authen_reply(session, RADIUS_CODE_ACCESS_ACCEPT, NULL); + break; default: report(session, LOG_ERR, ~0, "%s: code %d is unsupported", ctx->device_addr_ascii, pak->code); cleanup_session(session); @@ -960,10 +966,16 @@ void rad_udp_inject(struct context *ctx) switch (pak->code) { case RADIUS_CODE_ACCESS_REQUEST: rad_authen(session); - break; + return; case RADIUS_CODE_ACCOUNTING_REQUEST: rad_acct(session); - break; + return; + case RADIUS_CODE_STATUS_SERVER: + if (ctx->rad_acct) + rad_send_acct_reply(session); + else + rad_send_authen_reply(session, RADIUS_CODE_ACCESS_ACCEPT, NULL); + return; default: report(session, LOG_ERR, ~0, "%s: code %d is unsupported", ctx->device_addr_ascii, pak->code); cleanup(ctx, -1); @@ -1030,10 +1042,10 @@ struct type_s { static struct type_s types[] = { { "", 0 }, #define S "authen" - { S, sizeof(S) - 1}, + { S, sizeof(S) - 1 }, #undef S #define S "author" - { S, sizeof(S) - 1}, + { S, sizeof(S) - 1 }, #undef S #define S "acct" { S, sizeof(S) - 1 }, diff --git a/tac_plus-ng/sample/tac_plus-ng-radius.cfg b/tac_plus-ng/sample/tac_plus-ng-radius.cfg index 8e6ace48..c15ab05e 100755 --- a/tac_plus-ng/sample/tac_plus-ng-radius.cfg +++ b/tac_plus-ng/sample/tac_plus-ng-radius.cfg @@ -5,7 +5,7 @@ id = spawnd { # single process = yes listen { port = 4949 } # TACACS+, non-standart port listen { port = 1812 protocol = UDP } # RADIUS - listen { port = 1813 protocol = UDP } # RADIUS + listen { port = 1813 protocol = UDP flag = accounting } # RADIUS spawn { instances min = 1 instances max = 32