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