xref: /openbsd-src/usr.sbin/tcpdump/privsep.c (revision c90a81c56dcebd6a1b73fe4aff9b03385b8e63b3)
1 /*	$OpenBSD: privsep.c,v 1.52 2018/11/17 16:52:02 brynet Exp $	*/
2 
3 /*
4  * Copyright (c) 2003 Can Erkin Acar
5  * Copyright (c) 2003 Anil Madhavapeddy <anil@recoil.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/wait.h>
23 #include <sys/ioctl.h>
24 
25 #include <netinet/in.h>
26 #include <net/if.h>
27 #include <netinet/if_ether.h>
28 #include <net/bpf.h>
29 #include <net/pfvar.h>
30 
31 #include <rpc/rpc.h>
32 
33 #include <err.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <netdb.h>
37 #include <paths.h>
38 #include <pwd.h>
39 #include <signal.h>
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <syslog.h>
45 #include <unistd.h>
46 
47 #include "interface.h"
48 #include "privsep.h"
49 #include "pfctl_parser.h"
50 
51 /*
52  * tcpdump goes through four states: STATE_INIT is where the
53  * bpf device and the input file is opened. In STATE_BPF, the
54  * pcap filter gets set. STATE_FILTER is used for parsing
55  * /etc/services and /etc/protocols and opening the output
56  * file. STATE_RUN is the packet processing part.
57  */
58 
59 enum priv_state {
60 	STATE_INIT,		/* initial state */
61 	STATE_BPF,		/* input file/device opened */
62 	STATE_FILTER,		/* filter applied */
63 	STATE_RUN,		/* running and accepting network traffic */
64 	STATE_EXIT		/* in the process of dying */
65 };
66 
67 #define ALLOW(action)	(1 << (action))
68 
69 /*
70  * Set of maximum allowed actions.
71  */
72 static const int allowed_max[] = {
73 	/* INIT */	ALLOW(PRIV_OPEN_BPF) | ALLOW(PRIV_OPEN_DUMP) |
74 			ALLOW(PRIV_SETFILTER),
75 	/* BPF */	ALLOW(PRIV_SETFILTER),
76 	/* FILTER */	ALLOW(PRIV_OPEN_PFOSFP) | ALLOW(PRIV_OPEN_OUTPUT) |
77 			ALLOW(PRIV_GETSERVENTRIES) |
78 			ALLOW(PRIV_GETPROTOENTRIES) |
79 			ALLOW(PRIV_ETHER_NTOHOST) | ALLOW(PRIV_INIT_DONE),
80 	/* RUN */	ALLOW(PRIV_GETHOSTBYADDR) | ALLOW(PRIV_ETHER_NTOHOST) |
81 			ALLOW(PRIV_GETRPCBYNUMBER) | ALLOW(PRIV_LOCALTIME) |
82 			ALLOW(PRIV_PCAP_STATS),
83 	/* EXIT */	0
84 };
85 
86 /*
87  * Default set of allowed actions. More actions get added
88  * later depending on the supplied parameters.
89  */
90 static int allowed_ext[] = {
91 	/* INIT */	ALLOW(PRIV_SETFILTER),
92 	/* BPF */	ALLOW(PRIV_SETFILTER),
93 	/* FILTER */	ALLOW(PRIV_GETSERVENTRIES),
94 	/* RUN */	ALLOW(PRIV_LOCALTIME) | ALLOW(PRIV_PCAP_STATS),
95 	/* EXIT */	0
96 };
97 
98 int		debug_level = LOG_INFO;
99 int		priv_fd = -1;
100 volatile	pid_t child_pid = -1;
101 static volatile	sig_atomic_t cur_state = STATE_INIT;
102 
103 extern void	set_slave_signals(void);
104 
105 static void	drop_privs(int);
106 
107 static void	impl_open_bpf(int, int *);
108 static void	impl_open_dump(int, const char *);
109 static void	impl_open_pfosfp(int);
110 static void	impl_open_output(int, const char *);
111 static void	impl_setfilter(int, char *, int *);
112 static void	impl_init_done(int, int *);
113 static void	impl_gethostbyaddr(int);
114 static void	impl_ether_ntohost(int);
115 static void	impl_getrpcbynumber(int);
116 static void	impl_getserventries(int);
117 static void	impl_getprotoentries(int);
118 static void	impl_localtime(int fd);
119 static void	impl_pcap_stats(int, int *);
120 
121 static void	test_state(int, int);
122 static void	logmsg(int, const char *, ...);
123 
124 static void
125 drop_privs(int nochroot)
126 {
127 	struct passwd *pw;
128 
129 	/*
130 	 * If run as regular user, then tcpdump will rely on
131 	 * pledge(2). If we are root, we want to chroot also..
132 	 */
133 	if (getuid() != 0)
134 		return;
135 
136 	pw = getpwnam("_tcpdump");
137 	if (pw == NULL)
138 		errx(1, "unknown user _tcpdump");
139 
140 	if (!nochroot) {
141 		if (chroot(pw->pw_dir) == -1)
142 			err(1, "unable to chroot");
143 		if (chdir("/") == -1)
144 			err(1, "unable to chdir");
145 	}
146 
147 	/* drop to _tcpdump */
148 	if (setgroups(1, &pw->pw_gid) == -1)
149 		err(1, "setgroups() failed");
150 	if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
151 		err(1, "setresgid() failed");
152 	if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
153 		err(1, "setresuid() failed");
154 }
155 
156 int
157 priv_init(int argc, char **argv)
158 {
159 	int i, nargc, socks[2];
160 	sigset_t allsigs, oset;
161 	char **privargv;
162 
163 	closefrom(STDERR_FILENO + 1);
164 	for (i = 1; i < _NSIG; i++)
165 		signal(i, SIG_DFL);
166 
167 	/* Create sockets */
168 	if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, socks) == -1)
169 		err(1, "socketpair() failed");
170 
171 	sigfillset(&allsigs);
172 	sigprocmask(SIG_BLOCK, &allsigs, &oset);
173 
174 	child_pid = fork();
175 	if (child_pid < 0)
176 		err(1, "fork() failed");
177 
178 	if (child_pid) {
179 		close(socks[0]);
180 		priv_fd = socks[1];
181 
182 		set_slave_signals();
183 		sigprocmask(SIG_SETMASK, &oset, NULL);
184 
185 		drop_privs(0);
186 
187 		return (0);
188 	}
189 	close(socks[1]);
190 
191 	if (dup2(socks[0], 3) == -1)
192 		err(1, "dup2 priv sock failed");
193 	closefrom(4);
194 
195 	if ((privargv = reallocarray(NULL, argc + 2, sizeof(char *))) == NULL)
196 		err(1, "alloc priv argv failed");
197 	nargc = 0;
198 	privargv[nargc++] = argv[0];
199 	privargv[nargc++] = "-P";
200 	for (i = 1; i < argc; i++)
201 		privargv[nargc++] = argv[i];
202 	privargv[nargc] = NULL;
203 	execvp(privargv[0], privargv);
204 	err(1, "exec priv '%s' failed", privargv[0]);
205 }
206 
207 __dead void
208 priv_exec(int argc, char *argv[])
209 {
210 	int bpfd = -1;
211 	int i, sock, cmd, nflag = 0, oflag = 0, Pflag = 0;
212 	char *cmdbuf, *infile = NULL;
213 	char *RFileName = NULL;
214 	char *WFileName = NULL;
215 
216 	sock = 3;
217 
218 	closefrom(4);
219 	for (i = 1; i < _NSIG; i++)
220 		signal(i, SIG_DFL);
221 
222 	signal(SIGINT, SIG_IGN);
223 
224 	/* parse the arguments for required options */
225 	opterr = 0;
226 	while ((i = getopt(argc, argv,
227 	    "ac:D:deE:fF:i:lLnNOopPqr:s:StT:vw:xXy:Y")) != -1) {
228 		switch (i) {
229 		case 'n':
230 			nflag++;
231 			break;
232 
233 		case 'o':
234 			oflag = 1;
235 			break;
236 
237 		case 'r':
238 			RFileName = optarg;
239 			break;
240 
241 		case 'w':
242 			WFileName = optarg;
243 			break;
244 
245 		case 'F':
246 			infile = optarg;
247 			break;
248 
249 		case 'P':
250 			Pflag = 1;
251 			break;
252 
253 		default:
254 			/* nothing */
255 			break;
256 		}
257 	}
258 
259 	if (!Pflag)
260 		errx(1, "exec without priv");
261 
262 	if (RFileName != NULL) {
263 		if (strcmp(RFileName, "-") != 0)
264 			allowed_ext[STATE_INIT] |= ALLOW(PRIV_OPEN_DUMP);
265 	} else
266 		allowed_ext[STATE_INIT] |= ALLOW(PRIV_OPEN_BPF);
267 	if (WFileName != NULL) {
268 		if (strcmp(WFileName, "-") != 0)
269 			allowed_ext[STATE_FILTER] |= ALLOW(PRIV_OPEN_OUTPUT);
270 	}
271 	allowed_ext[STATE_FILTER] |= ALLOW(PRIV_INIT_DONE);
272 	if (!nflag) {
273 		allowed_ext[STATE_RUN] |= ALLOW(PRIV_GETHOSTBYADDR);
274 		allowed_ext[STATE_FILTER] |= ALLOW(PRIV_ETHER_NTOHOST);
275 		allowed_ext[STATE_RUN] |= ALLOW(PRIV_ETHER_NTOHOST);
276 		allowed_ext[STATE_RUN] |= ALLOW(PRIV_GETRPCBYNUMBER);
277 		allowed_ext[STATE_FILTER] |= ALLOW(PRIV_GETPROTOENTRIES);
278 	}
279 	if (oflag)
280 		allowed_ext[STATE_FILTER] |= ALLOW(PRIV_OPEN_PFOSFP);
281 
282 	if (infile)
283 		cmdbuf = read_infile(infile);
284 	else
285 		cmdbuf = copy_argv(&argv[optind]);
286 
287 	setproctitle("[priv]");
288 
289 	for (;;) {
290 		if (may_read(sock, &cmd, sizeof(int)))
291 			break;
292 		switch (cmd) {
293 		case PRIV_OPEN_BPF:
294 			test_state(cmd, STATE_BPF);
295 			impl_open_bpf(sock, &bpfd);
296 			break;
297 		case PRIV_OPEN_DUMP:
298 			test_state(cmd, STATE_BPF);
299 			impl_open_dump(sock, RFileName);
300 			break;
301 		case PRIV_OPEN_PFOSFP:
302 			test_state(cmd, STATE_FILTER);
303 			impl_open_pfosfp(sock);
304 			break;
305 		case PRIV_OPEN_OUTPUT:
306 			test_state(cmd, STATE_FILTER);
307 			impl_open_output(sock, WFileName);
308 			break;
309 		case PRIV_SETFILTER:
310 			test_state(cmd, STATE_FILTER);
311 			impl_setfilter(sock, cmdbuf, &bpfd);
312 			break;
313 		case PRIV_INIT_DONE:
314 			test_state(cmd, STATE_RUN);
315 			impl_init_done(sock, &bpfd);
316 
317 			drop_privs(1);
318 			if (unveil("/etc/ethers", "r") == -1)
319 				err(1, "unveil");
320 			if (unveil("/etc/rpc", "r") == -1)
321 				err(1, "unveil");
322 			if (pledge("stdio rpath dns bpf", NULL) == -1)
323 				err(1, "pledge");
324 
325 			break;
326 		case PRIV_GETHOSTBYADDR:
327 			test_state(cmd, STATE_RUN);
328 			impl_gethostbyaddr(sock);
329 			break;
330 		case PRIV_ETHER_NTOHOST:
331 			test_state(cmd, cur_state);
332 			impl_ether_ntohost(sock);
333 			break;
334 		case PRIV_GETRPCBYNUMBER:
335 			test_state(cmd, STATE_RUN);
336 			impl_getrpcbynumber(sock);
337 			break;
338 		case PRIV_GETSERVENTRIES:
339 			test_state(cmd, STATE_FILTER);
340 			impl_getserventries(sock);
341 			break;
342 		case PRIV_GETPROTOENTRIES:
343 			test_state(cmd, STATE_FILTER);
344 			impl_getprotoentries(sock);
345 			break;
346 		case PRIV_LOCALTIME:
347 			test_state(cmd, STATE_RUN);
348 			impl_localtime(sock);
349 			break;
350 		case PRIV_PCAP_STATS:
351 			test_state(cmd, STATE_RUN);
352 			impl_pcap_stats(sock, &bpfd);
353 			break;
354 		default:
355 			logmsg(LOG_ERR, "[priv]: unknown command %d", cmd);
356 			exit(1);
357 			/* NOTREACHED */
358 		}
359 	}
360 
361 	/* NOTREACHED */
362 	exit(0);
363 }
364 
365 static void
366 impl_open_bpf(int fd, int *bpfd)
367 {
368 	int snaplen, promisc, err;
369 	u_int dlt, dirfilt;
370 	char device[IFNAMSIZ];
371 	size_t iflen;
372 
373 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_BPF received");
374 
375 	must_read(fd, &snaplen, sizeof(int));
376 	must_read(fd, &promisc, sizeof(int));
377 	must_read(fd, &dlt, sizeof(u_int));
378 	must_read(fd, &dirfilt, sizeof(u_int));
379 	iflen = read_string(fd, device, sizeof(device), __func__);
380 	if (iflen == 0)
381 		errx(1, "Invalid interface size specified");
382 	*bpfd = pcap_live(device, snaplen, promisc, dlt, dirfilt);
383 	err = errno;
384 	if (*bpfd < 0)
385 		logmsg(LOG_DEBUG,
386 		    "[priv]: failed to open bpf device for %s: %s",
387 		    device, strerror(errno));
388 	send_fd(fd, *bpfd);
389 	must_write(fd, &err, sizeof(int));
390 	/* do not close bpfd until filter is set */
391 }
392 
393 static void
394 impl_open_dump(int fd, const char *RFileName)
395 {
396 	int file, err = 0;
397 
398 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_DUMP received");
399 
400 	if (RFileName == NULL) {
401 		file = -1;
402 		logmsg(LOG_ERR, "[priv]: No offline file specified");
403 	} else {
404 		file = open(RFileName, O_RDONLY, 0);
405 		err = errno;
406 		if (file < 0)
407 			logmsg(LOG_DEBUG, "[priv]: failed to open %s: %s",
408 			    RFileName, strerror(errno));
409 	}
410 	send_fd(fd, file);
411 	must_write(fd, &err, sizeof(int));
412 	if (file >= 0)
413 		close(file);
414 }
415 
416 static void
417 impl_open_pfosfp(int fd)
418 {
419 	int file, err = 0;
420 
421 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_PFOSFP received");
422 
423 	file = open(PF_OSFP_FILE, O_RDONLY, 0);
424 	err = errno;
425 	if (file < 0)
426 		logmsg(LOG_DEBUG, "[priv]: failed to open %s: %s",
427 		    PF_OSFP_FILE, strerror(errno));
428 	send_fd(fd, file);
429 	must_write(fd, &err, sizeof(int));
430 	if (file >= 0)
431 		close(file);
432 }
433 
434 static void
435 impl_open_output(int fd, const char *WFileName)
436 {
437 	int file, err;
438 
439 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_OUTPUT received");
440 
441 	file = open(WFileName, O_WRONLY|O_CREAT|O_TRUNC, 0666);
442 	err = errno;
443 	send_fd(fd, file);
444 	must_write(fd, &err, sizeof(int));
445 	if (file < 0)
446 		logmsg(LOG_DEBUG, "[priv]: failed to open %s: %s",
447 		    WFileName, strerror(err));
448 	else
449 		close(file);
450 }
451 
452 static void
453 impl_setfilter(int fd, char *cmdbuf, int *bpfd)
454 {
455 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_SETFILTER received");
456 
457 	if (setfilter(*bpfd, fd, cmdbuf))
458 		logmsg(LOG_DEBUG, "[priv]: setfilter() failed");
459 }
460 
461 static void
462 impl_init_done(int fd, int *bpfd)
463 {
464 	int ret;
465 
466 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_INIT_DONE received");
467 
468 	ret = 0;
469 	must_write(fd, &ret, sizeof(ret));
470 }
471 
472 static void
473 impl_gethostbyaddr(int fd)
474 {
475 	char hostname[HOST_NAME_MAX+1];
476 	size_t hostname_len;
477 	int addr_af;
478 	struct hostent *hp;
479 
480 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETHOSTBYADDR received");
481 
482 	/* Expecting: address block, address family */
483 	hostname_len = read_block(fd, hostname, sizeof(hostname), __func__);
484 	if (hostname_len == 0)
485 		_exit(1);
486 	must_read(fd, &addr_af, sizeof(int));
487 	hp = gethostbyaddr(hostname, hostname_len, addr_af);
488 	if (hp == NULL)
489 		write_zero(fd);
490 	else
491 		write_string(fd, hp->h_name);
492 }
493 
494 static void
495 impl_ether_ntohost(int fd)
496 {
497 	struct ether_addr ether;
498 	char hostname[HOST_NAME_MAX+1];
499 
500 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_ETHER_NTOHOST received");
501 
502 	/* Expecting: ethernet address */
503 	must_read(fd, &ether, sizeof(ether));
504 	if (ether_ntohost(hostname, &ether) == -1)
505 		write_zero(fd);
506 	else
507 		write_string(fd, hostname);
508 }
509 
510 static void
511 impl_getrpcbynumber(int fd)
512 {
513 	int rpc;
514 	struct rpcent *rpce;
515 
516 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETRPCBYNUMBER received");
517 
518 	must_read(fd, &rpc, sizeof(int));
519 	rpce = getrpcbynumber(rpc);
520 	if (rpce == NULL)
521 		write_zero(fd);
522 	else
523 		write_string(fd, rpce->r_name);
524 }
525 
526 static void
527 impl_getserventries(int fd)
528 {
529 	struct servent *sp;
530 
531 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETSERVENTRIES received");
532 
533 	for (;;) {
534 		sp = getservent();
535 		if (sp == NULL) {
536 			write_zero(fd);
537 			break;
538 		} else {
539 			write_string(fd, sp->s_name);
540 			must_write(fd, &sp->s_port, sizeof(int));
541 			write_string(fd, sp->s_proto);
542 		}
543 	}
544 	endservent();
545 }
546 
547 static void
548 impl_getprotoentries(int fd)
549 {
550 	struct protoent *pe;
551 
552 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETPROTOENTRIES received");
553 
554 	for (;;) {
555 		pe = getprotoent();
556 		if (pe == NULL) {
557 			write_zero(fd);
558 			break;
559 		} else {
560 			write_string(fd, pe->p_name);
561 			must_write(fd, &pe->p_proto, sizeof(int));
562 		}
563 	}
564 	endprotoent();
565 }
566 
567 /* read the time and send the corresponding localtime and gmtime
568  * results back to the unprivileged process */
569 static void
570 impl_localtime(int fd)
571 {
572 	struct tm *lt, *gt;
573 	time_t t;
574 
575 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_LOCALTIME received");
576 
577 	must_read(fd, &t, sizeof(time_t));
578 
579 	/* this must be done separately, since they apparently use the
580 	 * same local buffer */
581 	if ((lt = localtime(&t)) == NULL)
582 		errx(1, "localtime()");
583 	must_write(fd, lt, sizeof(*lt));
584 
585 	if ((gt = gmtime(&t)) == NULL)
586 		errx(1, "gmtime()");
587 	must_write(fd, gt, sizeof(*gt));
588 
589 	if (lt->tm_zone == NULL)
590 		write_zero(fd);
591 	else
592 		write_string(fd, lt->tm_zone);
593 }
594 
595 static void
596 impl_pcap_stats(int fd, int *bpfd)
597 {
598 	struct pcap_stat stats;
599 
600 	logmsg(LOG_DEBUG, "[priv]: msg PRIV_PCAP_STATS received");
601 
602 	if (ioctl(*bpfd, BIOCGSTATS, &stats) == -1)
603 		write_zero(fd);
604 	else
605 		must_write(fd, &stats, sizeof(stats));
606 }
607 
608 void
609 priv_init_done(void)
610 {
611 	int ret;
612 
613 	if (priv_fd < 0)
614 		errx(1, "%s: called from privileged portion", __func__);
615 
616 	write_command(priv_fd, PRIV_INIT_DONE);
617 	must_read(priv_fd, &ret, sizeof(int));
618 }
619 
620 /* Reverse address resolution; response is placed into res, and length of
621  * response is returned (zero on error) */
622 size_t
623 priv_gethostbyaddr(char *addr, size_t addr_len, int af, char *res, size_t res_len)
624 {
625 	if (priv_fd < 0)
626 		errx(1, "%s called from privileged portion", __func__);
627 
628 	write_command(priv_fd, PRIV_GETHOSTBYADDR);
629 	write_block(priv_fd, addr_len, addr);
630 	must_write(priv_fd, &af, sizeof(int));
631 
632 	return (read_string(priv_fd, res, res_len, __func__));
633 }
634 
635 size_t
636 priv_ether_ntohost(char *name, size_t name_len, struct ether_addr *e)
637 {
638 	if (priv_fd < 0)
639 		errx(1, "%s called from privileged portion", __func__);
640 
641 	write_command(priv_fd, PRIV_ETHER_NTOHOST);
642 	must_write(priv_fd, e, sizeof(*e));
643 
644 	/* Read the host name */
645 	return (read_string(priv_fd, name, name_len, __func__));
646 }
647 
648 size_t
649 priv_getrpcbynumber(int rpc, char *progname, size_t progname_len)
650 {
651 	if (priv_fd < 0)
652 		errx(1, "%s called from privileged portion", __func__);
653 
654 	write_command(priv_fd, PRIV_GETRPCBYNUMBER);
655 	must_write(priv_fd, &rpc, sizeof(int));
656 
657 	return read_string(priv_fd, progname, progname_len, __func__);
658 }
659 
660 /* start getting service entries */
661 void
662 priv_getserventries(void)
663 {
664 	if (priv_fd < 0)
665 		errx(1, "%s called from privileged portion", __func__);
666 
667 	write_command(priv_fd, PRIV_GETSERVENTRIES);
668 }
669 
670 /* retrieve a service entry, should be called repeatedly after calling
671    priv_getserventries(), until it returns zero. */
672 size_t
673 priv_getserventry(char *name, size_t name_len, int *port, char *prot,
674     size_t prot_len)
675 {
676 	if (priv_fd < 0)
677 		errx(1, "%s called from privileged portion", __func__);
678 
679 	/* read the service name */
680 	if (read_string(priv_fd, name, name_len, __func__) == 0)
681 		return 0;
682 
683 	/* read the port */
684 	must_read(priv_fd, port, sizeof(int));
685 
686 	/* read the protocol */
687 	return (read_string(priv_fd, prot, prot_len, __func__));
688 }
689 
690 /* start getting ip protocol entries */
691 void
692 priv_getprotoentries(void)
693 {
694 	if (priv_fd < 0)
695 		errx(1, "%s called from privileged portion", __func__);
696 
697 	write_command(priv_fd, PRIV_GETPROTOENTRIES);
698 }
699 
700 /* retrieve a ip protocol entry, should be called repeatedly after calling
701    priv_getprotoentries(), until it returns zero. */
702 size_t
703 priv_getprotoentry(char *name, size_t name_len, int *num)
704 {
705 	if (priv_fd < 0)
706 		errx(1, "%s called from privileged portion", __func__);
707 
708 	/* read the proto name */
709 	if (read_string(priv_fd, name, name_len, __func__) == 0)
710 		return 0;
711 
712 	/* read the num */
713 	must_read(priv_fd, num, sizeof(int));
714 
715 	return (1);
716 }
717 
718 /* localtime() replacement: ask the privileged process for localtime and
719  * gmtime, cache the localtime for about one minute i.e. until one of the
720  * fields other than seconds changes. The check is done using gmtime
721  * values since they are the same in parent and child. */
722 struct	tm *
723 priv_localtime(const time_t *t)
724 {
725 	static struct tm lt, gt0;
726 	static struct tm *gt = NULL;
727 	static char zone[PATH_MAX];
728 
729 	if (gt != NULL) {
730 		gt = gmtime(t);
731 		gt0.tm_sec = gt->tm_sec;
732 		gt0.tm_zone = gt->tm_zone;
733 
734 		if (memcmp(gt, &gt0, sizeof(struct tm)) == 0) {
735 			lt.tm_sec = gt0.tm_sec;
736 			return &lt;
737 		}
738 	}
739 
740 	write_command(priv_fd, PRIV_LOCALTIME);
741 	must_write(priv_fd, t, sizeof(time_t));
742 	must_read(priv_fd, &lt, sizeof(lt));
743 	must_read(priv_fd, &gt0, sizeof(gt0));
744 
745 	if (read_string(priv_fd, zone, sizeof(zone), __func__))
746 		lt.tm_zone = zone;
747 	else
748 		lt.tm_zone = NULL;
749 
750 	gt0.tm_zone = NULL;
751 	gt = &gt0;
752 
753 	return &lt;
754 }
755 
756 int
757 priv_pcap_stats(struct pcap_stat *ps)
758 {
759 	if (priv_fd < 0)
760 		errx(1, "%s: called from privileged portion", __func__);
761 
762 	write_command(priv_fd, PRIV_PCAP_STATS);
763 	must_read(priv_fd, ps, sizeof(*ps));
764 	return (0);
765 }
766 
767 int
768 priv_open_pfosfp(void)
769 {
770 	int fd, err = 0;
771 	write_command(priv_fd, PRIV_OPEN_PFOSFP);
772 
773 	fd = receive_fd(priv_fd);
774 	must_read(priv_fd, &err, sizeof(int));
775 	if (fd < 0) {
776 		warnc(err, "%s", PF_OSFP_FILE);
777 		return (-1);
778 	}
779 
780 	return (fd);
781 }
782 
783 /* Read all data or return 1 for error. */
784 int
785 may_read(int fd, void *buf, size_t n)
786 {
787 	char *s = buf;
788 	ssize_t res, pos = 0;
789 
790 	while (n > pos) {
791 		res = read(fd, s + pos, n - pos);
792 		switch (res) {
793 		case -1:
794 			if (errno == EINTR || errno == EAGAIN)
795 				continue;
796 			/* FALLTHROUGH */
797 		case 0:
798 			return (1);
799 		default:
800 			pos += res;
801 		}
802 	}
803 	return (0);
804 }
805 
806 /* Read data with the assertion that it all must come through, or
807  * else abort the process.  Based on atomicio() from openssh. */
808 void
809 must_read(int fd, void *buf, size_t n)
810 {
811 	char *s = buf;
812 	ssize_t res, pos = 0;
813 
814 	while (n > pos) {
815 		res = read(fd, s + pos, n - pos);
816 		switch (res) {
817 		case -1:
818 			if (errno == EINTR || errno == EAGAIN)
819 				continue;
820 			/* FALLTHROUGH */
821 		case 0:
822 			_exit(0);
823 		default:
824 			pos += res;
825 		}
826 	}
827 }
828 
829 /* Write data with the assertion that it all has to be written, or
830  * else abort the process.  Based on atomicio() from openssh. */
831 void
832 must_write(int fd, const void *buf, size_t n)
833 {
834 	const char *s = buf;
835 	ssize_t res, pos = 0;
836 
837 	while (n > pos) {
838 		res = write(fd, s + pos, n - pos);
839 		switch (res) {
840 		case -1:
841 			if (errno == EINTR || errno == EAGAIN)
842 				continue;
843 			/* FALLTHROUGH */
844 		case 0:
845 			_exit(0);
846 		default:
847 			pos += res;
848 		}
849 	}
850 }
851 
852 /* test for a given state, and possibly increase state */
853 static void
854 test_state(int action, int next)
855 {
856 	if (cur_state < 0 || cur_state > STATE_RUN) {
857 		logmsg(LOG_ERR, "[priv] Invalid state: %d", cur_state);
858 		_exit(1);
859 	}
860 	if ((allowed_max[cur_state] & allowed_ext[cur_state]
861 	    & ALLOW(action)) == 0) {
862 		logmsg(LOG_ERR, "[priv] Invalid action %d in state %d",
863 		    action, cur_state);
864 		_exit(1);
865 	}
866 	if (next < cur_state) {
867 		logmsg(LOG_ERR, "[priv] Invalid next state: %d < %d",
868 		    next, cur_state);
869 		_exit(1);
870 	}
871 
872 	cur_state = next;
873 }
874 
875 static void
876 logmsg(int pri, const char *message, ...)
877 {
878 	va_list ap;
879 	if (pri > debug_level)
880 		return;
881 	va_start(ap, message);
882 
883 	vfprintf(stderr, message, ap);
884 	fprintf(stderr, "\n");
885 	va_end(ap);
886 }
887 
888 /* write a command to the peer */
889 void
890 write_command(int fd, int cmd)
891 {
892 	must_write(fd, &cmd, sizeof(cmd));
893 }
894 
895 /* write a zero 'length' to signal an error to read_{string|block} */
896 void
897 write_zero(int fd)
898 {
899 	size_t len = 0;
900 	must_write(fd, &len, sizeof(size_t));
901 }
902 
903 /* send a string */
904 void
905 write_string(int fd, const char *str)
906 {
907 	size_t len;
908 
909 	len = strlen(str) + 1;
910 	must_write(fd, &len, sizeof(size_t));
911 	must_write(fd, str, len);
912 }
913 
914 /* send a block of data of given size */
915 void
916 write_block(int fd, size_t size, const char *str)
917 {
918 	must_write(fd, &size, sizeof(size_t));
919 	must_write(fd, str, size);
920 }
921 
922 /* read a string from the channel, return 0 if error, or total size of
923  * the buffer, including the terminating '\0' */
924 size_t
925 read_string(int fd, char *buf, size_t size, const char *func)
926 {
927 	size_t len;
928 
929 	len = read_block(fd, buf, size, func);
930 	if (len == 0)
931 		return (0);
932 
933 	if (buf[len - 1] != '\0')
934 		errx(1, "%s: received invalid string", func);
935 
936 	return (len);
937 }
938 
939 /* read a block of data from the channel, return length of data, or 0
940  * if error */
941 size_t
942 read_block(int fd, char *buf, size_t size, const char *func)
943 {
944 	size_t len;
945 	/* Expect back an integer size, and then a string of that length */
946 	must_read(fd, &len, sizeof(size_t));
947 
948 	/* Check there was no error (indicated by a return of 0) */
949 	if (len == 0)
950 		return (0);
951 
952 	/* Make sure we aren't overflowing the passed in buffer */
953 	if (size < len)
954 		errx(1, "%s: overflow attempt in return", func);
955 
956 	/* Read the string and make sure we got all of it */
957 	must_read(fd, buf, len);
958 	return (len);
959 }
960