1 /* $OpenBSD: privsep.c,v 1.26 2024/08/22 07:56:47 florian 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_pton(AF_INET, 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_pton(AF_INET, 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