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