1 /* $OpenBSD: tftp-proxy.c,v 1.10 2013/12/23 13:08:25 florian Exp $ 2 * 3 * Copyright (c) 2005 DLS Internet Services 4 * Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/ioctl.h> 31 #include <sys/param.h> 32 #include <sys/types.h> 33 #include <sys/socket.h> 34 #include <sys/uio.h> 35 36 #include <netinet/in.h> 37 #include <arpa/inet.h> 38 #include <arpa/tftp.h> 39 #include <net/if.h> 40 #include <net/pfvar.h> 41 #include <netdb.h> 42 43 #include <unistd.h> 44 #include <errno.h> 45 #include <err.h> 46 #include <pwd.h> 47 #include <stdio.h> 48 #include <syslog.h> 49 #include <string.h> 50 #include <stdlib.h> 51 #include <event.h> 52 53 #include "filter.h" 54 55 #define CHROOT_DIR "/var/empty" 56 #define NOPRIV_USER "proxy" 57 58 #define DEFTRANSWAIT 2 59 #define NTOP_BUFS 4 60 #define PKTSIZE SEGSIZE+4 61 62 const char *opcode(int); 63 const char *sock_ntop(struct sockaddr *); 64 static void usage(void); 65 66 struct proxy_listener { 67 struct event ev; 68 TAILQ_ENTRY(proxy_listener) entry; 69 int (*cmsg2dst)(struct cmsghdr *, struct sockaddr_storage *); 70 int s; 71 }; 72 73 void proxy_listen(const char *, const char *, int); 74 void proxy_listener_events(void); 75 int proxy_dst4(struct cmsghdr *, struct sockaddr_storage *); 76 int proxy_dst6(struct cmsghdr *, struct sockaddr_storage *); 77 void proxy_recv(int, short, void *); 78 79 struct fd_reply { 80 TAILQ_ENTRY(fd_reply) entry; 81 int fd; 82 }; 83 84 struct privproc { 85 struct event pop_ev; 86 struct event push_ev; 87 TAILQ_HEAD(, fd_reply) replies; 88 struct evbuffer *buf; 89 }; 90 91 void proxy_privproc(int, struct passwd *); 92 void privproc_push(int, short, void *); 93 void privproc_pop(int, short, void *); 94 95 void unprivproc_push(int, short, void *); 96 void unprivproc_pop(int, short, void *); 97 void unprivproc_timeout(int, short, void *); 98 99 char ntop_buf[NTOP_BUFS][INET6_ADDRSTRLEN]; 100 101 struct loggers { 102 void (*err)(int, const char *, ...); 103 void (*errx)(int, const char *, ...); 104 void (*warn)(const char *, ...); 105 void (*warnx)(const char *, ...); 106 void (*info)(const char *, ...); 107 }; 108 109 const struct loggers conslogger = { 110 err, 111 errx, 112 warn, 113 warnx, 114 warnx 115 }; 116 117 void syslog_err(int, const char *, ...); 118 void syslog_errx(int, const char *, ...); 119 void syslog_warn(const char *, ...); 120 void syslog_warnx(const char *, ...); 121 void syslog_info(const char *, ...); 122 void syslog_vstrerror(int, int, const char *, va_list); 123 124 const struct loggers syslogger = { 125 syslog_err, 126 syslog_errx, 127 syslog_warn, 128 syslog_warnx, 129 syslog_info, 130 }; 131 132 const struct loggers *logger = &conslogger; 133 134 #define lerr(_e, _f...) logger->err((_e), _f) 135 #define lerrx(_e, _f...) logger->errx((_e), _f) 136 #define lwarn(_f...) logger->warn(_f) 137 #define lwarnx(_f...) logger->warnx(_f) 138 #define linfo(_f...) logger->info(_f) 139 140 __dead void 141 usage(void) 142 { 143 extern char *__progname; 144 fprintf(stderr, "usage: %s [-46dv] [-a address] [-l address] [-p port]" 145 " [-w transwait]\n", __progname); 146 exit(1); 147 } 148 149 int debug = 0; 150 int verbose = 0; 151 struct timeval transwait = { DEFTRANSWAIT, 0 }; 152 153 int on = 1; 154 155 struct addr_pair { 156 struct sockaddr_storage src; 157 struct sockaddr_storage dst; 158 }; 159 160 struct proxy_request { 161 char buf[SEGSIZE_MAX + 4]; 162 size_t buflen; 163 164 struct addr_pair addrs; 165 166 struct event ev; 167 TAILQ_ENTRY(proxy_request) entry; 168 u_int32_t id; 169 }; 170 171 struct proxy_child { 172 TAILQ_HEAD(, proxy_request) fdrequests; 173 TAILQ_HEAD(, proxy_request) tmrequests; 174 struct event push_ev; 175 struct event pop_ev; 176 struct evbuffer *buf; 177 }; 178 179 struct proxy_child *child = NULL; 180 TAILQ_HEAD(, proxy_listener) proxy_listeners; 181 182 struct src_addr { 183 TAILQ_ENTRY(src_addr) entry; 184 struct sockaddr_storage addr; 185 socklen_t addrlen; 186 }; 187 TAILQ_HEAD(, src_addr) src_addrs; 188 189 void source_addresses(const char*, int); 190 191 int 192 main(int argc, char *argv[]) 193 { 194 extern char *__progname; 195 196 int c; 197 const char *errstr; 198 199 struct src_addr *saddr, *saddr2; 200 struct passwd *pw; 201 202 char *addr = "localhost"; 203 char *port = "6969"; 204 int family = AF_UNSPEC; 205 206 int pair[2]; 207 208 TAILQ_INIT(&src_addrs); 209 210 while ((c = getopt(argc, argv, "46a:dvl:p:w:")) != -1) { 211 switch (c) { 212 case '4': 213 family = AF_INET; 214 break; 215 case '6': 216 family = AF_INET6; 217 break; 218 case 'a': 219 source_addresses(optarg, family); 220 break; 221 case 'd': 222 verbose = debug = 1; 223 break; 224 case 'l': 225 addr = optarg; 226 break; 227 case 'p': 228 port = optarg; 229 break; 230 case 'v': 231 verbose = 1; 232 break; 233 case 'w': 234 transwait.tv_sec = strtonum(optarg, 1, 30, &errstr); 235 if (errstr) 236 errx(1, "wait is %s", errstr); 237 break; 238 default: 239 usage(); 240 /* NOTREACHED */ 241 } 242 } 243 244 if (geteuid() != 0) 245 errx(1, "need root privileges"); 246 247 if (!debug && daemon(1, 0) == -1) 248 err(1, "daemon"); 249 250 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) == -1) 251 lerr(1, "socketpair"); 252 253 pw = getpwnam(NOPRIV_USER); 254 if (pw == NULL) 255 lerrx(1, "no %s user", NOPRIV_USER); 256 257 /* Family option may have been specified late. */ 258 if (family != AF_UNSPEC) 259 TAILQ_FOREACH_SAFE(saddr, &src_addrs, entry, saddr2) 260 if (saddr->addr.ss_family != family) { 261 TAILQ_REMOVE(&src_addrs, saddr, entry); 262 free(saddr); 263 } 264 265 switch (fork()) { 266 case -1: 267 lerr(1, "fork"); 268 269 case 0: 270 setproctitle("privproc"); 271 close(pair[1]); 272 proxy_privproc(pair[0], pw); 273 /* this never returns */ 274 275 default: 276 setproctitle("unprivproc"); 277 close(pair[0]); 278 break; 279 } 280 281 child = calloc(1, sizeof(*child)); 282 if (child == NULL) 283 lerr(1, "alloc(child)"); 284 285 child->buf = evbuffer_new(); 286 if (child->buf == NULL) 287 lerr(1, "child evbuffer"); 288 289 TAILQ_INIT(&child->fdrequests); 290 TAILQ_INIT(&child->tmrequests); 291 292 if (!debug) { 293 openlog(__progname, LOG_PID|LOG_NDELAY, LOG_DAEMON); 294 tzset(); 295 logger = &syslogger; 296 } 297 298 proxy_listen(addr, port, family); 299 300 /* open /dev/pf */ 301 init_filter(NULL, verbose); 302 303 /* revoke privs */ 304 pw = getpwnam(NOPRIV_USER); 305 if (!pw) 306 lerrx(1, "no such user %s", NOPRIV_USER); 307 308 if (chroot(CHROOT_DIR) == -1) 309 lerr(1, "chroot %s", CHROOT_DIR); 310 311 if (chdir("/") == -1) 312 lerr(1, "chdir %s", CHROOT_DIR); 313 314 if (setgroups(1, &pw->pw_gid) || 315 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 316 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 317 err(1, "unable to revoke privs"); 318 319 event_init(); 320 321 proxy_listener_events(); 322 323 if (ioctl(pair[1], FIONBIO, &on) == -1) 324 lerr(1, "ioctl(FIONBIO)"); 325 326 event_set(&child->pop_ev, pair[1], EV_READ | EV_PERSIST, 327 unprivproc_pop, NULL); 328 event_set(&child->push_ev, pair[1], EV_WRITE, 329 unprivproc_push, NULL); 330 331 event_add(&child->pop_ev, NULL); 332 333 event_dispatch(); 334 335 return(0); 336 } 337 338 void 339 source_addresses(const char* name, int family) 340 { 341 struct addrinfo hints, *res, *res0; 342 struct src_addr *saddr; 343 int error; 344 345 memset(&hints, 0, sizeof(hints)); 346 hints.ai_family = family; 347 hints.ai_socktype = SOCK_DGRAM; 348 hints.ai_flags = AI_PASSIVE; 349 error = getaddrinfo(name, NULL, &hints, &res0); 350 if (error) 351 lerrx(1, "%s: %s", name, gai_strerror(error)); 352 for (res = res0; res != NULL; res = res->ai_next) { 353 if ((saddr = calloc(1, sizeof(struct src_addr))) == NULL) 354 lerrx(1, "calloc"); 355 memcpy(&(saddr->addr), res->ai_addr, res->ai_addrlen); 356 saddr->addrlen = res->ai_addrlen; 357 TAILQ_INSERT_TAIL(&src_addrs, saddr, entry); 358 } 359 freeaddrinfo(res0); 360 } 361 362 void 363 proxy_privproc(int s, struct passwd *pw) 364 { 365 extern char *__progname; 366 struct privproc p; 367 368 if (!debug) { 369 openlog(__progname, LOG_PID|LOG_NDELAY, LOG_DAEMON); 370 tzset(); 371 logger = &syslogger; 372 } 373 374 if (ioctl(s, FIONBIO, &on) == -1) 375 lerr(1, "ioctl(FIONBIO)"); 376 377 if (chroot(CHROOT_DIR) == -1) 378 lerr(1, "chroot to %s", CHROOT_DIR); 379 380 if (chdir("/") == -1) 381 lerr(1, "chdir to %s", CHROOT_DIR); 382 383 if (setgroups(1, &pw->pw_gid) || 384 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid)) 385 lerr(1, "unable to set group ids"); 386 387 TAILQ_INIT(&p.replies); 388 389 p.buf = evbuffer_new(); 390 if (p.buf == NULL) 391 err(1, "pop evbuffer_new"); 392 393 event_init(); 394 395 event_set(&p.pop_ev, s, EV_READ | EV_PERSIST, privproc_pop, &p); 396 event_set(&p.push_ev, s, EV_WRITE, privproc_push, &p); 397 398 event_add(&p.pop_ev, NULL); 399 400 event_dispatch(); 401 } 402 403 void 404 privproc_pop(int fd, short events, void *arg) 405 { 406 struct addr_pair req; 407 struct privproc *p = arg; 408 struct fd_reply *rep; 409 struct src_addr *saddr; 410 int add = 0; 411 412 switch (evbuffer_read(p->buf, fd, sizeof(req))) { 413 case 0: 414 lerrx(1, "unprivproc has gone"); 415 case -1: 416 switch (errno) { 417 case EAGAIN: 418 case EINTR: 419 return; 420 default: 421 lerr(1, "privproc_pop read"); 422 } 423 default: 424 break; 425 } 426 427 while (EVBUFFER_LENGTH(p->buf) >= sizeof(req)) { 428 evbuffer_remove(p->buf, &req, sizeof(req)); 429 430 /* do i really need to check this? */ 431 if (req.src.ss_family != req.dst.ss_family) 432 lerrx(1, "family mismatch"); 433 434 rep = calloc(1, sizeof(*rep)); 435 if (rep == NULL) 436 lerr(1, "reply calloc"); 437 438 rep->fd = socket(req.src.ss_family, SOCK_DGRAM, IPPROTO_UDP); 439 if (rep->fd == -1) 440 lerr(1, "privproc socket"); 441 442 if (ioctl(rep->fd, FIONBIO, &on) == -1) 443 err(1, "privproc ioctl(FIONBIO)"); 444 445 if (setsockopt(rep->fd, SOL_SOCKET, SO_BINDANY, 446 &on, sizeof(on)) == -1) 447 lerr(1, "privproc setsockopt(BINDANY)"); 448 449 if (setsockopt(rep->fd, SOL_SOCKET, SO_REUSEADDR, 450 &on, sizeof(on)) == -1) 451 lerr(1, "privproc setsockopt(REUSEADDR)"); 452 453 if (setsockopt(rep->fd, SOL_SOCKET, SO_REUSEPORT, 454 &on, sizeof(on)) == -1) 455 lerr(1, "privproc setsockopt(REUSEPORT)"); 456 457 TAILQ_FOREACH(saddr, &src_addrs, entry) 458 if (saddr->addr.ss_family == req.src.ss_family) 459 break; 460 if (saddr == NULL) { 461 if (bind(rep->fd, (struct sockaddr *)&req.src, 462 req.src.ss_len) == -1) 463 lerr(1, "privproc bind"); 464 } else { 465 if (bind(rep->fd, (struct sockaddr*)&saddr->addr, 466 saddr->addrlen) == -1) 467 lerr(1, "privproc bind"); 468 } 469 470 if (TAILQ_EMPTY(&p->replies)) 471 add = 1; 472 473 TAILQ_INSERT_TAIL(&p->replies, rep, entry); 474 } 475 476 if (add) 477 event_add(&p->push_ev, NULL); 478 } 479 480 void 481 privproc_push(int fd, short events, void *arg) 482 { 483 struct privproc *p = arg; 484 struct fd_reply *rep; 485 486 struct msghdr msg; 487 union { 488 struct cmsghdr hdr; 489 char buf[CMSG_SPACE(sizeof(int))]; 490 } cmsgbuf; 491 struct cmsghdr *cmsg; 492 struct iovec iov; 493 int result = 0; 494 495 while ((rep = TAILQ_FIRST(&p->replies)) != NULL) { 496 memset(&msg, 0, sizeof(msg)); 497 498 msg.msg_control = (caddr_t)&cmsgbuf.buf; 499 msg.msg_controllen = sizeof(cmsgbuf.buf); 500 cmsg = CMSG_FIRSTHDR(&msg); 501 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 502 cmsg->cmsg_level = SOL_SOCKET; 503 cmsg->cmsg_type = SCM_RIGHTS; 504 *(int *)CMSG_DATA(cmsg) = rep->fd; 505 506 iov.iov_base = &result; 507 iov.iov_len = sizeof(int); 508 msg.msg_iov = &iov; 509 msg.msg_iovlen = 1; 510 511 switch (sendmsg(fd, &msg, 0)) { 512 case sizeof(int): 513 break; 514 515 case -1: 516 if (errno == EAGAIN) 517 goto again; 518 519 lerr(1, "privproc sendmsg"); 520 /* NOTREACHED */ 521 522 default: 523 lerrx(1, "privproc sendmsg weird len"); 524 } 525 526 TAILQ_REMOVE(&p->replies, rep, entry); 527 close(rep->fd); 528 free(rep); 529 } 530 531 if (TAILQ_EMPTY(&p->replies)) 532 return; 533 534 again: 535 event_add(&p->push_ev, NULL); 536 } 537 538 void 539 proxy_listen(const char *addr, const char *port, int family) 540 { 541 struct proxy_listener *l; 542 543 struct addrinfo hints, *res, *res0; 544 int error; 545 int s, on = 1; 546 int serrno; 547 const char *cause = NULL; 548 549 memset(&hints, 0, sizeof(hints)); 550 hints.ai_family = family; 551 hints.ai_socktype = SOCK_DGRAM; 552 hints.ai_flags = AI_PASSIVE; 553 554 TAILQ_INIT(&proxy_listeners); 555 556 error = getaddrinfo(addr, port, &hints, &res0); 557 if (error) 558 errx(1, "%s:%s: %s", addr, port, gai_strerror(error)); 559 560 for (res = res0; res != NULL; res = res->ai_next) { 561 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 562 if (s == -1) { 563 cause = "socket"; 564 continue; 565 } 566 567 if (bind(s, res->ai_addr, res->ai_addrlen) == -1) { 568 cause = "bind"; 569 serrno = errno; 570 close(s); 571 errno = serrno; 572 continue; 573 } 574 575 l = calloc(1, sizeof(*l)); 576 if (l == NULL) 577 err(1, "listener alloc"); 578 579 if (ioctl(s, FIONBIO, &on) == -1) 580 err(1, "ioctl(FIONBIO)"); 581 582 switch (res->ai_family) { 583 case AF_INET: 584 l->cmsg2dst = proxy_dst4; 585 586 if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, 587 &on, sizeof(on)) == -1) 588 errx(1, "setsockopt(IP_RECVDSTADDR)"); 589 if (setsockopt(s, IPPROTO_IP, IP_RECVDSTPORT, 590 &on, sizeof(on)) == -1) 591 errx(1, "setsockopt(IP_RECVDSTPORT)"); 592 break; 593 case AF_INET6: 594 l->cmsg2dst = proxy_dst6; 595 596 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, 597 &on, sizeof(on)) == -1) 598 errx(1, "setsockopt(IPV6_RECVPKTINFO)"); 599 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTPORT, 600 &on, sizeof(on)) == -1) 601 errx(1, "setsockopt(IPV6_RECVDSTPORT)"); 602 break; 603 } 604 l->s = s; 605 606 TAILQ_INSERT_TAIL(&proxy_listeners, l, entry); 607 } 608 freeaddrinfo(res0); 609 610 if (TAILQ_EMPTY(&proxy_listeners)) 611 err(1, "%s", cause); 612 } 613 614 void 615 proxy_listener_events(void) 616 { 617 struct proxy_listener *l; 618 619 TAILQ_FOREACH(l, &proxy_listeners, entry) { 620 event_set(&l->ev, l->s, EV_READ | EV_PERSIST, proxy_recv, l); 621 event_add(&l->ev, NULL); 622 } 623 } 624 625 char safety[SEGSIZE_MAX + 4]; 626 627 int 628 proxy_dst4(struct cmsghdr *cmsg, struct sockaddr_storage *ss) 629 { 630 struct sockaddr_in *sin = (struct sockaddr_in *)ss; 631 632 if (cmsg->cmsg_level != IPPROTO_IP) 633 return (0); 634 635 switch (cmsg->cmsg_type) { 636 case IP_RECVDSTADDR: 637 memcpy(&sin->sin_addr, CMSG_DATA(cmsg), sizeof(sin->sin_addr)); 638 if (sin->sin_addr.s_addr == INADDR_BROADCAST) 639 return (-1); 640 break; 641 642 case IP_RECVDSTPORT: 643 memcpy(&sin->sin_port, CMSG_DATA(cmsg), sizeof(sin->sin_port)); 644 break; 645 } 646 647 return (0); 648 } 649 650 int 651 proxy_dst6(struct cmsghdr *cmsg, struct sockaddr_storage *ss) 652 { 653 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ss; 654 struct in6_pktinfo *ipi = (struct in6_pktinfo *)CMSG_DATA(cmsg); 655 656 if (cmsg->cmsg_level != IPPROTO_IPV6) 657 return (0); 658 659 switch (cmsg->cmsg_type) { 660 case IPV6_PKTINFO: 661 memcpy(&sin6->sin6_addr, &ipi->ipi6_addr, 662 sizeof(sin6->sin6_addr)); 663 #ifdef __KAME__ 664 if (IN6_IS_ADDR_LINKLOCAL(&ipi->ipi6_addr)) 665 sin6->sin6_scope_id = ipi->ipi6_ifindex; 666 #endif 667 break; 668 case IPV6_RECVDSTPORT: 669 memcpy(&sin6->sin6_port, CMSG_DATA(cmsg), 670 sizeof(sin6->sin6_port)); 671 break; 672 } 673 674 return (0); 675 } 676 677 void 678 proxy_recv(int fd, short events, void *arg) 679 { 680 struct proxy_listener *l = arg; 681 682 union { 683 struct cmsghdr hdr; 684 char buf[CMSG_SPACE(sizeof(struct sockaddr_storage)) + 685 CMSG_SPACE(sizeof(in_port_t))]; 686 } cmsgbuf; 687 struct cmsghdr *cmsg; 688 struct msghdr msg; 689 struct iovec iov; 690 ssize_t n; 691 692 struct proxy_request *r; 693 struct tftphdr *tp; 694 695 r = calloc(1, sizeof(*r)); 696 if (r == NULL) { 697 recv(fd, safety, sizeof(safety), 0); 698 return; 699 } 700 r->id = arc4random(); /* XXX unique? */ 701 702 bzero(&msg, sizeof(msg)); 703 iov.iov_base = r->buf; 704 iov.iov_len = sizeof(r->buf); 705 msg.msg_name = &r->addrs.src; 706 msg.msg_namelen = sizeof(r->addrs.src); 707 msg.msg_iov = &iov; 708 msg.msg_iovlen = 1; 709 msg.msg_control = &cmsgbuf.buf; 710 msg.msg_controllen = sizeof(cmsgbuf.buf); 711 712 n = recvmsg(fd, &msg, 0); 713 if (n == -1) { 714 switch (errno) { 715 case EAGAIN: 716 case EINTR: 717 goto err; 718 default: 719 lerr(1, "recvmsg"); 720 /* NOTREACHED */ 721 } 722 } 723 r->buflen = n; 724 725 /* check the packet */ 726 if (n < 5) { 727 /* not enough to be a real packet */ 728 goto err; 729 } 730 tp = (struct tftphdr *)r->buf; 731 switch (ntohs(tp->th_opcode)) { 732 case RRQ: 733 case WRQ: 734 break; 735 default: 736 goto err; 737 } 738 739 r->addrs.dst.ss_family = r->addrs.src.ss_family; 740 r->addrs.dst.ss_len = r->addrs.src.ss_len; 741 742 /* get local address if possible */ 743 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 744 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 745 if (l->cmsg2dst(cmsg, &r->addrs.dst) == -1) 746 goto err; 747 } 748 749 if (verbose) { 750 linfo("%s:%d -> %s:%d \"%s %s\"", 751 sock_ntop((struct sockaddr *)&r->addrs.src), 752 ntohs(((struct sockaddr_in *)&r->addrs.src)->sin_port), 753 sock_ntop((struct sockaddr *)&r->addrs.dst), 754 ntohs(((struct sockaddr_in *)&r->addrs.dst)->sin_port), 755 opcode(ntohs(tp->th_opcode)), tp->th_stuff); 756 /* XXX tp->th_stuff could be garbage */ 757 } 758 759 TAILQ_INSERT_TAIL(&child->fdrequests, r, entry); 760 evbuffer_add(child->buf, &r->addrs, sizeof(r->addrs)); 761 event_add(&child->push_ev, NULL); 762 763 return; 764 765 err: 766 free(r); 767 } 768 769 void 770 unprivproc_push(int fd, short events, void *arg) 771 { 772 if (evbuffer_write(child->buf, fd) == -1) 773 lerr(1, "child evbuffer_write"); 774 775 if (EVBUFFER_LENGTH(child->buf)) 776 event_add(&child->push_ev, NULL); 777 } 778 779 void 780 unprivproc_pop(int fd, short events, void *arg) 781 { 782 struct proxy_request *r; 783 784 struct msghdr msg; 785 union { 786 struct cmsghdr hdr; 787 char buf[CMSG_SPACE(sizeof(int))]; 788 } cmsgbuf; 789 struct cmsghdr *cmsg; 790 struct iovec iov; 791 struct src_addr *src_addr; 792 struct sockaddr_storage saddr; 793 socklen_t len; 794 int result; 795 int s; 796 797 len = sizeof(saddr); 798 799 do { 800 memset(&msg, 0, sizeof(msg)); 801 iov.iov_base = &result; 802 iov.iov_len = sizeof(int); 803 msg.msg_iov = &iov; 804 msg.msg_iovlen = 1; 805 msg.msg_control = &cmsgbuf.buf; 806 msg.msg_controllen = sizeof(cmsgbuf.buf); 807 808 switch (recvmsg(fd, &msg, 0)) { 809 case sizeof(int): 810 break; 811 812 case -1: 813 switch (errno) { 814 case EAGAIN: 815 case EINTR: 816 return; 817 default: 818 lerr(1, "child recvmsg"); 819 } 820 /* NOTREACHED */ 821 822 case 0: 823 lerrx(1, "privproc closed connection"); 824 825 default: 826 lerrx(1, "child recvmsg was weird"); 827 /* NOTREACHED */ 828 } 829 830 if (result != 0) { 831 errno = result; 832 lerr(1, "child fdpass fail"); 833 } 834 835 cmsg = CMSG_FIRSTHDR(&msg); 836 if (cmsg == NULL) 837 lerrx(1, "%s: no message header", __func__); 838 839 if (cmsg->cmsg_type != SCM_RIGHTS) { 840 lerrx(1, "%s: expected type %d got %d", __func__, 841 SCM_RIGHTS, cmsg->cmsg_type); 842 } 843 844 s = (*(int *)CMSG_DATA(cmsg)); 845 846 r = TAILQ_FIRST(&child->fdrequests); 847 if (r == NULL) 848 lerrx(1, "got fd without a pending request"); 849 850 TAILQ_REMOVE(&child->fdrequests, r, entry); 851 852 /* get ready to add rules */ 853 if (prepare_commit(r->id) == -1) 854 lerr(1, "%s: prepare_commit", __func__); 855 856 TAILQ_FOREACH(src_addr, &src_addrs, entry) 857 if (src_addr->addr.ss_family == r->addrs.dst.ss_family) 858 break; 859 if (src_addr == NULL) { 860 if (add_filter(r->id, PF_IN, (struct sockaddr *) 861 &r->addrs.dst, (struct sockaddr *)&r->addrs.src, 862 ntohs(((struct sockaddr_in *)&r->addrs.src) 863 ->sin_port), IPPROTO_UDP) == -1) 864 lerr(1, "%s: couldn't add pass in", __func__); 865 } else { 866 if (getsockname(s, (struct sockaddr*)&saddr, &len) == -1) 867 lerr(1, "%s: getsockname", __func__); 868 if (add_rdr(r->id, (struct sockaddr *)&r->addrs.dst, 869 (struct sockaddr*)&saddr, 870 ntohs(((struct sockaddr_in *)&saddr)->sin_port), 871 (struct sockaddr *)&r->addrs.src, 872 ntohs(((struct sockaddr_in *)&r->addrs.src)-> 873 sin_port), IPPROTO_UDP ) == -1) 874 lerr(1, "%s: couldn't add rdr rule", __func__); 875 } 876 877 if (add_filter(r->id, PF_OUT, (struct sockaddr *)&r->addrs.dst, 878 (struct sockaddr *)&r->addrs.src, 879 ntohs(((struct sockaddr_in *)&r->addrs.src)->sin_port), 880 IPPROTO_UDP) == -1) 881 lerr(1, "%s: couldn't add pass out", __func__); 882 883 if (do_commit() == -1) 884 lerr(1, "%s: couldn't commit rules", __func__); 885 886 /* forward the initial tftp request and start the insanity */ 887 if (sendto(s, r->buf, r->buflen, 0, 888 (struct sockaddr *)&r->addrs.dst, 889 r->addrs.dst.ss_len) == -1) 890 lerr(1, "%s: unable to send", __func__); 891 892 close(s); 893 894 evtimer_set(&r->ev, unprivproc_timeout, r); 895 evtimer_add(&r->ev, &transwait); 896 897 TAILQ_INSERT_TAIL(&child->tmrequests, r, entry); 898 } while (!TAILQ_EMPTY(&child->fdrequests)); 899 } 900 901 void 902 unprivproc_timeout(int fd, short events, void *arg) 903 { 904 struct proxy_request *r = arg; 905 906 TAILQ_REMOVE(&child->tmrequests, r, entry); 907 908 /* delete our rdr rule and clean up */ 909 prepare_commit(r->id); 910 do_commit(); 911 912 free(r); 913 } 914 915 916 const char * 917 opcode(int code) 918 { 919 static char str[6]; 920 921 switch (code) { 922 case 1: 923 (void)snprintf(str, sizeof(str), "RRQ"); 924 break; 925 case 2: 926 (void)snprintf(str, sizeof(str), "WRQ"); 927 break; 928 default: 929 (void)snprintf(str, sizeof(str), "(%d)", code); 930 break; 931 } 932 933 return (str); 934 } 935 936 const char * 937 sock_ntop(struct sockaddr *sa) 938 { 939 static int n = 0; 940 941 /* Cycle to next buffer. */ 942 n = (n + 1) % NTOP_BUFS; 943 ntop_buf[n][0] = '\0'; 944 945 if (sa->sa_family == AF_INET) { 946 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 947 948 return (inet_ntop(AF_INET, &sin->sin_addr, ntop_buf[n], 949 sizeof ntop_buf[0])); 950 } 951 952 if (sa->sa_family == AF_INET6) { 953 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 954 955 return (inet_ntop(AF_INET6, &sin6->sin6_addr, ntop_buf[n], 956 sizeof ntop_buf[0])); 957 } 958 959 return (NULL); 960 } 961 962 void 963 syslog_vstrerror(int e, int priority, const char *fmt, va_list ap) 964 { 965 char *s; 966 967 if (vasprintf(&s, fmt, ap) == -1) { 968 syslog(LOG_EMERG, "unable to alloc in syslog_vstrerror"); 969 exit(1); 970 } 971 972 syslog(priority, "%s: %s", s, strerror(e)); 973 974 free(s); 975 } 976 977 void 978 syslog_err(int ecode, const char *fmt, ...) 979 { 980 va_list ap; 981 982 va_start(ap, fmt); 983 syslog_vstrerror(errno, LOG_EMERG, fmt, ap); 984 va_end(ap); 985 986 exit(ecode); 987 } 988 989 void 990 syslog_errx(int ecode, const char *fmt, ...) 991 { 992 va_list ap; 993 994 va_start(ap, fmt); 995 vsyslog(LOG_WARNING, fmt, ap); 996 va_end(ap); 997 998 exit(ecode); 999 } 1000 1001 void 1002 syslog_warn(const char *fmt, ...) 1003 { 1004 va_list ap; 1005 1006 va_start(ap, fmt); 1007 syslog_vstrerror(errno, LOG_WARNING, fmt, ap); 1008 va_end(ap); 1009 } 1010 1011 void 1012 syslog_warnx(const char *fmt, ...) 1013 { 1014 va_list ap; 1015 1016 va_start(ap, fmt); 1017 vsyslog(LOG_WARNING, fmt, ap); 1018 va_end(ap); 1019 } 1020 1021 void 1022 syslog_info(const char *fmt, ...) 1023 { 1024 va_list ap; 1025 1026 va_start(ap, fmt); 1027 vsyslog(LOG_INFO, fmt, ap); 1028 va_end(ap); 1029 } 1030 1031