1 /* $OpenBSD: privsep.c,v 1.49 2018/09/28 06:48:59 mestre Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Can Erkin Acar 5 * Copyright (c) 2003 Anil Madhavapeddy <anil@recoil.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/socket.h> 22 #include <sys/wait.h> 23 #include <sys/ioctl.h> 24 25 #include <netinet/in.h> 26 #include <net/if.h> 27 #include <netinet/if_ether.h> 28 #include <net/bpf.h> 29 #include <net/pfvar.h> 30 31 #include <rpc/rpc.h> 32 33 #include <err.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <netdb.h> 37 #include <paths.h> 38 #include <pwd.h> 39 #include <signal.h> 40 #include <stdarg.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <syslog.h> 45 #include <unistd.h> 46 47 #include "interface.h" 48 #include "privsep.h" 49 #include "pfctl_parser.h" 50 51 /* 52 * tcpdump goes through four states: STATE_INIT is where the 53 * bpf device and the input file is opened. In STATE_BPF, the 54 * pcap filter gets set. STATE_FILTER is used for parsing 55 * /etc/services and /etc/protocols and opening the output 56 * file. STATE_RUN is the packet processing part. 57 */ 58 59 enum priv_state { 60 STATE_INIT, /* initial state */ 61 STATE_BPF, /* input file/device opened */ 62 STATE_FILTER, /* filter applied */ 63 STATE_RUN, /* running and accepting network traffic */ 64 STATE_EXIT /* in the process of dying */ 65 }; 66 67 #define ALLOW(action) (1 << (action)) 68 69 /* 70 * Set of maximum allowed actions. 71 */ 72 static const int allowed_max[] = { 73 /* INIT */ ALLOW(PRIV_OPEN_BPF) | ALLOW(PRIV_OPEN_DUMP) | 74 ALLOW(PRIV_SETFILTER), 75 /* BPF */ ALLOW(PRIV_SETFILTER), 76 /* FILTER */ ALLOW(PRIV_OPEN_OUTPUT) | ALLOW(PRIV_GETSERVENTRIES) | 77 ALLOW(PRIV_GETPROTOENTRIES) | 78 ALLOW(PRIV_ETHER_NTOHOST) | ALLOW(PRIV_INIT_DONE), 79 /* RUN */ ALLOW(PRIV_GETHOSTBYADDR) | ALLOW(PRIV_ETHER_NTOHOST) | 80 ALLOW(PRIV_GETRPCBYNUMBER) | ALLOW(PRIV_GETLINES) | 81 ALLOW(PRIV_LOCALTIME) | ALLOW(PRIV_PCAP_STATS), 82 /* EXIT */ 0 83 }; 84 85 /* 86 * Default set of allowed actions. More actions get added 87 * later depending on the supplied parameters. 88 */ 89 static int allowed_ext[] = { 90 /* INIT */ ALLOW(PRIV_SETFILTER), 91 /* BPF */ ALLOW(PRIV_SETFILTER), 92 /* FILTER */ ALLOW(PRIV_GETSERVENTRIES), 93 /* RUN */ ALLOW(PRIV_GETLINES) | ALLOW(PRIV_LOCALTIME) | 94 ALLOW(PRIV_PCAP_STATS), 95 /* EXIT */ 0 96 }; 97 98 struct ftab { 99 char *name; 100 int max; 101 int count; 102 }; 103 104 static struct ftab file_table[] = {{PF_OSFP_FILE, 1, 0}}; 105 106 #define NUM_FILETAB (sizeof(file_table) / sizeof(struct ftab)) 107 108 int debug_level = LOG_INFO; 109 int priv_fd = -1; 110 volatile pid_t child_pid = -1; 111 static volatile sig_atomic_t cur_state = STATE_INIT; 112 113 extern void set_slave_signals(void); 114 115 static void impl_open_bpf(int, int *); 116 static void impl_open_dump(int, const char *); 117 static void impl_open_output(int, const char *); 118 static void impl_setfilter(int, char *, int *); 119 static void impl_init_done(int, int *); 120 static void impl_gethostbyaddr(int); 121 static void impl_ether_ntohost(int); 122 static void impl_getrpcbynumber(int); 123 static void impl_getserventries(int); 124 static void impl_getprotoentries(int); 125 static void impl_localtime(int fd); 126 static void impl_getlines(int); 127 static void impl_pcap_stats(int, int *); 128 129 static void test_state(int, int); 130 static void logmsg(int, const char *, ...); 131 132 int 133 priv_init(int argc, char **argv) 134 { 135 int i, nargc, socks[2]; 136 struct passwd *pw; 137 sigset_t allsigs, oset; 138 char **privargv; 139 140 closefrom(STDERR_FILENO + 1); 141 for (i = 1; i < _NSIG; i++) 142 signal(i, SIG_DFL); 143 144 /* Create sockets */ 145 if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, socks) == -1) 146 err(1, "socketpair() failed"); 147 148 sigfillset(&allsigs); 149 sigprocmask(SIG_BLOCK, &allsigs, &oset); 150 151 child_pid = fork(); 152 if (child_pid < 0) 153 err(1, "fork() failed"); 154 155 if (child_pid) { 156 close(socks[0]); 157 priv_fd = socks[1]; 158 159 set_slave_signals(); 160 sigprocmask(SIG_SETMASK, &oset, NULL); 161 162 /* 163 * If run as regular user, packet parser will rely on 164 * pledge(2). If we are root, we want to chroot also.. 165 */ 166 if (getuid() != 0) 167 return (0); 168 169 pw = getpwnam("_tcpdump"); 170 if (pw == NULL) 171 errx(1, "unknown user _tcpdump"); 172 173 if (chroot(pw->pw_dir) == -1) 174 err(1, "unable to chroot"); 175 if (chdir("/") == -1) 176 err(1, "unable to chdir"); 177 178 /* drop to _tcpdump */ 179 if (setgroups(1, &pw->pw_gid) == -1) 180 err(1, "setgroups() failed"); 181 if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) 182 err(1, "setresgid() failed"); 183 if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) 184 err(1, "setresuid() failed"); 185 186 return (0); 187 } 188 close(socks[1]); 189 190 if (dup2(socks[0], 3) == -1) 191 err(1, "dup2 priv sock failed"); 192 closefrom(4); 193 194 if ((privargv = reallocarray(NULL, argc + 2, sizeof(char *))) == NULL) 195 err(1, "alloc priv argv failed"); 196 nargc = 0; 197 privargv[nargc++] = argv[0]; 198 privargv[nargc++] = "-P"; 199 for (i = 1; i < argc; i++) 200 privargv[nargc++] = argv[i]; 201 privargv[nargc] = NULL; 202 execvp(privargv[0], privargv); 203 err(1, "exec priv '%s' failed", privargv[0]); 204 } 205 206 __dead void 207 priv_exec(int argc, char *argv[]) 208 { 209 int bpfd = -1; 210 int i, sock, cmd, nflag = 0, oflag = 0, Pflag = 0; 211 char *cmdbuf, *infile = NULL; 212 char *RFileName = NULL; 213 char *WFileName = NULL; 214 215 sock = 3; 216 217 closefrom(4); 218 for (i = 1; i < _NSIG; i++) 219 signal(i, SIG_DFL); 220 221 signal(SIGINT, SIG_IGN); 222 223 /* parse the arguments for required options */ 224 opterr = 0; 225 while ((i = getopt(argc, argv, 226 "ac:D:deE:fF:i:lLnNOopPqr:s:StT:vw:xXy:Y")) != -1) { 227 switch (i) { 228 case 'n': 229 nflag++; 230 break; 231 232 case 'o': 233 oflag = 1; 234 break; 235 236 case 'r': 237 RFileName = optarg; 238 break; 239 240 case 'w': 241 WFileName = optarg; 242 break; 243 244 case 'F': 245 infile = optarg; 246 break; 247 248 case 'P': 249 Pflag = 1; 250 break; 251 252 default: 253 /* nothing */ 254 break; 255 } 256 } 257 258 if (!Pflag) 259 errx(1, "exec without priv"); 260 261 if (RFileName != NULL) { 262 if (strcmp(RFileName, "-") != 0) 263 allowed_ext[STATE_INIT] |= ALLOW(PRIV_OPEN_DUMP); 264 } else 265 allowed_ext[STATE_INIT] |= ALLOW(PRIV_OPEN_BPF); 266 if (WFileName != NULL) { 267 if (strcmp(WFileName, "-") != 0) 268 allowed_ext[STATE_FILTER] |= ALLOW(PRIV_OPEN_OUTPUT); 269 else 270 allowed_ext[STATE_FILTER] |= ALLOW(PRIV_INIT_DONE); 271 } else 272 allowed_ext[STATE_FILTER] |= ALLOW(PRIV_INIT_DONE); 273 if (!nflag) { 274 allowed_ext[STATE_RUN] |= ALLOW(PRIV_GETHOSTBYADDR); 275 allowed_ext[STATE_FILTER] |= ALLOW(PRIV_ETHER_NTOHOST); 276 allowed_ext[STATE_RUN] |= ALLOW(PRIV_ETHER_NTOHOST); 277 allowed_ext[STATE_RUN] |= ALLOW(PRIV_GETRPCBYNUMBER); 278 allowed_ext[STATE_FILTER] |= ALLOW(PRIV_GETPROTOENTRIES); 279 } 280 281 if (infile) 282 cmdbuf = read_infile(infile); 283 else 284 cmdbuf = copy_argv(&argv[optind]); 285 286 setproctitle("[priv]"); 287 288 for (;;) { 289 if (may_read(sock, &cmd, sizeof(int))) 290 break; 291 switch (cmd) { 292 case PRIV_OPEN_BPF: 293 test_state(cmd, STATE_BPF); 294 impl_open_bpf(sock, &bpfd); 295 break; 296 case PRIV_OPEN_DUMP: 297 test_state(cmd, STATE_BPF); 298 impl_open_dump(sock, RFileName); 299 break; 300 case PRIV_OPEN_OUTPUT: 301 test_state(cmd, STATE_RUN); 302 impl_open_output(sock, WFileName); 303 break; 304 case PRIV_SETFILTER: 305 test_state(cmd, STATE_FILTER); 306 impl_setfilter(sock, cmdbuf, &bpfd); 307 break; 308 case PRIV_INIT_DONE: 309 test_state(cmd, STATE_RUN); 310 impl_init_done(sock, &bpfd); 311 312 if (oflag) { 313 if (unveil("/etc/pf.os", "r") == -1) 314 err(1, "unveil"); 315 } 316 if (unveil("/etc/ethers", "r") == -1) 317 err(1, "unveil"); 318 if (unveil("/etc/rpc", "r") == -1) 319 err(1, "unveil"); 320 if (pledge("stdio rpath inet dns recvfd bpf", NULL) == -1) 321 err(1, "pledge"); 322 323 break; 324 case PRIV_GETHOSTBYADDR: 325 test_state(cmd, STATE_RUN); 326 impl_gethostbyaddr(sock); 327 break; 328 case PRIV_ETHER_NTOHOST: 329 test_state(cmd, cur_state); 330 impl_ether_ntohost(sock); 331 break; 332 case PRIV_GETRPCBYNUMBER: 333 test_state(cmd, STATE_RUN); 334 impl_getrpcbynumber(sock); 335 break; 336 case PRIV_GETSERVENTRIES: 337 test_state(cmd, STATE_FILTER); 338 impl_getserventries(sock); 339 break; 340 case PRIV_GETPROTOENTRIES: 341 test_state(cmd, STATE_FILTER); 342 impl_getprotoentries(sock); 343 break; 344 case PRIV_LOCALTIME: 345 test_state(cmd, STATE_RUN); 346 impl_localtime(sock); 347 break; 348 case PRIV_GETLINES: 349 test_state(cmd, STATE_RUN); 350 impl_getlines(sock); 351 break; 352 case PRIV_PCAP_STATS: 353 test_state(cmd, STATE_RUN); 354 impl_pcap_stats(sock, &bpfd); 355 break; 356 default: 357 logmsg(LOG_ERR, "[priv]: unknown command %d", cmd); 358 exit(1); 359 /* NOTREACHED */ 360 } 361 } 362 363 /* NOTREACHED */ 364 exit(0); 365 } 366 367 static void 368 impl_open_bpf(int fd, int *bpfd) 369 { 370 int snaplen, promisc, err; 371 u_int dlt, dirfilt; 372 char device[IFNAMSIZ]; 373 size_t iflen; 374 375 logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_BPF received"); 376 377 must_read(fd, &snaplen, sizeof(int)); 378 must_read(fd, &promisc, sizeof(int)); 379 must_read(fd, &dlt, sizeof(u_int)); 380 must_read(fd, &dirfilt, sizeof(u_int)); 381 iflen = read_string(fd, device, sizeof(device), __func__); 382 if (iflen == 0) 383 errx(1, "Invalid interface size specified"); 384 *bpfd = pcap_live(device, snaplen, promisc, dlt, dirfilt); 385 err = errno; 386 if (*bpfd < 0) 387 logmsg(LOG_DEBUG, 388 "[priv]: failed to open bpf device for %s: %s", 389 device, strerror(errno)); 390 send_fd(fd, *bpfd); 391 must_write(fd, &err, sizeof(int)); 392 /* do not close bpfd until filter is set */ 393 } 394 395 static void 396 impl_open_dump(int fd, const char *RFileName) 397 { 398 int file, err = 0; 399 400 logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_DUMP received"); 401 402 if (RFileName == NULL) { 403 file = -1; 404 logmsg(LOG_ERR, "[priv]: No offline file specified"); 405 } else { 406 file = open(RFileName, O_RDONLY, 0); 407 err = errno; 408 if (file < 0) 409 logmsg(LOG_DEBUG, "[priv]: failed to open %s: %s", 410 RFileName, strerror(errno)); 411 } 412 send_fd(fd, file); 413 must_write(fd, &err, sizeof(int)); 414 if (file >= 0) 415 close(file); 416 } 417 418 static void 419 impl_open_output(int fd, const char *WFileName) 420 { 421 int file, err; 422 423 logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_OUTPUT received"); 424 425 file = open(WFileName, O_WRONLY|O_CREAT|O_TRUNC, 0666); 426 err = errno; 427 send_fd(fd, file); 428 must_write(fd, &err, sizeof(int)); 429 if (file < 0) 430 logmsg(LOG_DEBUG, "[priv]: failed to open %s: %s", 431 WFileName, strerror(err)); 432 else 433 close(file); 434 } 435 436 static void 437 impl_setfilter(int fd, char *cmdbuf, int *bpfd) 438 { 439 logmsg(LOG_DEBUG, "[priv]: msg PRIV_SETFILTER received"); 440 441 if (setfilter(*bpfd, fd, cmdbuf)) 442 logmsg(LOG_DEBUG, "[priv]: setfilter() failed"); 443 } 444 445 static void 446 impl_init_done(int fd, int *bpfd) 447 { 448 int ret; 449 450 logmsg(LOG_DEBUG, "[priv]: msg PRIV_INIT_DONE received"); 451 452 ret = 0; 453 must_write(fd, &ret, sizeof(ret)); 454 } 455 456 static void 457 impl_gethostbyaddr(int fd) 458 { 459 char hostname[HOST_NAME_MAX+1]; 460 size_t hostname_len; 461 int addr_af; 462 struct hostent *hp; 463 464 logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETHOSTBYADDR received"); 465 466 /* Expecting: address block, address family */ 467 hostname_len = read_block(fd, hostname, sizeof(hostname), __func__); 468 if (hostname_len == 0) 469 _exit(1); 470 must_read(fd, &addr_af, sizeof(int)); 471 hp = gethostbyaddr(hostname, hostname_len, addr_af); 472 if (hp == NULL) 473 write_zero(fd); 474 else 475 write_string(fd, hp->h_name); 476 } 477 478 static void 479 impl_ether_ntohost(int fd) 480 { 481 struct ether_addr ether; 482 char hostname[HOST_NAME_MAX+1]; 483 484 logmsg(LOG_DEBUG, "[priv]: msg PRIV_ETHER_NTOHOST received"); 485 486 /* Expecting: ethernet address */ 487 must_read(fd, ðer, sizeof(ether)); 488 if (ether_ntohost(hostname, ðer) == -1) 489 write_zero(fd); 490 else 491 write_string(fd, hostname); 492 } 493 494 static void 495 impl_getrpcbynumber(int fd) 496 { 497 int rpc; 498 struct rpcent *rpce; 499 500 logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETRPCBYNUMBER received"); 501 502 must_read(fd, &rpc, sizeof(int)); 503 rpce = getrpcbynumber(rpc); 504 if (rpce == NULL) 505 write_zero(fd); 506 else 507 write_string(fd, rpce->r_name); 508 } 509 510 static void 511 impl_getserventries(int fd) 512 { 513 struct servent *sp; 514 515 logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETSERVENTRIES received"); 516 517 for (;;) { 518 sp = getservent(); 519 if (sp == NULL) { 520 write_zero(fd); 521 break; 522 } else { 523 write_string(fd, sp->s_name); 524 must_write(fd, &sp->s_port, sizeof(int)); 525 write_string(fd, sp->s_proto); 526 } 527 } 528 endservent(); 529 } 530 531 static void 532 impl_getprotoentries(int fd) 533 { 534 struct protoent *pe; 535 536 logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETPROTOENTRIES received"); 537 538 for (;;) { 539 pe = getprotoent(); 540 if (pe == NULL) { 541 write_zero(fd); 542 break; 543 } else { 544 write_string(fd, pe->p_name); 545 must_write(fd, &pe->p_proto, sizeof(int)); 546 } 547 } 548 endprotoent(); 549 } 550 551 /* read the time and send the corresponding localtime and gmtime 552 * results back to the unprivileged process */ 553 static void 554 impl_localtime(int fd) 555 { 556 struct tm *lt, *gt; 557 time_t t; 558 559 logmsg(LOG_DEBUG, "[priv]: msg PRIV_LOCALTIME received"); 560 561 must_read(fd, &t, sizeof(time_t)); 562 563 /* this must be done separately, since they apparently use the 564 * same local buffer */ 565 if ((lt = localtime(&t)) == NULL) 566 errx(1, "localtime()"); 567 must_write(fd, lt, sizeof(*lt)); 568 569 if ((gt = gmtime(&t)) == NULL) 570 errx(1, "gmtime()"); 571 must_write(fd, gt, sizeof(*gt)); 572 573 if (lt->tm_zone == NULL) 574 write_zero(fd); 575 else 576 write_string(fd, lt->tm_zone); 577 } 578 579 static void 580 impl_getlines(int fd) 581 { 582 FILE *fp; 583 char *buf, *lbuf, *file; 584 size_t len, fid; 585 586 logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETLINES received"); 587 588 must_read(fd, &fid, sizeof(size_t)); 589 if (fid >= NUM_FILETAB) 590 errx(1, "invalid file id"); 591 592 file = file_table[fid].name; 593 594 if (file == NULL) 595 errx(1, "invalid file referenced"); 596 597 if (file_table[fid].count >= file_table[fid].max) 598 errx(1, "maximum open count exceeded for %s", file); 599 600 file_table[fid].count++; 601 602 if ((fp = fopen(file, "r")) == NULL) { 603 write_zero(fd); 604 return; 605 } 606 607 lbuf = NULL; 608 while ((buf = fgetln(fp, &len))) { 609 if (buf[len - 1] == '\n') 610 buf[len - 1] = '\0'; 611 else { 612 if ((lbuf = malloc(len + 1)) == NULL) 613 err(1, NULL); 614 memcpy(lbuf, buf, len); 615 lbuf[len] = '\0'; 616 buf = lbuf; 617 } 618 619 write_string(fd, buf); 620 621 free(lbuf); 622 lbuf = NULL; 623 } 624 write_zero(fd); 625 fclose(fp); 626 } 627 628 static void 629 impl_pcap_stats(int fd, int *bpfd) 630 { 631 struct pcap_stat stats; 632 633 logmsg(LOG_DEBUG, "[priv]: msg PRIV_PCAP_STATS received"); 634 635 if (ioctl(*bpfd, BIOCGSTATS, &stats) == -1) 636 write_zero(fd); 637 else 638 must_write(fd, &stats, sizeof(stats)); 639 } 640 641 void 642 priv_init_done(void) 643 { 644 int ret; 645 646 if (priv_fd < 0) 647 errx(1, "%s: called from privileged portion", __func__); 648 649 write_command(priv_fd, PRIV_INIT_DONE); 650 must_read(priv_fd, &ret, sizeof(int)); 651 } 652 653 /* Reverse address resolution; response is placed into res, and length of 654 * response is returned (zero on error) */ 655 size_t 656 priv_gethostbyaddr(char *addr, size_t addr_len, int af, char *res, size_t res_len) 657 { 658 if (priv_fd < 0) 659 errx(1, "%s called from privileged portion", __func__); 660 661 write_command(priv_fd, PRIV_GETHOSTBYADDR); 662 write_block(priv_fd, addr_len, addr); 663 must_write(priv_fd, &af, sizeof(int)); 664 665 return (read_string(priv_fd, res, res_len, __func__)); 666 } 667 668 size_t 669 priv_ether_ntohost(char *name, size_t name_len, struct ether_addr *e) 670 { 671 if (priv_fd < 0) 672 errx(1, "%s called from privileged portion", __func__); 673 674 write_command(priv_fd, PRIV_ETHER_NTOHOST); 675 must_write(priv_fd, e, sizeof(*e)); 676 677 /* Read the host name */ 678 return (read_string(priv_fd, name, name_len, __func__)); 679 } 680 681 size_t 682 priv_getrpcbynumber(int rpc, char *progname, size_t progname_len) 683 { 684 if (priv_fd < 0) 685 errx(1, "%s called from privileged portion", __func__); 686 687 write_command(priv_fd, PRIV_GETRPCBYNUMBER); 688 must_write(priv_fd, &rpc, sizeof(int)); 689 690 return read_string(priv_fd, progname, progname_len, __func__); 691 } 692 693 /* start getting service entries */ 694 void 695 priv_getserventries(void) 696 { 697 if (priv_fd < 0) 698 errx(1, "%s called from privileged portion", __func__); 699 700 write_command(priv_fd, PRIV_GETSERVENTRIES); 701 } 702 703 /* retrieve a service entry, should be called repeatedly after calling 704 priv_getserventries(), until it returns zero. */ 705 size_t 706 priv_getserventry(char *name, size_t name_len, int *port, char *prot, 707 size_t prot_len) 708 { 709 if (priv_fd < 0) 710 errx(1, "%s called from privileged portion", __func__); 711 712 /* read the service name */ 713 if (read_string(priv_fd, name, name_len, __func__) == 0) 714 return 0; 715 716 /* read the port */ 717 must_read(priv_fd, port, sizeof(int)); 718 719 /* read the protocol */ 720 return (read_string(priv_fd, prot, prot_len, __func__)); 721 } 722 723 /* start getting ip protocol entries */ 724 void 725 priv_getprotoentries(void) 726 { 727 if (priv_fd < 0) 728 errx(1, "%s called from privileged portion", __func__); 729 730 write_command(priv_fd, PRIV_GETPROTOENTRIES); 731 } 732 733 /* retrieve a ip protocol entry, should be called repeatedly after calling 734 priv_getprotoentries(), until it returns zero. */ 735 size_t 736 priv_getprotoentry(char *name, size_t name_len, int *num) 737 { 738 if (priv_fd < 0) 739 errx(1, "%s called from privileged portion", __func__); 740 741 /* read the proto name */ 742 if (read_string(priv_fd, name, name_len, __func__) == 0) 743 return 0; 744 745 /* read the num */ 746 must_read(priv_fd, num, sizeof(int)); 747 748 return (1); 749 } 750 751 /* localtime() replacement: ask the privileged process for localtime and 752 * gmtime, cache the localtime for about one minute i.e. until one of the 753 * fields other than seconds changes. The check is done using gmtime 754 * values since they are the same in parent and child. */ 755 struct tm * 756 priv_localtime(const time_t *t) 757 { 758 static struct tm lt, gt0; 759 static struct tm *gt = NULL; 760 static char zone[PATH_MAX]; 761 762 if (gt != NULL) { 763 gt = gmtime(t); 764 gt0.tm_sec = gt->tm_sec; 765 gt0.tm_zone = gt->tm_zone; 766 767 if (memcmp(gt, >0, sizeof(struct tm)) == 0) { 768 lt.tm_sec = gt0.tm_sec; 769 return < 770 } 771 } 772 773 write_command(priv_fd, PRIV_LOCALTIME); 774 must_write(priv_fd, t, sizeof(time_t)); 775 must_read(priv_fd, <, sizeof(lt)); 776 must_read(priv_fd, >0, sizeof(gt0)); 777 778 if (read_string(priv_fd, zone, sizeof(zone), __func__)) 779 lt.tm_zone = zone; 780 else 781 lt.tm_zone = NULL; 782 783 gt0.tm_zone = NULL; 784 gt = >0; 785 786 return < 787 } 788 789 /* start getting lines from a file */ 790 void 791 priv_getlines(size_t sz) 792 { 793 if (priv_fd < 0) 794 errx(1, "%s called from privileged portion", __func__); 795 796 write_command(priv_fd, PRIV_GETLINES); 797 must_write(priv_fd, &sz, sizeof(size_t)); 798 } 799 800 int 801 priv_pcap_stats(struct pcap_stat *ps) 802 { 803 if (priv_fd < 0) 804 errx(1, "%s: called from privileged portion", __func__); 805 806 write_command(priv_fd, PRIV_PCAP_STATS); 807 must_read(priv_fd, ps, sizeof(*ps)); 808 return (0); 809 } 810 811 /* retrieve a line from a file, should be called repeatedly after calling 812 priv_getlines(), until it returns zero. */ 813 size_t 814 priv_getline(char *line, size_t line_len) 815 { 816 if (priv_fd < 0) 817 errx(1, "%s called from privileged portion", __func__); 818 819 /* read the line */ 820 return (read_string(priv_fd, line, line_len, __func__)); 821 } 822 823 /* Read all data or return 1 for error. */ 824 int 825 may_read(int fd, void *buf, size_t n) 826 { 827 char *s = buf; 828 ssize_t res, pos = 0; 829 830 while (n > pos) { 831 res = read(fd, s + pos, n - pos); 832 switch (res) { 833 case -1: 834 if (errno == EINTR || errno == EAGAIN) 835 continue; 836 /* FALLTHROUGH */ 837 case 0: 838 return (1); 839 default: 840 pos += res; 841 } 842 } 843 return (0); 844 } 845 846 /* Read data with the assertion that it all must come through, or 847 * else abort the process. Based on atomicio() from openssh. */ 848 void 849 must_read(int fd, void *buf, size_t n) 850 { 851 char *s = buf; 852 ssize_t res, pos = 0; 853 854 while (n > pos) { 855 res = read(fd, s + pos, n - pos); 856 switch (res) { 857 case -1: 858 if (errno == EINTR || errno == EAGAIN) 859 continue; 860 /* FALLTHROUGH */ 861 case 0: 862 _exit(0); 863 default: 864 pos += res; 865 } 866 } 867 } 868 869 /* Write data with the assertion that it all has to be written, or 870 * else abort the process. Based on atomicio() from openssh. */ 871 void 872 must_write(int fd, const void *buf, size_t n) 873 { 874 const char *s = buf; 875 ssize_t res, pos = 0; 876 877 while (n > pos) { 878 res = write(fd, s + pos, n - pos); 879 switch (res) { 880 case -1: 881 if (errno == EINTR || errno == EAGAIN) 882 continue; 883 /* FALLTHROUGH */ 884 case 0: 885 _exit(0); 886 default: 887 pos += res; 888 } 889 } 890 } 891 892 /* test for a given state, and possibly increase state */ 893 static void 894 test_state(int action, int next) 895 { 896 if (cur_state < 0 || cur_state > STATE_RUN) { 897 logmsg(LOG_ERR, "[priv] Invalid state: %d", cur_state); 898 _exit(1); 899 } 900 if ((allowed_max[cur_state] & allowed_ext[cur_state] 901 & ALLOW(action)) == 0) { 902 logmsg(LOG_ERR, "[priv] Invalid action %d in state %d", 903 action, cur_state); 904 _exit(1); 905 } 906 if (next < cur_state) { 907 logmsg(LOG_ERR, "[priv] Invalid next state: %d < %d", 908 next, cur_state); 909 _exit(1); 910 } 911 912 cur_state = next; 913 } 914 915 static void 916 logmsg(int pri, const char *message, ...) 917 { 918 va_list ap; 919 if (pri > debug_level) 920 return; 921 va_start(ap, message); 922 923 vfprintf(stderr, message, ap); 924 fprintf(stderr, "\n"); 925 va_end(ap); 926 } 927 928 /* write a command to the peer */ 929 void 930 write_command(int fd, int cmd) 931 { 932 must_write(fd, &cmd, sizeof(cmd)); 933 } 934 935 /* write a zero 'length' to signal an error to read_{string|block} */ 936 void 937 write_zero(int fd) 938 { 939 size_t len = 0; 940 must_write(fd, &len, sizeof(size_t)); 941 } 942 943 /* send a string */ 944 void 945 write_string(int fd, const char *str) 946 { 947 size_t len; 948 949 len = strlen(str) + 1; 950 must_write(fd, &len, sizeof(size_t)); 951 must_write(fd, str, len); 952 } 953 954 /* send a block of data of given size */ 955 void 956 write_block(int fd, size_t size, const char *str) 957 { 958 must_write(fd, &size, sizeof(size_t)); 959 must_write(fd, str, size); 960 } 961 962 /* read a string from the channel, return 0 if error, or total size of 963 * the buffer, including the terminating '\0' */ 964 size_t 965 read_string(int fd, char *buf, size_t size, const char *func) 966 { 967 size_t len; 968 969 len = read_block(fd, buf, size, func); 970 if (len == 0) 971 return (0); 972 973 if (buf[len - 1] != '\0') 974 errx(1, "%s: received invalid string", func); 975 976 return (len); 977 } 978 979 /* read a block of data from the channel, return length of data, or 0 980 * if error */ 981 size_t 982 read_block(int fd, char *buf, size_t size, const char *func) 983 { 984 size_t len; 985 /* Expect back an integer size, and then a string of that length */ 986 must_read(fd, &len, sizeof(size_t)); 987 988 /* Check there was no error (indicated by a return of 0) */ 989 if (len == 0) 990 return (0); 991 992 /* Make sure we aren't overflowing the passed in buffer */ 993 if (size < len) 994 errx(1, "%s: overflow attempt in return", func); 995 996 /* Read the string and make sure we got all of it */ 997 must_read(fd, buf, len); 998 return (len); 999 } 1000