xref: /openbsd/sbin/isakmpd/monitor.c (revision ff9f425c)
1 /* $OpenBSD: monitor.c,v 1.83 2023/02/08 08:03:11 tb Exp $	 */
2 
3 /*
4  * Copyright (c) 2003 H�kan Olsson.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/ioctl.h>
30 #include <sys/stat.h>
31 #include <sys/wait.h>
32 #include <netinet/in.h>
33 
34 #include <dirent.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <pwd.h>
38 #include <signal.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <limits.h>
43 
44 #include <regex.h>
45 #include <keynote.h>
46 
47 #include "conf.h"
48 #include "log.h"
49 #include "monitor.h"
50 #include "policy.h"
51 #include "ui.h"
52 #include "util.h"
53 #include "pf_key_v2.h"
54 
55 struct monitor_state {
56 	pid_t           pid;
57 	int             s;
58 	char            root[PATH_MAX];
59 } m_state;
60 
61 extern char *pid_file;
62 
63 extern void	set_slave_signals(void);
64 
65 /* Private functions.  */
66 static void	must_read(void *, size_t);
67 static void	must_write(const void *, size_t);
68 
69 static void	m_priv_getfd(void);
70 static void	m_priv_setsockopt(void);
71 static void	m_priv_req_readdir(void);
72 static void	m_priv_bind(void);
73 static void	m_priv_pfkey_open(void);
74 static int	m_priv_local_sanitize_path(const char *, size_t, int);
75 static int	m_priv_check_sockopt(int, int);
76 static int	m_priv_check_bind(const struct sockaddr *, socklen_t);
77 
78 static void	set_monitor_signals(void);
79 static void	sig_pass_to_chld(int);
80 
81 /*
82  * Public functions, unprivileged.
83  */
84 
85 /* Setup monitor context, fork, drop child privs.  */
86 pid_t
monitor_init(int debug)87 monitor_init(int debug)
88 {
89 	struct passwd  *pw;
90 	int             p[2];
91 
92 	bzero(&m_state, sizeof m_state);
93 
94 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, p) != 0)
95 		log_fatal("monitor_init: socketpair() failed");
96 
97 	pw = getpwnam(ISAKMPD_PRIVSEP_USER);
98 	if (pw == NULL)
99 		log_fatalx("monitor_init: getpwnam(\"%s\") failed",
100 		    ISAKMPD_PRIVSEP_USER);
101 	strlcpy(m_state.root, pw->pw_dir, sizeof m_state.root);
102 
103 	set_monitor_signals();
104 	m_state.pid = fork();
105 
106 	if (m_state.pid == -1)
107 		log_fatal("monitor_init: fork of unprivileged child failed");
108 	if (m_state.pid == 0) {
109 		/* The child process drops privileges. */
110 		set_slave_signals();
111 
112 		if (chroot(pw->pw_dir) != 0 || chdir("/") != 0)
113 			log_fatal("monitor_init: chroot failed");
114 
115 		if (setgroups(1, &pw->pw_gid) == -1 ||
116 		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
117 		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
118 			log_fatal("monitor_init: can't drop privileges");
119 
120 		m_state.s = p[0];
121 		close(p[1]);
122 
123 		LOG_DBG((LOG_MISC, 10,
124 		    "monitor_init: privileges dropped for child process"));
125 	} else {
126 		/* Privileged monitor. */
127 		setproctitle("monitor [priv]");
128 
129 		m_state.s = p[1];
130 		close(p[0]);
131 	}
132 
133 	/* With "-dd", stop and wait here. For gdb "attach" etc.  */
134 	if (debug > 1) {
135 		log_print("monitor_init: stopped %s PID %d fd %d%s",
136 		    m_state.pid ? "priv" : "child", getpid(), m_state.s,
137 		    m_state.pid ? ", waiting for SIGCONT" : "");
138 		kill(getpid(), SIGSTOP);	/* Wait here for SIGCONT.  */
139 		if (m_state.pid)
140 			kill(m_state.pid, SIGCONT); /* Continue child.  */
141 	}
142 
143 	return m_state.pid;
144 }
145 
146 void
monitor_exit(int code)147 monitor_exit(int code)
148 {
149 	int status = 0, gotstatus = 0;
150 	pid_t pid;
151 
152 	if (m_state.pid != 0) {
153 		/* When called from the monitor, kill slave and wait for it  */
154 		kill(m_state.pid, SIGTERM);
155 
156 		do {
157 			pid = waitpid(m_state.pid, &status, 0);
158 		} while (pid == -1 && errno == EINTR);
159 		if (pid != -1)
160 			gotstatus = 1;
161 
162 		/* Remove FIFO and pid files.  */
163 		unlink(ui_fifo);
164 		unlink(pid_file);
165 	}
166 
167 	close(m_state.s);
168 	if (code == 0 && gotstatus)
169 		exit(WIFEXITED(status)? WEXITSTATUS(status) : 1);
170 	else
171 		exit(code);
172 }
173 
174 int
monitor_pf_key_v2_open(void)175 monitor_pf_key_v2_open(void)
176 {
177 	int	err, cmd;
178 
179 	cmd = MONITOR_PFKEY_OPEN;
180 	must_write(&cmd, sizeof cmd);
181 
182 	must_read(&err, sizeof err);
183 	if (err < 0) {
184 		log_error("monitor_pf_key_v2_open: parent could not create "
185 		    "PF_KEY socket");
186 		return -1;
187 	}
188 	pf_key_v2_socket = mm_receive_fd(m_state.s);
189 	if (pf_key_v2_socket < 0) {
190 		log_error("monitor_pf_key_v2_open: mm_receive_fd() failed");
191 		return -1;
192 	}
193 
194 	return pf_key_v2_socket;
195 }
196 
197 int
monitor_open(const char * path,int flags,mode_t mode)198 monitor_open(const char *path, int flags, mode_t mode)
199 {
200 	size_t	len;
201 	int	fd, err, cmd;
202 	char	pathreal[PATH_MAX];
203 
204 	if (path[0] == '/')
205 		strlcpy(pathreal, path, sizeof pathreal);
206 	else
207 		snprintf(pathreal, sizeof pathreal, "%s/%s", m_state.root,
208 		    path);
209 
210 	cmd = MONITOR_GET_FD;
211 	must_write(&cmd, sizeof cmd);
212 
213 	len = strlen(pathreal);
214 	must_write(&len, sizeof len);
215 	must_write(&pathreal, len);
216 
217 	must_write(&flags, sizeof flags);
218 	must_write(&mode, sizeof mode);
219 
220 	must_read(&err, sizeof err);
221 	if (err != 0) {
222 		errno = err;
223 		return -1;
224 	}
225 
226 	fd = mm_receive_fd(m_state.s);
227 	if (fd < 0) {
228 		log_error("monitor_open: mm_receive_fd () failed");
229 		return -1;
230 	}
231 
232 	return fd;
233 }
234 
235 FILE *
monitor_fopen(const char * path,const char * mode)236 monitor_fopen(const char *path, const char *mode)
237 {
238 	FILE	*fp;
239 	int	 fd, flags = 0, saved_errno;
240 	mode_t	 mask, cur_umask;
241 
242 	/* Only the child process is supposed to run this.  */
243 	if (m_state.pid)
244 		log_fatal("[priv] bad call to monitor_fopen");
245 
246 	switch (mode[0]) {
247 	case 'r':
248 		flags = (mode[1] == '+' ? O_RDWR : O_RDONLY);
249 		break;
250 	case 'w':
251 		flags = (mode[1] == '+' ? O_RDWR : O_WRONLY) | O_CREAT |
252 		    O_TRUNC;
253 		break;
254 	case 'a':
255 		flags = (mode[1] == '+' ? O_RDWR : O_WRONLY) | O_CREAT |
256 		    O_APPEND;
257 		break;
258 	default:
259 		log_fatal("monitor_fopen: bad call");
260 	}
261 
262 	cur_umask = umask(0);
263 	(void)umask(cur_umask);
264 	mask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
265 	mask &= ~cur_umask;
266 
267 	fd = monitor_open(path, flags, mask);
268 	if (fd < 0)
269 		return NULL;
270 
271 	/* Got the fd, attach a FILE * to it.  */
272 	fp = fdopen(fd, mode);
273 	if (!fp) {
274 		log_error("monitor_fopen: fdopen() failed");
275 		saved_errno = errno;
276 		close(fd);
277 		errno = saved_errno;
278 		return NULL;
279 	}
280 	return fp;
281 }
282 
283 int
monitor_stat(const char * path,struct stat * sb)284 monitor_stat(const char *path, struct stat *sb)
285 {
286 	int	fd, r, saved_errno;
287 
288 	/* O_NONBLOCK is needed for stat'ing fifos. */
289 	fd = monitor_open(path, O_RDONLY | O_NONBLOCK, 0);
290 	if (fd < 0)
291 		return -1;
292 
293 	r = fstat(fd, sb);
294 	saved_errno = errno;
295 	close(fd);
296 	errno = saved_errno;
297 	return r;
298 }
299 
300 int
monitor_setsockopt(int s,int level,int optname,const void * optval,socklen_t optlen)301 monitor_setsockopt(int s, int level, int optname, const void *optval,
302     socklen_t optlen)
303 {
304 	int	ret, err, cmd;
305 
306 	cmd = MONITOR_SETSOCKOPT;
307 	must_write(&cmd, sizeof cmd);
308 	if (mm_send_fd(m_state.s, s)) {
309 		log_print("monitor_setsockopt: read/write error");
310 		return -1;
311 	}
312 
313 	must_write(&level, sizeof level);
314 	must_write(&optname, sizeof optname);
315 	must_write(&optlen, sizeof optlen);
316 	must_write(optval, optlen);
317 
318 	must_read(&err, sizeof err);
319 	must_read(&ret, sizeof ret);
320 	if (err != 0)
321 		errno = err;
322 	return ret;
323 }
324 
325 int
monitor_bind(int s,const struct sockaddr * name,socklen_t namelen)326 monitor_bind(int s, const struct sockaddr *name, socklen_t namelen)
327 {
328 	int	ret, err, cmd;
329 
330 	cmd = MONITOR_BIND;
331 	must_write(&cmd, sizeof cmd);
332 	if (mm_send_fd(m_state.s, s)) {
333 		log_print("monitor_bind: read/write error");
334 		return -1;
335 	}
336 
337 	must_write(&namelen, sizeof namelen);
338 	must_write(name, namelen);
339 
340 	must_read(&err, sizeof err);
341 	must_read(&ret, sizeof ret);
342 	if (err != 0)
343 		errno = err;
344 	return ret;
345 }
346 
347 int
monitor_req_readdir(const char * filename)348 monitor_req_readdir(const char *filename)
349 {
350 	int cmd, err;
351 	size_t len;
352 
353 	cmd = MONITOR_REQ_READDIR;
354 	must_write(&cmd, sizeof cmd);
355 
356 	len = strlen(filename);
357 	must_write(&len, sizeof len);
358 	must_write(filename, len);
359 
360 	must_read(&err, sizeof err);
361 	if (err == -1)
362 		must_read(&errno, sizeof errno);
363 
364 	return err;
365 }
366 
367 int
monitor_readdir(char * file,size_t size)368 monitor_readdir(char *file, size_t size)
369 {
370 	int fd;
371 	size_t len;
372 
373 	must_read(&len, sizeof len);
374 	if (len == 0)
375 		return -1;
376 	if (len >= size)
377 		log_fatal("monitor_readdir: received bad length from monitor");
378 	must_read(file, len);
379 	file[len] = '\0';
380 	fd = mm_receive_fd(m_state.s);
381 	return fd;
382 }
383 
384 void
monitor_init_done(void)385 monitor_init_done(void)
386 {
387 	int	cmd;
388 
389 	cmd = MONITOR_INIT_DONE;
390 	must_write(&cmd, sizeof cmd);
391 }
392 
393 /*
394  * Start of code running with privileges (the monitor process).
395  */
396 
397 static void
set_monitor_signals(void)398 set_monitor_signals(void)
399 {
400 	int n;
401 
402 	for (n = 1; n < _NSIG; n++)
403 		signal(n, SIG_DFL);
404 
405 	/* Forward some signals to the child. */
406 	signal(SIGTERM, sig_pass_to_chld);
407 	signal(SIGHUP, sig_pass_to_chld);
408 	signal(SIGUSR1, sig_pass_to_chld);
409 }
410 
411 static void
sig_pass_to_chld(int sig)412 sig_pass_to_chld(int sig)
413 {
414 	int	oerrno = errno;
415 
416 	if (m_state.pid > 0)
417 		kill(m_state.pid, sig);
418 	errno = oerrno;
419 }
420 
421 /* This function is where the privileged process waits(loops) indefinitely.  */
422 void
monitor_loop(int debug)423 monitor_loop(int debug)
424 {
425 	int	 msgcode;
426 
427 	if (!debug)
428 		log_to(0);
429 
430 	for (;;) {
431 		must_read(&msgcode, sizeof msgcode);
432 
433 		switch (msgcode) {
434 		case MONITOR_GET_FD:
435 			m_priv_getfd();
436 			break;
437 
438 		case MONITOR_PFKEY_OPEN:
439 			LOG_DBG((LOG_MISC, 80,
440 			    "monitor_loop: MONITOR_PFKEY_OPEN"));
441 			m_priv_pfkey_open();
442 			break;
443 
444 		case MONITOR_SETSOCKOPT:
445 			LOG_DBG((LOG_MISC, 80,
446 			    "monitor_loop: MONITOR_SETSOCKOPT"));
447 			m_priv_setsockopt();
448 			break;
449 
450 		case MONITOR_BIND:
451 			LOG_DBG((LOG_MISC, 80,
452 			    "monitor_loop: MONITOR_BIND"));
453 			m_priv_bind();
454 			break;
455 
456 		case MONITOR_REQ_READDIR:
457 			LOG_DBG((LOG_MISC, 80,
458 			    "monitor_loop: MONITOR_REQ_READDIR"));
459 			m_priv_req_readdir();
460 			break;
461 
462 		case MONITOR_INIT_DONE:
463 			LOG_DBG((LOG_MISC, 80,
464 			    "monitor_loop: MONITOR_INIT_DONE"));
465 			break;
466 
467 		case MONITOR_SHUTDOWN:
468 			LOG_DBG((LOG_MISC, 80,
469 			    "monitor_loop: MONITOR_SHUTDOWN"));
470 			break;
471 
472 		default:
473 			log_print("monitor_loop: got unknown code %d",
474 			    msgcode);
475 		}
476 	}
477 
478 	exit(0);
479 }
480 
481 
482 /* Privileged: called by monitor_loop.  */
483 static void
m_priv_pfkey_open(void)484 m_priv_pfkey_open(void)
485 {
486 	int	fd, err = 0;
487 
488 	fd = pf_key_v2_open();
489 	if (fd < 0)
490 		err = -1;
491 
492 	must_write(&err, sizeof err);
493 
494 	if (fd > 0 && mm_send_fd(m_state.s, fd)) {
495 		log_error("m_priv_pfkey_open: read/write operation failed");
496 		close(fd);
497 		return;
498 	}
499 	close(fd);
500 }
501 
502 /* Privileged: called by monitor_loop.  */
503 static void
m_priv_getfd(void)504 m_priv_getfd(void)
505 {
506 	char	path[PATH_MAX];
507 	size_t	len;
508 	int	v, flags, ret;
509 	int	err = 0;
510 	mode_t	mode;
511 
512 	must_read(&len, sizeof len);
513 	if (len == 0 || len >= sizeof path)
514 		log_fatal("m_priv_getfd: invalid pathname length");
515 
516 	must_read(path, len);
517 	path[len] = '\0';
518 	if (strlen(path) != len)
519 		log_fatal("m_priv_getfd: invalid pathname");
520 
521 	must_read(&flags, sizeof flags);
522 	must_read(&mode, sizeof mode);
523 
524 	if ((ret = m_priv_local_sanitize_path(path, sizeof path, flags))
525 	    != 0) {
526 		if (errno != ENOENT)
527 			log_print("m_priv_getfd: illegal path \"%s\"", path);
528 		err = errno;
529 		v = -1;
530 	} else {
531 		if ((v = open(path, flags, mode)) == -1)
532 			err = errno;
533 	}
534 
535 	must_write(&err, sizeof err);
536 
537 	if (v != -1) {
538 		if (mm_send_fd(m_state.s, v) == -1)
539 			log_error("m_priv_getfd: sending fd failed");
540 		close(v);
541 	}
542 }
543 
544 /* Privileged: called by monitor_loop.  */
545 static void
m_priv_setsockopt(void)546 m_priv_setsockopt(void)
547 {
548 	int		 sock, level, optname, v;
549 	int		 err = 0;
550 	char		*optval = 0;
551 	socklen_t	 optlen;
552 
553 	sock = mm_receive_fd(m_state.s);
554 	if (sock < 0) {
555 		log_print("m_priv_setsockopt: read/write error");
556 		return;
557 	}
558 
559 	must_read(&level, sizeof level);
560 	must_read(&optname, sizeof optname);
561 	must_read(&optlen, sizeof optlen);
562 
563 	optval = malloc(optlen);
564 	if (!optval) {
565 		log_print("m_priv_setsockopt: malloc failed");
566 		close(sock);
567 		return;
568 	}
569 
570 	must_read(optval, optlen);
571 
572 	if (m_priv_check_sockopt(level, optname) != 0) {
573 		err = EACCES;
574 		v = -1;
575 	} else {
576 		v = setsockopt(sock, level, optname, optval, optlen);
577 		if (v < 0)
578 			err = errno;
579 	}
580 
581 	close(sock);
582 	sock = -1;
583 
584 	must_write(&err, sizeof err);
585 	must_write(&v, sizeof v);
586 
587 	free(optval);
588 	return;
589 }
590 
591 /* Privileged: called by monitor_loop.  */
592 static void
m_priv_bind(void)593 m_priv_bind(void)
594 {
595 	int		 sock, v, err = 0;
596 	struct sockaddr *name = 0;
597 	socklen_t        namelen;
598 
599 	sock = mm_receive_fd(m_state.s);
600 	if (sock < 0) {
601 		log_print("m_priv_bind: read/write error");
602 		return;
603 	}
604 
605 	must_read(&namelen, sizeof namelen);
606 	name = malloc(namelen);
607 	if (!name) {
608 		log_print("m_priv_bind: malloc failed");
609 		close(sock);
610 		return;
611 	}
612 	must_read((char *)name, namelen);
613 
614 	if (m_priv_check_bind(name, namelen) != 0) {
615 		err = EACCES;
616 		v = -1;
617 	} else {
618 		v = bind(sock, name, namelen);
619 		if (v == -1) {
620 			log_error("m_priv_bind: bind(%d,%p,%d) returned %d",
621 			    sock, name, namelen, v);
622 			err = errno;
623 		}
624 	}
625 
626 	close(sock);
627 	sock = -1;
628 
629 	must_write(&err, sizeof err);
630 	must_write(&v, sizeof v);
631 
632 	free(name);
633 	return;
634 }
635 
636 /*
637  * Help functions, used by both privileged and unprivileged code
638  */
639 
640 /*
641  * Read data with the assertion that it all must come through, or else abort
642  * the process.  Based on atomicio() from openssh.
643  */
644 static void
must_read(void * buf,size_t n)645 must_read(void *buf, size_t n)
646 {
647         char *s = buf;
648 	size_t pos = 0;
649         ssize_t res;
650 
651         while (n > pos) {
652                 res = read(m_state.s, s + pos, n - pos);
653                 switch (res) {
654                 case -1:
655                         if (errno == EINTR || errno == EAGAIN)
656                                 continue;
657                 case 0:
658 			monitor_exit(0);
659                 default:
660                         pos += res;
661                 }
662         }
663 }
664 
665 /*
666  * Write data with the assertion that it all has to be written, or else abort
667  * the process.  Based on atomicio() from openssh.
668  */
669 static void
must_write(const void * buf,size_t n)670 must_write(const void *buf, size_t n)
671 {
672         const char *s = buf;
673 	size_t pos = 0;
674 	ssize_t res;
675 
676         while (n > pos) {
677                 res = write(m_state.s, s + pos, n - pos);
678                 switch (res) {
679                 case -1:
680                         if (errno == EINTR || errno == EAGAIN)
681                                 continue;
682                 case 0:
683 			monitor_exit(0);
684                 default:
685                         pos += res;
686                 }
687         }
688 }
689 
690 /* Check that path/mode is permitted.  */
691 static int
m_priv_local_sanitize_path(const char * path,size_t pmax,int flags)692 m_priv_local_sanitize_path(const char *path, size_t pmax, int flags)
693 {
694 	char new_path[PATH_MAX], var_run[PATH_MAX], *enddir;
695 
696 	/*
697 	 * We only permit paths starting with
698 	 *  /etc/isakmpd/	(read only)
699 	 *  /var/run/		(rw)
700 	 */
701 
702 	if (realpath(path, new_path) == NULL) {
703 		if (errno != ENOENT)
704 			return 1;
705 		/*
706 		 * It is ok if the directory exists,
707 		 * but the file should be created.
708 		 */
709 		if (strlcpy(new_path, path, sizeof(new_path)) >=
710 		    sizeof(new_path))
711 			return 1;
712 		enddir = strrchr(new_path, '/');
713 		if (enddir == NULL || enddir[1] == '\0')
714 			return 1;
715 		enddir[1] = '\0';
716 		if (realpath(new_path, new_path) == NULL) {
717 			errno = ENOENT;
718 			return 1;
719 		}
720 		enddir = strrchr(path, '/');
721 		strlcat(new_path, enddir, sizeof(new_path));
722 	}
723 
724 	if (realpath("/var/run/", var_run) == NULL)
725 		return 1;
726 	strlcat(var_run, "/", sizeof(var_run));
727 
728 	if (strncmp(var_run, new_path, strlen(var_run)) == 0)
729 		return 0;
730 
731 	if (strncmp(ISAKMPD_ROOT, new_path, strlen(ISAKMPD_ROOT)) == 0 &&
732 	    (flags & O_ACCMODE) == O_RDONLY)
733 		return 0;
734 
735 	errno = EACCES;
736 	return 1;
737 }
738 
739 /* Check setsockopt */
740 static int
m_priv_check_sockopt(int level,int name)741 m_priv_check_sockopt(int level, int name)
742 {
743 	switch (level) {
744 		/* These are allowed */
745 		case SOL_SOCKET:
746 		case IPPROTO_IP:
747 		case IPPROTO_IPV6:
748 		break;
749 
750 	default:
751 		log_print("m_priv_check_sockopt: Illegal level %d", level);
752 		return 1;
753 	}
754 
755 	switch (name) {
756 		/* These are allowed */
757 	case SO_REUSEPORT:
758 	case SO_REUSEADDR:
759 	case IP_AUTH_LEVEL:
760 	case IP_ESP_TRANS_LEVEL:
761 	case IP_ESP_NETWORK_LEVEL:
762 	case IP_IPCOMP_LEVEL:
763 	case IPV6_AUTH_LEVEL:
764 	case IPV6_ESP_TRANS_LEVEL:
765 	case IPV6_ESP_NETWORK_LEVEL:
766 	case IPV6_IPCOMP_LEVEL:
767 		break;
768 
769 	default:
770 		log_print("m_priv_check_sockopt: Illegal option name %d",
771 		    name);
772 		return 1;
773 	}
774 
775 	return 0;
776 }
777 
778 /* Check bind */
779 static int
m_priv_check_bind(const struct sockaddr * sa,socklen_t salen)780 m_priv_check_bind(const struct sockaddr *sa, socklen_t salen)
781 {
782 	in_port_t       port;
783 
784 	if (sa == NULL) {
785 		log_print("NULL address");
786 		return 1;
787 	}
788 	if (SA_LEN(sa) != salen) {
789 		log_print("Length mismatch: %lu %lu", (unsigned long)sa->sa_len,
790 		    (unsigned long)salen);
791 		return 1;
792 	}
793 	switch (sa->sa_family) {
794 	case AF_INET:
795 		if (salen != sizeof(struct sockaddr_in)) {
796 			log_print("Invalid inet address length");
797 			return 1;
798 		}
799 		port = ((const struct sockaddr_in *)sa)->sin_port;
800 		break;
801 	case AF_INET6:
802 		if (salen != sizeof(struct sockaddr_in6)) {
803 			log_print("Invalid inet6 address length");
804 			return 1;
805 		}
806 		port = ((const struct sockaddr_in6 *)sa)->sin6_port;
807 		break;
808 	default:
809 		log_print("Unknown address family");
810 		return 1;
811 	}
812 
813 	port = ntohs(port);
814 
815 	if (port != ISAKMP_PORT_DEFAULT && port < 1024) {
816 		log_print("Disallowed port %u", port);
817 		return 1;
818 	}
819 	return 0;
820 }
821 
822 static void
m_priv_req_readdir(void)823 m_priv_req_readdir(void)
824 {
825 	size_t len;
826 	char path[PATH_MAX];
827 	DIR *dp;
828 	struct dirent *file;
829 	struct stat sb;
830 	int off, size, fd, ret, serrno;
831 
832 	must_read(&len, sizeof len);
833 	if (len == 0 || len >= sizeof path)
834 		log_fatal("m_priv_req_readdir: invalid pathname length");
835 	must_read(path, len);
836 	path[len] = '\0';
837 	if (strlen(path) != len)
838 		log_fatal("m_priv_req_readdir: invalid pathname");
839 
840 	off = strlen(path);
841 	size = sizeof path - off;
842 
843 	if ((dp = opendir(path)) == NULL) {
844 		serrno = errno;
845 		ret = -1;
846 		must_write(&ret, sizeof ret);
847 		must_write(&serrno, sizeof serrno);
848 		return;
849 	}
850 
851 	/* report opendir() success */
852 	ret = 0;
853 	must_write(&ret, sizeof ret);
854 
855 	while ((file = readdir(dp)) != NULL) {
856 		strlcpy(path + off, file->d_name, size);
857 
858 		if (m_priv_local_sanitize_path(path, sizeof path, O_RDONLY)
859 		    != 0)
860 			continue;
861 		fd = open(path, O_RDONLY);
862 		if (fd == -1) {
863 			log_error("m_priv_req_readdir: open "
864 			    "(\"%s\", O_RDONLY, 0) failed", path);
865 			continue;
866 		}
867 		if ((fstat(fd, &sb) == -1) ||
868 		    !(S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode))) {
869 			close(fd);
870 			continue;
871 		}
872 
873 		len = strlen(path);
874 		must_write(&len, sizeof len);
875 		must_write(path, len);
876 
877 		mm_send_fd(m_state.s, fd);
878 		close(fd);
879 	}
880 	closedir(dp);
881 
882 	len = 0;
883 	must_write(&len, sizeof len);
884 }
885