1 /*
2 * Copyright (c) 2004,2005 Damien Miller <djm@mindrot.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16 #include "flowd-common.h"
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/wait.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <signal.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <syslog.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <pwd.h>
33 #include <grp.h>
34 #include <netdb.h>
35
36 #include "flowd.h"
37 #include "privsep.h"
38 #include "atomicio.h"
39
40 RCSID("$Id: privsep.c,v 1.33 2008/04/23 02:01:04 djm Exp $");
41
42 #ifndef offsetof
43 # define offsetof(type, member) ((size_t) &((type *)0)->member)
44 #endif
45
46 static sig_atomic_t child_exited = 0;
47 static pid_t child_pid = -1;
48 static int monitor_to_child_sock = -1;
49
50 #define C2M_MSG_OPEN_LOG 1 /* send: nothing ret: fdpass */
51 #define C2M_MSG_OPEN_SOCKET 2 /* send: nothing ret: fdpass */
52 #define C2M_MSG_RECONFIGURE 3 /* send: nothing ret: conf+fdpass */
53
54 /* Utility functions */
55 static char *
privsep_read_string(int fd,int nullok)56 privsep_read_string(int fd, int nullok)
57 {
58 size_t len;
59 char buf[8192], *ret;
60
61 if (atomicio(read, fd, &len, sizeof(len)) != sizeof(len))
62 logerrx("%s: read len", __func__);
63 if (nullok && len == 0)
64 return (NULL);
65 if (len <= 0 || len >= sizeof(buf))
66 logerrx("%s: silly len: %u", __func__, len);
67 if (atomicio(read, fd, buf, len) != len) {
68 logitm(LOG_ERR, "%s: read str", __func__);
69 return (NULL);
70 }
71 buf[len] = '\0';
72 if ((ret = strdup(buf)) == NULL)
73 logit(LOG_ERR, "%s: strdup failed", __func__);
74
75 return (ret);
76 }
77
78 static int
privsep_write_string(int fd,char * s,int nullok)79 privsep_write_string(int fd, char *s, int nullok)
80 {
81 size_t len;
82
83 if (s == NULL) {
84 if (!nullok)
85 logerrx("%s: s == NULL", s);
86 len = 0;
87 } else if ((len = strlen(s)) <= 0) {
88 logit(LOG_ERR, "%s: silly len: %u", __func__, len);
89 return (-1);
90 }
91 if (atomicio(vwrite, fd, &len, sizeof(len)) != sizeof(len)) {
92 logitm(LOG_ERR, "%s: write len", __func__);
93 return (-1);
94 }
95 if (len > 0 && atomicio(vwrite, fd, s, len) != len) {
96 logitm(LOG_ERR, "%s: write(str)", __func__);
97 return (-1);
98 }
99
100 return (0);
101 }
102
103 static int
write_pid_file(const char * path)104 write_pid_file(const char *path)
105 {
106 FILE *pid_file;
107
108 if ((pid_file = fopen(path, "w")) == NULL) {
109 logitm(LOG_ERR, "fopen(%s)", path);
110 return (-1);
111 }
112 if (fprintf(pid_file, "%ld\n", (long)getpid()) == -1) {
113 logitm(LOG_ERR, "fprintf(%s)", path);
114 return (-1);
115 }
116 fclose(pid_file);
117
118 return (0);
119 }
120
121 int
open_listener(struct xaddr * addr,u_int16_t port,size_t bufsiz,struct join_groups * groups)122 open_listener(struct xaddr *addr, u_int16_t port, size_t bufsiz,
123 struct join_groups *groups)
124 {
125 int fd, fl, i, orig;
126 struct sockaddr_storage ss;
127 socklen_t slen = sizeof(ss);
128 struct join_group *jg;
129 struct ip_mreq v4mreq;
130 struct ipv6_mreq v6mreq;
131
132 if (addr_xaddr_to_sa(addr, (struct sockaddr *)&ss, &slen, port) == -1) {
133 logit(LOG_ERR, "addr_xaddr_to_sa");
134 return (-1);
135 }
136
137 if ((fd = socket(addr->af, SOCK_DGRAM, 0)) == -1) {
138 logitm(LOG_ERR, "socket");
139 return (-1);
140 }
141
142 /* Set non-blocking */
143 if ((fl = fcntl(fd, F_GETFL, 0)) == -1) {
144 logitm(LOG_ERR, "fcntl(%d, F_GETFL, 0)", fd);
145 return (-1);
146 }
147 fl |= O_NONBLOCK;
148 if (fcntl(fd, F_SETFL, fl) == -1) {
149 logitm(LOG_ERR, "fcntl(%d, F_SETFL, O_NONBLOCK)", fd);
150 return (-1);
151 }
152
153 #ifdef IPV6_V6ONLY
154 /* Set v6-only for AF_INET6 sockets (no mapped address crap) */
155 fl = 1;
156 if (addr->af == AF_INET6 &&
157 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &fl, sizeof(fl)) == -1) {
158 logitm(LOG_ERR, "setsockopt(IPV6_V6ONLY)");
159 return (-1);
160 }
161 #endif
162
163 if (bind(fd, (struct sockaddr *)&ss, slen) == -1) {
164 logitm(LOG_ERR, "bind");
165 return (-1);
166 }
167
168 logit(LOG_DEBUG, "Listener for [%s]:%d fd = %d", addr_ntop_buf(addr),
169 port, fd);
170
171 /*
172 * Crank up socket receive buffer size to cope with bursts of flows
173 * If the config doesn't contain an explicit buffer size, we
174 * fall back to guessing.
175 */
176 slen = sizeof(fl);
177 if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &orig, &slen) == 0) {
178 if (bufsiz > 0) {
179 fl = bufsiz;
180 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &fl,
181 sizeof(fl)) == 0) {
182 logit(LOG_DEBUG, "Adjusted socket receive "
183 "buffer from %d to %d", orig, fl);
184 } else
185 logerr("%s: setsockopt(SO_RCVBUF)", __func__);
186 } else {
187 for (i = 3; i >= 1; i--) {
188 fl = (1024 * 64) << i;
189 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &fl,
190 sizeof(fl)) == 0) {
191 logit(LOG_DEBUG, "Adjusted socket receive "
192 "buffer from %d to %d", orig, fl);
193 break;
194 } else if (i == 1)
195 logitm(LOG_DEBUG, "setsockopt(SO_RCVBUF)");
196 }
197 }
198 }
199
200 /* Shrink send buffer, because we never use it */
201 fl = 1024;
202 logit(LOG_DEBUG, "Setting socket send buf to %d", fl);
203 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &fl, sizeof(fl)) == -1)
204 logitm(LOG_DEBUG, "setsockopt(SO_SNDBUF)");
205
206 TAILQ_FOREACH(jg, groups, entry) {
207 if (jg->addr.af != addr->af)
208 continue;
209 logit(LOG_DEBUG, "Multicast join on fd %d to [%s]", fd,
210 addr_ntop_buf(&jg->addr));
211 switch (addr->af) {
212 case AF_INET:
213 bzero(&v4mreq, sizeof(v4mreq));
214 v4mreq.imr_multiaddr = jg->addr.v4;
215 v4mreq.imr_interface.s_addr = INADDR_ANY;
216 if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
217 &v4mreq, sizeof(v4mreq)) == -1)
218 logitm(LOG_ERR, "setsockopt(IP_ADD_MEMBERSHIP)");
219 /* non-fatal for now */
220 break;
221 case AF_INET6:
222 bzero(&v6mreq, sizeof(v6mreq));
223 v6mreq.ipv6mr_multiaddr = jg->addr.v6;
224 v6mreq.ipv6mr_interface = jg->addr.scope_id;
225 if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
226 &v6mreq, sizeof(v6mreq)) == -1)
227 logitm(LOG_ERR, "setsockopt(IPV6_JOIN_GROUP)");
228 /* non-fatal for now */
229 break;
230 }
231 }
232
233 return (fd);
234 }
235
236 static void
replace_conf(struct flowd_config * conf,struct flowd_config * newconf)237 replace_conf(struct flowd_config *conf, struct flowd_config *newconf)
238 {
239 struct listen_addr *la;
240 struct filter_rule *fr;
241 struct allowed_device *ad;
242 struct join_group *jg;
243
244 if (conf->log_file != NULL)
245 free(conf->log_file);
246 if (conf->log_socket != NULL)
247 free(conf->log_socket);
248 free(conf->pid_file);
249 while ((la = TAILQ_FIRST(&conf->listen_addrs)) != NULL) {
250 if (la->fd != -1)
251 close(la->fd);
252 TAILQ_REMOVE(&conf->listen_addrs, la, entry);
253 free(la);
254 }
255 while ((fr = TAILQ_FIRST(&conf->filter_list)) != NULL) {
256 TAILQ_REMOVE(&conf->filter_list, fr, entry);
257 free(fr);
258 }
259 while ((ad = TAILQ_FIRST(&conf->allowed_devices)) != NULL) {
260 TAILQ_REMOVE(&conf->allowed_devices, ad, entry);
261 free(ad);
262 }
263 while ((jg = TAILQ_FIRST(&conf->join_groups)) != NULL) {
264 TAILQ_REMOVE(&conf->join_groups, jg, entry);
265 free(jg);
266 }
267
268 memcpy(conf, newconf, sizeof(*conf));
269 TAILQ_INIT(&conf->listen_addrs);
270 TAILQ_INIT(&conf->filter_list);
271 TAILQ_INIT(&conf->allowed_devices);
272 TAILQ_INIT(&conf->join_groups);
273
274 while ((la = TAILQ_LAST(&newconf->listen_addrs, listen_addrs)) != NULL) {
275 TAILQ_REMOVE(&newconf->listen_addrs, la, entry);
276 TAILQ_INSERT_HEAD(&conf->listen_addrs, la, entry);
277 }
278 while ((fr = TAILQ_LAST(&newconf->filter_list, filter_list)) != NULL) {
279 TAILQ_REMOVE(&newconf->filter_list, fr, entry);
280 TAILQ_INSERT_HEAD(&conf->filter_list, fr, entry);
281 }
282 while ((ad = TAILQ_LAST(&newconf->allowed_devices,
283 allowed_devices)) != NULL) {
284 TAILQ_REMOVE(&newconf->allowed_devices, ad, entry);
285 TAILQ_INSERT_HEAD(&conf->allowed_devices, ad, entry);
286 }
287 while ((jg = TAILQ_LAST(&newconf->join_groups, join_groups)) != NULL) {
288 TAILQ_REMOVE(&newconf->join_groups, jg, entry);
289 TAILQ_INSERT_HEAD(&conf->join_groups, jg, entry);
290 }
291
292 bzero(newconf, sizeof(*newconf));
293 }
294
295 static int
recv_config(int fd,struct flowd_config * conf)296 recv_config(int fd, struct flowd_config *conf)
297 {
298 u_int n, i;
299 struct listen_addr *la;
300 struct filter_rule *fr;
301 struct allowed_device *ad;
302 struct join_group *jg;
303 struct flowd_config newconf;
304
305 logit(LOG_DEBUG, "%s: entering fd = %d", __func__, fd);
306
307 bzero(&newconf, sizeof(newconf));
308 TAILQ_INIT(&newconf.listen_addrs);
309 TAILQ_INIT(&newconf.filter_list);
310 TAILQ_INIT(&newconf.allowed_devices);
311 TAILQ_INIT(&newconf.join_groups);
312
313 logit(LOG_DEBUG, "%s: ready to receive config", __func__);
314
315 newconf.log_file = privsep_read_string(fd, 1);
316 newconf.log_socket = privsep_read_string(fd, 1);
317
318 if (atomicio(read, fd, &newconf.log_socket_bufsiz,
319 sizeof(newconf.log_socket_bufsiz)) !=
320 sizeof(newconf.log_socket_bufsiz)) {
321 logitm(LOG_ERR, "%s: read(conf.log_socket_bufsiz)", __func__);
322 return (-1);
323 }
324
325 if ((newconf.pid_file = privsep_read_string(fd, 0)) == NULL) {
326 logit(LOG_ERR, "%s: Couldn't read conf.pid_file", __func__);
327 return (-1);
328 }
329
330 if (atomicio(read, fd, &newconf.store_mask,
331 sizeof(newconf.store_mask)) != sizeof(newconf.store_mask)) {
332 logitm(LOG_ERR, "%s: read(conf.store_mask)", __func__);
333 return (-1);
334 }
335
336 if (atomicio(read, fd, &newconf.opts, sizeof(newconf.opts)) !=
337 sizeof(newconf.opts)) {
338 logitm(LOG_ERR, "%s: read(conf.opts)", __func__);
339 return (-1);
340 }
341
342 /* Read Listen Addrs */
343 if (atomicio(read, fd, &n, sizeof(n)) != sizeof(n)) {
344 logitm(LOG_ERR, "%s: read(num listen_addrs)", __func__);
345 return (-1);
346 }
347 if (n == 0 || n > 8192) {
348 logit(LOG_ERR, "%s: silly number of listen_addrs: %d",
349 __func__, n);
350 return (-1);
351 }
352 for (i = 0; i < n; i++) {
353 if ((la = calloc(1, sizeof(*la))) == NULL) {
354 logit(LOG_ERR, "%s: calloc", __func__);
355 return (-1);
356 }
357 if (atomicio(read, fd, la, sizeof(*la)) != sizeof(*la)) {
358 logitm(LOG_ERR, "%s: read(listen_addr)", __func__);
359 return (-1);
360 }
361 if (la->fd != -1 && (la->fd = receive_fd(fd)) == -1)
362 return (-1);
363 TAILQ_INSERT_TAIL(&newconf.listen_addrs, la, entry);
364 }
365
366 /* Read Filter Rules */
367 if (atomicio(read, fd, &n, sizeof(n)) != sizeof(n)) {
368 logitm(LOG_ERR, "%s: read(num filter_rules)", __func__);
369 return (-1);
370 }
371 if (n > 1024*1024) {
372 logit(LOG_ERR, "%s: silly number of filter_rules: %d",
373 __func__, n);
374 return (-1);
375 }
376 for (i = 0; i < n; i++) {
377 if ((fr = calloc(1, sizeof(*fr))) == NULL) {
378 logit(LOG_ERR, "%s: calloc", __func__);
379 return (-1);
380 }
381 if (atomicio(read, fd, fr, sizeof(*fr)) != sizeof(*fr)) {
382 logitm(LOG_ERR, "%s: read(filter_rule)", __func__);
383 return (-1);
384 }
385 TAILQ_INSERT_TAIL(&newconf.filter_list, fr, entry);
386 }
387
388 /* Read Allowed Devices */
389 if (atomicio(read, fd, &n, sizeof(n)) != sizeof(n)) {
390 logitm(LOG_ERR, "%s: read(num allowed_devices)", __func__);
391 return (-1);
392 }
393 if (n > 1024*1024) {
394 logit(LOG_ERR, "%s: silly number of allowed_devices: %d",
395 __func__, n);
396 return (-1);
397 }
398 for (i = 0; i < n; i++) {
399 if ((ad = calloc(1, sizeof(*ad))) == NULL) {
400 logit(LOG_ERR, "%s: calloc", __func__);
401 return (-1);
402 }
403 if (atomicio(read, fd, ad, sizeof(*ad)) != sizeof(*ad)) {
404 logitm(LOG_ERR, "%s: read(allowed_device)", __func__);
405 return (-1);
406 }
407 TAILQ_INSERT_TAIL(&newconf.allowed_devices, ad, entry);
408 }
409
410 /* Read multicast join groups */
411 if (atomicio(read, fd, &n, sizeof(n)) != sizeof(n)) {
412 logitm(LOG_ERR, "%s: read(num join_groups)", __func__);
413 return (-1);
414 }
415 if (n > 1024*1024) {
416 logit(LOG_ERR, "%s: silly number of join_groups: %d",
417 __func__, n);
418 return (-1);
419 }
420 for (i = 0; i < n; i++) {
421 if ((jg = calloc(1, sizeof(*jg))) == NULL) {
422 logit(LOG_ERR, "%s: calloc", __func__);
423 return (-1);
424 }
425 if (atomicio(read, fd, jg, sizeof(*jg)) != sizeof(*jg)) {
426 logitm(LOG_ERR, "%s: read(join_group)", __func__);
427 return (-1);
428 }
429 TAILQ_INSERT_TAIL(&newconf.join_groups, jg, entry);
430 }
431
432 replace_conf(conf, &newconf);
433
434 return (0);
435 }
436
437 static int
send_config(int fd,struct flowd_config * conf)438 send_config(int fd, struct flowd_config *conf)
439 {
440 u_int n;
441 struct listen_addr *la;
442 struct filter_rule *fr;
443 struct allowed_device *ad;
444 struct join_group *jg;
445
446 logit(LOG_DEBUG, "%s: entering fd = %d", __func__, fd);
447
448 if (privsep_write_string(fd, conf->log_file, 1) == -1) {
449 logit(LOG_ERR, "%s: Couldn't write conf.log_file", __func__);
450 return (-1);
451 }
452 if (privsep_write_string(fd, conf->log_socket, 1) == -1) {
453 logit(LOG_ERR, "%s: Couldn't write conf.log_socket", __func__);
454 return (-1);
455 }
456 if (atomicio(vwrite, fd, &conf->log_socket_bufsiz,
457 sizeof(conf->log_socket_bufsiz)) !=
458 sizeof(conf->log_socket_bufsiz)) {
459 logitm(LOG_ERR, "%s: write(conf.log_socket_bufsiz)", __func__);
460 return (-1);
461 }
462
463 if (privsep_write_string(fd, conf->pid_file, 0) == -1) {
464 logit(LOG_ERR, "%s: Couldn't write conf.pid_file", __func__);
465 return (-1);
466 }
467
468 if (atomicio(vwrite, fd, &conf->store_mask,
469 sizeof(conf->store_mask)) != sizeof(conf->store_mask)) {
470 logitm(LOG_ERR, "%s: write(conf.store_mask)", __func__);
471 return (-1);
472 }
473
474 if (atomicio(vwrite, fd, &conf->opts,
475 sizeof(conf->opts)) != sizeof(conf->opts)) {
476 logitm(LOG_ERR, "%s: write(conf.opts)", __func__);
477 return (-1);
478 }
479
480 /* Write Listen Addrs */
481 n = 0;
482 TAILQ_FOREACH(la, &conf->listen_addrs, entry)
483 n++;
484 if (atomicio(vwrite, fd, &n, sizeof(n)) != sizeof(n)) {
485 logitm(LOG_ERR, "%s: write(num listen_addrs)", __func__);
486 return (-1);
487 }
488 TAILQ_FOREACH(la, &conf->listen_addrs, entry) {
489 if (atomicio(vwrite, fd, la, sizeof(*la)) != sizeof(*la)) {
490 logitm(LOG_ERR, "%s: write(listen_addr)", __func__);
491 return (-1);
492 }
493 if (la->fd != -1 && send_fd(fd, la->fd) == -1)
494 return (-1);
495 }
496
497 /* Write Filter Rules */
498 n = 0;
499 TAILQ_FOREACH(fr, &conf->filter_list, entry)
500 n++;
501 if (atomicio(vwrite, fd, &n, sizeof(n)) != sizeof(n)) {
502 logitm(LOG_ERR, "%s: write(num filter_rules)", __func__);
503 return (-1);
504 }
505 TAILQ_FOREACH(fr, &conf->filter_list, entry) {
506 if (atomicio(vwrite, fd, fr, sizeof(*fr)) != sizeof(*fr)) {
507 logitm(LOG_ERR, "%s: write(filter_rule)", __func__);
508 return (-1);
509 }
510 }
511
512 /* Write Allowed Devices */
513 n = 0;
514 TAILQ_FOREACH(ad, &conf->allowed_devices, entry)
515 n++;
516 if (atomicio(vwrite, fd, &n, sizeof(n)) != sizeof(n)) {
517 logitm(LOG_ERR, "%s: write(num allowed_devices)", __func__);
518 return (-1);
519 }
520 TAILQ_FOREACH(ad, &conf->allowed_devices, entry) {
521 if (atomicio(vwrite, fd, ad, sizeof(*ad)) != sizeof(*ad)) {
522 logitm(LOG_ERR, "%s: write(allowed_devices)", __func__);
523 return (-1);
524 }
525 }
526
527 /* Write Multicast join groups */
528 n = 0;
529 TAILQ_FOREACH(jg, &conf->join_groups, entry)
530 n++;
531 if (atomicio(vwrite, fd, &n, sizeof(n)) != sizeof(n)) {
532 logitm(LOG_ERR, "%s: write(num join_group)", __func__);
533 return (-1);
534 }
535 TAILQ_FOREACH(jg, &conf->join_groups, entry) {
536 if (atomicio(vwrite, fd, jg, sizeof(*jg)) != sizeof(*jg)) {
537 logitm(LOG_ERR, "%s: write(join_group)", __func__);
538 return (-1);
539 }
540 }
541
542 logit(LOG_DEBUG, "%s: done", __func__);
543
544 return (0);
545 }
546
547 static int
drop_privs(struct passwd * pw,int do_chroot)548 drop_privs(struct passwd *pw, int do_chroot)
549 {
550 logit(LOG_DEBUG, "drop_privs: dropping privs %s chroot",
551 do_chroot ? "with" : "without");
552
553 if (setsid() == -1) {
554 logitm(LOG_ERR, "setsid");
555 return (-1);
556 }
557 if (do_chroot) {
558 if (chdir(pw->pw_dir) == -1) {
559 logitm(LOG_ERR, "chdir(%s)", pw->pw_dir);
560 return (-1);
561 }
562 if (chroot(pw->pw_dir) == -1) {
563 logitm(LOG_ERR, "chroot(%s)", pw->pw_dir);
564 return (-1);
565 }
566 }
567 if (chdir("/") == -1) {
568 logitm(LOG_ERR, "chdir(/)");
569 return (-1);
570 }
571 if (setgroups(1, &pw->pw_gid) == -1) {
572 logitm(LOG_ERR, "setgroups");
573 return (-1);
574 }
575 #if defined(HAVE_SETRESGID)
576 if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) {
577 logitm(LOG_ERR, "setresgid");
578 return (-1);
579 }
580 #elif defined(HAVE_SETREGID)
581 if (setregid(pw->pw_gid, pw->pw_gid) == -1) {
582 logitm(LOG_ERR, "setregid");
583 return (-1);
584 }
585 #else
586 # error No suitable setgid function found
587 #endif
588 #if defined(HAVE_SETRESUID)
589 if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) {
590 logitm(LOG_ERR, "setresuid");
591 return (-1);
592 }
593 #elif defined(HAVE_SETREUID)
594 if (setreuid(pw->pw_uid, pw->pw_uid) == -1) {
595 logitm(LOG_ERR, "setreuid");
596 return (-1);
597 }
598 #else
599 # error No suitable setuid function found
600 #endif
601 return (0);
602 }
603
604 static int
child_get_config(const char * path,struct flowd_config * conf)605 child_get_config(const char *path, struct flowd_config *conf)
606 {
607 int s[2], ok, status;
608 pid_t ccpid;
609 void (*oldsigchld)(int);
610 FILE *cfg;
611 struct passwd *pw = NULL;
612 struct flowd_config newconf = {
613 NULL, NULL, 0, NULL, 0, 0,
614 TAILQ_HEAD_INITIALIZER(newconf.listen_addrs),
615 TAILQ_HEAD_INITIALIZER(newconf.filter_list),
616 TAILQ_HEAD_INITIALIZER(newconf.allowed_devices),
617 TAILQ_HEAD_INITIALIZER(newconf.join_groups)
618 };
619
620 logit(LOG_DEBUG, "%s: entering", __func__);
621
622 if ((conf->opts & FLOWD_OPT_INSECURE) == 0 &&
623 (pw = getpwnam(PRIVSEP_USER)) == NULL) {
624 logit(LOG_ERR, "Privilege separation user %s doesn't exist",
625 PRIVSEP_USER);
626 return(-1);
627 }
628 endpwent();
629
630 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s) == -1) {
631 logitm(LOG_ERR, "%s: socketpair", __func__);
632 return (-1);
633 }
634
635 oldsigchld = signal(SIGCHLD, SIG_DFL);
636 switch (ccpid = fork()) {
637 case -1:
638 logitm(LOG_ERR, "%s: fork", __func__);
639 return (-1);
640 case 0: /* Child */
641 close(s[0]);
642 setproctitle("config");
643
644 if ((cfg = fopen(path, "r")) == NULL) {
645 logitm(LOG_ERR, "fopen(%s)", path);
646 exit(1);
647 }
648
649 if ((conf->opts & FLOWD_OPT_INSECURE) == 0 &&
650 drop_privs(pw, 0) == -1)
651 exit(1);
652
653 ok = (parse_config(path, cfg, &newconf, 0) == 0);
654 fclose(cfg);
655 if (atomicio(vwrite, s[1], &ok, sizeof(ok)) != sizeof(ok)) {
656 logitm(LOG_ERR, "%s: write(ok)", __func__);
657 exit(1);
658 }
659 if (!ok)
660 exit(1);
661 if (send_config(s[1], &newconf) == -1)
662 exit(1);
663 logit(LOG_DEBUG, "%s: child config done", __func__);
664
665 exit(0);
666 default: /* Parent */
667 close(s[1]);
668 break;
669 }
670
671 /* Parent */
672 if (atomicio(read, s[0], &ok, sizeof(ok)) != sizeof(ok)) {
673 logitm(LOG_ERR, "%s: read(ok)", __func__);
674 return (-1);
675 }
676 if (!ok)
677 return (-1);
678 if (recv_config(s[0], conf) == -1)
679 return (-1);
680 close(s[0]);
681
682 if (waitpid(ccpid, &status, 0) == -1) {
683 logitm(LOG_ERR, "%s: waitpid", __func__);
684 return (-1);
685 }
686 if (!WIFEXITED(status)) {
687 logit(LOG_ERR, "child exited abnormally");
688 return (-1);
689 }
690 if (WEXITSTATUS(status) != 0) {
691 logit(LOG_ERR, "child exited with status %d",
692 WEXITSTATUS(status));
693 return (-1);
694 }
695
696 signal(SIGCHLD, oldsigchld);
697
698 return (0);
699 }
700
701 int
read_config(const char * path,struct flowd_config * conf)702 read_config(const char *path, struct flowd_config *conf)
703 {
704 u_int32_t opts;
705
706 logit(LOG_DEBUG, "%s: entering", __func__);
707
708 /* Preserve options not set in config file */
709 opts = conf->opts &
710 (FLOWD_OPT_DONT_FORK|FLOWD_OPT_VERBOSE|FLOWD_OPT_INSECURE);
711
712 if (child_get_config(path, conf))
713 return (-1);
714
715 conf->opts |= opts;
716
717 return (0);
718 }
719
720 /* Client functions */
721 int
client_open_log(int monitor_fd)722 client_open_log(int monitor_fd)
723 {
724 int fd = -1;
725 u_int msg = C2M_MSG_OPEN_LOG;
726
727 logit(LOG_DEBUG, "%s: entering", __func__);
728
729 if (atomicio(vwrite, monitor_fd, &msg, sizeof(msg)) != sizeof(msg)) {
730 logitm(LOG_ERR, "%s: write", __func__);
731 return (-1);
732 }
733 if ((fd = receive_fd(monitor_fd)) == -1)
734 return (-1);
735
736 return (fd);
737 }
738
739 int
client_open_socket(int monitor_fd)740 client_open_socket(int monitor_fd)
741 {
742 int fd = -1;
743 u_int msg = C2M_MSG_OPEN_SOCKET;
744
745 logit(LOG_DEBUG, "%s: entering", __func__);
746
747 if (atomicio(vwrite, monitor_fd, &msg, sizeof(msg)) != sizeof(msg)) {
748 logitm(LOG_ERR, "%s: write", __func__);
749 return (-1);
750 }
751 if ((fd = receive_fd(monitor_fd)) == -1)
752 return (-1);
753
754 return (fd);
755 }
756
757 int
client_reconfigure(int monitor_fd,struct flowd_config * conf)758 client_reconfigure(int monitor_fd, struct flowd_config *conf)
759 {
760 u_int msg = C2M_MSG_RECONFIGURE, ok;
761 struct listen_addr *la;
762
763 logit(LOG_DEBUG, "%s: entering", __func__);
764
765 TAILQ_FOREACH(la, &conf->listen_addrs, entry) {
766 if (la->fd != -1)
767 close(la->fd);
768 la->fd = -1;
769 }
770
771 if (atomicio(vwrite, monitor_fd, &msg, sizeof(msg)) != sizeof(msg)) {
772 logitm(LOG_ERR, "%s: write", __func__);
773 return (-1);
774 }
775
776 if (atomicio(read, monitor_fd, &ok, sizeof(ok)) != sizeof(ok)) {
777 logitm(LOG_ERR, "%s: read(ok)", __func__);
778 return (-1);
779 }
780 if (!ok) {
781 logit(LOG_ERR, "New config is invalid");
782 return (-1);
783 }
784
785 if (recv_config(monitor_fd, conf) == -1)
786 return (-1);
787
788 logit(LOG_DEBUG, "%s: done", __func__);
789
790 return (0);
791 }
792
793 /* Client answer functions */
794 static int
answer_open_log(struct flowd_config * conf,int client_fd)795 answer_open_log(struct flowd_config *conf, int client_fd)
796 {
797 int fd;
798
799 logit(LOG_DEBUG, "%s: entering", __func__);
800
801 if (conf->log_file == NULL)
802 logerrx("%s: attempt to open NULL log", __func__);
803
804 fd = open(conf->log_file, O_RDWR|O_APPEND|O_CREAT, 0600);
805 if (fd == -1) {
806 logitm(LOG_ERR, "%s: open", __func__);
807 return (-1);
808 }
809 if (send_fd(client_fd, fd) == -1)
810 return (-1);
811 close(fd);
812 return (0);
813 }
814
815 static int
answer_open_socket(struct flowd_config * conf,int client_fd)816 answer_open_socket(struct flowd_config *conf, int client_fd)
817 {
818 int fd, slen, orig;
819 struct sockaddr_un to;
820 socklen_t tolen;
821
822 logit(LOG_DEBUG, "%s: entering", __func__);
823
824 if (conf->log_socket == NULL)
825 logerrx("%s: attempt to open NULL log", __func__);
826
827 if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
828 logitm(LOG_ERR, "%s: socket", __func__);
829 return (-1);
830 }
831
832 bzero(&to, sizeof(to));
833 if (strlcpy(to.sun_path, conf->log_socket,
834 sizeof(to.sun_path)) >= sizeof(to.sun_path))
835 logerrx("Log socket path too long");
836 to.sun_family = AF_UNIX;
837 tolen = offsetof(struct sockaddr_un, sun_path) +
838 strlen(conf->log_socket) + 1;
839 #ifdef SOCK_HAS_LEN
840 to.sun_len = tolen;
841 #endif
842
843 if (connect(fd, (struct sockaddr *)&to, tolen) == -1) {
844 logitm(LOG_ERR, "connect to logsock");
845 return (-1);
846 }
847
848 slen = sizeof(orig);
849 if (conf->log_socket_bufsiz > 0 &&
850 getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &orig, &slen) == 0) {
851 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
852 &conf->log_socket_bufsiz,
853 sizeof(conf->log_socket_bufsiz)) == 0) {
854 logit(LOG_DEBUG, "Adjusted log_socket send "
855 "buffer from %d to %d", orig,
856 conf->log_socket_bufsiz);
857 } else
858 logerr("%s: setsockopt(SO_SNDBUF)", __func__);
859 }
860
861 if (send_fd(client_fd, fd) == -1)
862 return (-1);
863
864 close(fd);
865 return (0);
866 }
867
868 static int
answer_reconfigure(struct flowd_config * conf,int client_fd,const char * config_path)869 answer_reconfigure(struct flowd_config *conf, int client_fd,
870 const char *config_path)
871 {
872 u_int ok, rewrite_pidfile;
873 struct flowd_config newconf;
874 struct listen_addr *la;
875
876 bzero(&newconf, sizeof(newconf));
877 TAILQ_INIT(&newconf.listen_addrs);
878 TAILQ_INIT(&newconf.filter_list);
879 TAILQ_INIT(&newconf.allowed_devices);
880 TAILQ_INIT(&newconf.join_groups);
881
882 /* Transcribe flags not set in config file */
883 newconf.opts |= (conf->opts &
884 (FLOWD_OPT_DONT_FORK|FLOWD_OPT_VERBOSE|FLOWD_OPT_INSECURE));
885
886 logit(LOG_DEBUG, "%s: entering", __func__);
887
888 ok = 1;
889 if (read_config(config_path, &newconf) == -1) {
890 logit(LOG_ERR, "New config has errors");
891 ok = 0;
892 }
893
894 TAILQ_FOREACH(la, &newconf.listen_addrs, entry) {
895 if ((la->fd = open_listener(&la->addr, la->port, la->bufsiz,
896 &conf->join_groups)) == -1) {
897 logit(LOG_ERR, "Listener setup of [%s]:%d failed",
898 addr_ntop_buf(&la->addr), la->port);
899 ok = 0;
900 break;
901 }
902 }
903
904 logit(LOG_DEBUG, "%s: post listener open, ok = %d", __func__, ok);
905 if (atomicio(vwrite, client_fd, &ok, sizeof(ok)) != sizeof(ok)) {
906 logitm(LOG_ERR, "%s: write(ok)", __func__);
907 return (-1);
908 }
909 if (ok == 0)
910 return (-1);
911
912 if (send_config(client_fd, &newconf) == -1)
913 return (-1);
914
915 TAILQ_FOREACH(la, &newconf.listen_addrs, entry) {
916 close(la->fd);
917 la->fd = -1;
918 }
919
920 /* Cleanup old config and move new one into place */
921 rewrite_pidfile = (strcmp(conf->pid_file, newconf.pid_file) != 0);
922
923 replace_conf(conf, &newconf);
924
925 if (rewrite_pidfile && write_pid_file(conf->pid_file) == -1)
926 return (-1);
927
928 logit(LOG_DEBUG, "%s: done", __func__);
929
930 return (0);
931 }
932
933 /* Signal handlers */
934 static void
sighand_exit(int signo)935 sighand_exit(int signo)
936 {
937 if (monitor_to_child_sock != -1)
938 shutdown(monitor_to_child_sock, SHUT_RDWR);
939 if (!child_exited && child_pid > 1)
940 kill(child_pid, signo);
941 }
942
943 static void
sighand_child(int signo)944 sighand_child(int signo)
945 {
946 child_exited = 1;
947 }
948
949 static void
sighand_relay(int signo)950 sighand_relay(int signo)
951 {
952 if (!child_exited && child_pid > 1)
953 if (kill(child_pid, signo) != 0)
954 _exit(1);
955 signal(signo, sighand_relay);
956 }
957
958 static void
privsep_master(struct flowd_config * conf,const char * config_path)959 privsep_master(struct flowd_config *conf, const char *config_path)
960 {
961 int status, r;
962 u_int what;
963
964 for (;!child_exited;) {
965 r = atomicio(read, monitor_to_child_sock, &what, sizeof(what));
966 if (r == 0) {
967 logit(LOG_DEBUG, "%s: child exited", __func__);
968 break;
969 }
970 if (r != sizeof(what)) {
971 logitm(LOG_ERR, "%s: read", __func__);
972 unlink(conf->pid_file);
973 exit(1);
974 }
975
976 switch (what) {
977 case C2M_MSG_OPEN_LOG:
978 if (answer_open_log(conf, monitor_to_child_sock)) {
979 unlink(conf->pid_file);
980 exit(1);
981 }
982 break;
983 case C2M_MSG_OPEN_SOCKET:
984 if (answer_open_socket(conf, monitor_to_child_sock)) {
985 unlink(conf->pid_file);
986 exit(1);
987 }
988 break;
989 case C2M_MSG_RECONFIGURE:
990 if (answer_reconfigure(conf, monitor_to_child_sock,
991 config_path)) {
992 unlink(conf->pid_file);
993 exit(1);
994 }
995 break;
996 default:
997 logit(LOG_ERR, "Unknown message %d", what);
998 break;
999 }
1000 }
1001
1002 r = 0;
1003 if (child_exited) {
1004 if (waitpid(child_pid, &status, 0) == -1) {
1005 logitm(LOG_ERR, "%s: waitpid", __func__);
1006 r = 1;
1007 } else if (!WIFEXITED(status)) {
1008 logit(LOG_ERR, "child exited abnormally");
1009 r = 1;
1010 } else if (WEXITSTATUS(status) != 0) {
1011 logit(LOG_ERR, "child exited with status %d",
1012 WEXITSTATUS(status));
1013 r = 1;
1014 }
1015 }
1016
1017 unlink(conf->pid_file);
1018 exit(r);
1019 }
1020
1021 void
privsep_init(struct flowd_config * conf,int * child_to_monitor_sock,const char * config_path)1022 privsep_init(struct flowd_config *conf, int *child_to_monitor_sock,
1023 const char *config_path)
1024 {
1025 int s[2], devnull;
1026 struct passwd *pw = NULL;
1027 struct listen_addr *la;
1028
1029 logit(LOG_DEBUG, "%s: entering", __func__);
1030
1031 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s) == -1)
1032 logerr("socketpair");
1033
1034 monitor_to_child_sock = s[0];
1035 *child_to_monitor_sock = s[1];
1036
1037 if ((conf->opts & FLOWD_OPT_INSECURE) == 0 &&
1038 (pw = getpwnam(PRIVSEP_USER)) == NULL) {
1039 logerrx("Privilege separation user %s doesn't exist",
1040 PRIVSEP_USER);
1041 }
1042 endpwent();
1043
1044 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
1045 logerr("open(/dev/null)");
1046
1047 if ((conf->opts & FLOWD_OPT_DONT_FORK) == 0 && daemon(0, 1) == -1)
1048 logerr("daemon");
1049
1050 if (dup2(devnull, STDIN_FILENO) == -1 ||
1051 dup2(devnull, STDOUT_FILENO) == -1)
1052 logerr("dup2");
1053
1054 switch (child_pid = fork()) {
1055 case -1:
1056 logerr("fork");
1057 case 0: /* Child */
1058 loginit(PROGNAME, (conf->opts & FLOWD_OPT_VERBOSE),
1059 (conf->opts & FLOWD_OPT_DONT_FORK));
1060 close(monitor_to_child_sock);
1061
1062 if ((conf->opts & FLOWD_OPT_INSECURE) == 0 &&
1063 drop_privs(pw, 1) == -1)
1064 exit(1);
1065
1066 if ((conf->opts & FLOWD_OPT_DONT_FORK) == 0 &&
1067 dup2(devnull, STDERR_FILENO) == -1)
1068 logerr("dup2");
1069 close(devnull);
1070 setproctitle("net");
1071 return;
1072 default: /* Parent */
1073 loginit(PROGNAME, (conf->opts & FLOWD_OPT_VERBOSE),
1074 (conf->opts & FLOWD_OPT_DONT_FORK));
1075 if ((conf->opts & FLOWD_OPT_DONT_FORK) == 0 &&
1076 dup2(devnull, STDERR_FILENO) == -1)
1077 logerr("dup2");
1078 close(devnull);
1079 close(*child_to_monitor_sock);
1080 TAILQ_FOREACH(la, &conf->listen_addrs, entry) {
1081 if (la->fd != -1)
1082 close(la->fd);
1083 la->fd = -1;
1084 }
1085 setproctitle("monitor");
1086 if (write_pid_file(conf->pid_file) == -1)
1087 exit(1);
1088
1089 signal(SIGINT, sighand_exit);
1090 signal(SIGTERM, sighand_exit);
1091 signal(SIGCHLD, sighand_child);
1092 signal(SIGHUP, sighand_relay);
1093 #ifdef SIGINFO
1094 signal(SIGINFO, sighand_relay);
1095 #endif
1096 signal(SIGUSR1, sighand_relay);
1097 signal(SIGUSR2, sighand_relay);
1098
1099 privsep_master(conf, config_path);
1100 }
1101 /* NOTREACHED */
1102 }
1103
1104