From: yasuoka Date: Fri, 9 Feb 2024 07:46:32 +0000 (+0000) Subject: Refactor some functions to prepare accounting support. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=936475aa266e64fa05aff58443575af837422bf9;p=openbsd Refactor some functions to prepare accounting support. --- diff --git a/usr.sbin/radiusd/radiusd.c b/usr.sbin/radiusd/radiusd.c index 7d87d04ab7d..3fc7ad0e454 100644 --- a/usr.sbin/radiusd/radiusd.c +++ b/usr.sbin/radiusd/radiusd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: radiusd.c,v 1.34 2024/01/08 04:16:48 yasuoka Exp $ */ +/* $OpenBSD: radiusd.c,v 1.35 2024/02/09 07:46:32 yasuoka Exp $ */ /* * Copyright (c) 2013, 2023 Internet Initiative Japan Inc. @@ -54,12 +54,14 @@ static int radiusd_start(struct radiusd *); static void radiusd_stop(struct radiusd *); static void radiusd_free(struct radiusd *); static void radiusd_listen_on_event(int, short, void *); +static void radiusd_listen_handle_packet(struct radiusd_listen *, + RADIUS_PACKET *, struct sockaddr *, socklen_t); static void radiusd_on_sigterm(int, short, void *); static void radiusd_on_sigint(int, short, void *); static void radiusd_on_sighup(int, short, void *); static void radiusd_on_sigchld(int, short, void *); -static void radius_query_request(struct radius_query *); -static void radius_query_response(struct radius_query *); +static void raidus_query_access_request(struct radius_query *); +static void radius_query_access_response(struct radius_query *); static const char *radius_code_string(int); static int radiusd_access_response_fixup (struct radius_query *); @@ -350,19 +352,12 @@ radiusd_free(struct radiusd *radiusd) static void radiusd_listen_on_event(int fd, short evmask, void *ctx) { - int i, sz, req_id, req_code; - struct radiusd_listen *listn = ctx; - static u_char buf[65535]; - static char username[256]; + int sz; + RADIUS_PACKET *packet = NULL; struct sockaddr_storage peer; socklen_t peersz; - RADIUS_PACKET *packet = NULL; - char peerstr[NI_MAXHOST + NI_MAXSERV + 30]; - struct radiusd_authentication *authen; - struct radiusd_client *client; - struct radius_query *q; -#define in(_x) (((struct sockaddr_in *)_x)->sin_addr) -#define in6(_x) (((struct sockaddr_in6 *)_x)->sin6_addr) + struct radiusd_listen *listn = ctx; + static u_char buf[65535]; if (evmask & EV_READ) { peersz = sizeof(peer); @@ -371,115 +366,128 @@ radiusd_listen_on_event(int fd, short evmask, void *ctx) if (errno == EAGAIN) return; log_warn("%s: recvfrom() failed", __func__); - goto on_error; + return; } RADIUSD_ASSERT(peer.ss_family == AF_INET || peer.ss_family == AF_INET6); - - /* prepare some information about this messages */ - if (addrport_tostring((struct sockaddr *)&peer, peersz, - peerstr, sizeof(peerstr)) == NULL) { - log_warn("%s: getnameinfo() failed", __func__); - goto on_error; - } - if ((packet = radius_convert_packet(buf, sz)) == NULL) { + if ((packet = radius_convert_packet(buf, sz)) == NULL) log_warn("%s: radius_convert_packet() failed", __func__); - goto on_error; - } - req_id = radius_get_id(packet); - req_code = radius_get_code(packet); + else + radiusd_listen_handle_packet(listn, packet, + (struct sockaddr *)&peer, peersz); + } +} - /* - * Find a matching `client' entry - */ - TAILQ_FOREACH(client, &listn->radiusd->client, next) { - if (client->af != peer.ss_family) - continue; - if (peer.ss_family == AF_INET && - IPv4_cmp(&((struct sockaddr_in *)&peer)->sin_addr, - &client->addr, &client->mask)) - break; - else if (peer.ss_family == AF_INET6 && - IPv6_cmp(&((struct sockaddr_in6 *)&peer)->sin6_addr, - &client->addr, &client->mask)) - break; - } - if (client == NULL) { - log_warnx("Received %s(code=%d) from %s id=%d: " - "no `client' matches", radius_code_string(req_code), - req_code, peerstr, req_id); - goto on_error; - } +static void +radiusd_listen_handle_packet(struct radiusd_listen *listn, + RADIUS_PACKET *packet, struct sockaddr *peer, socklen_t peerlen) +{ + int i, req_id, req_code; + static char username[256]; + char peerstr[NI_MAXHOST + NI_MAXSERV + 30]; + struct radiusd_authentication *authen; + struct radiusd_client *client; + struct radius_query *q = NULL; +#define in(_x) (((struct sockaddr_in *)_x)->sin_addr) +#define in6(_x) (((struct sockaddr_in6 *)_x)->sin6_addr) - /* Check the client's Message-Authenticator */ - if (client->msgauth_required && - !radius_has_attr(packet, - RADIUS_TYPE_MESSAGE_AUTHENTICATOR)) { - log_warnx("Received %s(code=%d) from %s id=%d: " - "no message authenticator", - radius_code_string(req_code), req_code, peerstr, - req_id); - goto on_error; - } + req_id = radius_get_id(packet); + req_code = radius_get_code(packet); + /* prepare some information about this messages */ + if (addrport_tostring(peer, peerlen, peerstr, sizeof(peerstr)) == + NULL) { + log_warn("%s: getnameinfo() failed", __func__); + goto on_error; + } - if (radius_has_attr(packet, - RADIUS_TYPE_MESSAGE_AUTHENTICATOR) && - radius_check_message_authenticator(packet, client->secret) - != 0) { - log_warnx("Received %s(code=%d) from %s id=%d: " - "bad message authenticator", - radius_code_string(req_code), req_code, peerstr, - req_id); - goto on_error; - } + /* + * Find a matching `client' entry + */ + TAILQ_FOREACH(client, &listn->radiusd->client, next) { + if (client->af != peer->sa_family) + continue; + if (peer->sa_family == AF_INET && IPv4_cmp( + &in(peer), &client->addr, &client->mask)) + break; + else if (peer->sa_family == AF_INET6 && IPv6_cmp( + &in6(peer), &client->addr, &client->mask)) + break; + } + if (client == NULL) { + log_warnx("Received %s(code=%d) from %s id=%d: no `client' " + "matches", radius_code_string(req_code), req_code, peerstr, + req_id); + goto on_error; + } - /* - * Find a duplicate request. In RFC 2865, it has the same - * source IP address and source UDP port and Identifier. - */ - TAILQ_FOREACH(q, &listn->radiusd->query, next) { - if (peer.ss_family == q->clientaddr.ss_family && - ((peer.ss_family == AF_INET && - in(&q->clientaddr).s_addr == - in(&peer).s_addr) || - (peer.ss_family == AF_INET6 && - IN6_ARE_ADDR_EQUAL( - &in6(&q->clientaddr), &in6(&peer)))) && - ((struct sockaddr_in *)&q->clientaddr)->sin_port == - ((struct sockaddr_in *)&peer)->sin_port && - req_id == q->req_id) - break; /* found it */ - } - if (q != NULL) { - log_info("Received %s(code=%d) from %s id=%d: " - "duplicate request by q=%u", - radius_code_string(req_code), req_code, peerstr, - req_id, q->id); - /* XXX RFC 5080 suggests to answer the cached result */ - goto on_error; - } + /* Check the client's Message-Authenticator */ + if (client->msgauth_required && !radius_has_attr(packet, + RADIUS_TYPE_MESSAGE_AUTHENTICATOR)) { + log_warnx("Received %s(code=%d) from %s id=%d: no message " + "authenticator", radius_code_string(req_code), req_code, + peerstr, req_id); + goto on_error; + } - /* FIXME: we can support other request codes */ - if (req_code != RADIUS_CODE_ACCESS_REQUEST) { - log_info("Received %s(code=%d) from %s id=%d: %s " - "is not supported in this implementation", - radius_code_string(req_code), req_code, peerstr, - req_id, radius_code_string(req_code)); - goto on_error; - } + if (radius_has_attr(packet, RADIUS_TYPE_MESSAGE_AUTHENTICATOR) && + radius_check_message_authenticator(packet, client->secret) != 0) { + log_warnx("Received %s(code=%d) from %s id=%d: bad message " + "authenticator", radius_code_string(req_code), req_code, + peerstr, req_id); + goto on_error; + } + + /* + * Find a duplicate request. In RFC 2865, it has the same source IP + * address and source UDP port and Identifier. + */ + TAILQ_FOREACH(q, &listn->radiusd->query, next) { + if (peer->sa_family == q->clientaddr.ss_family && + ((peer->sa_family == AF_INET && in(&q->clientaddr).s_addr == + in(peer).s_addr) || (peer->sa_family == AF_INET6 && + IN6_ARE_ADDR_EQUAL(&in6(&q->clientaddr), &in6(peer)))) && + ((struct sockaddr_in *)&q->clientaddr)->sin_port == + ((struct sockaddr_in *)peer)->sin_port && + req_id == q->req_id) + break; /* found it */ + } + if (q != NULL) { + log_info("Received %s(code=%d) from %s id=%d: duplicate " + "request by q=%u", radius_code_string(req_code), req_code, + peerstr, req_id, q->id); + /* XXX RFC 5080 suggests to answer the cached result */ + goto on_error; + } + + if ((q = calloc(1, sizeof(struct radius_query))) == NULL) { + log_warn("%s: Out of memory", __func__); + goto on_error; + } + if (radius_get_string_attr(packet, RADIUS_TYPE_USER_NAME, username, + sizeof(username)) != 0) { + log_info("Received %s(code=%d) from %s id=%d: no User-Name " + "attribute", radius_code_string(req_code), req_code, + peerstr, req_id); + } else + strlcpy(q->username, username, sizeof(q->username)); + q->id = ++radius_query_id_seq; + q->clientaddrlen = peerlen; + memcpy(&q->clientaddr, peer, peerlen); + q->listen = listn; + q->req = packet; + q->client = client; + q->req_id = req_id; + radius_get_authenticator(packet, q->req_auth); + packet = NULL; + TAILQ_INSERT_TAIL(&listn->radiusd->query, q, next); + + switch (req_code) { + case RADIUS_CODE_ACCESS_REQUEST: /* * Find a matching `authenticate' entry */ - if (radius_get_string_attr(packet, RADIUS_TYPE_USER_NAME, - username, sizeof(username)) != 0) { - log_info("Received %s(code=%d) from %s id=%d: " - "no User-Name attribute", - radius_code_string(req_code), req_code, peerstr, - req_id); - goto on_error; - } TAILQ_FOREACH(authen, &listn->radiusd->authen, next) { for (i = 0; authen->username[i] != NULL; i++) { if (fnmatch(authen->username[i], username, 0) @@ -487,7 +495,7 @@ radiusd_listen_on_event(int fd, short evmask, void *ctx) goto found; } } -found: + found: if (authen == NULL) { log_warnx("Received %s(code=%d) from %s id=%d " "username=%s: no `authenticate' matches.", @@ -495,7 +503,7 @@ found: req_id, username); goto on_error; } - RADIUSD_ASSERT(authen->auth != NULL); + q->authen = authen; if (!MODULE_DO_USERPASS(authen->auth->module) && !MODULE_DO_ACCSREQ(authen->auth->module)) { @@ -505,42 +513,32 @@ found: req_id, username, authen->auth->module->name); goto on_error; } - if ((q = calloc(1, sizeof(struct radius_query))) == NULL) { - log_warn("%s: Out of memory", __func__); - goto on_error; - } - memcpy(&q->clientaddr, &peer, peersz); - strlcpy(q->username, username, sizeof(q->username)); - q->id = ++radius_query_id_seq; - q->clientaddrlen = peersz; - q->authen = authen; - q->listen = listn; - q->req = packet; - q->client = client; - q->req_id = req_id; - radius_get_authenticator(packet, q->req_auth); log_info("Received %s(code=%d) from %s id=%d username=%s " "q=%u: `%s' authentication is starting", radius_code_string(req_code), req_code, peerstr, q->req_id, q->username, q->id, q->authen->auth->module->name); - TAILQ_INSERT_TAIL(&listn->radiusd->query, q, next); - - radius_query_request(q); + raidus_query_access_request(q); return; + default: + log_info("Received %s(code=%d) from %s id=%d: %s is not " + "supported in this implementation", radius_code_string( + req_code), req_code, peerstr, req_id, radius_code_string( + req_code)); + break; } on_error: if (packet != NULL) radius_delete_packet(packet); + if (q != NULL) + radiusd_access_request_aborted(q); #undef in #undef in6 - - return; } static void -radius_query_request(struct radius_query *q) +raidus_query_access_request(struct radius_query *q) { struct radiusd_authentication *authen = q->authen; @@ -566,7 +564,7 @@ radius_query_request(struct radius_query *q) } static void -radius_query_response(struct radius_query *q) +radius_query_access_response(struct radius_query *q) { int sz, res_id, res_code; char buf[NI_MAXHOST + NI_MAXSERV + 30]; @@ -609,7 +607,6 @@ radius_query_response(struct radius_query *q) log_warn("Sending a RADIUS response failed"); on_error: radiusd_access_request_aborted(q); - } /*********************************************************************** @@ -643,7 +640,7 @@ radiusd_access_request_answer(struct radius_query *q) } RADIUSD_ASSERT(q->deco == NULL); - radius_query_response(q); + radius_query_access_response(q); return; on_error: @@ -957,7 +954,8 @@ radiusd_module_load(struct radiusd *radiusd, const char *path, const char *name) goto on_error; } if (fcntl(module->fd, F_SETFL, ival | O_NONBLOCK) == -1) { - log_warn("Could not load module `%s': fcntl(F_SETFL,O_NONBLOCK)", + log_warn( + "Could not load module `%s': fcntl(F_SETFL,O_NONBLOCK)", name); goto on_error; } @@ -1281,7 +1279,7 @@ radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg) radius_delete_packet(q->req); q->req = radpkt; } - radius_query_request(q); + raidus_query_access_request(q); break; case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER: if (radpkt == NULL) { @@ -1299,7 +1297,7 @@ radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg) q->req); q->res = radpkt; } - radius_query_response(q); + radius_query_access_response(q); break; } }