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