xref: /openbsd/usr.sbin/npppd/npppd/privsep.c (revision 882428cd)
1 /*	$OpenBSD: privsep.c,v 1.29 2024/11/21 13:43:10 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2010 Yasuoka Masahiko <yasuoka@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 #include <sys/queue.h>
19 #include <sys/uio.h>
20 #include <sys/socket.h>
21 #include <sys/ioctl.h>
22 #include <arpa/inet.h>
23 #include <net/if.h>
24 #include <net/pfkeyv2.h>
25 #include <netinet/in.h>
26 
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <imsg.h>
30 #include <stddef.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 
35 #include "pathnames.h"
36 #include "privsep.h"
37 
38 #include "npppd.h"
39 #include "ppp.h"
40 #include "log.h"
41 
42 #ifndef nitems
43 #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
44 #endif
45 
46 enum imsg_code {
47 	PRIVSEP_OK,
48 	PRIVSEP_OPEN,
49 	PRIVSEP_SOCKET,
50 	PRIVSEP_BIND,
51 	PRIVSEP_SENDTO,
52 	PRIVSEP_UNLINK,
53 	PRIVSEP_GET_USER_INFO,
54 	PRIVSEP_GET_IF_ADDR,
55 	PRIVSEP_SET_IF_ADDR,
56 	PRIVSEP_DEL_IF_ADDR,
57 	PRIVSEP_GET_IF_FLAGS,
58 	PRIVSEP_SET_IF_FLAGS
59 };
60 
61 struct PRIVSEP_OPEN_ARG {
62 	char			 path[PATH_MAX];
63 	int			 flags;
64 };
65 
66 struct PRIVSEP_SOCKET_ARG {
67 	int			 domain;
68 	int			 type;
69 	int			 protocol;
70 };
71 
72 struct PRIVSEP_BIND_ARG {
73 	struct sockaddr_storage	 name;
74 	socklen_t		 namelen;
75 };
76 
77 struct PRIVSEP_SENDTO_ARG {
78 	size_t			 len;
79 	int			 flags;
80 	struct sockaddr_storage	 to;
81 	socklen_t		 tolen;
82 	u_char			 msg[0];
83 };
84 
85 struct PRIVSEP_UNLINK_ARG {
86 	char			 path[PATH_MAX];
87 };
88 
89 struct PRIVSEP_GET_USER_INFO_ARG {
90 	char			 path[PATH_MAX];
91 	char			 username[MAX_USERNAME_LENGTH];
92 };
93 
94 struct PRIVSEP_GET_IF_ADDR_ARG {
95 	char			 ifname[IFNAMSIZ];
96 };
97 
98 struct PRIVSEP_GET_IF_ADDR_RESP {
99 	int			 retval;
100 	int			 rerrno;
101 	struct in_addr		 addr;
102 };
103 
104 struct PRIVSEP_SET_IF_ADDR_ARG {
105 	char			 ifname[IFNAMSIZ];
106 	struct in_addr		 addr;
107 };
108 
109 struct PRIVSEP_DEL_IF_ADDR_ARG {
110 	char			 ifname[IFNAMSIZ];
111 };
112 
113 struct PRIVSEP_GET_IF_FLAGS_ARG {
114 	char			 ifname[IFNAMSIZ];
115 	int			 flags;
116 };
117 
118 struct PRIVSEP_GET_IF_FLAGS_RESP {
119 	int			 retval;
120 	int			 rerrno;
121 	int			 flags;
122 };
123 
124 struct PRIVSEP_SET_IF_FLAGS_ARG {
125 	char			 ifname[IFNAMSIZ];
126 	int			 flags;
127 };
128 
129 struct PRIVSEP_COMMON_RESP {
130 	int			 retval;
131 	int			 rerrno;
132 };
133 
134 struct PRIVSEP_GET_USER_INFO_RESP {
135 	int			 retval;
136 	int			 rerrno;
137 	char			 password[MAX_PASSWORD_LENGTH];
138 	struct in_addr		 framed_ip_address;
139 	struct in_addr		 framed_ip_netmask;
140 	char			 calling_number[NPPPD_PHONE_NUMBER_LEN + 1];
141 };
142 
143 static void	 privsep_priv_main (int);
144 static void	 privsep_priv_dispatch_imsg (struct imsgbuf *);
145 int		 imsg_read_and_get(struct imsgbuf *, struct imsg *);
146 static int	 startswith(const char *, const char *);
147 static int	 privsep_recvfd (void);
148 static int	 privsep_common_resp (void);
149 
150 static int	 privsep_npppd_check_open (struct PRIVSEP_OPEN_ARG *);
151 static int	 privsep_npppd_check_socket (struct PRIVSEP_SOCKET_ARG *);
152 static int	 privsep_npppd_check_bind (struct PRIVSEP_BIND_ARG *);
153 static int	 privsep_npppd_check_sendto (struct PRIVSEP_SENDTO_ARG *);
154 static int	 privsep_npppd_check_unlink (struct PRIVSEP_UNLINK_ARG *);
155 static int	 privsep_npppd_check_get_user_info (
156 		    struct PRIVSEP_GET_USER_INFO_ARG *);
157 static int	 privsep_npppd_check_get_if_addr (
158 		    struct PRIVSEP_GET_IF_ADDR_ARG *);
159 static int	 privsep_npppd_check_set_if_addr (
160 		    struct PRIVSEP_SET_IF_ADDR_ARG *);
161 static int	 privsep_npppd_check_del_if_addr (
162 		    struct PRIVSEP_DEL_IF_ADDR_ARG *);
163 static int	 privsep_npppd_check_get_if_flags (
164 		    struct PRIVSEP_GET_IF_FLAGS_ARG *);
165 static int	 privsep_npppd_check_set_if_flags (
166 		    struct PRIVSEP_SET_IF_FLAGS_ARG *);
167 
168 static int		 privsep_sock = -1;
169 static struct imsgbuf	 privsep_ibuf;
170 static pid_t		 privsep_pid;
171 
172 int
privsep_init(void)173 privsep_init(void)
174 {
175 	pid_t	 pid;
176 	int	 pairsock[2];
177 
178 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pairsock) == -1)
179 		return (-1);
180 
181 	if ((pid = fork()) < 0)
182 		goto fail;
183 	else if (pid == 0) {
184 		setsid();
185 		/* privileged process */
186 		setproctitle("[priv]");
187 		close(pairsock[1]);
188 		privsep_priv_main(pairsock[0]);
189 		_exit(0);
190 		/* NOTREACHED */
191 	}
192 	close(pairsock[0]);
193 	privsep_sock = pairsock[1];
194 	privsep_pid = pid;
195 	if (imsgbuf_init(&privsep_ibuf, privsep_sock) == -1)
196 		goto fail;
197 	imsgbuf_allow_fdpass(&privsep_ibuf);
198 
199 	return (0);
200 	/* NOTREACHED */
201 fail:
202 	if (pairsock[0] >= 0) {
203 		close(pairsock[0]);
204 		close(pairsock[1]);
205 	}
206 
207 	return (-1);
208 }
209 
210 void
privsep_fini(void)211 privsep_fini(void)
212 {
213 	imsgbuf_clear(&privsep_ibuf);
214 	if (privsep_sock >= 0) {
215 		close(privsep_sock);
216 		privsep_sock = -1;
217 	}
218 }
219 
220 pid_t
privsep_priv_pid(void)221 privsep_priv_pid(void)
222 {
223 	return (privsep_pid);
224 }
225 
226 /***********************************************************************
227  * Functions for from jail
228  ***********************************************************************/
229 int
priv_bind(int sock,const struct sockaddr * name,socklen_t namelen)230 priv_bind(int sock, const struct sockaddr *name, socklen_t namelen)
231 {
232 	struct PRIVSEP_BIND_ARG	 a;
233 
234 	if (namelen > sizeof(a.name)) {
235 		errno = EINVAL;
236 		return (-1);
237 	}
238 	if ((sock = dup(sock)) == -1)
239 		return (-1);
240 
241 	memcpy(&a.name, name, namelen);
242 	a.namelen = namelen;
243 
244 	(void)imsg_compose(&privsep_ibuf, PRIVSEP_BIND, 0, 0, sock,
245 	    &a, sizeof(a));
246 	imsgbuf_flush(&privsep_ibuf);
247 
248 	return (privsep_common_resp());
249 }
250 
251 int
priv_socket(int domain,int type,int protocol)252 priv_socket(int domain, int type, int protocol)
253 {
254 	struct PRIVSEP_SOCKET_ARG a;
255 
256 	a.domain = domain;
257 	a.type = type;
258 	a.protocol = protocol;
259 	(void)imsg_compose(&privsep_ibuf, PRIVSEP_SOCKET, 0, 0, -1,
260 	    &a, sizeof(a));
261 	imsgbuf_flush(&privsep_ibuf);
262 
263 	return (privsep_recvfd());
264 }
265 
266 int
priv_open(const char * path,int flags)267 priv_open(const char *path, int flags)
268 {
269 	struct PRIVSEP_OPEN_ARG a;
270 
271 	strlcpy(a.path, path, sizeof(a.path));
272 	a.flags = flags;
273 	(void)imsg_compose(&privsep_ibuf, PRIVSEP_OPEN, 0, 0, -1,
274 	    &a, sizeof(a));
275 	imsgbuf_flush(&privsep_ibuf);
276 
277 	return (privsep_recvfd());
278 }
279 
280 FILE *
priv_fopen(const char * path)281 priv_fopen(const char *path)
282 {
283 	int f;
284 	FILE *fp;
285 
286 	if ((f = priv_open(path, O_RDONLY)) < 0)
287 		return (NULL);
288 
289 	if ((fp = fdopen(f, "r")) == NULL) {
290 		close(f);
291 		return (NULL);
292 	} else
293 		return (fp);
294 }
295 
296 int
priv_sendto(int s,const void * msg,int len,int flags,const struct sockaddr * to,socklen_t tolen)297 priv_sendto(int s, const void *msg, int len, int flags,
298     const struct sockaddr *to, socklen_t tolen)
299 {
300 	struct PRIVSEP_SENDTO_ARG	 a;
301 	struct iovec			 iov[2];
302 
303 	if (tolen > sizeof(a.to)) {
304 		errno = EINVAL;
305 		return (-1);
306 	}
307 	if ((s = dup(s)) == -1)
308 		return (-1);
309 
310 	a.len = len;
311 	a.flags = flags;
312 	a.tolen = tolen;
313 	if (tolen > 0)
314 		memcpy(&a.to, to, tolen);
315 	iov[0].iov_base = &a;
316 	iov[0].iov_len = offsetof(struct PRIVSEP_SENDTO_ARG, msg);
317 	iov[1].iov_base = (void *)msg;
318 	iov[1].iov_len = len;
319 
320 	(void)imsg_composev(&privsep_ibuf, PRIVSEP_SENDTO, 0, 0, s,
321 	    iov, nitems(iov));
322 	imsgbuf_flush(&privsep_ibuf);
323 
324 	return (privsep_common_resp());
325 }
326 
327 int
priv_send(int s,const void * msg,int len,int flags)328 priv_send(int s, const void *msg, int len, int flags)
329 {
330 	return (priv_sendto(s, msg, len, flags, NULL, 0));
331 }
332 
333 int
priv_unlink(const char * path)334 priv_unlink(const char *path)
335 {
336 	struct PRIVSEP_UNLINK_ARG a;
337 
338 	strlcpy(a.path, path, sizeof(a.path));
339 	(void)imsg_compose(&privsep_ibuf, PRIVSEP_UNLINK, 0, 0, -1,
340 	    &a, sizeof(a));
341 	imsgbuf_flush(&privsep_ibuf);
342 
343 	return (privsep_common_resp());
344 }
345 
346 int
priv_get_user_info(const char * path,const char * username,npppd_auth_user ** puser)347 priv_get_user_info(const char *path, const char *username,
348     npppd_auth_user **puser)
349 {
350 	struct imsg				 imsg;
351 	ssize_t					 n;
352 	struct PRIVSEP_GET_USER_INFO_RESP	*r;
353 	struct PRIVSEP_GET_USER_INFO_ARG	 a;
354 	npppd_auth_user				*u;
355 	char					*cp;
356 	int					 sz;
357 
358 	strlcpy(a.path, path, sizeof(a.path));
359 	strlcpy(a.username, username, sizeof(a.username));
360 
361 	(void)imsg_compose(&privsep_ibuf, PRIVSEP_GET_USER_INFO, 0, 0, -1,
362 	    &a, sizeof(a));
363 	imsgbuf_flush(&privsep_ibuf);
364 
365 	if ((n = imsg_read_and_get(&privsep_ibuf, &imsg)) == -1)
366 		return (-1);
367 	if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*r)) {
368 		errno = EACCES;
369 		goto on_error;
370 	}
371 	r = imsg.data;
372 	if (r->retval != 0) {
373 		errno = r->rerrno;
374 		goto on_error;
375 	}
376 
377 	sz = strlen(username) + strlen(r->password) +
378 	    strlen(r->calling_number) + 3;
379 
380 	if ((u = malloc(offsetof(npppd_auth_user, space[sz]))) == NULL)
381 		goto on_error;
382 
383 	cp = u->space;
384 
385 	u->username = cp;
386 	n = strlcpy(cp, username, sz);
387 	cp += ++n; sz -= n;
388 
389 	u->password = cp;
390 	n = strlcpy(cp, r->password, sz);
391 	cp += ++n; sz -= n;
392 
393 	u->calling_number = cp;
394 	n = strlcpy(cp, r->calling_number, sz);
395 	cp += ++n; sz -= n;
396 
397 	u->framed_ip_address = r->framed_ip_address;
398 	u->framed_ip_netmask = r->framed_ip_netmask;
399 
400 	*puser = u;
401 	imsg_free(&imsg);
402 
403 	return (0);
404 
405 on_error:
406 	imsg_free(&imsg);
407 	return (-1);
408 }
409 
410 int
priv_get_if_addr(const char * ifname,struct in_addr * addr)411 priv_get_if_addr(const char *ifname, struct in_addr *addr)
412 {
413 	struct PRIVSEP_GET_IF_ADDR_ARG   a;
414 	struct PRIVSEP_GET_IF_ADDR_RESP *r;
415 	struct imsg			 imsg;
416 	int				 retval = -1;
417 
418 	strlcpy(a.ifname, ifname, sizeof(a.ifname));
419 
420 	(void)imsg_compose(&privsep_ibuf, PRIVSEP_GET_IF_ADDR, 0, 0, -1,
421 	    &a, sizeof(a));
422 	imsgbuf_flush(&privsep_ibuf);
423 
424 	if (imsg_read_and_get(&privsep_ibuf, &imsg) == -1)
425 		return (-1);
426 
427 	if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*r))
428 		errno = EACCES;
429 	else {
430 		r = imsg.data;
431 		if (r->retval != -1)
432 			*addr = r->addr;
433 		else
434 			errno = r->rerrno;
435 		retval = r->retval;
436 	}
437 	imsg_free(&imsg);
438 
439 	return (retval);
440 }
441 
442 int
priv_delete_if_addr(const char * ifname)443 priv_delete_if_addr(const char *ifname)
444 {
445 	struct PRIVSEP_DEL_IF_ADDR_ARG   a;
446 
447 	strlcpy(a.ifname, ifname, sizeof(a.ifname));
448 	(void)imsg_compose(&privsep_ibuf, PRIVSEP_DEL_IF_ADDR, 0, 0, -1,
449 	    &a, sizeof(a));
450 	imsgbuf_flush(&privsep_ibuf);
451 
452 	return (privsep_common_resp());
453 }
454 
455 int
priv_set_if_addr(const char * ifname,struct in_addr * addr)456 priv_set_if_addr(const char *ifname, struct in_addr *addr)
457 {
458 	struct PRIVSEP_SET_IF_ADDR_ARG   a;
459 
460 	strlcpy(a.ifname, ifname, sizeof(a.ifname));
461 	a.addr = *addr;
462 	(void)imsg_compose(&privsep_ibuf, PRIVSEP_SET_IF_ADDR, 0, 0, -1,
463 	    &a, sizeof(a));
464 	imsgbuf_flush(&privsep_ibuf);
465 
466 	return (privsep_common_resp());
467 }
468 
469 int
priv_get_if_flags(const char * ifname,int * pflags)470 priv_get_if_flags(const char *ifname, int *pflags)
471 {
472 	struct PRIVSEP_GET_IF_FLAGS_ARG		 a;
473 	struct PRIVSEP_GET_IF_FLAGS_RESP	*r;
474 	struct imsg				 imsg;
475 	int					 retval = -1;
476 
477 	strlcpy(a.ifname, ifname, sizeof(a.ifname));
478 	a.flags = 0;
479 
480 	(void)imsg_compose(&privsep_ibuf, PRIVSEP_GET_IF_FLAGS, 0, 0, -1,
481 	    &a, sizeof(a));
482 	imsgbuf_flush(&privsep_ibuf);
483 
484 	if (imsg_read_and_get(&privsep_ibuf, &imsg) == -1)
485 		return (-1);
486 	if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*r))
487 		errno = EACCES;
488 	else {
489 		r = imsg.data;
490 		*pflags = r->flags;
491 		if (r->retval != 0)
492 			errno = r->rerrno;
493 		retval = r->retval;
494 	}
495 	imsg_free(&imsg);
496 
497 	return (retval);
498 }
499 
500 int
priv_set_if_flags(const char * ifname,int flags)501 priv_set_if_flags(const char *ifname, int flags)
502 {
503 	struct PRIVSEP_SET_IF_FLAGS_ARG   a;
504 
505 	strlcpy(a.ifname, ifname, sizeof(a.ifname));
506 	a.flags = flags;
507 
508 	(void)imsg_compose(&privsep_ibuf, PRIVSEP_SET_IF_FLAGS, 0, 0, -1,
509 	    &a, sizeof(a));
510 	imsgbuf_flush(&privsep_ibuf);
511 
512 	return (privsep_common_resp());
513 }
514 
515 static int
privsep_recvfd(void)516 privsep_recvfd(void)
517 {
518 	struct PRIVSEP_COMMON_RESP	*r;
519 	struct imsg			 imsg;
520 	int				 retval = -1;
521 
522 	if (imsg_read_and_get(&privsep_ibuf, &imsg) == -1)
523 		return (-1);
524 	if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*r))
525 		errno = EACCES;
526 	else {
527 		r = imsg.data;
528 		retval = r->retval;
529 		if (r->retval != 0)
530 			errno = r->rerrno;
531 		else
532 			retval = imsg_get_fd(&imsg);
533 	}
534 	imsg_free(&imsg);
535 
536 	return (retval);
537 }
538 
539 static int
privsep_common_resp(void)540 privsep_common_resp(void)
541 {
542 	struct PRIVSEP_COMMON_RESP	*r;
543 	struct imsg			 imsg;
544 	int				 retval = -1;
545 
546 	if (imsg_read_and_get(&privsep_ibuf, &imsg) == -1) {
547 		errno = EACCES;
548 		return (-1);
549 	}
550 	if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*r))
551 		errno = EACCES;
552 	else {
553 		r = imsg.data;
554 		if (r->retval != 0)
555 			errno = r->rerrno;
556 		retval = r->retval;
557 	}
558 	imsg_free(&imsg);
559 
560 	return (retval);
561 }
562 
563 /***********************************************************************
564  * privileged process
565  ***********************************************************************/
566 static void
privsep_priv_main(int sock)567 privsep_priv_main(int sock)
568 {
569 	struct imsgbuf	 ibuf;
570 
571 	if (imsgbuf_init(&ibuf, sock) == -1)
572 		fatal("imsgbuf_init");
573 	imsgbuf_allow_fdpass(&ibuf);
574 	privsep_priv_dispatch_imsg(&ibuf);
575 	imsgbuf_clear(&ibuf);
576 	close(sock);
577 
578 	exit(EXIT_SUCCESS);
579 }
580 
581 static void
privsep_priv_dispatch_imsg(struct imsgbuf * ibuf)582 privsep_priv_dispatch_imsg(struct imsgbuf *ibuf)
583 {
584 	struct imsg	 imsg;
585 
586 	for (;;) {
587 		if (imsg_read_and_get(ibuf, &imsg) == -1)
588 			return;
589 
590 		switch (imsg.hdr.type) {
591 		case PRIVSEP_OPEN: {
592 			int				 f = -1;
593 			struct PRIVSEP_OPEN_ARG		*a = imsg.data;
594 			struct PRIVSEP_COMMON_RESP	 r = { -1, 0 };
595 
596 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
597 				r.rerrno = EINVAL;
598 			else if (privsep_npppd_check_open(a))
599 				r.rerrno = EACCES;
600 			else {
601 				if ((f = open(a->path, a->flags & ~O_CREAT))
602 				    == -1)
603 					r.rerrno = errno;
604 				else
605 					r.retval = 0;
606 			}
607 			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, f,
608 			    &r, sizeof(r));
609 			imsgbuf_flush(ibuf);
610 		    }
611 			break;
612 		case PRIVSEP_SOCKET: {
613 			int				 s = -1;
614 			struct PRIVSEP_SOCKET_ARG	*a = imsg.data;
615 			struct PRIVSEP_COMMON_RESP	 r = { -1, 0 };
616 
617 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
618 				r.rerrno = EINVAL;
619 			else if (privsep_npppd_check_socket(a))
620 				r.rerrno = EACCES;
621 			else {
622 				if ((s = socket(a->domain, a->type,
623 				    a->protocol)) == -1)
624 					r.rerrno = errno;
625 				else
626 					r.retval = 0;
627 			}
628 			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, s,
629 			    &r, sizeof(r));
630 			imsgbuf_flush(ibuf);
631 		    }
632 			break;
633 		case PRIVSEP_UNLINK: {
634 			struct PRIVSEP_UNLINK_ARG *a = imsg.data;
635 			struct PRIVSEP_COMMON_RESP r = { -1, 0 };
636 
637 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
638 				r.rerrno = EINVAL;
639 			else if (privsep_npppd_check_unlink(a))
640 				r.rerrno = EACCES;
641 			else {
642 				if ((r.retval = unlink(a->path)) != 0)
643 					r.rerrno = errno;
644 			}
645 
646 			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
647 			    &r, sizeof(r));
648 			imsgbuf_flush(ibuf);
649 		    }
650 			break;
651 		case PRIVSEP_BIND: {
652 			struct PRIVSEP_BIND_ARG	*a = imsg.data;
653 			struct PRIVSEP_COMMON_RESP r = { -1, 0 };
654 			int fd;
655 
656 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a) ||
657 			    (fd = imsg_get_fd(&imsg)) < 0)
658 				r.rerrno = EINVAL;
659 			else if (privsep_npppd_check_bind(a))
660 				r.rerrno = EACCES;
661 			else {
662 				if ((r.retval = bind(fd,
663 				    (struct sockaddr *)&a->name, a->namelen))
664 				    != 0)
665 					r.rerrno = errno;
666 				close(fd);
667 			}
668 			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
669 			    &r, sizeof(r));
670 			imsgbuf_flush(ibuf);
671 		    }
672 			break;
673 		case PRIVSEP_GET_USER_INFO: {
674 			struct PRIVSEP_GET_USER_INFO_ARG *a = imsg.data;
675 			struct PRIVSEP_GET_USER_INFO_RESP r;
676 			int   retval;
677 			char *str, *buf, *db[2] = { NULL, NULL };
678 
679 			memset(&r, 0, sizeof(r));
680 			r.retval = -1;
681 			r.framed_ip_address.s_addr = INADDR_NAS_SELECT;
682 			r.framed_ip_netmask.s_addr = INADDR_NONE;
683 			str = buf = NULL;
684 
685 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a)) {
686 				r.rerrno = EINVAL;
687 				(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
688 				    &r, sizeof(r));
689 				return;
690 			}
691 			db[0] = a->path;
692 			if (privsep_npppd_check_get_user_info(a))
693 				r.rerrno = EACCES;
694 			else if ((retval = cgetent(&buf, db, a->username))
695 			    == 0) {
696 				if ((retval = cgetstr(buf, "password", &str))
697 				    >= 0) {
698 					if (strlcpy(r.password, str,
699 					    sizeof(r.password)) >=
700 					    sizeof(r.password))
701 						goto on_broken_entry;
702 					free(str);
703 					str = NULL;
704 				}
705 				if ((retval = cgetstr(buf, "calling-number",
706 				    &str)) >= 0) {
707 					if (strlcpy(r.calling_number, str,
708 					    sizeof(r.calling_number)) >=
709 					    sizeof(r.calling_number))
710 						goto on_broken_entry;
711 					free(str);
712 					str = NULL;
713 				}
714 				if ((retval = cgetstr(buf, "framed-ip-address",
715 				    &str)) >= 0) {
716 					if (inet_pton(AF_INET, str,
717 					    &r.framed_ip_address) != 1)
718 						goto on_broken_entry;
719 					free(str);
720 					str = NULL;
721 				}
722 
723 				if ((retval = cgetstr(buf, "framed-ip-netmask",
724 				    &str)) >= 0) {
725 					if (inet_pton(AF_INET, str,
726 					    &r.framed_ip_netmask) != 1)
727 						goto on_broken_entry;
728 					free(str);
729 					str = NULL;
730 				}
731 				cgetclose();
732 				free(buf);
733 				r.retval = 0;
734 			} else if (retval == -1) {
735 				buf = NULL;
736 on_broken_entry:
737 				free(buf);
738 				free(str);
739 				r.retval = -1;
740 				r.rerrno = ENOENT;
741 			} else {
742 				r.retval = retval;
743 				r.rerrno = errno;
744 			}
745 			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
746 			    &r, sizeof(r));
747 			imsgbuf_flush(ibuf);
748 		    }
749 			break;
750 		case PRIVSEP_SENDTO: {
751 			struct PRIVSEP_SENDTO_ARG *a = imsg.data;
752 			struct PRIVSEP_COMMON_RESP r = { -1, 0 };
753 			int fd;
754 
755 			if (imsg.hdr.len < IMSG_HEADER_SIZE + sizeof(*a) ||
756 			    imsg.hdr.len < IMSG_HEADER_SIZE +
757 				offsetof(struct PRIVSEP_SENDTO_ARG,
758 					msg[a->len]))
759 				r.rerrno = EMSGSIZE;
760 			else if ((fd = imsg_get_fd(&imsg)) < 0)
761 				r.rerrno = EINVAL;
762 			else if (privsep_npppd_check_sendto(a))
763 				r.rerrno = EACCES;
764 			else {
765 				if (a->tolen > 0)
766 					r.retval = sendto(fd, a->msg,
767 					    a->len, a->flags,
768 					    (struct sockaddr *)&a->to,
769 					    a->tolen);
770 				else
771 					r.retval = send(fd, a->msg, a->len,
772 					    a->flags);
773 				if (r.retval < 0)
774 					r.rerrno = errno;
775 				close(fd);
776 			}
777 			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
778 			    &r, sizeof(r));
779 			imsgbuf_flush(ibuf);
780 		    }
781 			break;
782 		case PRIVSEP_GET_IF_ADDR: {
783 			int                              s;
784 			struct ifreq                     ifr;
785 			struct PRIVSEP_GET_IF_ADDR_ARG  *a = imsg.data;
786 			struct PRIVSEP_GET_IF_ADDR_RESP  r;
787 
788 			memset(&r, 0, sizeof(r));
789 			r.retval = -1;
790 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
791 				r.rerrno = EINVAL;
792 			else if (privsep_npppd_check_get_if_addr(a))
793 				r.rerrno = EACCES;
794 			else {
795 				memset(&ifr, 0, sizeof(ifr));
796 				strlcpy(ifr.ifr_name, a->ifname,
797 				    sizeof(ifr.ifr_name));
798 				if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
799 				    ioctl(s, SIOCGIFADDR, &ifr) != 0) {
800 					r.retval = -1;
801 					r.rerrno = errno;
802 				} else {
803 					r.retval = 0;
804 					r.addr = ((struct sockaddr_in *)
805 					    &ifr.ifr_addr)->sin_addr;
806 				}
807 				if (s >= 0)
808 					close(s);
809 			}
810 			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
811 			    &r, sizeof(r));
812 			imsgbuf_flush(ibuf);
813 		    }
814 			break;
815 		case PRIVSEP_SET_IF_ADDR: {
816 			int                              s;
817 			struct ifaliasreq                ifra;
818 			struct PRIVSEP_SET_IF_ADDR_ARG  *a = imsg.data;
819 			struct PRIVSEP_COMMON_RESP       r = { -1, 0 };
820 			struct sockaddr_in              *sin4;
821 
822 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
823 				r.rerrno = EINVAL;
824 			else if (privsep_npppd_check_set_if_addr(a))
825 				r.rerrno = EACCES;
826 			else {
827 				memset(&ifra, 0, sizeof(ifra));
828 				strlcpy(ifra.ifra_name, a->ifname,
829 				    sizeof(ifra.ifra_name));
830 
831 				sin4 = (struct sockaddr_in *)&ifra.ifra_addr;
832 				sin4->sin_family = AF_INET;
833 				sin4->sin_len = sizeof(struct sockaddr_in);
834 				sin4->sin_addr = a->addr;
835 
836 				sin4 = (struct sockaddr_in *)&ifra.ifra_mask;
837 				sin4->sin_family = AF_INET;
838 				sin4->sin_len = sizeof(struct sockaddr_in);
839 				sin4->sin_addr.s_addr = 0xffffffffUL;
840 
841 				sin4 =
842 				    (struct sockaddr_in *)&ifra.ifra_broadaddr;
843 				sin4->sin_family = AF_INET;
844 				sin4->sin_len = sizeof(struct sockaddr_in);
845 				sin4->sin_addr.s_addr = 0;
846 
847 				if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
848 				    ioctl(s, SIOCAIFADDR, &ifra) != 0) {
849 					r.retval = -1;
850 					r.rerrno = errno;
851 				} else
852 					r.retval = 0;
853 				if (s >= 0)
854 					close(s);
855 			}
856 			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
857 			    &r, sizeof(r));
858 			imsgbuf_flush(ibuf);
859 		    }
860 			break;
861 		case PRIVSEP_DEL_IF_ADDR: {
862 			int                              s;
863 			struct ifreq                     ifr;
864 			struct PRIVSEP_DEL_IF_ADDR_ARG  *a = imsg.data;
865 			struct PRIVSEP_COMMON_RESP       r = { 0, -1 };
866 
867 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
868 				r.rerrno = EINVAL;
869 			else if (privsep_npppd_check_del_if_addr(a))
870 				r.rerrno = EACCES;
871 			else {
872 				memset(&ifr, 0, sizeof(ifr));
873 				strlcpy(ifr.ifr_name, a->ifname,
874 				    sizeof(ifr.ifr_name));
875 				if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
876 				    ioctl(s, SIOCDIFADDR, &ifr) != 0) {
877 					r.retval = -1;
878 					r.rerrno = errno;
879 				} else
880 					r.retval = 0;
881 				if (s >= 0)
882 					close(s);
883 			}
884 			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
885 			    &r, sizeof(r));
886 			imsgbuf_flush(ibuf);
887 		    }
888 			break;
889 		case PRIVSEP_GET_IF_FLAGS: {
890 			int                               s;
891 			struct ifreq                      ifr;
892 			struct PRIVSEP_GET_IF_FLAGS_ARG  *a = imsg.data;
893 			struct PRIVSEP_GET_IF_FLAGS_RESP  r;
894 
895 			memset(&r, 0, sizeof(r));
896 			r.retval = -1;
897 
898 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
899 				r.rerrno = EINVAL;
900 			else if (privsep_npppd_check_get_if_flags(a)) {
901 				r.rerrno = EACCES;
902 			} else {
903 				memset(&ifr, 0, sizeof(ifr));
904 				strlcpy(ifr.ifr_name, a->ifname,
905 				    sizeof(ifr.ifr_name));
906 				if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
907 				    ioctl(s, SIOCGIFFLAGS, &ifr) != 0) {
908 					r.retval = -1;
909 					r.rerrno = errno;
910 				} else {
911 					r.retval = 0;
912 					r.flags = ifr.ifr_flags;
913 				}
914 				if (s >= 0)
915 					close(s);
916 			}
917 			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
918 			    &r, sizeof(r));
919 			imsgbuf_flush(ibuf);
920 		    }
921 			break;
922 		case PRIVSEP_SET_IF_FLAGS: {
923 			int                               s;
924 			struct ifreq                      ifr;
925 			struct PRIVSEP_SET_IF_FLAGS_ARG  *a = imsg.data;
926 			struct PRIVSEP_COMMON_RESP        r = { -1, 0 };
927 
928 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
929 				r.rerrno = EINVAL;
930 			else if (privsep_npppd_check_set_if_flags(a))
931 				r.rerrno = EACCES;
932 			else {
933 				memset(&ifr, 0, sizeof(ifr));
934 				strlcpy(ifr.ifr_name, a->ifname,
935 				    sizeof(ifr.ifr_name));
936 				ifr.ifr_flags = a->flags;
937 				if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
938 				    ioctl(s, SIOCGIFFLAGS, &ifr) != 0) {
939 					r.retval = -1;
940 					r.rerrno = errno;
941 				} else
942 					r.retval = 0;
943 				if (s >= 0)
944 					close(s);
945 			}
946 			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
947 			    &r, sizeof(r));
948 			imsgbuf_flush(ibuf);
949 		    }
950 			break;
951 		}
952 		imsg_free(&imsg);
953 	}
954 }
955 
956 int
imsg_read_and_get(struct imsgbuf * ibuf,struct imsg * imsg)957 imsg_read_and_get(struct imsgbuf *ibuf, struct imsg *imsg)
958 {
959 	ssize_t	 n;
960 
961 	for (;;) {
962 		if (imsgbuf_read(ibuf) != 1)
963 			return (-1);
964 		if ((n = imsg_get(ibuf, imsg)) < 0)
965 			return (-1);
966 		if (n == 0)
967 			continue;
968 		break;
969 	}
970 
971 	return (0);
972 }
973 
974 static int
startswith(const char * str,const char * prefix)975 startswith(const char *str, const char *prefix)
976 {
977 	return (strncmp(str, prefix, strlen(prefix)) == 0)? 1 : 0;
978 }
979 
980 static int
privsep_npppd_check_open(struct PRIVSEP_OPEN_ARG * arg)981 privsep_npppd_check_open(struct PRIVSEP_OPEN_ARG *arg)
982 {
983 	int i;
984 	struct _allow_paths {
985 		const char *path;
986 		int path_is_prefix;
987 		int readonly;
988 	} const allow_paths[] = {
989 		{ NPPPD_DIR "/",	1,	1 },
990 		{ "/dev/bpf",		0,	0 },
991 		{ "/etc/resolv.conf",	0,	1 },
992 		{ "/dev/tun",		1,	0 },
993 		{ "/dev/pppac",		1,	0 },
994 		{ "/dev/pppx",		1,	0 }
995 	};
996 
997 	/* O_NONBLOCK is the only 'extra' flag permitted */
998 	if (arg->flags & ~(O_ACCMODE | O_NONBLOCK))
999 		return (1);
1000 	for (i = 0; i < (int)nitems(allow_paths); i++) {
1001 		if (allow_paths[i].path_is_prefix) {
1002 			if (!startswith(arg->path, allow_paths[i].path))
1003 				continue;
1004 		} else if (strcmp(arg->path, allow_paths[i].path) != 0)
1005 			continue;
1006 		if (allow_paths[i].readonly) {
1007 			if ((arg->flags & O_ACCMODE) != O_RDONLY)
1008 				continue;
1009 		}
1010 		return (0);
1011 	}
1012 	return (1);
1013 }
1014 
1015 static int
privsep_npppd_check_socket(struct PRIVSEP_SOCKET_ARG * arg)1016 privsep_npppd_check_socket(struct PRIVSEP_SOCKET_ARG *arg)
1017 {
1018 	/* npppd uses routing socket */
1019 	if (arg->domain == PF_ROUTE && arg->type == SOCK_RAW &&
1020 	    arg->protocol  == AF_UNSPEC)
1021 		return (0);
1022 
1023 	/* npppd uses raw ip socket for GRE */
1024 	if (arg->domain == AF_INET && arg->type == SOCK_RAW &&
1025 	    arg->protocol == IPPROTO_GRE)
1026 		return (0);
1027 
1028 	/* L2TP uses PF_KEY socket to delete IPsec-SA */
1029 	if (arg->domain == PF_KEY && arg->type == SOCK_RAW &&
1030 	    arg->protocol == PF_KEY_V2)
1031 		return (0);
1032 
1033 	return (1);
1034 }
1035 
1036 static int
privsep_npppd_check_bind(struct PRIVSEP_BIND_ARG * arg)1037 privsep_npppd_check_bind(struct PRIVSEP_BIND_ARG *arg)
1038 {
1039 	return (1);
1040 }
1041 
1042 static int
privsep_npppd_check_sendto(struct PRIVSEP_SENDTO_ARG * arg)1043 privsep_npppd_check_sendto(struct PRIVSEP_SENDTO_ARG *arg)
1044 {
1045 	/* for reply npppdctl's request */
1046 	if (arg->flags == 0 && arg->tolen > 0 &&
1047 	    arg->to.ss_family == AF_UNIX)
1048 		return (0);
1049 
1050 	/* for sending a routing socket message. */
1051 	if (arg->flags == 0 && arg->tolen == 0)
1052 		return (0);
1053 
1054 	return (1);
1055 }
1056 
1057 static int
privsep_npppd_check_unlink(struct PRIVSEP_UNLINK_ARG * arg)1058 privsep_npppd_check_unlink(struct PRIVSEP_UNLINK_ARG *arg)
1059 {
1060 
1061 	return (1);
1062 }
1063 
1064 static int
privsep_npppd_check_get_user_info(struct PRIVSEP_GET_USER_INFO_ARG * arg)1065 privsep_npppd_check_get_user_info(struct PRIVSEP_GET_USER_INFO_ARG *arg)
1066 {
1067 	int l;
1068 
1069 	l = strlen(NPPPD_DIR "/");
1070 	if (strncmp(arg->path, NPPPD_DIR "/", l) == 0)
1071 		return (0);
1072 
1073 	return (1);
1074 }
1075 
1076 static int
privsep_npppd_check_ifname(const char * ifname)1077 privsep_npppd_check_ifname(const char *ifname)
1078 {
1079 	if (startswith(ifname, "tun") ||
1080 	    startswith(ifname, "pppac") ||
1081 	    startswith(ifname, "pppx"))
1082 		return (0);
1083 
1084 	return (0);
1085 }
1086 
1087 static int
privsep_npppd_check_get_if_addr(struct PRIVSEP_GET_IF_ADDR_ARG * arg)1088 privsep_npppd_check_get_if_addr(struct PRIVSEP_GET_IF_ADDR_ARG *arg)
1089 {
1090 	return (privsep_npppd_check_ifname(arg->ifname));
1091 }
1092 
1093 static int
privsep_npppd_check_set_if_addr(struct PRIVSEP_SET_IF_ADDR_ARG * arg)1094 privsep_npppd_check_set_if_addr(struct PRIVSEP_SET_IF_ADDR_ARG *arg)
1095 {
1096 	return (privsep_npppd_check_ifname(arg->ifname));
1097 }
1098 
1099 static int
privsep_npppd_check_del_if_addr(struct PRIVSEP_DEL_IF_ADDR_ARG * arg)1100 privsep_npppd_check_del_if_addr(struct PRIVSEP_DEL_IF_ADDR_ARG *arg)
1101 {
1102 	return (privsep_npppd_check_ifname(arg->ifname));
1103 }
1104 
1105 static int
privsep_npppd_check_get_if_flags(struct PRIVSEP_GET_IF_FLAGS_ARG * arg)1106 privsep_npppd_check_get_if_flags(struct PRIVSEP_GET_IF_FLAGS_ARG *arg)
1107 {
1108 	return (privsep_npppd_check_ifname(arg->ifname));
1109 }
1110 
1111 static int
privsep_npppd_check_set_if_flags(struct PRIVSEP_SET_IF_FLAGS_ARG * arg)1112 privsep_npppd_check_set_if_flags(struct PRIVSEP_SET_IF_FLAGS_ARG *arg)
1113 {
1114 	return (privsep_npppd_check_ifname(arg->ifname));
1115 }
1116