Bug Summary

File:src/usr.sbin/radiusd/radiusd/../radiusd.c
Warning:line 1292, column 12
Use of memory after it is freed

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),
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))
37
Assuming field 'req' is equal to NULL
38
Taking false branch
657 radius_delete_packet(q->req);
658 if (q->res != NULL((void *)0))
39
Assuming field 'res' is equal to NULL
40
Taking false branch
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)
;
41
Assuming field 'tqe_next' is not equal to null
42
Taking true branch
43
Loop condition is false. Exiting loop
661 free(q);
44
Memory is released
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)
1
Assuming the condition is false
1088 module->writeready = true1;
1089
1090 if (evmask & EV_READ0x02 || module->ibuf.r.wpos > IMSG_HEADER_SIZEsizeof(struct imsg_hdr)) {
2
Assuming the condition is false
3
Assuming the condition is true
4
Taking true branch
1091 if (radiusd_module_imsg_read(module,
6
Calling 'radiusd_module_imsg_read'
1092 (evmask & EV_READ0x02)? true1 : false0) == -1)
5
'?' condition is false
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
6.1
'doread' is false
) {
7
Taking false branch
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 (;;) {
8
Loop condition is true. Entering loop body
13
Loop condition is true. Entering loop body
18
Loop condition is true. Entering loop body
1167 if ((n = imsg_get(&module->ibuf, &imsg)) == -1) {
9
Assuming the condition is false
10
Taking false branch
14
Assuming the condition is false
15
Taking false branch
19
Assuming the condition is false
20
Taking false branch
1168 log_warn("Receiving a message from module `%s' failed: "
1169 "imsg_get", module->name);
1170 return (-1);
1171 }
1172 if (n == 0)
11
Assuming 'n' is not equal to 0
12
Taking false branch
16
Assuming 'n' is not equal to 0
17
Taking false branch
21
Assuming 'n' is not equal to 0
22
Taking false branch
1173 return (0);
1174 radiusd_module_imsg(module, &imsg);
23
Calling 'radiusd_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) {
24
Control jumps to 'case IMSG_RADIUSD_MODULE_RESDECO_DONE:' at line 1235
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) {
25
Control jumps to 'case IMSG_RADIUSD_MODULE_RESDECO_DONE:' at line 1247
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 <
26
Execution continues on line 1252
27
Assuming the condition is false
28
Taking false branch
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)) {
29
Assuming 'q' is not equal to NULL
30
Taking false branch
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,
31
Assuming the condition is true
32
Taking true branch
1266 imsg->hdr.type, typestr)) != NULL((void *)0)) {
1267 RADIUS_PACKET *radpkt = NULL((void *)0);
1268
1269 if (module->radpktoff > 0 &&
33
Assuming field 'radpktoff' is <= 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) {
34
Control jumps to 'case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:' at line 1286
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
34.1
'radpkt' is equal to NULL
== NULL((void *)0)) {
35
Taking true branch
1288 log_warn("q=%u wrong pkt from module",
1289 q->id);
1290 radiusd_access_request_aborted(q);
36
Calling 'radiusd_access_request_aborted'
45
Returning; memory was released via 1st parameter
1291 }
1292 q->res = radpkt;
46
Use of memory after it is freed
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}