1 /* $OpenBSD: identd.c,v 1.31 2015/08/20 11:06:35 dlg Exp $ */ 2 3 /* 4 * Copyright (c) 2013 David Gwynne <dlg@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 19 #include <sys/types.h> 20 #include <sys/ioctl.h> 21 #include <sys/socket.h> 22 #include <sys/socketvar.h> 23 #include <sys/stat.h> 24 #include <sys/sysctl.h> 25 #include <sys/uio.h> 26 27 #include <netinet/in.h> 28 #include <netinet/tcp.h> 29 #include <netinet/tcp_timer.h> 30 #include <netinet/tcp_var.h> 31 32 #include <netdb.h> 33 34 #include <err.h> 35 #include <ctype.h> 36 #include <errno.h> 37 #include <event.h> 38 #include <fcntl.h> 39 #include <pwd.h> 40 #include <stdio.h> 41 #include <limits.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <signal.h> 45 #include <syslog.h> 46 #include <unistd.h> 47 48 #define IDENTD_USER "_identd" 49 50 #define DOTNOIDENT ".noident" 51 52 #define TIMEOUT_MIN 4 53 #define TIMEOUT_MAX 240 54 #define TIMEOUT_DEFAULT 120 55 #define INPUT_MAX 256 56 57 enum ident_client_state { 58 S_BEGINNING = 0, 59 S_SERVER_PORT, 60 S_PRE_COMMA, 61 S_POST_COMMA, 62 S_CLIENT_PORT, 63 S_PRE_EOL, 64 S_EOL, 65 66 S_DEAD, 67 S_QUEUED 68 }; 69 70 #define E_NONE 0 71 #define E_NOUSER 1 72 #define E_UNKNOWN 2 73 #define E_HIDDEN 3 74 75 struct ident_client { 76 struct { 77 /* from the socket */ 78 struct sockaddr_storage ss; 79 socklen_t len; 80 81 /* from the request */ 82 u_int port; 83 } client, server; 84 SIMPLEQ_ENTRY(ident_client) entry; 85 enum ident_client_state state; 86 struct event ev; 87 struct event tmo; 88 size_t rxbytes; 89 90 char *buf; 91 size_t buflen; 92 size_t bufoff; 93 uid_t uid; 94 }; 95 96 struct ident_resolver { 97 SIMPLEQ_ENTRY(ident_resolver) entry; 98 char *buf; 99 size_t buflen; 100 u_int error; 101 }; 102 103 struct identd_listener { 104 struct event ev, pause; 105 }; 106 107 void parent_rd(int, short, void *); 108 void parent_wr(int, short, void *); 109 int parent_username(struct ident_resolver *, struct passwd *); 110 int parent_uid(struct ident_resolver *, struct passwd *); 111 int parent_token(struct ident_resolver *, struct passwd *); 112 void parent_noident(struct ident_resolver *, struct passwd *); 113 114 void child_rd(int, short, void *); 115 void child_wr(int, short, void *); 116 117 void identd_listen(const char *, const char *, int); 118 void identd_paused(int, short, void *); 119 void identd_accept(int, short, void *); 120 int identd_error(struct ident_client *, const char *); 121 void identd_close(struct ident_client *); 122 void identd_timeout(int, short, void *); 123 void identd_request(int, short, void *); 124 enum ident_client_state 125 identd_parse(struct ident_client *, int); 126 void identd_resolving(int, short, void *); 127 void identd_response(int, short, void *); 128 int fetchuid(struct ident_client *); 129 130 const char *gethost(struct sockaddr_storage *); 131 const char *getport(struct sockaddr_storage *); 132 const char *gentoken(void); 133 134 struct loggers { 135 void (*err)(int, const char *, ...); 136 void (*errx)(int, const char *, ...); 137 void (*warn)(const char *, ...); 138 void (*warnx)(const char *, ...); 139 void (*notice)(const char *, ...); 140 void (*debug)(const char *, ...); 141 }; 142 143 const struct loggers conslogger = { 144 err, 145 errx, 146 warn, 147 warnx, 148 warnx, /* notice */ 149 warnx /* debug */ 150 }; 151 152 void syslog_err(int, const char *, ...); 153 void syslog_errx(int, const char *, ...); 154 void syslog_warn(const char *, ...); 155 void syslog_warnx(const char *, ...); 156 void syslog_notice(const char *, ...); 157 void syslog_debug(const char *, ...); 158 void syslog_vstrerror(int, int, const char *, va_list); 159 160 const struct loggers syslogger = { 161 syslog_err, 162 syslog_errx, 163 syslog_warn, 164 syslog_warnx, 165 syslog_notice, 166 syslog_debug 167 }; 168 169 const struct loggers *logger = &conslogger; 170 171 #define lerr(_e, _f...) logger->err((_e), _f) 172 #define lerrx(_e, _f...) logger->errx((_e), _f) 173 #define lwarn(_f...) logger->warn(_f) 174 #define lwarnx(_f...) logger->warnx(_f) 175 #define lnotice(_f...) logger->notice(_f) 176 #define ldebug(_f...) logger->debug(_f) 177 178 #define sa(_ss) ((struct sockaddr *)(_ss)) 179 180 static __dead void 181 usage(void) 182 { 183 extern char *__progname; 184 fprintf(stderr, "usage: %s [-46deHhNn] [-l address] [-t timeout]\n", 185 __progname); 186 exit(1); 187 } 188 189 struct timeval timeout = { TIMEOUT_DEFAULT, 0 }; 190 int debug = 0; 191 int noident = 0; 192 int unknown_err = 0; 193 int hideall = 0; 194 195 int (*parent_uprintf)(struct ident_resolver *, struct passwd *) = 196 parent_username; 197 198 struct event proc_rd, proc_wr; 199 union { 200 struct { 201 SIMPLEQ_HEAD(, ident_resolver) replies; 202 } parent; 203 struct { 204 SIMPLEQ_HEAD(, ident_client) pushing, popping; 205 } child; 206 } sc; 207 208 int 209 main(int argc, char *argv[]) 210 { 211 extern char *__progname; 212 const char *errstr = NULL; 213 214 int c; 215 struct passwd *pw; 216 217 char *addr = NULL; 218 int family = AF_UNSPEC; 219 220 int pair[2]; 221 pid_t parent; 222 int sibling; 223 224 while ((c = getopt(argc, argv, "46deHhl:Nnt:")) != -1) { 225 switch (c) { 226 case '4': 227 family = AF_INET; 228 break; 229 case '6': 230 family = AF_INET6; 231 break; 232 case 'd': 233 debug = 1; 234 break; 235 case 'e': 236 unknown_err = 1; 237 break; 238 case 'H': 239 hideall = 1; 240 /* FALLTHROUGH */ 241 case 'h': 242 parent_uprintf = parent_token; 243 break; 244 case 'l': 245 addr = optarg; 246 break; 247 case 'N': 248 noident = 1; 249 break; 250 case 'n': 251 parent_uprintf = parent_uid; 252 break; 253 case 't': 254 timeout.tv_sec = strtonum(optarg, 255 TIMEOUT_MIN, TIMEOUT_MAX, &errstr); 256 if (errstr != NULL) 257 errx(1, "timeout %s is %s", optarg, errstr); 258 break; 259 default: 260 usage(); 261 /* NOTREACHED */ 262 } 263 } 264 265 argc -= optind; 266 argv += optind; 267 268 if (argc != 0) 269 usage(); 270 271 if (geteuid() != 0) 272 errx(1, "need root privileges"); 273 274 if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 275 PF_UNSPEC, pair) == -1) 276 err(1, "socketpair"); 277 278 pw = getpwnam(IDENTD_USER); 279 if (pw == NULL) 280 errx(1, "no %s user", IDENTD_USER); 281 282 if (!debug && daemon(1, 0) == -1) 283 err(1, "daemon"); 284 285 parent = fork(); 286 switch (parent) { 287 case -1: 288 lerr(1, "fork"); 289 290 case 0: 291 /* child */ 292 setproctitle("listener"); 293 close(pair[1]); 294 sibling = pair[0]; 295 break; 296 297 default: 298 /* parent */ 299 setproctitle("resolver"); 300 close(pair[0]); 301 sibling = pair[1]; 302 break; 303 } 304 305 if (!debug) { 306 openlog(__progname, LOG_PID|LOG_NDELAY, LOG_DAEMON); 307 tzset(); 308 logger = &syslogger; 309 } 310 311 event_init(); 312 313 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) 314 lerr(1, "signal(SIGPIPE)"); 315 316 if (parent) { 317 SIMPLEQ_INIT(&sc.parent.replies); 318 319 event_set(&proc_rd, sibling, EV_READ | EV_PERSIST, 320 parent_rd, NULL); 321 event_set(&proc_wr, sibling, EV_WRITE, 322 parent_wr, NULL); 323 } else { 324 SIMPLEQ_INIT(&sc.child.pushing); 325 SIMPLEQ_INIT(&sc.child.popping); 326 327 identd_listen(addr, "auth", family); 328 329 if (chroot(pw->pw_dir) == -1) 330 lerr(1, "chroot(%s)", pw->pw_dir); 331 332 if (chdir("/") == -1) 333 lerr(1, "chdir(%s)", pw->pw_dir); 334 335 event_set(&proc_rd, sibling, EV_READ | EV_PERSIST, 336 child_rd, NULL); 337 event_set(&proc_wr, sibling, EV_WRITE, 338 child_wr, NULL); 339 } 340 341 if (setgroups(1, &pw->pw_gid) || 342 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 343 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 344 lerr(1, "unable to revoke privs"); 345 346 event_add(&proc_rd, NULL); 347 event_dispatch(); 348 return (0); 349 } 350 351 void 352 parent_rd(int fd, short events, void *arg) 353 { 354 struct ident_resolver *r; 355 struct passwd *pw; 356 ssize_t n; 357 uid_t uid; 358 359 n = read(fd, &uid, sizeof(uid)); 360 switch (n) { 361 case -1: 362 switch (errno) { 363 case EAGAIN: 364 case EINTR: 365 return; 366 default: 367 lerr(1, "parent read"); 368 } 369 break; 370 case 0: 371 lerrx(1, "child has gone"); 372 case sizeof(uid): 373 break; 374 default: 375 lerrx(1, "unexpected %zd data from child", n); 376 } 377 378 r = calloc(1, sizeof(*r)); 379 if (r == NULL) 380 lerr(1, "resolver alloc"); 381 382 pw = getpwuid(uid); 383 if (pw == NULL && !hideall) { 384 r->error = E_NOUSER; 385 goto done; 386 } 387 388 if (noident && !hideall) { 389 parent_noident(r, pw); 390 if (r->error != E_NONE) 391 goto done; 392 } 393 394 n = (*parent_uprintf)(r, pw); 395 if (n == -1) { 396 r->error = E_UNKNOWN; 397 goto done; 398 } 399 400 r->buflen = n + 1; 401 402 done: 403 SIMPLEQ_INSERT_TAIL(&sc.parent.replies, r, entry); 404 event_add(&proc_wr, NULL); 405 } 406 407 int 408 parent_username(struct ident_resolver *r, struct passwd *pw) 409 { 410 return (asprintf(&r->buf, "%s", pw->pw_name)); 411 } 412 413 int 414 parent_uid(struct ident_resolver *r, struct passwd *pw) 415 { 416 return (asprintf(&r->buf, "%u", (u_int)pw->pw_uid)); 417 } 418 419 int 420 parent_token(struct ident_resolver *r, struct passwd *pw) 421 { 422 const char *token; 423 int rv; 424 425 token = gentoken(); 426 rv = asprintf(&r->buf, "%s", token); 427 if (rv != -1) { 428 if (pw) 429 lnotice("token %s == uid %u (%s)", token, 430 (u_int)pw->pw_uid, pw->pw_name); 431 else 432 lnotice("token %s == NO USER", token); 433 } 434 435 return (rv); 436 } 437 438 void 439 parent_noident(struct ident_resolver *r, struct passwd *pw) 440 { 441 char path[PATH_MAX]; 442 struct stat st; 443 int rv; 444 445 rv = snprintf(path, sizeof(path), "%s/%s", pw->pw_dir, DOTNOIDENT); 446 if (rv == -1 || rv >= sizeof(path)) { 447 r->error = E_UNKNOWN; 448 return; 449 } 450 451 if (stat(path, &st) == -1) 452 return; 453 454 r->error = E_HIDDEN; 455 } 456 457 void 458 parent_wr(int fd, short events, void *arg) 459 { 460 struct ident_resolver *r = SIMPLEQ_FIRST(&sc.parent.replies); 461 struct iovec iov[2]; 462 int iovcnt = 0; 463 ssize_t n; 464 465 iov[iovcnt].iov_base = &r->error; 466 iov[iovcnt].iov_len = sizeof(r->error); 467 iovcnt++; 468 469 if (r->buflen > 0) { 470 iov[iovcnt].iov_base = r->buf; 471 iov[iovcnt].iov_len = r->buflen; 472 iovcnt++; 473 } 474 475 n = writev(fd, iov, iovcnt); 476 if (n == -1) { 477 switch (errno) { 478 case EINTR: 479 case EAGAIN: 480 event_add(&proc_wr, NULL); 481 return; 482 default: 483 lerr(1, "parent write"); 484 } 485 } 486 487 if (n != sizeof(r->error) + r->buflen) 488 lerrx(1, "unexpected parent write length %zd", n); 489 490 SIMPLEQ_REMOVE_HEAD(&sc.parent.replies, entry); 491 492 if (r->buflen > 0) 493 free(r->buf); 494 495 free(r); 496 497 if (!SIMPLEQ_EMPTY(&sc.parent.replies)) 498 event_add(&proc_wr, NULL); 499 } 500 501 void 502 child_rd(int fd, short events, void *arg) 503 { 504 struct ident_client *c; 505 struct { 506 u_int error; 507 char buf[512]; 508 } reply; 509 ssize_t n; 510 511 n = read(fd, &reply, sizeof(reply)); 512 switch (n) { 513 case -1: 514 switch (errno) { 515 case EAGAIN: 516 case EINTR: 517 return; 518 default: 519 lerr(1, "child read"); 520 } 521 break; 522 case 0: 523 lerrx(1, "parent has gone"); 524 default: 525 break; 526 } 527 528 c = SIMPLEQ_FIRST(&sc.child.popping); 529 if (c == NULL) 530 lerrx(1, "unsolicited data from parent"); 531 532 SIMPLEQ_REMOVE_HEAD(&sc.child.popping, entry); 533 534 if (n < sizeof(reply.error)) 535 lerrx(1, "short data from parent"); 536 537 /* check if something went wrong while the parent was working */ 538 if (c->state == S_DEAD) { 539 free(c); 540 return; 541 } 542 c->state = S_DEAD; 543 544 switch (reply.error) { 545 case E_NONE: 546 n = asprintf(&c->buf, "%u , %u : USERID : UNIX : %s\r\n", 547 c->server.port, c->client.port, reply.buf); 548 break; 549 case E_NOUSER: 550 n = asprintf(&c->buf, "%u , %u : ERROR : %s\r\n", 551 c->server.port, c->client.port, 552 unknown_err ? "UNKNOWN-ERROR" : "NO-USER"); 553 break; 554 case E_UNKNOWN: 555 n = asprintf(&c->buf, "%u , %u : ERROR : UNKNOWN-ERROR\r\n", 556 c->server.port, c->client.port); 557 break; 558 case E_HIDDEN: 559 n = asprintf(&c->buf, "%u , %u : ERROR : HIDDEN-USER\r\n", 560 c->server.port, c->client.port); 561 break; 562 default: 563 lerrx(1, "unexpected error from parent %u", reply.error); 564 } 565 if (n == -1) 566 goto fail; 567 568 c->buflen = n; 569 570 fd = EVENT_FD(&c->ev); 571 event_del(&c->ev); 572 event_set(&c->ev, fd, EV_READ | EV_WRITE | EV_PERSIST, 573 identd_response, c); 574 event_add(&c->ev, NULL); 575 return; 576 577 fail: 578 identd_close(c); 579 } 580 581 void 582 child_wr(int fd, short events, void *arg) 583 { 584 struct ident_client *c = SIMPLEQ_FIRST(&sc.child.pushing); 585 const char *errstr = NULL; 586 ssize_t n; 587 588 n = write(fd, &c->uid, sizeof(c->uid)); 589 switch (n) { 590 case -1: 591 switch (errno) { 592 case EINTR: 593 case EAGAIN: 594 event_add(&proc_wr, NULL); 595 return; 596 case ENOBUFS: /* parent has a backlog of requests */ 597 errstr = "UNKNOWN-ERROR"; 598 break; 599 default: 600 lerr(1, "child write"); 601 } 602 break; 603 case sizeof(c->uid): 604 break; 605 default: 606 lerrx(1, "unexpected child write length %zd", n); 607 } 608 609 SIMPLEQ_REMOVE_HEAD(&sc.child.pushing, entry); 610 if (errstr == NULL) 611 SIMPLEQ_INSERT_TAIL(&sc.child.popping, c, entry); 612 else if (identd_error(c, errstr) == -1) 613 identd_close(c); 614 615 if (!SIMPLEQ_EMPTY(&sc.child.pushing)) 616 event_add(&proc_wr, NULL); 617 } 618 619 void 620 identd_listen(const char *addr, const char *port, int family) 621 { 622 struct identd_listener *l = NULL; 623 624 struct addrinfo hints, *res, *res0; 625 int error, s; 626 const char *cause = NULL; 627 int on = 1; 628 629 memset(&hints, 0, sizeof(hints)); 630 hints.ai_family = family; 631 hints.ai_socktype = SOCK_STREAM; 632 hints.ai_flags = AI_PASSIVE; 633 634 error = getaddrinfo(addr, port, &hints, &res0); 635 if (error) 636 lerrx(1, "%s/%s: %s", addr, port, gai_strerror(error)); 637 638 for (res = res0; res != NULL; res = res->ai_next) { 639 s = socket(res->ai_family, res->ai_socktype | SOCK_NONBLOCK, 640 res->ai_protocol); 641 if (s == -1) { 642 cause = "socket"; 643 continue; 644 } 645 646 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 647 &on, sizeof(on)) == -1) 648 err(1, "listener setsockopt(SO_REUSEADDR)"); 649 650 if (bind(s, res->ai_addr, res->ai_addrlen) == -1) { 651 int serrno = errno; 652 653 cause = "bind"; 654 close(s); 655 errno = serrno; 656 continue; 657 } 658 659 if (listen(s, 5) == -1) 660 err(1, "listen"); 661 662 l = calloc(1, sizeof(*l)); 663 if (l == NULL) 664 err(1, "listener ev alloc"); 665 666 event_set(&l->ev, s, EV_READ | EV_PERSIST, identd_accept, l); 667 event_add(&l->ev, NULL); 668 evtimer_set(&l->pause, identd_paused, l); 669 } 670 if (l == NULL) 671 err(1, "%s", cause); 672 673 freeaddrinfo(res0); 674 } 675 676 void 677 identd_paused(int fd, short events, void *arg) 678 { 679 struct identd_listener *l = arg; 680 event_add(&l->ev, NULL); 681 } 682 683 void 684 identd_accept(int fd, short events, void *arg) 685 { 686 struct identd_listener *l = arg; 687 struct sockaddr_storage ss; 688 struct timeval pause = { 1, 0 }; 689 struct ident_client *c = NULL; 690 socklen_t len; 691 int s; 692 693 len = sizeof(ss); 694 s = accept4(fd, sa(&ss), &len, SOCK_NONBLOCK); 695 if (s == -1) { 696 switch (errno) { 697 case EINTR: 698 case EWOULDBLOCK: 699 case ECONNABORTED: 700 return; 701 case EMFILE: 702 case ENFILE: 703 event_del(&l->ev); 704 evtimer_add(&l->pause, &pause); 705 return; 706 default: 707 lerr(1, "accept"); 708 } 709 } 710 711 c = calloc(1, sizeof(*c)); 712 if (c == NULL) { 713 lwarn("client alloc"); 714 close(fd); 715 return; 716 } 717 718 memcpy(&c->client.ss, &ss, len); 719 c->client.len = len; 720 ldebug("client: %s", gethost(&ss)); 721 722 /* lookup the local ip it connected to */ 723 c->server.len = sizeof(c->server.ss); 724 if (getsockname(s, sa(&c->server.ss), &c->server.len) == -1) 725 lerr(1, "getsockname"); 726 727 event_set(&c->ev, s, EV_READ | EV_PERSIST, identd_request, c); 728 event_add(&c->ev, NULL); 729 730 event_set(&c->tmo, s, 0, identd_timeout, c); 731 event_add(&c->tmo, &timeout); 732 } 733 734 void 735 identd_timeout(int fd, short events, void *arg) 736 { 737 struct ident_client *c = arg; 738 739 event_del(&c->ev); 740 close(fd); 741 free(c->buf); 742 743 if (c->state == S_QUEUED) /* it is queued for resolving */ 744 c->state = S_DEAD; 745 else 746 free(c); 747 } 748 749 void 750 identd_request(int fd, short events, void *arg) 751 { 752 struct ident_client *c = arg; 753 unsigned char buf[64]; 754 ssize_t n, i; 755 char *errstr = unknown_err ? "UNKNOWN-ERROR" : "INVALID-PORT"; 756 757 n = read(fd, buf, sizeof(buf)); 758 switch (n) { 759 case -1: 760 switch (errno) { 761 case EINTR: 762 case EAGAIN: 763 return; 764 default: 765 lwarn("%s read", gethost(&c->client.ss)); 766 goto fail; 767 } 768 break; 769 770 case 0: 771 ldebug("%s closed connection", gethost(&c->client.ss)); 772 goto fail; 773 default: 774 break; 775 } 776 777 c->rxbytes += n; 778 if (c->rxbytes >= INPUT_MAX) 779 goto fail; 780 781 for (i = 0; c->state < S_EOL && i < n; i++) 782 c->state = identd_parse(c, buf[i]); 783 784 if (c->state == S_DEAD) 785 goto error; 786 if (c->state != S_EOL) 787 return; 788 789 if (c->server.port < 1 || c->client.port < 1) 790 goto error; 791 792 if (fetchuid(c) == -1) { 793 errstr = unknown_err ? "UNKNOWN-ERROR" : "NO-USER"; 794 goto error; 795 } 796 797 SIMPLEQ_INSERT_TAIL(&sc.child.pushing, c, entry); 798 c->state = S_QUEUED; 799 800 event_del(&c->ev); 801 event_set(&c->ev, fd, EV_READ | EV_PERSIST, identd_resolving, c); 802 event_add(&c->ev, NULL); 803 804 event_add(&proc_wr, NULL); 805 return; 806 807 error: 808 if (identd_error(c, errstr) == -1) 809 goto fail; 810 811 return; 812 813 fail: 814 identd_close(c); 815 } 816 817 int 818 identd_error(struct ident_client *c, const char *errstr) 819 { 820 int fd = EVENT_FD(&c->ev); 821 ssize_t n; 822 823 n = asprintf(&c->buf, "%u , %u : ERROR : %s\r\n", 824 c->server.port, c->client.port, errstr); 825 if (n == -1) 826 return (-1); 827 828 c->buflen = n; 829 830 event_del(&c->ev); 831 event_set(&c->ev, fd, EV_READ | EV_WRITE | EV_PERSIST, 832 identd_response, c); 833 event_add(&c->ev, NULL); 834 835 return (0); 836 } 837 838 void 839 identd_close(struct ident_client *c) 840 { 841 int fd = EVENT_FD(&c->ev); 842 843 evtimer_del(&c->tmo); 844 event_del(&c->ev); 845 close(fd); 846 free(c->buf); 847 free(c); 848 } 849 850 void 851 identd_resolving(int fd, short events, void *arg) 852 { 853 struct ident_client *c = arg; 854 char buf[64]; 855 ssize_t n; 856 857 /* 858 * something happened while we're waiting for the parent to lookup 859 * the user. 860 */ 861 862 n = read(fd, buf, sizeof(buf)); 863 switch (n) { 864 case -1: 865 switch (errno) { 866 case EINTR: 867 case EAGAIN: 868 return; 869 default: 870 lwarn("resolving read"); 871 break; 872 } 873 break; 874 case 0: 875 ldebug("%s closed connection during resolving", 876 gethost(&c->client.ss)); 877 break; 878 default: 879 c->rxbytes += n; 880 if (c->rxbytes >= INPUT_MAX) 881 break; 882 883 /* ignore extra input */ 884 return; 885 } 886 887 evtimer_del(&c->tmo); 888 event_del(&c->ev); 889 close(fd); 890 c->state = S_DEAD; /* on the resolving queue */ 891 } 892 893 enum ident_client_state 894 identd_parse(struct ident_client *c, int ch) 895 { 896 enum ident_client_state s = c->state; 897 898 switch (s) { 899 case S_BEGINNING: 900 /* ignore leading space */ 901 if (ch == '\t' || ch == ' ') 902 return (s); 903 904 if (ch == '0' || !isdigit(ch)) 905 return (S_DEAD); 906 907 c->server.port = ch - '0'; 908 return (S_SERVER_PORT); 909 910 case S_SERVER_PORT: 911 if (ch == '\t' || ch == ' ') 912 return (S_PRE_COMMA); 913 if (ch == ',') 914 return (S_POST_COMMA); 915 916 if (!isdigit(ch)) 917 return (S_DEAD); 918 919 c->server.port *= 10; 920 c->server.port += ch - '0'; 921 if (c->server.port > 65535) 922 return (S_DEAD); 923 924 return (s); 925 926 case S_PRE_COMMA: 927 if (ch == '\t' || ch == ' ') 928 return (s); 929 if (ch == ',') 930 return (S_POST_COMMA); 931 932 return (S_DEAD); 933 934 case S_POST_COMMA: 935 if (ch == '\t' || ch == ' ') 936 return (s); 937 938 if (ch == '0' || !isdigit(ch)) 939 return (S_DEAD); 940 941 c->client.port = ch - '0'; 942 return (S_CLIENT_PORT); 943 944 case S_CLIENT_PORT: 945 if (ch == '\t' || ch == ' ') 946 return (S_PRE_EOL); 947 if (ch == '\r' || ch == '\n') 948 return (S_EOL); 949 950 if (!isdigit(ch)) 951 return (S_DEAD); 952 953 c->client.port *= 10; 954 c->client.port += ch - '0'; 955 if (c->client.port > 65535) 956 return (S_DEAD); 957 958 return (s); 959 960 case S_PRE_EOL: 961 if (ch == '\t' || ch == ' ') 962 return (s); 963 if (ch == '\r' || ch == '\n') 964 return (S_EOL); 965 966 return (S_DEAD); 967 968 case S_EOL: 969 /* ignore trailing garbage */ 970 return (s); 971 972 default: 973 return (S_DEAD); 974 } 975 } 976 977 void 978 identd_response(int fd, short events, void *arg) 979 { 980 struct ident_client *c = arg; 981 char buf[64]; 982 ssize_t n; 983 984 if (events & EV_READ) { 985 n = read(fd, buf, sizeof(buf)); 986 switch (n) { 987 case -1: 988 switch (errno) { 989 case EINTR: 990 case EAGAIN: 991 /* meh, try a write */ 992 break; 993 default: 994 lwarn("response read"); 995 goto done; 996 } 997 break; 998 case 0: 999 ldebug("%s closed connection during response", 1000 gethost(&c->client.ss)); 1001 goto done; 1002 default: 1003 c->rxbytes += n; 1004 if (c->rxbytes >= INPUT_MAX) 1005 goto done; 1006 1007 /* ignore extra input */ 1008 break; 1009 } 1010 } 1011 1012 if (!(events & EV_WRITE)) 1013 return; /* try again later */ 1014 1015 n = write(fd, c->buf + c->bufoff, c->buflen - c->bufoff); 1016 if (n == -1) { 1017 switch (errno) { 1018 case EINTR: 1019 case EAGAIN: 1020 return; /* try again later */ 1021 case EPIPE: 1022 goto done; 1023 default: 1024 lwarn("response write"); 1025 goto done; 1026 } 1027 } 1028 1029 c->bufoff += n; 1030 if (c->bufoff != c->buflen) 1031 return; /* try again later */ 1032 1033 done: 1034 identd_close(c); 1035 } 1036 1037 void 1038 syslog_vstrerror(int e, int priority, const char *fmt, va_list ap) 1039 { 1040 char *s; 1041 1042 if (vasprintf(&s, fmt, ap) == -1) { 1043 syslog(LOG_EMERG, "unable to alloc in syslog_vstrerror"); 1044 exit(1); 1045 } 1046 syslog(priority, "%s: %s", s, strerror(e)); 1047 free(s); 1048 } 1049 1050 void 1051 syslog_err(int ecode, const char *fmt, ...) 1052 { 1053 va_list ap; 1054 1055 va_start(ap, fmt); 1056 syslog_vstrerror(errno, LOG_EMERG, fmt, ap); 1057 va_end(ap); 1058 exit(ecode); 1059 } 1060 1061 void 1062 syslog_errx(int ecode, const char *fmt, ...) 1063 { 1064 va_list ap; 1065 1066 va_start(ap, fmt); 1067 vsyslog(LOG_WARNING, fmt, ap); 1068 va_end(ap); 1069 exit(ecode); 1070 } 1071 1072 void 1073 syslog_warn(const char *fmt, ...) 1074 { 1075 va_list ap; 1076 1077 va_start(ap, fmt); 1078 syslog_vstrerror(errno, LOG_WARNING, fmt, ap); 1079 va_end(ap); 1080 } 1081 1082 void 1083 syslog_warnx(const char *fmt, ...) 1084 { 1085 va_list ap; 1086 1087 va_start(ap, fmt); 1088 vsyslog(LOG_WARNING, fmt, ap); 1089 va_end(ap); 1090 } 1091 1092 void 1093 syslog_notice(const char *fmt, ...) 1094 { 1095 va_list ap; 1096 1097 va_start(ap, fmt); 1098 vsyslog(LOG_NOTICE, fmt, ap); 1099 va_end(ap); 1100 } 1101 1102 void 1103 syslog_debug(const char *fmt, ...) 1104 { 1105 va_list ap; 1106 1107 if (!debug) 1108 return; 1109 1110 va_start(ap, fmt); 1111 vsyslog(LOG_DEBUG, fmt, ap); 1112 va_end(ap); 1113 } 1114 1115 const char * 1116 gethost(struct sockaddr_storage *ss) 1117 { 1118 struct sockaddr *sa = (struct sockaddr *)ss; 1119 static char buf[NI_MAXHOST]; 1120 1121 if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), 1122 NULL, 0, NI_NUMERICHOST) != 0) 1123 return ("(unknown)"); 1124 1125 return (buf); 1126 } 1127 1128 const char * 1129 getport(struct sockaddr_storage *ss) 1130 { 1131 struct sockaddr *sa = (struct sockaddr *)ss; 1132 static char buf[NI_MAXSERV]; 1133 1134 if (getnameinfo(sa, sa->sa_len, NULL, 0, buf, sizeof(buf), 1135 NI_NUMERICSERV) != 0) 1136 return ("(unknown)"); 1137 1138 return (buf); 1139 } 1140 1141 const char * 1142 gentoken(void) 1143 { 1144 static char buf[21]; 1145 u_int32_t r; 1146 int i; 1147 1148 buf[0] = 'a' + arc4random_uniform(26); 1149 for (i = 1; i < sizeof(buf) - 1; i++) { 1150 r = arc4random_uniform(36); 1151 buf[i] = (r < 26 ? 'a' : '0' - 26) + r; 1152 } 1153 buf[i] = '\0'; 1154 1155 return (buf); 1156 } 1157 1158 int 1159 fetchuid(struct ident_client *c) 1160 { 1161 struct tcp_ident_mapping tir; 1162 int mib[] = { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_IDENT }; 1163 struct sockaddr_in *s4; 1164 struct sockaddr_in6 *s6; 1165 int err = 0; 1166 size_t len; 1167 1168 memset(&tir, 0, sizeof(tir)); 1169 memcpy(&tir.faddr, &c->client.ss, sizeof(tir.faddr)); 1170 memcpy(&tir.laddr, &c->server.ss, sizeof(tir.laddr)); 1171 1172 switch (c->server.ss.ss_family) { 1173 case AF_INET: 1174 s4 = (struct sockaddr_in *)&tir.faddr; 1175 s4->sin_port = htons(c->client.port); 1176 1177 s4 = (struct sockaddr_in *)&tir.laddr; 1178 s4->sin_port = htons(c->server.port); 1179 break; 1180 case AF_INET6: 1181 s6 = (struct sockaddr_in6 *)&tir.faddr; 1182 s6->sin6_port = htons(c->client.port); 1183 1184 s6 = (struct sockaddr_in6 *)&tir.laddr; 1185 s6->sin6_port = htons(c->server.port); 1186 break; 1187 default: 1188 lerrx(1, "unexpected family %d", c->server.ss.ss_family); 1189 } 1190 1191 len = sizeof(tir); 1192 err = sysctl(mib, sizeof(mib) / sizeof(mib[0]), &tir, &len, NULL, 0); 1193 if (err == -1) 1194 lerr(1, "sysctl"); 1195 1196 if (tir.ruid == -1) 1197 return (-1); 1198 1199 c->uid = tir.ruid; 1200 return (0); 1201 } 1202