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 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 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 221 privsep_priv_pid(void) 222 { 223 return (privsep_pid); 224 } 225 226 /*********************************************************************** 227 * Functions for from jail 228 ***********************************************************************/ 229 int 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 975 startswith(const char *str, const char *prefix) 976 { 977 return (strncmp(str, prefix, strlen(prefix)) == 0)? 1 : 0; 978 } 979 980 static int 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 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 1037 privsep_npppd_check_bind(struct PRIVSEP_BIND_ARG *arg) 1038 { 1039 return (1); 1040 } 1041 1042 static int 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 1058 privsep_npppd_check_unlink(struct PRIVSEP_UNLINK_ARG *arg) 1059 { 1060 1061 return (1); 1062 } 1063 1064 static int 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 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 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 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 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 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 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