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