Bug Summary

File:src/usr.sbin/radiusd/radiusd/../radiusd.c
Warning:line 606, column 7
Although the value stored to 'sz' is used in the enclosing expression, the value is never actually read from 'sz'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name radiusd.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/radiusd/radiusd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/radiusd/radiusd/.. -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/usr/src/usr.sbin/radiusd/radiusd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/radiusd/radiusd/../radiusd.c
1/* $OpenBSD: radiusd.c,v 1.34 2024/01/08 04:16:48 yasuoka Exp $ */
2
3/*
4 * Copyright (c) 2013, 2023 Internet Initiative Japan Inc.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20#include <netinet/in.h>
21#include <arpa/inet.h>
22#include <sys/queue.h>
23#include <sys/socket.h>
24#include <sys/time.h>
25#include <sys/uio.h>
26#include <sys/wait.h>
27
28#include <err.h>
29#include <errno(*__errno()).h>
30#include <event.h>
31#include <fcntl.h>
32#include <fnmatch.h>
33#include <imsg.h>
34#include <md5.h>
35#include <netdb.h>
36#include <pwd.h>
37#include <signal.h>
38#include <stdbool.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <syslog.h>
43#include <unistd.h>
44
45#include <radius.h>
46
47#include "radiusd.h"
48#include "radiusd_local.h"
49#include "log.h"
50#include "util.h"
51#include "imsg_subr.h"
52
53static int radiusd_start(struct radiusd *);
54static void radiusd_stop(struct radiusd *);
55static void radiusd_free(struct radiusd *);
56static void radiusd_listen_on_event(int, short, void *);
57static void radiusd_on_sigterm(int, short, void *);
58static void radiusd_on_sigint(int, short, void *);
59static void radiusd_on_sighup(int, short, void *);
60static void radiusd_on_sigchld(int, short, void *);
61static void radius_query_request(struct radius_query *);
62static void radius_query_response(struct radius_query *);
63static const char *radius_code_string(int);
64static int radiusd_access_response_fixup (struct radius_query *);
65
66
67
68static void radiusd_module_reset_ev_handler(
69 struct radiusd_module *);
70static int radiusd_module_imsg_read(struct radiusd_module *,
71 bool_Bool);
72static void radiusd_module_imsg(struct radiusd_module *,
73 struct imsg *);
74
75static struct radiusd_module_radpkt_arg *
76 radiusd_module_recv_radpkt(struct radiusd_module *,
77 struct imsg *, uint32_t, const char *);
78static void radiusd_module_on_imsg_io(int, short, void *);
79void radiusd_module_start(struct radiusd_module *);
80void radiusd_module_stop(struct radiusd_module *);
81static void radiusd_module_close(struct radiusd_module *);
82static void radiusd_module_userpass(struct radiusd_module *,
83 struct radius_query *);
84static void radiusd_module_access_request(struct radiusd_module *,
85 struct radius_query *);
86static void radiusd_module_request_decoration(
87 struct radiusd_module *, struct radius_query *);
88static void radiusd_module_response_decoration(
89 struct radiusd_module *, struct radius_query *);
90static int imsg_compose_radius_packet(struct imsgbuf *,
91 uint32_t, u_int, RADIUS_PACKET *);
92
93static u_int radius_query_id_seq = 0;
94int debug = 0;
95
96static __dead__attribute__((__noreturn__)) void
97usage(void)
98{
99 extern char *__progname;
100
101 fprintf(stderr(&__sF[2]), "usage: %s [-dn] [-f file]\n", __progname);
102 exit(EXIT_FAILURE1);
103}
104
105int
106main(int argc, char *argv[])
107{
108 extern char *__progname;
109 const char *conffile = CONFFILE"/etc/radiusd.conf";
110 int ch;
111 struct radiusd *radiusd;
112 bool_Bool noaction = false0;
113 struct passwd *pw;
114
115 while ((ch = getopt(argc, argv, "df:n")) != -1)
116 switch (ch) {
117 case 'd':
118 debug++;
119 break;
120
121 case 'f':
122 conffile = optarg;
123 break;
124
125 case 'n':
126 noaction = true1;
127 break;
128
129 default:
130 usage();
131 /* NOTREACHED */
132 }
133
134 argc -= optind;
135 argv += optind;
136
137 if (argc != 0)
138 usage();
139
140 if ((radiusd = calloc(1, sizeof(*radiusd))) == NULL((void *)0))
141 err(1, "calloc");
142 TAILQ_INIT(&radiusd->listen)do { (&radiusd->listen)->tqh_first = ((void *)0); (
&radiusd->listen)->tqh_last = &(&radiusd->
listen)->tqh_first; } while (0)
;
143 TAILQ_INIT(&radiusd->query)do { (&radiusd->query)->tqh_first = ((void *)0); (&
radiusd->query)->tqh_last = &(&radiusd->query
)->tqh_first; } while (0)
;
144
145 log_init(debug);
146 if (parse_config(conffile, radiusd) != 0)
147 errx(EXIT_FAILURE1, "config error");
148 if (noaction) {
149 fprintf(stderr(&__sF[2]), "configuration OK\n");
150 exit(EXIT_SUCCESS0);
151 }
152
153 if (debug == 0)
154 daemon(0, 0);
155 event_init();
156
157 if ((pw = getpwnam(RADIUSD_USER"_radiusd")) == NULL((void *)0))
158 errx(EXIT_FAILURE1, "user `%s' is not found in password "
159 "database", RADIUSD_USER"_radiusd");
160
161 if (chroot(pw->pw_dir) == -1)
162 err(EXIT_FAILURE1, "chroot");
163 if (chdir("/") == -1)
164 err(EXIT_FAILURE1, "chdir(\"/\")");
165
166 if (setgroups(1, &pw->pw_gid) ||
167 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
168 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
169 err(EXIT_FAILURE1, "cannot drop privileges");
170
171 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
172 openlog(NULL((void *)0), LOG_PID0x01, LOG_DAEMON(3<<3));
173
174 signal_set(&radiusd->ev_sigterm, SIGTERM, radiusd_on_sigterm, radiusd)event_set(&radiusd->ev_sigterm, 15, 0x08|0x10, radiusd_on_sigterm
, radiusd)
;
175 signal_set(&radiusd->ev_sigint, SIGINT, radiusd_on_sigint, radiusd)event_set(&radiusd->ev_sigint, 2, 0x08|0x10, radiusd_on_sigint
, radiusd)
;
176 signal_set(&radiusd->ev_sighup, SIGHUP, radiusd_on_sighup, radiusd)event_set(&radiusd->ev_sighup, 1, 0x08|0x10, radiusd_on_sighup
, radiusd)
;
177 signal_set(&radiusd->ev_sigchld, SIGCHLD, radiusd_on_sigchld, radiusd)event_set(&radiusd->ev_sigchld, 20, 0x08|0x10, radiusd_on_sigchld
, radiusd)
;
178
179 if (radiusd_start(radiusd) != 0)
180 errx(EXIT_FAILURE1, "start failed");
181
182 if (pledge("stdio inet", NULL((void *)0)) == -1)
183 err(EXIT_FAILURE1, "pledge");
184
185 if (event_loop(0) < 0)
186 radiusd_stop(radiusd);
187
188 radiusd_free(radiusd);
189 event_base_free(NULL((void *)0));
190
191 exit(EXIT_SUCCESS0);
192}
193
194static int
195radiusd_start(struct radiusd *radiusd)
196{
197 struct radiusd_listen *l;
198 struct radiusd_module *module;
199 int s;
200 char hbuf[NI_MAXHOST256];
201
202 TAILQ_FOREACH(l, &radiusd->listen, next)for((l) = ((&radiusd->listen)->tqh_first); (l) != (
(void *)0); (l) = ((l)->next.tqe_next))
{
203 if (getnameinfo(
204 (struct sockaddr *)&l->addr, l->addr.ipv4.sin_len,
205 hbuf, sizeof(hbuf), NULL((void *)0), 0, NI_NUMERICHOST1) != 0) {
206 log_warn("%s: getnameinfo()", __func__);
207 goto on_error;
208 }
209 if ((s = socket(l->addr.ipv4.sin_family,
210 l->stype | SOCK_NONBLOCK0x4000, l->sproto)) == -1) {
211 log_warn("Listen %s port %d is failed: socket()",
212 hbuf, (int)htons(l->addr.ipv4.sin_port)(__uint16_t)(__builtin_constant_p(l->addr.ipv4.sin_port) ?
(__uint16_t)(((__uint16_t)(l->addr.ipv4.sin_port) & 0xffU
) << 8 | ((__uint16_t)(l->addr.ipv4.sin_port) & 0xff00U
) >> 8) : __swap16md(l->addr.ipv4.sin_port))
);
213 goto on_error;
214 }
215 if (bind(s, (struct sockaddr *)&l->addr, l->addr.ipv4.sin_len)
216 != 0) {
217 log_warn("Listen %s port %d is failed: bind()",
218 hbuf, (int)htons(l->addr.ipv4.sin_port)(__uint16_t)(__builtin_constant_p(l->addr.ipv4.sin_port) ?
(__uint16_t)(((__uint16_t)(l->addr.ipv4.sin_port) & 0xffU
) << 8 | ((__uint16_t)(l->addr.ipv4.sin_port) & 0xff00U
) >> 8) : __swap16md(l->addr.ipv4.sin_port))
);
219 close(s);
220 goto on_error;
221 }
222 if (l->addr.ipv4.sin_family == AF_INET2)
223 log_info("Start listening on %s:%d/udp", hbuf,
224 (int)ntohs(l->addr.ipv4.sin_port)(__uint16_t)(__builtin_constant_p(l->addr.ipv4.sin_port) ?
(__uint16_t)(((__uint16_t)(l->addr.ipv4.sin_port) & 0xffU
) << 8 | ((__uint16_t)(l->addr.ipv4.sin_port) & 0xff00U
) >> 8) : __swap16md(l->addr.ipv4.sin_port))
);
225 else
226 log_info("Start listening on [%s]:%d/udp", hbuf,
227 (int)ntohs(l->addr.ipv4.sin_port)(__uint16_t)(__builtin_constant_p(l->addr.ipv4.sin_port) ?
(__uint16_t)(((__uint16_t)(l->addr.ipv4.sin_port) & 0xffU
) << 8 | ((__uint16_t)(l->addr.ipv4.sin_port) & 0xff00U
) >> 8) : __swap16md(l->addr.ipv4.sin_port))
);
228 event_set(&l->ev, s, EV_READ0x02 | EV_PERSIST0x10,
229 radiusd_listen_on_event, l);
230 if (event_add(&l->ev, NULL((void *)0)) != 0) {
231 log_warn("event_add() failed at %s()", __func__);
232 close(s);
233 goto on_error;
234 }
235 l->sock = s;
236 l->radiusd = radiusd;
237 }
238
239 signal_add(&radiusd->ev_sigterm, NULL)event_add(&radiusd->ev_sigterm, ((void *)0));
240 signal_add(&radiusd->ev_sigint, NULL)event_add(&radiusd->ev_sigint, ((void *)0));
241 signal_add(&radiusd->ev_sighup, NULL)event_add(&radiusd->ev_sighup, ((void *)0));
242 signal_add(&radiusd->ev_sigchld, NULL)event_add(&radiusd->ev_sigchld, ((void *)0));
243
244 TAILQ_FOREACH(module, &radiusd->module, next)for((module) = ((&radiusd->module)->tqh_first); (module
) != ((void *)0); (module) = ((module)->next.tqe_next))
{
245 if (debug > 0)
246 radiusd_module_set(module, "_debug", 0, NULL((void *)0));
247 radiusd_module_start(module);
248 }
249
250 return (0);
251on_error:
252 radiusd_stop(radiusd);
253
254 return (-1);
255}
256
257static void
258radiusd_stop(struct radiusd *radiusd)
259{
260 char hbuf[NI_MAXHOST256];
261 struct radiusd_listen *l;
262 struct radiusd_module *module;
263
264 TAILQ_FOREACH_REVERSE(l, &radiusd->listen, radiusd_listen_head, next)for((l) = (*(((struct radiusd_listen_head *)((&radiusd->
listen)->tqh_last))->tqh_last)); (l) != ((void *)0); (l
) = (*(((struct radiusd_listen_head *)((l)->next.tqe_prev)
)->tqh_last)))
{
265 if (l->sock >= 0) {
266 if (getnameinfo(
267 (struct sockaddr *)&l->addr, l->addr.ipv4.sin_len,
268 hbuf, sizeof(hbuf), NULL((void *)0), 0, NI_NUMERICHOST1) != 0)
269 strlcpy(hbuf, "error", sizeof(hbuf));
270 if (l->addr.ipv4.sin_family == AF_INET2)
271 log_info("Stop listening on %s:%d/udp", hbuf,
272 (int)ntohs(l->addr.ipv4.sin_port)(__uint16_t)(__builtin_constant_p(l->addr.ipv4.sin_port) ?
(__uint16_t)(((__uint16_t)(l->addr.ipv4.sin_port) & 0xffU
) << 8 | ((__uint16_t)(l->addr.ipv4.sin_port) & 0xff00U
) >> 8) : __swap16md(l->addr.ipv4.sin_port))
);
273 else
274 log_info("Stop listening on [%s]:%d/udp", hbuf,
275 (int)ntohs(l->addr.ipv4.sin_port)(__uint16_t)(__builtin_constant_p(l->addr.ipv4.sin_port) ?
(__uint16_t)(((__uint16_t)(l->addr.ipv4.sin_port) & 0xffU
) << 8 | ((__uint16_t)(l->addr.ipv4.sin_port) & 0xff00U
) >> 8) : __swap16md(l->addr.ipv4.sin_port))
);
276 event_del(&l->ev);
277 close(l->sock);
278 }
279 l->sock = -1;
280 }
281 TAILQ_FOREACH(module, &radiusd->module, next)for((module) = ((&radiusd->module)->tqh_first); (module
) != ((void *)0); (module) = ((module)->next.tqe_next))
{
282 radiusd_module_stop(module);
283 radiusd_module_close(module);
284 }
285 if (signal_pending(&radiusd->ev_sigterm, NULL)event_pending(&radiusd->ev_sigterm, 0x08, ((void *)0)))
286 signal_del(&radiusd->ev_sigterm)event_del(&radiusd->ev_sigterm);
287 if (signal_pending(&radiusd->ev_sigint, NULL)event_pending(&radiusd->ev_sigint, 0x08, ((void *)0)))
288 signal_del(&radiusd->ev_sigint)event_del(&radiusd->ev_sigint);
289 if (signal_pending(&radiusd->ev_sighup, NULL)event_pending(&radiusd->ev_sighup, 0x08, ((void *)0)))
290 signal_del(&radiusd->ev_sighup)event_del(&radiusd->ev_sighup);
291 if (signal_pending(&radiusd->ev_sigchld, NULL)event_pending(&radiusd->ev_sigchld, 0x08, ((void *)0)))
292 signal_del(&radiusd->ev_sigchld)event_del(&radiusd->ev_sigchld);
293}
294
295static void
296radiusd_free(struct radiusd *radiusd)
297{
298 int i;
299 struct radiusd_listen *listn, *listnt;
300 struct radiusd_client *client, *clientt;
301 struct radiusd_module *module, *modulet;
302 struct radiusd_module_ref *modref, *modreft;
303 struct radiusd_authentication *authen, *authent;
304
305 TAILQ_FOREACH_SAFE(authen, &radiusd->authen, next, authent)for ((authen) = ((&radiusd->authen)->tqh_first); (authen
) != ((void *)0) && ((authent) = ((authen)->next.tqe_next
), 1); (authen) = (authent))
{
306 TAILQ_REMOVE(&radiusd->authen, authen, next)do { if (((authen)->next.tqe_next) != ((void *)0)) (authen
)->next.tqe_next->next.tqe_prev = (authen)->next.tqe_prev
; else (&radiusd->authen)->tqh_last = (authen)->
next.tqe_prev; *(authen)->next.tqe_prev = (authen)->next
.tqe_next; ; ; } while (0)
;
307 free(authen->auth);
308 TAILQ_FOREACH_SAFE(modref, &authen->deco, next, modreft)for ((modref) = ((&authen->deco)->tqh_first); (modref
) != ((void *)0) && ((modreft) = ((modref)->next.tqe_next
), 1); (modref) = (modreft))
{
309 TAILQ_REMOVE(&authen->deco, modref, next)do { if (((modref)->next.tqe_next) != ((void *)0)) (modref
)->next.tqe_next->next.tqe_prev = (modref)->next.tqe_prev
; else (&authen->deco)->tqh_last = (modref)->next
.tqe_prev; *(modref)->next.tqe_prev = (modref)->next.tqe_next
; ; ; } while (0)
;
310 free(modref);
311 }
312 for (i = 0; authen->username[i] != NULL((void *)0); i++)
313 free(authen->username[i]);
314 free(authen->username);
315 free(authen);
316 }
317 TAILQ_FOREACH_SAFE(module, &radiusd->module, next, modulet)for ((module) = ((&radiusd->module)->tqh_first); (module
) != ((void *)0) && ((modulet) = ((module)->next.tqe_next
), 1); (module) = (modulet))
{
318 TAILQ_REMOVE(&radiusd->module, module, next)do { if (((module)->next.tqe_next) != ((void *)0)) (module
)->next.tqe_next->next.tqe_prev = (module)->next.tqe_prev
; else (&radiusd->module)->tqh_last = (module)->
next.tqe_prev; *(module)->next.tqe_prev = (module)->next
.tqe_next; ; ; } while (0)
;
319 radiusd_module_unload(module);
320 }
321 TAILQ_FOREACH_SAFE(client, &radiusd->client, next, clientt)for ((client) = ((&radiusd->client)->tqh_first); (client
) != ((void *)0) && ((clientt) = ((client)->next.tqe_next
), 1); (client) = (clientt))
{
322 TAILQ_REMOVE(&radiusd->client, client, next)do { if (((client)->next.tqe_next) != ((void *)0)) (client
)->next.tqe_next->next.tqe_prev = (client)->next.tqe_prev
; else (&radiusd->client)->tqh_last = (client)->
next.tqe_prev; *(client)->next.tqe_prev = (client)->next
.tqe_next; ; ; } while (0)
;
323 explicit_bzero(client->secret, sizeof(client->secret));
324 free(client);
325 }
326 TAILQ_FOREACH_SAFE(listn, &radiusd->listen, next, listnt)for ((listn) = ((&radiusd->listen)->tqh_first); (listn
) != ((void *)0) && ((listnt) = ((listn)->next.tqe_next
), 1); (listn) = (listnt))
{
327 TAILQ_REMOVE(&radiusd->listen, listn, next)do { if (((listn)->next.tqe_next) != ((void *)0)) (listn)->
next.tqe_next->next.tqe_prev = (listn)->next.tqe_prev; else
(&radiusd->listen)->tqh_last = (listn)->next.tqe_prev
; *(listn)->next.tqe_prev = (listn)->next.tqe_next; ; ;
} while (0)
;
328 free(listn);
329 }
330 free(radiusd);
331}
332
333/***********************************************************************
334 * Network event handlers
335 ***********************************************************************/
336#define IPv4_cmp(_in, _addr, _mask)( ((_in)->s_addr & (_mask)->addr.ipv4.s_addr) == (_addr
)->addr.ipv4.s_addr)
( \
337 ((_in)->s_addr & (_mask)->addr.ipv4.s_addr) == \
338 (_addr)->addr.ipv4.s_addr)
339#define s6_addr32(_in6)((uint32_t *)(_in6)->__u6_addr.__u6_addr8) ((uint32_t *)(_in6)->s6_addr__u6_addr.__u6_addr8)
340#define IPv6_cmp(_in6, _addr, _mask)( ((((uint32_t *)(_in6)->__u6_addr.__u6_addr8)[3] & (_mask
)->addr.addr32[3]) == (_addr)->addr.addr32[3]) &&
((((uint32_t *)(_in6)->__u6_addr.__u6_addr8)[2] & (_mask
)->addr.addr32[2]) == (_addr)->addr.addr32[2]) &&
((((uint32_t *)(_in6)->__u6_addr.__u6_addr8)[1] & (_mask
)->addr.addr32[1]) == (_addr)->addr.addr32[1]) &&
((((uint32_t *)(_in6)->__u6_addr.__u6_addr8)[0] & (_mask
)->addr.addr32[0]) == (_addr)->addr.addr32[0]))
( \
341 ((s6_addr32(_in6)((uint32_t *)(_in6)->__u6_addr.__u6_addr8)[3] & (_mask)->addr.addr32[3]) \
342 == (_addr)->addr.addr32[3]) && \
343 ((s6_addr32(_in6)((uint32_t *)(_in6)->__u6_addr.__u6_addr8)[2] & (_mask)->addr.addr32[2]) \
344 == (_addr)->addr.addr32[2]) && \
345 ((s6_addr32(_in6)((uint32_t *)(_in6)->__u6_addr.__u6_addr8)[1] & (_mask)->addr.addr32[1]) \
346 == (_addr)->addr.addr32[1]) && \
347 ((s6_addr32(_in6)((uint32_t *)(_in6)->__u6_addr.__u6_addr8)[0] & (_mask)->addr.addr32[0]) \
348 == (_addr)->addr.addr32[0]))
349
350static void
351radiusd_listen_on_event(int fd, short evmask, void *ctx)
352{
353 int i, sz, req_id, req_code;
354 struct radiusd_listen *listn = ctx;
355 static u_char buf[65535];
356 static char username[256];
357 struct sockaddr_storage peer;
358 socklen_t peersz;
359 RADIUS_PACKET *packet = NULL((void *)0);
360 char peerstr[NI_MAXHOST256 + NI_MAXSERV32 + 30];
361 struct radiusd_authentication *authen;
362 struct radiusd_client *client;
363 struct radius_query *q;
364#define in(_x) (((struct sockaddr_in *)_x)->sin_addr)
365#define in6(_x) (((struct sockaddr_in6 *)_x)->sin6_addr)
366
367 if (evmask & EV_READ0x02) {
368 peersz = sizeof(peer);
369 if ((sz = recvfrom(listn->sock, buf, sizeof(buf), 0,
370 (struct sockaddr *)&peer, &peersz)) == -1) {
371 if (errno(*__errno()) == EAGAIN35)
372 return;
373 log_warn("%s: recvfrom() failed", __func__);
374 goto on_error;
375 }
376 RADIUSD_ASSERT(peer.ss_family == AF_INET ||do { if (!(peer.ss_family == 2 || peer.ss_family == 24)) { log_warnx
( "ASSERT(%s) failed in %s() at %s:%d", "peer.ss_family == AF_INET || peer.ss_family == AF_INET6"
, __func__, "/usr/src/usr.sbin/radiusd/radiusd/../radiusd.c",
377); if (debug) abort(); } } while (0 )
377 peer.ss_family == AF_INET6)do { if (!(peer.ss_family == 2 || peer.ss_family == 24)) { log_warnx
( "ASSERT(%s) failed in %s() at %s:%d", "peer.ss_family == AF_INET || peer.ss_family == AF_INET6"
, __func__, "/usr/src/usr.sbin/radiusd/radiusd/../radiusd.c",
377); if (debug) abort(); } } while (0 )
;
378
379 /* prepare some information about this messages */
380 if (addrport_tostring((struct sockaddr *)&peer, peersz,
381 peerstr, sizeof(peerstr)) == NULL((void *)0)) {
382 log_warn("%s: getnameinfo() failed", __func__);
383 goto on_error;
384 }
385 if ((packet = radius_convert_packet(buf, sz)) == NULL((void *)0)) {
386 log_warn("%s: radius_convert_packet() failed",
387 __func__);
388 goto on_error;
389 }
390 req_id = radius_get_id(packet);
391 req_code = radius_get_code(packet);
392
393 /*
394 * Find a matching `client' entry
395 */
396 TAILQ_FOREACH(client, &listn->radiusd->client, next)for((client) = ((&listn->radiusd->client)->tqh_first
); (client) != ((void *)0); (client) = ((client)->next.tqe_next
))
{
397 if (client->af != peer.ss_family)
398 continue;
399 if (peer.ss_family == AF_INET2 &&
400 IPv4_cmp(&((struct sockaddr_in *)&peer)->sin_addr,( ((&((struct sockaddr_in *)&peer)->sin_addr)->
s_addr & (&client->mask)->addr.ipv4.s_addr) == (
&client->addr)->addr.ipv4.s_addr)
401 &client->addr, &client->mask)( ((&((struct sockaddr_in *)&peer)->sin_addr)->
s_addr & (&client->mask)->addr.ipv4.s_addr) == (
&client->addr)->addr.ipv4.s_addr)
)
402 break;
403 else if (peer.ss_family == AF_INET624 &&
404 IPv6_cmp(&((struct sockaddr_in6 *)&peer)->sin6_addr,( ((((uint32_t *)(&((struct sockaddr_in6 *)&peer)->
sin6_addr)->__u6_addr.__u6_addr8)[3] & (&client->
mask)->addr.addr32[3]) == (&client->addr)->addr.
addr32[3]) && ((((uint32_t *)(&((struct sockaddr_in6
*)&peer)->sin6_addr)->__u6_addr.__u6_addr8)[2] &
(&client->mask)->addr.addr32[2]) == (&client->
addr)->addr.addr32[2]) && ((((uint32_t *)(&((struct
sockaddr_in6 *)&peer)->sin6_addr)->__u6_addr.__u6_addr8
)[1] & (&client->mask)->addr.addr32[1]) == (&
client->addr)->addr.addr32[1]) && ((((uint32_t *
)(&((struct sockaddr_in6 *)&peer)->sin6_addr)->
__u6_addr.__u6_addr8)[0] & (&client->mask)->addr
.addr32[0]) == (&client->addr)->addr.addr32[0]))
405 &client->addr, &client->mask)( ((((uint32_t *)(&((struct sockaddr_in6 *)&peer)->
sin6_addr)->__u6_addr.__u6_addr8)[3] & (&client->
mask)->addr.addr32[3]) == (&client->addr)->addr.
addr32[3]) && ((((uint32_t *)(&((struct sockaddr_in6
*)&peer)->sin6_addr)->__u6_addr.__u6_addr8)[2] &
(&client->mask)->addr.addr32[2]) == (&client->
addr)->addr.addr32[2]) && ((((uint32_t *)(&((struct
sockaddr_in6 *)&peer)->sin6_addr)->__u6_addr.__u6_addr8
)[1] & (&client->mask)->addr.addr32[1]) == (&
client->addr)->addr.addr32[1]) && ((((uint32_t *
)(&((struct sockaddr_in6 *)&peer)->sin6_addr)->
__u6_addr.__u6_addr8)[0] & (&client->mask)->addr
.addr32[0]) == (&client->addr)->addr.addr32[0]))
)
406 break;
407 }
408 if (client == NULL((void *)0)) {
409 log_warnx("Received %s(code=%d) from %s id=%d: "
410 "no `client' matches", radius_code_string(req_code),
411 req_code, peerstr, req_id);
412 goto on_error;
413 }
414
415 /* Check the client's Message-Authenticator */
416 if (client->msgauth_required &&
417 !radius_has_attr(packet,
418 RADIUS_TYPE_MESSAGE_AUTHENTICATOR80)) {
419 log_warnx("Received %s(code=%d) from %s id=%d: "
420 "no message authenticator",
421 radius_code_string(req_code), req_code, peerstr,
422 req_id);
423 goto on_error;
424 }
425
426 if (radius_has_attr(packet,
427 RADIUS_TYPE_MESSAGE_AUTHENTICATOR80) &&
428 radius_check_message_authenticator(packet, client->secret)
429 != 0) {
430 log_warnx("Received %s(code=%d) from %s id=%d: "
431 "bad message authenticator",
432 radius_code_string(req_code), req_code, peerstr,
433 req_id);
434 goto on_error;
435 }
436
437 /*
438 * Find a duplicate request. In RFC 2865, it has the same
439 * source IP address and source UDP port and Identifier.
440 */
441 TAILQ_FOREACH(q, &listn->radiusd->query, next)for((q) = ((&listn->radiusd->query)->tqh_first);
(q) != ((void *)0); (q) = ((q)->next.tqe_next))
{
442 if (peer.ss_family == q->clientaddr.ss_family &&
443 ((peer.ss_family == AF_INET2 &&
444 in(&q->clientaddr).s_addr ==
445 in(&peer).s_addr) ||
446 (peer.ss_family == AF_INET624 &&
447 IN6_ARE_ADDR_EQUAL((memcmp(&(&in6(&q->clientaddr))->__u6_addr.
__u6_addr8[0], &(&in6(&peer))->__u6_addr.__u6_addr8
[0], sizeof(struct in6_addr)) == 0)
448 &in6(&q->clientaddr), &in6(&peer))(memcmp(&(&in6(&q->clientaddr))->__u6_addr.
__u6_addr8[0], &(&in6(&peer))->__u6_addr.__u6_addr8
[0], sizeof(struct in6_addr)) == 0)
)) &&
449 ((struct sockaddr_in *)&q->clientaddr)->sin_port ==
450 ((struct sockaddr_in *)&peer)->sin_port &&
451 req_id == q->req_id)
452 break; /* found it */
453 }
454 if (q != NULL((void *)0)) {
455 log_info("Received %s(code=%d) from %s id=%d: "
456 "duplicate request by q=%u",
457 radius_code_string(req_code), req_code, peerstr,
458 req_id, q->id);
459 /* XXX RFC 5080 suggests to answer the cached result */
460 goto on_error;
461 }
462
463 /* FIXME: we can support other request codes */
464 if (req_code != RADIUS_CODE_ACCESS_REQUEST1) {
465 log_info("Received %s(code=%d) from %s id=%d: %s "
466 "is not supported in this implementation",
467 radius_code_string(req_code), req_code, peerstr,
468 req_id, radius_code_string(req_code));
469 goto on_error;
470 }
471
472 /*
473 * Find a matching `authenticate' entry
474 */
475 if (radius_get_string_attr(packet, RADIUS_TYPE_USER_NAME1,
476 username, sizeof(username)) != 0) {
477 log_info("Received %s(code=%d) from %s id=%d: "
478 "no User-Name attribute",
479 radius_code_string(req_code), req_code, peerstr,
480 req_id);
481 goto on_error;
482 }
483 TAILQ_FOREACH(authen, &listn->radiusd->authen, next)for((authen) = ((&listn->radiusd->authen)->tqh_first
); (authen) != ((void *)0); (authen) = ((authen)->next.tqe_next
))
{
484 for (i = 0; authen->username[i] != NULL((void *)0); i++) {
485 if (fnmatch(authen->username[i], username, 0)
486 == 0)
487 goto found;
488 }
489 }
490found:
491 if (authen == NULL((void *)0)) {
492 log_warnx("Received %s(code=%d) from %s id=%d "
493 "username=%s: no `authenticate' matches.",
494 radius_code_string(req_code), req_code, peerstr,
495 req_id, username);
496 goto on_error;
497 }
498 RADIUSD_ASSERT(authen->auth != NULL)do { if (!(authen->auth != ((void *)0))) { log_warnx( "ASSERT(%s) failed in %s() at %s:%d"
, "authen->auth != NULL", __func__, "/usr/src/usr.sbin/radiusd/radiusd/../radiusd.c"
, 498); if (debug) abort(); } } while (0 )
;
499
500 if (!MODULE_DO_USERPASS(authen->auth->module)((authen->auth->module)->fd >= 0 && ((authen
->auth->module)->capabilities & 0x1) != 0)
&&
501 !MODULE_DO_ACCSREQ(authen->auth->module)((authen->auth->module)->fd >= 0 && ((authen
->auth->module)->capabilities & 0x2) != 0)
) {
502 log_warnx("Received %s(code=%d) from %s id=%d "
503 "username=%s: module `%s' is not running.",
504 radius_code_string(req_code), req_code, peerstr,
505 req_id, username, authen->auth->module->name);
506 goto on_error;
507 }
508 if ((q = calloc(1, sizeof(struct radius_query))) == NULL((void *)0)) {
509 log_warn("%s: Out of memory", __func__);
510 goto on_error;
511 }
512 memcpy(&q->clientaddr, &peer, peersz);
513 strlcpy(q->username, username, sizeof(q->username));
514 q->id = ++radius_query_id_seq;
515 q->clientaddrlen = peersz;
516 q->authen = authen;
517 q->listen = listn;
518 q->req = packet;
519 q->client = client;
520 q->req_id = req_id;
521 radius_get_authenticator(packet, q->req_auth);
522
523 log_info("Received %s(code=%d) from %s id=%d username=%s "
524 "q=%u: `%s' authentication is starting",
525 radius_code_string(req_code), req_code, peerstr, q->req_id,
526 q->username, q->id, q->authen->auth->module->name);
527 TAILQ_INSERT_TAIL(&listn->radiusd->query, q, next)do { (q)->next.tqe_next = ((void *)0); (q)->next.tqe_prev
= (&listn->radiusd->query)->tqh_last; *(&listn
->radiusd->query)->tqh_last = (q); (&listn->radiusd
->query)->tqh_last = &(q)->next.tqe_next; } while
(0)
;
528
529 radius_query_request(q);
530
531 return;
532 }
533on_error:
534 if (packet != NULL((void *)0))
535 radius_delete_packet(packet);
536#undef in
537#undef in6
538
539 return;
540}
541
542static void
543radius_query_request(struct radius_query *q)
544{
545 struct radiusd_authentication *authen = q->authen;
546
547 /* first or next request decoration */
548 for (;;) {
549 if (q->deco == NULL((void *)0))
550 q->deco = TAILQ_FIRST(&q->authen->deco)((&q->authen->deco)->tqh_first);
551 else
552 q->deco = TAILQ_NEXT(q->deco, next)((q->deco)->next.tqe_next);
553 if (q->deco == NULL((void *)0) || MODULE_DO_REQDECO(q->deco->module)((q->deco->module)->fd >= 0 && ((q->deco
->module)->capabilities & 0x4) != 0)
)
554 break;
555 }
556
557 if (q->deco != NULL((void *)0))
558 radiusd_module_request_decoration(q->deco->module, q);
559 else {
560 RADIUSD_ASSERT(authen->auth != NULL)do { if (!(authen->auth != ((void *)0))) { log_warnx( "ASSERT(%s) failed in %s() at %s:%d"
, "authen->auth != NULL", __func__, "/usr/src/usr.sbin/radiusd/radiusd/../radiusd.c"
, 560); if (debug) abort(); } } while (0 )
;
561 if (MODULE_DO_ACCSREQ(authen->auth->module)((authen->auth->module)->fd >= 0 && ((authen
->auth->module)->capabilities & 0x2) != 0)
)
562 radiusd_module_access_request(authen->auth->module, q);
563 else if (MODULE_DO_USERPASS(authen->auth->module)((authen->auth->module)->fd >= 0 && ((authen
->auth->module)->capabilities & 0x1) != 0)
)
564 radiusd_module_userpass(authen->auth->module, q);
565 }
566}
567
568static void
569radius_query_response(struct radius_query *q)
570{
571 int sz, res_id, res_code;
572 char buf[NI_MAXHOST256 + NI_MAXSERV32 + 30];
573
574 /* first or next response decoration */
575 for (;;) {
576 if (q->deco == NULL((void *)0))
577 q->deco = TAILQ_FIRST(&q->authen->deco)((&q->authen->deco)->tqh_first);
578 else
579 q->deco = TAILQ_NEXT(q->deco, next)((q->deco)->next.tqe_next);
580 if (q->deco == NULL((void *)0) || MODULE_DO_RESDECO(q->deco->module)((q->deco->module)->fd >= 0 && ((q->deco
->module)->capabilities & 0x8) != 0)
)
581 break;
582 }
583
584 if (q->deco != NULL((void *)0)) {
585 radiusd_module_response_decoration(q->deco->module, q);
586 return;
587 }
588
589 if (radiusd_access_response_fixup(q) != 0)
590 goto on_error;
591
592 res_id = radius_get_id(q->res);
593 res_code = radius_get_code(q->res);
594
595 /* Reset response/message authenticator */
596 if (radius_has_attr(q->res, RADIUS_TYPE_MESSAGE_AUTHENTICATOR80))
597 radius_del_attr_all(q->res, RADIUS_TYPE_MESSAGE_AUTHENTICATOR80);
598 radius_put_message_authenticator(q->res, q->client->secret);
599 radius_set_response_authenticator(q->res, q->client->secret);
600
601 log_info("Sending %s(code=%d) to %s id=%u q=%u",
602 radius_code_string(res_code), res_code,
603 addrport_tostring((struct sockaddr *)&q->clientaddr,
604 q->clientaddrlen, buf, sizeof(buf)), res_id, q->id);
605
606 if ((sz = sendto(q->listen->sock, radius_get_data(q->res),
Although the value stored to 'sz' is used in the enclosing expression, the value is never actually read from 'sz'
607 radius_get_length(q->res), 0,
608 (struct sockaddr *)&q->clientaddr, q->clientaddrlen)) <= 0)
609 log_warn("Sending a RADIUS response failed");
610on_error:
611 radiusd_access_request_aborted(q);
612
613}
614
615/***********************************************************************
616 * Callback functions from the modules
617 ***********************************************************************/
618void
619radiusd_access_request_answer(struct radius_query *q)
620{
621 const char *authen_secret = q->authen->auth->module->secret;
622
623 radius_set_request_packet(q->res, q->req);
624
625 if (authen_secret == NULL((void *)0)) {
626 /*
627 * The module diddn't check the authenticators
628 */
629 if (radius_check_response_authenticator(q->res,
630 q->client->secret) != 0) {
631 log_info("Response from module has bad response "
632 "authenticator: id=%d", q->id);
633 goto on_error;
634 }
635 if (radius_has_attr(q->res,
636 RADIUS_TYPE_MESSAGE_AUTHENTICATOR80) &&
637 radius_check_message_authenticator(q->res,
638 q->client->secret) != 0) {
639 log_info("Response from module has bad message "
640 "authenticator: id=%d", q->id);
641 goto on_error;
642 }
643 }
644
645 RADIUSD_ASSERT(q->deco == NULL)do { if (!(q->deco == ((void *)0))) { log_warnx( "ASSERT(%s) failed in %s() at %s:%d"
, "q->deco == NULL", __func__, "/usr/src/usr.sbin/radiusd/radiusd/../radiusd.c"
, 645); if (debug) abort(); } } while (0 )
;
646 radius_query_response(q);
647
648 return;
649on_error:
650 radiusd_access_request_aborted(q);
651}
652
653void
654radiusd_access_request_aborted(struct radius_query *q)
655{
656 if (q->req != NULL((void *)0))
657 radius_delete_packet(q->req);
658 if (q->res != NULL((void *)0))
659 radius_delete_packet(q->res);
660 TAILQ_REMOVE(&q->listen->radiusd->query, q, next)do { if (((q)->next.tqe_next) != ((void *)0)) (q)->next
.tqe_next->next.tqe_prev = (q)->next.tqe_prev; else (&
q->listen->radiusd->query)->tqh_last = (q)->next
.tqe_prev; *(q)->next.tqe_prev = (q)->next.tqe_next; ; ;
} while (0)
;
661 free(q);
662}
663
664/***********************************************************************
665 * Signal handlers
666 ***********************************************************************/
667static void
668radiusd_on_sigterm(int fd, short evmask, void *ctx)
669{
670 struct radiusd *radiusd = ctx;
671
672 log_info("Received SIGTERM");
673 radiusd_stop(radiusd);
674}
675
676static void
677radiusd_on_sigint(int fd, short evmask, void *ctx)
678{
679 struct radiusd *radiusd = ctx;
680
681 log_info("Received SIGINT");
682 radiusd_stop(radiusd);
683}
684
685static void
686radiusd_on_sighup(int fd, short evmask, void *ctx)
687{
688 log_info("Received SIGHUP");
689}
690
691static void
692radiusd_on_sigchld(int fd, short evmask, void *ctx)
693{
694 struct radiusd *radiusd = ctx;
695 struct radiusd_module *module;
696 pid_t pid;
697 int status;
698
699 log_debug("Received SIGCHLD");
700 while ((pid = wait3(&status, WNOHANG0x01, NULL((void *)0))) != 0) {
701 if (pid == -1)
702 break;
703 TAILQ_FOREACH(module, &radiusd->module, next)for((module) = ((&radiusd->module)->tqh_first); (module
) != ((void *)0); (module) = ((module)->next.tqe_next))
{
704 if (module->pid == pid) {
705 if (WIFEXITED(status)(((status) & 0177) == 0))
706 log_warnx("module `%s'(pid=%d) exited "
707 "with status %d", module->name,
708 (int)pid, WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff));
709 else
710 log_warnx("module `%s'(pid=%d) exited "
711 "by signal %d", module->name,
712 (int)pid, WTERMSIG(status)(((status) & 0177)));
713 break;
714 }
715 }
716 if (!module) {
717 if (WIFEXITED(status)(((status) & 0177) == 0))
718 log_warnx("unkown child process pid=%d exited "
719 "with status %d", (int)pid,
720 WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff));
721 else
722 log_warnx("unkown child process pid=%d exited "
723 "by signal %d", (int)pid,
724 WTERMSIG(status)(((status) & 0177)));
725 }
726 }
727}
728
729static const char *
730radius_code_string(int code)
731{
732 int i;
733 struct _codestrings {
734 int code;
735 const char *string;
736 } codestrings[] = {
737 { RADIUS_CODE_ACCESS_REQUEST1, "Access-Request" },
738 { RADIUS_CODE_ACCESS_ACCEPT2, "Access-Accept" },
739 { RADIUS_CODE_ACCESS_REJECT3, "Access-Reject" },
740 { RADIUS_CODE_ACCOUNTING_REQUEST4, "Accounting-Request" },
741 { RADIUS_CODE_ACCOUNTING_RESPONSE5, "Accounting-Response" },
742 { RADIUS_CODE_ACCESS_CHALLENGE11, "Access-Challenge" },
743 { RADIUS_CODE_STATUS_SERVER12, "Status-Server" },
744 { RADIUS_CODE_STATUS_CLIENT13, "Status-Client" },
745 { -1, NULL((void *)0) }
746 };
747
748 for (i = 0; codestrings[i].code != -1; i++)
749 if (codestrings[i].code == code)
750 return (codestrings[i].string);
751
752 return ("Unknown");
753}
754
755void
756radiusd_conf_init(struct radiusd *conf)
757{
758
759 TAILQ_INIT(&conf->listen)do { (&conf->listen)->tqh_first = ((void *)0); (&
conf->listen)->tqh_last = &(&conf->listen)->
tqh_first; } while (0)
;
760 TAILQ_INIT(&conf->module)do { (&conf->module)->tqh_first = ((void *)0); (&
conf->module)->tqh_last = &(&conf->module)->
tqh_first; } while (0)
;
761 TAILQ_INIT(&conf->authen)do { (&conf->authen)->tqh_first = ((void *)0); (&
conf->authen)->tqh_last = &(&conf->authen)->
tqh_first; } while (0)
;
762 TAILQ_INIT(&conf->client)do { (&conf->client)->tqh_first = ((void *)0); (&
conf->client)->tqh_last = &(&conf->client)->
tqh_first; } while (0)
;
763
764 return;
765}
766
767/*
768 * Fix some attributes which depend the secret value.
769 */
770static int
771radiusd_access_response_fixup(struct radius_query *q)
772{
773 int res_id;
774 size_t attrlen;
775 u_char req_auth[16], attrbuf[256];
776 const char *authen_secret = q->authen->auth->module->secret;
777
778 radius_get_authenticator(q->req, req_auth);
779
780 if ((authen_secret != NULL((void *)0) &&
781 strcmp(authen_secret, q->client->secret) != 0) ||
782 timingsafe_bcmp(q->req_auth, req_auth, 16) != 0) {
783 const char *olds = q->client->secret;
784 const char *news = authen_secret;
785
786 if (news == NULL((void *)0))
787 news = olds;
788
789 /* RFC 2865 Tunnel-Password */
790 attrlen = sizeof(attrbuf);
791 if (radius_get_raw_attr(q->res, RADIUS_TYPE_TUNNEL_PASSWORD69,
792 attrbuf, &attrlen) == 0) {
793 radius_attr_unhide(news, req_auth,
794 attrbuf, attrbuf + 3, attrlen - 3);
795 radius_attr_hide(olds, q->req_auth,
796 attrbuf, attrbuf + 3, attrlen - 3);
797
798 radius_del_attr_all(q->res,
799 RADIUS_TYPE_TUNNEL_PASSWORD69);
800 radius_put_raw_attr(q->res,
801 RADIUS_TYPE_TUNNEL_PASSWORD69, attrbuf, attrlen);
802 }
803
804 /* RFC 2548 Microsoft MPPE-{Send,Recv}-Key */
805 attrlen = sizeof(attrbuf);
806 if (radius_get_vs_raw_attr(q->res, RADIUS_VENDOR_MICROSOFT311,
807 RADIUS_VTYPE_MPPE_SEND_KEY16, attrbuf, &attrlen) == 0) {
808
809 /* Re-crypt the KEY */
810 radius_attr_unhide(news, req_auth,
811 attrbuf, attrbuf + 2, attrlen - 2);
812 radius_attr_hide(olds, q->req_auth,
813 attrbuf, attrbuf + 2, attrlen - 2);
814
815 radius_del_vs_attr_all(q->res, RADIUS_VENDOR_MICROSOFT311,
816 RADIUS_VTYPE_MPPE_SEND_KEY16);
817 radius_put_vs_raw_attr(q->res, RADIUS_VENDOR_MICROSOFT311,
818 RADIUS_VTYPE_MPPE_SEND_KEY16, attrbuf, attrlen);
819 }
820 attrlen = sizeof(attrbuf);
821 if (radius_get_vs_raw_attr(q->res, RADIUS_VENDOR_MICROSOFT311,
822 RADIUS_VTYPE_MPPE_RECV_KEY17, attrbuf, &attrlen) == 0) {
823
824 /* Re-crypt the KEY */
825 radius_attr_unhide(news, req_auth,
826 attrbuf, attrbuf + 2, attrlen - 2);
827 radius_attr_hide(olds, q->req_auth,
828 attrbuf, attrbuf + 2, attrlen - 2);
829
830 radius_del_vs_attr_all(q->res, RADIUS_VENDOR_MICROSOFT311,
831 RADIUS_VTYPE_MPPE_RECV_KEY17);
832 radius_put_vs_raw_attr(q->res, RADIUS_VENDOR_MICROSOFT311,
833 RADIUS_VTYPE_MPPE_RECV_KEY17, attrbuf, attrlen);
834 }
835 }
836
837 res_id = radius_get_id(q->res);
838 if (res_id != q->req_id) {
839 /* authentication server change the id */
840 radius_set_id(q->res, q->req_id);
841 }
842
843 return (0);
844}
845
846void
847radius_attr_hide(const char *secret, const char *authenticator,
848 const u_char *salt, u_char *plain, int plainlen)
849{
850 int i, j;
851 u_char b[16];
852 MD5_CTX md5ctx;
853
854 i = 0;
855 do {
856 MD5Init(&md5ctx);
857 MD5Update(&md5ctx, secret, strlen(secret));
858 if (i == 0) {
859 MD5Update(&md5ctx, authenticator, 16);
860 if (salt != NULL((void *)0))
861 MD5Update(&md5ctx, salt, 2);
862 } else
863 MD5Update(&md5ctx, plain + i - 16, 16);
864 MD5Final(b, &md5ctx);
865
866 for (j = 0; j < 16 && i < plainlen; i++, j++)
867 plain[i] ^= b[j];
868 } while (i < plainlen);
869}
870
871void
872radius_attr_unhide(const char *secret, const char *authenticator,
873 const u_char *salt, u_char *crypt0, int crypt0len)
874{
875 int i, j;
876 u_char b[16];
877 MD5_CTX md5ctx;
878
879 i = 16 * ((crypt0len - 1) / 16);
880 while (i >= 0) {
881 MD5Init(&md5ctx);
882 MD5Update(&md5ctx, secret, strlen(secret));
883 if (i == 0) {
884 MD5Update(&md5ctx, authenticator, 16);
885 if (salt != NULL((void *)0))
886 MD5Update(&md5ctx, salt, 2);
887 } else
888 MD5Update(&md5ctx, crypt0 + i - 16, 16);
889 MD5Final(b, &md5ctx);
890
891 for (j = 0; j < 16 && i + j < crypt0len; j++)
892 crypt0[i + j] ^= b[j];
893 i -= 16;
894 }
895}
896
897static struct radius_query *
898radiusd_find_query(struct radiusd *radiusd, u_int q_id)
899{
900 struct radius_query *q;
901
902 TAILQ_FOREACH(q, &radiusd->query, next)for((q) = ((&radiusd->query)->tqh_first); (q) != ((
void *)0); (q) = ((q)->next.tqe_next))
{
903 if (q->id == q_id)
904 return (q);
905 }
906 return (NULL((void *)0));
907}
908
909/***********************************************************************
910 * radiusd module handling
911 ***********************************************************************/
912struct radiusd_module *
913radiusd_module_load(struct radiusd *radiusd, const char *path, const char *name)
914{
915 struct radiusd_module *module = NULL((void *)0);
916 pid_t pid;
917 int ival, pairsock[] = { -1, -1 };
918 const char *av[3];
919 ssize_t n;
920 struct imsg imsg;
921
922 module = calloc(1, sizeof(struct radiusd_module));
923 if (module == NULL((void *)0))
924 fatal("Out of memory");
925 module->radiusd = radiusd;
926
927 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, pairsock) == -1) {
928 log_warn("Could not load module `%s'(%s): pipe()", name, path);
929 goto on_error;
930 }
931
932 pid = fork();
933 if (pid == -1) {
934 log_warn("Could not load module `%s'(%s): fork()", name, path);
935 goto on_error;
936 }
937 if (pid == 0) {
938 setsid();
939 close(pairsock[0]);
940 av[0] = path;
941 av[1] = name;
942 av[2] = NULL((void *)0);
943 dup2(pairsock[1], STDIN_FILENO0);
944 dup2(pairsock[1], STDOUT_FILENO1);
945 close(pairsock[1]);
946 closefrom(STDERR_FILENO2 + 1);
947 execv(path, (char * const *)av);
948 log_warn("Failed to execute %s", path);
949 _exit(EXIT_FAILURE1);
950 }
951 close(pairsock[1]);
952
953 module->fd = pairsock[0];
954 if ((ival = fcntl(module->fd, F_GETFL3)) == -1) {
955 log_warn("Could not load module `%s': fcntl(F_GETFL)",
956 name);
957 goto on_error;
958 }
959 if (fcntl(module->fd, F_SETFL4, ival | O_NONBLOCK0x0004) == -1) {
960 log_warn("Could not load module `%s': fcntl(F_SETFL,O_NONBLOCK)",
961 name);
962 goto on_error;
963 }
964 strlcpy(module->name, name, sizeof(module->name));
965 module->pid = pid;
966 imsg_init(&module->ibuf, module->fd);
967
968 if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT2000) <= 0 ||
969 (n = imsg_get(&module->ibuf, &imsg)) <= 0) {
970 log_warnx("Could not load module `%s': module didn't "
971 "respond", name);
972 goto on_error;
973 }
974 if (imsg.hdr.type != IMSG_RADIUSD_MODULE_LOAD) {
975 imsg_free(&imsg);
976 log_warnx("Could not load module `%s': unknown imsg type=%d",
977 name, imsg.hdr.type);
978 goto on_error;
979 }
980
981 module->capabilities =
982 ((struct radiusd_module_load_arg *)imsg.data)->cap;
983
984 log_debug("Loaded module `%s' successfully. pid=%d", module->name,
985 module->pid);
986 imsg_free(&imsg);
987
988 return (module);
989
990on_error:
991 free(module);
992 if (pairsock[0] >= 0)
993 close(pairsock[0]);
994 if (pairsock[1] >= 0)
995 close(pairsock[1]);
996
997 return (NULL((void *)0));
998}
999
1000void
1001radiusd_module_start(struct radiusd_module *module)
1002{
1003 int datalen;
1004 struct imsg imsg;
1005 struct timeval tv = { 0, 0 };
1006
1007 RADIUSD_ASSERT(module->fd >= 0)do { if (!(module->fd >= 0)) { log_warnx( "ASSERT(%s) failed in %s() at %s:%d"
, "module->fd >= 0", __func__, "/usr/src/usr.sbin/radiusd/radiusd/../radiusd.c"
, 1007); if (debug) abort(); } } while (0 )
;
1008 imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_START, 0, 0, -1,
1009 NULL((void *)0), 0);
1010 imsg_sync_flush(&module->ibuf, MODULE_IO_TIMEOUT2000);
1011 if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT2000) <= 0 ||
1012 imsg_get(&module->ibuf, &imsg) <= 0) {
1013 log_warnx("Module `%s' could not start: no response",
1014 module->name);
1015 goto on_fail;
1016 }
1017
1018 datalen = imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr);
1019 if (imsg.hdr.type != IMSG_OK) {
1020 if (imsg.hdr.type == IMSG_NG) {
1021 if (datalen > 0)
1022 log_warnx("Module `%s' could not start: %s",
1023 module->name, (char *)imsg.data);
1024 else
1025 log_warnx("Module `%s' could not start",
1026 module->name);
1027 } else
1028 log_warnx("Module `%s' could not started: module "
1029 "returned unknown message type %d", module->name,
1030 imsg.hdr.type);
1031 goto on_fail;
1032 }
1033
1034 event_set(&module->ev, module->fd, EV_READ0x02, radiusd_module_on_imsg_io,
1035 module);
1036 event_add(&module->ev, &tv);
1037 log_debug("Module `%s' started successfully", module->name);
1038
1039 return;
1040on_fail:
1041 radiusd_module_close(module);
1042 return;
1043}
1044
1045void
1046radiusd_module_stop(struct radiusd_module *module)
1047{
1048 module->stopped = true1;
1049
1050 if (module->secret != NULL((void *)0)) {
1051 freezero(module->secret, strlen(module->secret));
1052 module->secret = NULL((void *)0);
1053 }
1054
1055 if (module->fd >= 0) {
1056 imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_STOP, 0, 0, -1,
1057 NULL((void *)0), 0);
1058 radiusd_module_reset_ev_handler(module);
1059 }
1060}
1061
1062static void
1063radiusd_module_close(struct radiusd_module *module)
1064{
1065 if (module->fd >= 0) {
1066 event_del(&module->ev);
1067 imsg_clear(&module->ibuf);
1068 close(module->fd);
1069 module->fd = -1;
1070 }
1071}
1072
1073void
1074radiusd_module_unload(struct radiusd_module *module)
1075{
1076 free(module->radpkt);
1077 radiusd_module_close(module);
1078 free(module);
1079}
1080
1081static void
1082radiusd_module_on_imsg_io(int fd, short evmask, void *ctx)
1083{
1084 struct radiusd_module *module = ctx;
1085 int ret;
1086
1087 if (evmask & EV_WRITE0x04)
1088 module->writeready = true1;
1089
1090 if (evmask & EV_READ0x02 || module->ibuf.r.wpos > IMSG_HEADER_SIZEsizeof(struct imsg_hdr)) {
1091 if (radiusd_module_imsg_read(module,
1092 (evmask & EV_READ0x02)? true1 : false0) == -1)
1093 goto on_error;
1094 }
1095
1096 while (module->writeready && module->ibuf.w.queued) {
1097 ret = msgbuf_write(&module->ibuf.w);
1098 if (ret > 0)
1099 continue;
1100 module->writeready = false0;
1101 if (ret == 0 && errno(*__errno()) == EAGAIN35)
1102 break;
1103 log_warn("Failed to write to module `%s': msgbuf_write()",
1104 module->name);
1105 goto on_error;
1106 }
1107 radiusd_module_reset_ev_handler(module);
1108
1109 return;
1110on_error:
1111 radiusd_module_close(module);
1112}
1113
1114static void
1115radiusd_module_reset_ev_handler(struct radiusd_module *module)
1116{
1117 short evmask;
1118 struct timeval *tvp = NULL((void *)0), tv = { 0, 0 };
1119
1120 RADIUSD_ASSERT(module->fd >= 0)do { if (!(module->fd >= 0)) { log_warnx( "ASSERT(%s) failed in %s() at %s:%d"
, "module->fd >= 0", __func__, "/usr/src/usr.sbin/radiusd/radiusd/../radiusd.c"
, 1120); if (debug) abort(); } } while (0 )
;
1121 event_del(&module->ev);
1122
1123 evmask = EV_READ0x02;
1124 if (module->ibuf.w.queued) {
1125 if (!module->writeready)
1126 evmask |= EV_WRITE0x04;
1127 else
1128 tvp = &tv; /* fire immediately */
1129 } else if (module->ibuf.r.wpos > IMSG_HEADER_SIZEsizeof(struct imsg_hdr))
1130 tvp = &tv; /* fire immediately */
1131
1132 /* module stopped and no event handler is set */
1133 if (evmask & EV_WRITE0x04 && tvp == NULL((void *)0) && module->stopped) {
1134 /* stop requested and no more to write */
1135 radiusd_module_close(module);
1136 return;
1137 }
1138
1139 event_set(&module->ev, module->fd, evmask, radiusd_module_on_imsg_io,
1140 module);
1141 if (event_add(&module->ev, tvp) == -1) {
1142 log_warn("Could not set event handlers for module `%s': "
1143 "event_add()", module->name);
1144 radiusd_module_close(module);
1145 }
1146}
1147
1148static int
1149radiusd_module_imsg_read(struct radiusd_module *module, bool_Bool doread)
1150{
1151 int n;
1152 struct imsg imsg;
1153
1154 if (doread) {
1155 if ((n = imsg_read(&module->ibuf)) == -1 || n == 0) {
1156 if (n == -1 && errno(*__errno()) == EAGAIN35)
1157 return (0);
1158 if (n == -1)
1159 log_warn("Receiving a message from module `%s' "
1160 "failed: imsg_read", module->name);
1161 /* else closed */
1162 radiusd_module_close(module);
1163 return (-1);
1164 }
1165 }
1166 for (;;) {
1167 if ((n = imsg_get(&module->ibuf, &imsg)) == -1) {
1168 log_warn("Receiving a message from module `%s' failed: "
1169 "imsg_get", module->name);
1170 return (-1);
1171 }
1172 if (n == 0)
1173 return (0);
1174 radiusd_module_imsg(module, &imsg);
1175 }
1176
1177 return (0);
1178}
1179
1180static void
1181radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg)
1182{
1183 int datalen;
1184 struct radius_query *q;
1185 u_int q_id;
1186
1187 datalen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr);
1188 switch (imsg->hdr.type) {
1189 case IMSG_RADIUSD_MODULE_NOTIFY_SECRET:
1190 if (datalen > 0) {
1191 module->secret = strdup(imsg->data);
1192 if (module->secret == NULL((void *)0))
1193 log_warn("Could not handle NOTIFY_SECRET "
1194 "from `%s'", module->name);
1195 }
1196 break;
1197 case IMSG_RADIUSD_MODULE_USERPASS_OK:
1198 case IMSG_RADIUSD_MODULE_USERPASS_FAIL:
1199 {
1200 char *msg = NULL((void *)0);
1201 const char *msgtypestr;
1202
1203 msgtypestr = (imsg->hdr.type == IMSG_RADIUSD_MODULE_USERPASS_OK)
1204 ? "USERPASS_OK" : "USERPASS_NG";
1205
1206 q_id = *(u_int *)imsg->data;
1207 if (datalen > (ssize_t)sizeof(u_int))
1208 msg = (char *)(((u_int *)imsg->data) + 1);
1209
1210 q = radiusd_find_query(module->radiusd, q_id);
1211 if (q == NULL((void *)0)) {
1212 log_warnx("Received %s from `%s', but query id=%u "
1213 "unknown", msgtypestr, module->name, q_id);
1214 break;
1215 }
1216
1217 if ((q->res = radius_new_response_packet(
1218 (imsg->hdr.type == IMSG_RADIUSD_MODULE_USERPASS_OK)
1219 ? RADIUS_CODE_ACCESS_ACCEPT2 : RADIUS_CODE_ACCESS_REJECT3,
1220 q->req)) == NULL((void *)0)) {
1221 log_warn("radius_new_response_packet() failed");
1222 radiusd_access_request_aborted(q);
1223 } else {
1224 if (msg)
1225 radius_put_string_attr(q->res,
1226 RADIUS_TYPE_REPLY_MESSAGE18, msg);
1227 radius_set_response_authenticator(q->res,
1228 q->client->secret);
1229 radiusd_access_request_answer(q);
1230 }
1231 break;
1232 }
1233 case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:
1234 case IMSG_RADIUSD_MODULE_REQDECO_DONE:
1235 case IMSG_RADIUSD_MODULE_RESDECO_DONE:
1236 {
1237 static struct radiusd_module_radpkt_arg *ans;
1238 const char *typestr = "unknown";
1239
1240 switch (imsg->hdr.type) {
1241 case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:
1242 typestr = "ACCSREQ_ANSWER";
1243 break;
1244 case IMSG_RADIUSD_MODULE_REQDECO_DONE:
1245 typestr = "REQDECO_DONE";
1246 break;
1247 case IMSG_RADIUSD_MODULE_RESDECO_DONE:
1248 typestr = "RESDECO_DONE";
1249 break;
1250 }
1251
1252 if (datalen <
1253 (ssize_t)sizeof(struct radiusd_module_radpkt_arg)) {
1254 log_warnx("Received %s message, but length is wrong",
1255 typestr);
1256 break;
1257 }
1258 q_id = ((struct radiusd_module_radpkt_arg *)imsg->data)->q_id;
1259 q = radiusd_find_query(module->radiusd, q_id);
1260 if (q == NULL((void *)0)) {
1261 log_warnx("Received %s from %s, but query id=%u "
1262 "unknown", typestr, module->name, q_id);
1263 break;
1264 }
1265 if ((ans = radiusd_module_recv_radpkt(module, imsg,
1266 imsg->hdr.type, typestr)) != NULL((void *)0)) {
1267 RADIUS_PACKET *radpkt = NULL((void *)0);
1268
1269 if (module->radpktoff > 0 &&
1270 (radpkt = radius_convert_packet(
1271 module->radpkt, module->radpktoff)) == NULL((void *)0)) {
1272 log_warn("q=%u radius_convert_packet() failed",
1273 q->id);
1274 radiusd_access_request_aborted(q);
1275 break;
1276 }
1277 module->radpktoff = 0;
1278 switch (imsg->hdr.type) {
1279 case IMSG_RADIUSD_MODULE_REQDECO_DONE:
1280 if (radpkt != NULL((void *)0)) {
1281 radius_delete_packet(q->req);
1282 q->req = radpkt;
1283 }
1284 radius_query_request(q);
1285 break;
1286 case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:
1287 if (radpkt == NULL((void *)0)) {
1288 log_warn("q=%u wrong pkt from module",
1289 q->id);
1290 radiusd_access_request_aborted(q);
1291 }
1292 q->res = radpkt;
1293 radiusd_access_request_answer(q);
1294 break;
1295 case IMSG_RADIUSD_MODULE_RESDECO_DONE:
1296 if (radpkt != NULL((void *)0)) {
1297 radius_delete_packet(q->res);
1298 radius_set_request_packet(radpkt,
1299 q->req);
1300 q->res = radpkt;
1301 }
1302 radius_query_response(q);
1303 break;
1304 }
1305 }
1306 break;
1307 }
1308 case IMSG_RADIUSD_MODULE_ACCSREQ_ABORTED:
1309 {
1310 q_id = *((u_int *)imsg->data);
1311 q = radiusd_find_query(module->radiusd, q_id);
1312 if (q == NULL((void *)0)) {
1313 log_warnx("Received ACCSREQ_ABORT from %s, but query "
1314 "id=%u unknown", module->name, q_id);
1315 break;
1316 }
1317 radiusd_access_request_aborted(q);
1318 break;
1319 }
1320 default:
1321 RADIUSD_DBG(("Unhandled imsg type=%d from %s", imsg->hdr.type,
1322 module->name));
1323 }
1324}
1325
1326static struct radiusd_module_radpkt_arg *
1327radiusd_module_recv_radpkt(struct radiusd_module *module, struct imsg *imsg,
1328 uint32_t imsg_type, const char *type_str)
1329{
1330 struct radiusd_module_radpkt_arg *ans;
1331 int datalen, chunklen;
1332
1333 datalen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr);
1334 ans = (struct radiusd_module_radpkt_arg *)imsg->data;
1335 if (module->radpktsiz < ans->pktlen) {
1336 u_char *nradpkt;
1337 if ((nradpkt = realloc(module->radpkt, ans->pktlen)) == NULL((void *)0)) {
1338 log_warn("Could not handle received %s message from "
1339 "`%s'", type_str, module->name);
1340 goto on_fail;
1341 }
1342 module->radpkt = nradpkt;
1343 module->radpktsiz = ans->pktlen;
1344 }
1345 chunklen = datalen - sizeof(struct radiusd_module_radpkt_arg);
1346 if (chunklen > module->radpktsiz - module->radpktoff) {
1347 log_warnx("Could not handle received %s message from `%s': "
1348 "received length is too big", type_str, module->name);
1349 goto on_fail;
1350 }
1351 if (chunklen > 0) {
1352 memcpy(module->radpkt + module->radpktoff,
1353 (caddr_t)(ans + 1), chunklen);
1354 module->radpktoff += chunklen;
1355 }
1356 if (!ans->final)
1357 return (NULL((void *)0)); /* again */
1358 if (module->radpktoff != ans->pktlen) {
1359 log_warnx("Could not handle received %s message from `%s': "
1360 "length is mismatch", type_str, module->name);
1361 goto on_fail;
1362 }
1363
1364 return (ans);
1365on_fail:
1366 module->radpktoff = 0;
1367 return (NULL((void *)0));
1368}
1369
1370int
1371radiusd_module_set(struct radiusd_module *module, const char *name,
1372 int argc, char * const * argv)
1373{
1374 struct radiusd_module_set_arg arg;
1375 struct radiusd_module_object *val;
1376 int i, niov = 0;
1377 u_char *buf = NULL((void *)0), *buf0;
1378 ssize_t n;
1379 size_t bufsiz = 0, bufoff = 0, bufsiz0;
1380 size_t vallen, valsiz;
1381 struct iovec iov[2];
1382 struct imsg imsg;
1383
1384 memset(&arg, 0, sizeof(arg));
1385 arg.nparamval = argc;
1386 strlcpy(arg.paramname, name, sizeof(arg.paramname));
1387
1388 iov[niov].iov_base = &arg;
1389 iov[niov].iov_len = sizeof(struct radiusd_module_set_arg);
1390 niov++;
1391
1392 for (i = 0; i < argc; i++) {
1393 vallen = strlen(argv[i]) + 1;
1394 valsiz = sizeof(struct radiusd_module_object) + vallen;
1395 if (bufsiz < bufoff + valsiz) {
1396 bufsiz0 = bufoff + valsiz + 128;
1397 if ((buf0 = realloc(buf, bufsiz0)) == NULL((void *)0)) {
1398 log_warn("Failed to set config parameter to "
1399 "module `%s': realloc", module->name);
1400 goto on_error;
1401 }
1402 buf = buf0;
1403 bufsiz = bufsiz0;
1404 memset(buf + bufoff, 0, bufsiz - bufoff);
1405 }
1406 val = (struct radiusd_module_object *)(buf + bufoff);
1407 val->size = valsiz;
1408 memcpy(val + 1, argv[i], vallen);
1409
1410 bufoff += valsiz;
1411 }
1412 iov[niov].iov_base = buf;
1413 iov[niov].iov_len = bufoff;
1414 niov++;
1415
1416 if (imsg_composev(&module->ibuf, IMSG_RADIUSD_MODULE_SET_CONFIG, 0, 0,
1417 -1, iov, niov) == -1) {
1418 log_warn("Failed to set config parameter to module `%s': "
1419 "imsg_composev", module->name);
1420 goto on_error;
1421 }
1422 if (imsg_sync_flush(&module->ibuf, MODULE_IO_TIMEOUT2000) == -1) {
1423 log_warn("Failed to set config parameter to module `%s': "
1424 "imsg_flush_timeout", module->name);
1425 goto on_error;
1426 }
1427 for (;;) {
1428 if (imsg_sync_read(&module->ibuf, MODULE_IO_TIMEOUT2000) <= 0) {
1429 log_warn("Failed to get reply from module `%s': "
1430 "imsg_sync_read", module->name);
1431 goto on_error;
1432 }
1433 if ((n = imsg_get(&module->ibuf, &imsg)) > 0)
1434 break;
1435 if (n < 0) {
1436 log_warn("Failed to get reply from module `%s': "
1437 "imsg_get", module->name);
1438 goto on_error;
1439 }
1440 }
1441 if (imsg.hdr.type == IMSG_NG) {
1442 log_warnx("Could not set `%s' for module `%s': %s", name,
1443 module->name, (char *)imsg.data);
1444 goto on_error;
1445 } else if (imsg.hdr.type != IMSG_OK) {
1446 imsg_free(&imsg);
1447 log_warnx("Failed to get reply from module `%s': "
1448 "unknown imsg type=%d", module->name, imsg.hdr.type);
1449 goto on_error;
1450 }
1451 imsg_free(&imsg);
1452
1453 free(buf);
1454 return (0);
1455
1456on_error:
1457 free(buf);
1458 return (-1);
1459}
1460
1461static void
1462radiusd_module_userpass(struct radiusd_module *module, struct radius_query *q)
1463{
1464 struct radiusd_module_userpass_arg userpass;
1465
1466 memset(&userpass, 0, sizeof(userpass));
1467 userpass.q_id = q->id;
1468
1469 if (radius_get_user_password_attr(q->req, userpass.pass,
1470 sizeof(userpass.pass), q->client->secret) == 0)
1471 userpass.has_pass = true1;
1472 else
1473 userpass.has_pass = false0;
1474 if (radius_get_string_attr(q->req, RADIUS_TYPE_USER_NAME1,
1475 userpass.user, sizeof(userpass.user)) != 0) {
1476 log_warnx("q=%u no User-Name attribute", q->id);
1477 goto on_error;
1478 }
1479 imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_USERPASS, 0, 0, -1,
1480 &userpass, sizeof(userpass));
1481 radiusd_module_reset_ev_handler(module);
1482 return;
1483on_error:
1484 radiusd_access_request_aborted(q);
1485}
1486
1487static void
1488radiusd_module_access_request(struct radiusd_module *module,
1489 struct radius_query *q)
1490{
1491 RADIUS_PACKET *radpkt;
1492 char pass[256];
1493
1494 if ((radpkt = radius_convert_packet(radius_get_data(q->req),
1495 radius_get_length(q->req))) == NULL((void *)0)) {
1496 log_warn("q=%u Could not send ACCSREQ to `%s'", q->id,
1497 module->name);
1498 radiusd_access_request_aborted(q);
1499 return;
1500 }
1501 if (q->client->secret[0] != '\0' && module->secret != NULL((void *)0) &&
1502 radius_get_user_password_attr(radpkt, pass, sizeof(pass),
1503 q->client->secret) == 0) {
1504 radius_del_attr_all(radpkt, RADIUS_TYPE_USER_PASSWORD2);
1505 (void)radius_put_raw_attr(radpkt, RADIUS_TYPE_USER_PASSWORD2,
1506 pass, strlen(pass));
1507 }
1508 if (imsg_compose_radius_packet(&module->ibuf,
1509 IMSG_RADIUSD_MODULE_ACCSREQ, q->id, radpkt) == -1) {
1510 log_warn("q=%u Could not send ACCSREQ to `%s'", q->id,
1511 module->name);
1512 radiusd_access_request_aborted(q);
1513 }
1514 radiusd_module_reset_ev_handler(module);
1515 radius_delete_packet(radpkt);
1516}
1517
1518static void
1519radiusd_module_request_decoration(struct radiusd_module *module,
1520 struct radius_query *q)
1521{
1522 if (module->fd < 0) {
1523 log_warnx("q=%u Could not send REQDECO to `%s': module is "
1524 "not running?", q->id, module->name);
1525 radiusd_access_request_aborted(q);
1526 return;
1527 }
1528 if (imsg_compose_radius_packet(&module->ibuf,
1529 IMSG_RADIUSD_MODULE_REQDECO, q->id, q->req) == -1) {
1530 log_warn("q=%u Could not send REQDECO to `%s'", q->id,
1531 module->name);
1532 radiusd_access_request_aborted(q);
1533 return;
1534 }
1535 radiusd_module_reset_ev_handler(module);
1536}
1537
1538static void
1539radiusd_module_response_decoration(struct radiusd_module *module,
1540 struct radius_query *q)
1541{
1542 if (module->fd < 0) {
1543 log_warnx("q=%u Could not send RESDECO to `%s': module is "
1544 "not running?", q->id, module->name);
1545 radiusd_access_request_aborted(q);
1546 return;
1547 }
1548 if (imsg_compose_radius_packet(&module->ibuf,
1549 IMSG_RADIUSD_MODULE_RESDECO0_REQ, q->id, q->req) == -1) {
1550 log_warn("q=%u Could not send RESDECO0_REQ to `%s'", q->id,
1551 module->name);
1552 radiusd_access_request_aborted(q);
1553 return;
1554 }
1555 if (imsg_compose_radius_packet(&module->ibuf,
1556 IMSG_RADIUSD_MODULE_RESDECO, q->id, q->res) == -1) {
1557 log_warn("q=%u Could not send RESDECO to `%s'", q->id,
1558 module->name);
1559 radiusd_access_request_aborted(q);
1560 return;
1561 }
1562 radiusd_module_reset_ev_handler(module);
1563}
1564
1565static int
1566imsg_compose_radius_packet(struct imsgbuf *ibuf, uint32_t type, u_int q_id,
1567 RADIUS_PACKET *radpkt)
1568{
1569 struct radiusd_module_radpkt_arg arg;
1570 int off = 0, len, siz;
1571 struct iovec iov[2];
1572 const u_char *pkt;
1573
1574 pkt = radius_get_data(radpkt);
1575 len = radius_get_length(radpkt);
1576 memset(&arg, 0, sizeof(arg));
1577 arg.q_id = q_id;
1578 arg.pktlen = len;
1579 while (off < len) {
1580 siz = MAX_IMSGSIZE16384 - sizeof(arg);
1581 if (len - off > siz)
1582 arg.final = false0;
1583 else {
1584 arg.final = true1;
1585 siz = len - off;
1586 }
1587 iov[0].iov_base = &arg;
1588 iov[0].iov_len = sizeof(arg);
1589 iov[1].iov_base = (caddr_t)pkt + off;
1590 iov[1].iov_len = siz;
1591 if (imsg_composev(ibuf, type, 0, 0, -1, iov, 2) == -1)
1592 return (-1);
1593 off += siz;
1594 }
1595 return (0);
1596}