Bug Summary

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