inetd.c revision 102937
1/* 2 * Copyright (c) 1983, 1991, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35static const char copyright[] = 36"@(#) Copyright (c) 1983, 1991, 1993, 1994\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41#if 0 42static char sccsid[] = "@(#)from: inetd.c 8.4 (Berkeley) 4/13/94"; 43#endif 44#endif /* not lint */ 45 46#include <sys/cdefs.h> 47__FBSDID("$FreeBSD: head/usr.sbin/inetd/inetd.c 102937 2002-09-04 20:15:20Z dwmalone $"); 48 49/* 50 * Inetd - Internet super-server 51 * 52 * This program invokes all internet services as needed. Connection-oriented 53 * services are invoked each time a connection is made, by creating a process. 54 * This process is passed the connection as file descriptor 0 and is expected 55 * to do a getpeername to find out the source host and port. 56 * 57 * Datagram oriented services are invoked when a datagram 58 * arrives; a process is created and passed a pending message 59 * on file descriptor 0. Datagram servers may either connect 60 * to their peer, freeing up the original socket for inetd 61 * to receive further messages on, or ``take over the socket'', 62 * processing all arriving datagrams and, eventually, timing 63 * out. The first type of server is said to be ``multi-threaded''; 64 * the second type of server ``single-threaded''. 65 * 66 * Inetd uses a configuration file which is read at startup 67 * and, possibly, at some later time in response to a hangup signal. 68 * The configuration file is ``free format'' with fields given in the 69 * order shown below. Continuation lines for an entry must begin with 70 * a space or tab. All fields must be present in each entry. 71 * 72 * service name must be in /etc/services 73 * or name a tcpmux service 74 * or specify a unix domain socket 75 * socket type stream/dgram/raw/rdm/seqpacket 76 * protocol tcp[4][6][/faith,ttcp], udp[4][6], unix 77 * wait/nowait single-threaded/multi-threaded 78 * user user to run daemon as 79 * server program full path name 80 * server program arguments maximum of MAXARGS (20) 81 * 82 * TCP services without official port numbers are handled with the 83 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for 84 * requests. When a connection is made from a foreign host, the service 85 * requested is passed to tcpmux, which looks it up in the servtab list 86 * and returns the proper entry for the service. Tcpmux returns a 87 * negative reply if the service doesn't exist, otherwise the invoked 88 * server is expected to return the positive reply if the service type in 89 * inetd.conf file has the prefix "tcpmux/". If the service type has the 90 * prefix "tcpmux/+", tcpmux will return the positive reply for the 91 * process; this is for compatibility with older server code, and also 92 * allows you to invoke programs that use stdin/stdout without putting any 93 * special server code in them. Services that use tcpmux are "nowait" 94 * because they do not have a well-known port and hence cannot listen 95 * for new requests. 96 * 97 * For RPC services 98 * service name/version must be in /etc/rpc 99 * socket type stream/dgram/raw/rdm/seqpacket 100 * protocol rpc/tcp[4][6], rpc/udp[4][6] 101 * wait/nowait single-threaded/multi-threaded 102 * user user to run daemon as 103 * server program full path name 104 * server program arguments maximum of MAXARGS 105 * 106 * Comment lines are indicated by a `#' in column 1. 107 * 108 * #ifdef IPSEC 109 * Comment lines that start with "#@" denote IPsec policy string, as described 110 * in ipsec_set_policy(3). This will affect all the following items in 111 * inetd.conf(8). To reset the policy, just use "#@" line. By default, 112 * there's no IPsec policy. 113 * #endif 114 */ 115#include <sys/param.h> 116#include <sys/ioctl.h> 117#include <sys/wait.h> 118#include <sys/time.h> 119#include <sys/resource.h> 120#include <sys/stat.h> 121#include <sys/un.h> 122 123#include <netinet/in.h> 124#include <netinet/tcp.h> 125#include <arpa/inet.h> 126#include <rpc/rpc.h> 127#include <rpc/pmap_clnt.h> 128 129#include <errno.h> 130#include <err.h> 131#include <fcntl.h> 132#include <grp.h> 133#include <netdb.h> 134#include <pwd.h> 135#include <signal.h> 136#include <stdio.h> 137#include <stdlib.h> 138#include <string.h> 139#include <syslog.h> 140#include <tcpd.h> 141#include <unistd.h> 142#include <libutil.h> 143#include <sysexits.h> 144#include <ctype.h> 145 146#include "inetd.h" 147#include "pathnames.h" 148 149#ifdef IPSEC 150#include <netinet6/ipsec.h> 151#ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */ 152#undef IPSEC 153#endif 154#endif 155 156/* wrapper for KAME-special getnameinfo() */ 157#ifndef NI_WITHSCOPEID 158#define NI_WITHSCOPEID 0 159#endif 160 161#ifndef LIBWRAP_ALLOW_FACILITY 162# define LIBWRAP_ALLOW_FACILITY LOG_AUTH 163#endif 164#ifndef LIBWRAP_ALLOW_SEVERITY 165# define LIBWRAP_ALLOW_SEVERITY LOG_INFO 166#endif 167#ifndef LIBWRAP_DENY_FACILITY 168# define LIBWRAP_DENY_FACILITY LOG_AUTH 169#endif 170#ifndef LIBWRAP_DENY_SEVERITY 171# define LIBWRAP_DENY_SEVERITY LOG_WARNING 172#endif 173 174#define ISWRAP(sep) \ 175 ( ((wrap_ex && !(sep)->se_bi) || (wrap_bi && (sep)->se_bi)) \ 176 && (sep->se_family == AF_INET || sep->se_family == AF_INET6) \ 177 && ( ((sep)->se_accept && (sep)->se_socktype == SOCK_STREAM) \ 178 || (sep)->se_socktype == SOCK_DGRAM)) 179 180#ifdef LOGIN_CAP 181#include <login_cap.h> 182 183/* see init.c */ 184#define RESOURCE_RC "daemon" 185 186#endif 187 188#ifndef MAXCHILD 189#define MAXCHILD -1 /* maximum number of this service 190 < 0 = no limit */ 191#endif 192 193#ifndef MAXCPM 194#define MAXCPM -1 /* rate limit invocations from a 195 single remote address, 196 < 0 = no limit */ 197#endif 198 199#ifndef MAXPERIP 200#define MAXPERIP -1 /* maximum number of this service 201 from a single remote address, 202 < 0 = no limit */ 203#endif 204 205#ifndef TOOMANY 206#define TOOMANY 256 /* don't start more than TOOMANY */ 207#endif 208#define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ 209#define RETRYTIME (60*10) /* retry after bind or server fail */ 210#define MAX_MAXCHLD 32767 /* max allowable max children */ 211 212#define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) 213 214void close_sep(struct servtab *); 215void flag_signal(int); 216void flag_config(int); 217void config(void); 218int cpmip(const struct servtab *, int); 219void endconfig(void); 220struct servtab *enter(struct servtab *); 221void freeconfig(struct servtab *); 222struct servtab *getconfigent(void); 223int matchservent(const char *, const char *, const char *); 224char *nextline(FILE *); 225void addchild(struct servtab *, int); 226void flag_reapchild(int); 227void reapchild(void); 228void enable(struct servtab *); 229void disable(struct servtab *); 230void flag_retry(int); 231void retry(void); 232int setconfig(void); 233void setup(struct servtab *); 234#ifdef IPSEC 235void ipsecsetup(struct servtab *); 236#endif 237void unregisterrpc(register struct servtab *sep); 238static struct conninfo *search_conn(struct servtab *sep, int ctrl); 239static int room_conn(struct servtab *sep, struct conninfo *conn); 240static void addchild_conn(struct conninfo *conn, pid_t pid); 241static void reapchild_conn(pid_t pid); 242static void free_conn(struct conninfo *conn); 243static void resize_conn(struct servtab *sep, int maxperip); 244static void free_connlist(struct servtab *sep); 245static void free_proc(struct procinfo *); 246static struct procinfo *search_proc(pid_t pid, int add); 247static int hashval(char *p, int len); 248 249int allow_severity; 250int deny_severity; 251int wrap_ex = 0; 252int wrap_bi = 0; 253int debug = 0; 254int log = 0; 255int maxsock; /* highest-numbered descriptor */ 256fd_set allsock; 257int options; 258int timingout; 259int toomany = TOOMANY; 260int maxchild = MAXCHILD; 261int maxcpm = MAXCPM; 262int maxperip = MAXPERIP; 263struct servent *sp; 264struct rpcent *rpc; 265char *hostname = NULL; 266struct sockaddr_in *bind_sa4; 267int no_v4bind = 1; 268#ifdef INET6 269struct sockaddr_in6 *bind_sa6; 270int no_v6bind = 1; 271#endif 272int signalpipe[2]; 273#ifdef SANITY_CHECK 274int nsock; 275#endif 276uid_t euid; 277gid_t egid; 278mode_t mask; 279 280struct servtab *servtab; 281 282extern struct biltin biltins[]; 283 284const char *CONFIG = _PATH_INETDCONF; 285const char *pid_file = _PATH_INETDPID; 286 287struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf; 288 289static LIST_HEAD(, procinfo) proctable[PERIPSIZE]; 290 291int 292getvalue(const char *arg, int *value, const char *whine) 293{ 294 int tmp; 295 char *p; 296 297 tmp = strtol(arg, &p, 0); 298 if (tmp < 0 || *p) { 299 syslog(LOG_ERR, whine, arg); 300 return 1; /* failure */ 301 } 302 *value = tmp; 303 return 0; /* success */ 304} 305 306int 307main(int argc, char **argv) 308{ 309 struct servtab *sep; 310 struct passwd *pwd; 311 struct group *grp; 312 struct sigaction sa, saalrm, sachld, sahup, sapipe; 313 int tmpint, ch, dofork; 314 pid_t pid; 315 char buf[50]; 316#ifdef LOGIN_CAP 317 login_cap_t *lc = NULL; 318#endif 319 struct request_info req; 320 int denied; 321 char *service = NULL; 322 union { 323 struct sockaddr peer_un; 324 struct sockaddr_in peer_un4; 325 struct sockaddr_in6 peer_un6; 326 struct sockaddr_storage peer_max; 327 } p_un; 328#define peer p_un.peer_un 329#define peer4 p_un.peer_un4 330#define peer6 p_un.peer_un6 331#define peermax p_un.peer_max 332 int i; 333 struct addrinfo hints, *res; 334 const char *servname; 335 int error; 336 struct conninfo *conn; 337 338 openlog("inetd", LOG_PID | LOG_NOWAIT | LOG_PERROR, LOG_DAEMON); 339 340 while ((ch = getopt(argc, argv, "dlwWR:a:c:C:p:s:")) != -1) 341 switch(ch) { 342 case 'd': 343 debug = 1; 344 options |= SO_DEBUG; 345 break; 346 case 'l': 347 log = 1; 348 break; 349 case 'R': 350 getvalue(optarg, &toomany, 351 "-R %s: bad value for service invocation rate"); 352 break; 353 case 'c': 354 getvalue(optarg, &maxchild, 355 "-c %s: bad value for maximum children"); 356 break; 357 case 'C': 358 getvalue(optarg, &maxcpm, 359 "-C %s: bad value for maximum children/minute"); 360 break; 361 case 'a': 362 hostname = optarg; 363 break; 364 case 'p': 365 pid_file = optarg; 366 break; 367 case 's': 368 getvalue(optarg, &maxperip, 369 "-s %s: bad value for maximum children per source address"); 370 break; 371 case 'w': 372 wrap_ex++; 373 break; 374 case 'W': 375 wrap_bi++; 376 break; 377 case '?': 378 default: 379 syslog(LOG_ERR, 380 "usage: inetd [-dlwW] [-a address] [-R rate]" 381 " [-c maximum] [-C rate]" 382 " [-p pidfile] [conf-file]"); 383 exit(EX_USAGE); 384 } 385 /* 386 * Initialize Bind Addrs. 387 * When hostname is NULL, wild card bind addrs are obtained from 388 * getaddrinfo(). But getaddrinfo() requires at least one of 389 * hostname or servname is non NULL. 390 * So when hostname is NULL, set dummy value to servname. 391 */ 392 servname = (hostname == NULL) ? "discard" /* dummy */ : NULL; 393 394 bzero(&hints, sizeof(struct addrinfo)); 395 hints.ai_flags = AI_PASSIVE; 396 hints.ai_family = AF_UNSPEC; 397 error = getaddrinfo(hostname, servname, &hints, &res); 398 if (error != 0) { 399 syslog(LOG_ERR, "-a %s: %s", hostname, gai_strerror(error)); 400 if (error == EAI_SYSTEM) 401 syslog(LOG_ERR, "%s", strerror(errno)); 402 exit(EX_USAGE); 403 } 404 do { 405 if (res->ai_addr == NULL) { 406 syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname); 407 exit(EX_USAGE); 408 } 409 switch (res->ai_addr->sa_family) { 410 case AF_INET: 411 if (no_v4bind == 0) 412 continue; 413 bind_sa4 = (struct sockaddr_in *)res->ai_addr; 414 /* init port num in case servname is dummy */ 415 bind_sa4->sin_port = 0; 416 no_v4bind = 0; 417 continue; 418#ifdef INET6 419 case AF_INET6: 420 if (no_v6bind == 0) 421 continue; 422 bind_sa6 = (struct sockaddr_in6 *)res->ai_addr; 423 /* init port num in case servname is dummy */ 424 bind_sa6->sin6_port = 0; 425 no_v6bind = 0; 426 continue; 427#endif 428 } 429 if (no_v4bind == 0 430#ifdef INET6 431 && no_v6bind == 0 432#endif 433 ) 434 break; 435 } while ((res = res->ai_next) != NULL); 436 if (no_v4bind != 0 437#ifdef INET6 438 && no_v6bind != 0 439#endif 440 ) { 441 syslog(LOG_ERR, "-a %s: unknown address family", hostname); 442 exit(EX_USAGE); 443 } 444 445 euid = geteuid(); 446 egid = getegid(); 447 umask(mask = umask(0777)); 448 449 argc -= optind; 450 argv += optind; 451 452 if (argc > 0) 453 CONFIG = argv[0]; 454 if (debug == 0) { 455 FILE *fp; 456 if (daemon(0, 0) < 0) { 457 syslog(LOG_WARNING, "daemon(0,0) failed: %m"); 458 } 459 /* From now on we don't want syslog messages going to stderr. */ 460 closelog(); 461 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); 462 /* 463 * In case somebody has started inetd manually, we need to 464 * clear the logname, so that old servers run as root do not 465 * get the user's logname.. 466 */ 467 if (setlogin("") < 0) { 468 syslog(LOG_WARNING, "cannot clear logname: %m"); 469 /* no big deal if it fails.. */ 470 } 471 pid = getpid(); 472 fp = fopen(pid_file, "w"); 473 if (fp) { 474 fprintf(fp, "%ld\n", (long)pid); 475 fclose(fp); 476 } else { 477 syslog(LOG_WARNING, "%s: %m", pid_file); 478 } 479 } 480 481 for (i = 0; i < PERIPSIZE; ++i) 482 LIST_INIT(&proctable[i]); 483 484 if (!no_v4bind) { 485 udpconf = getnetconfigent("udp"); 486 tcpconf = getnetconfigent("tcp"); 487 if (udpconf == NULL || tcpconf == NULL) { 488 syslog(LOG_ERR, "unknown rpc/udp or rpc/tcp"); 489 exit(EX_USAGE); 490 } 491 } 492#ifdef INET6 493 if (!no_v6bind) { 494 udp6conf = getnetconfigent("udp6"); 495 tcp6conf = getnetconfigent("tcp6"); 496 if (udp6conf == NULL || tcp6conf == NULL) { 497 syslog(LOG_ERR, "unknown rpc/udp6 or rpc/tcp6"); 498 exit(EX_USAGE); 499 } 500 } 501#endif 502 503 sa.sa_flags = 0; 504 sigemptyset(&sa.sa_mask); 505 sigaddset(&sa.sa_mask, SIGALRM); 506 sigaddset(&sa.sa_mask, SIGCHLD); 507 sigaddset(&sa.sa_mask, SIGHUP); 508 sa.sa_handler = flag_retry; 509 sigaction(SIGALRM, &sa, &saalrm); 510 config(); 511 sa.sa_handler = flag_config; 512 sigaction(SIGHUP, &sa, &sahup); 513 sa.sa_handler = flag_reapchild; 514 sigaction(SIGCHLD, &sa, &sachld); 515 sa.sa_handler = SIG_IGN; 516 sigaction(SIGPIPE, &sa, &sapipe); 517 518 { 519 /* space for daemons to overwrite environment for ps */ 520#define DUMMYSIZE 100 521 char dummy[DUMMYSIZE]; 522 523 (void)memset(dummy, 'x', DUMMYSIZE - 1); 524 dummy[DUMMYSIZE - 1] = '\0'; 525 (void)setenv("inetd_dummy", dummy, 1); 526 } 527 528 if (pipe(signalpipe) != 0) { 529 syslog(LOG_ERR, "pipe: %m"); 530 exit(EX_OSERR); 531 } 532 FD_SET(signalpipe[0], &allsock); 533#ifdef SANITY_CHECK 534 nsock++; 535#endif 536 if (signalpipe[0] > maxsock) 537 maxsock = signalpipe[0]; 538 if (signalpipe[1] > maxsock) 539 maxsock = signalpipe[1]; 540 541 for (;;) { 542 int n, ctrl; 543 fd_set readable; 544 545#ifdef SANITY_CHECK 546 if (nsock == 0) { 547 syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__); 548 exit(EX_SOFTWARE); 549 } 550#endif 551 readable = allsock; 552 if ((n = select(maxsock + 1, &readable, (fd_set *)0, 553 (fd_set *)0, (struct timeval *)0)) <= 0) { 554 if (n < 0 && errno != EINTR) { 555 syslog(LOG_WARNING, "select: %m"); 556 sleep(1); 557 } 558 continue; 559 } 560 /* handle any queued signal flags */ 561 if (FD_ISSET(signalpipe[0], &readable)) { 562 int nsig; 563 if (ioctl(signalpipe[0], FIONREAD, &nsig) != 0) { 564 syslog(LOG_ERR, "ioctl: %m"); 565 exit(EX_OSERR); 566 } 567 while (--nsig >= 0) { 568 char c; 569 if (read(signalpipe[0], &c, 1) != 1) { 570 syslog(LOG_ERR, "read: %m"); 571 exit(EX_OSERR); 572 } 573 if (debug) 574 warnx("handling signal flag %c", c); 575 switch(c) { 576 case 'A': /* sigalrm */ 577 retry(); 578 break; 579 case 'C': /* sigchld */ 580 reapchild(); 581 break; 582 case 'H': /* sighup */ 583 config(); 584 break; 585 } 586 } 587 } 588 for (sep = servtab; n && sep; sep = sep->se_next) 589 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) { 590 n--; 591 if (debug) 592 warnx("someone wants %s", sep->se_service); 593 dofork = !sep->se_bi || sep->se_bi->bi_fork || ISWRAP(sep); 594 conn = NULL; 595 if (sep->se_accept && sep->se_socktype == SOCK_STREAM) { 596 i = 1; 597 if (ioctl(sep->se_fd, FIONBIO, &i) < 0) 598 syslog(LOG_ERR, "ioctl (FIONBIO, 1): %m"); 599 ctrl = accept(sep->se_fd, (struct sockaddr *)0, 600 (socklen_t *)0); 601 if (debug) 602 warnx("accept, ctrl %d", ctrl); 603 if (ctrl < 0) { 604 if (errno != EINTR) 605 syslog(LOG_WARNING, 606 "accept (for %s): %m", 607 sep->se_service); 608 if (sep->se_accept && 609 sep->se_socktype == SOCK_STREAM) 610 close(ctrl); 611 continue; 612 } 613 i = 0; 614 if (ioctl(sep->se_fd, FIONBIO, &i) < 0) 615 syslog(LOG_ERR, "ioctl1(FIONBIO, 0): %m"); 616 if (ioctl(ctrl, FIONBIO, &i) < 0) 617 syslog(LOG_ERR, "ioctl2(FIONBIO, 0): %m"); 618 if (cpmip(sep, ctrl) < 0) { 619 close(ctrl); 620 continue; 621 } 622 if (dofork && 623 (conn = search_conn(sep, ctrl)) != NULL && 624 !room_conn(sep, conn)) { 625 close(ctrl); 626 continue; 627 } 628 } else 629 ctrl = sep->se_fd; 630 if (log && !ISWRAP(sep)) { 631 char pname[INET6_ADDRSTRLEN] = "unknown"; 632 socklen_t sl; 633 sl = sizeof peermax; 634 if (getpeername(ctrl, (struct sockaddr *) 635 &peermax, &sl)) { 636 sl = sizeof peermax; 637 if (recvfrom(ctrl, buf, sizeof(buf), 638 MSG_PEEK, 639 (struct sockaddr *)&peermax, 640 &sl) >= 0) { 641 getnameinfo((struct sockaddr *)&peermax, 642 peer.sa_len, 643 pname, sizeof(pname), 644 NULL, 0, 645 NI_NUMERICHOST| 646 NI_WITHSCOPEID); 647 } 648 } else { 649 getnameinfo((struct sockaddr *)&peermax, 650 peer.sa_len, 651 pname, sizeof(pname), 652 NULL, 0, 653 NI_NUMERICHOST| 654 NI_WITHSCOPEID); 655 } 656 syslog(LOG_INFO,"%s from %s", sep->se_service, pname); 657 } 658 (void) sigblock(SIGBLOCK); 659 pid = 0; 660 /* 661 * Fork for all external services, builtins which need to 662 * fork and anything we're wrapping (as wrapping might 663 * block or use hosts_options(5) twist). 664 */ 665 if (dofork) { 666 if (sep->se_count++ == 0) 667 (void)gettimeofday(&sep->se_time, (struct timezone *)NULL); 668 else if (toomany > 0 && sep->se_count >= toomany) { 669 struct timeval now; 670 671 (void)gettimeofday(&now, (struct timezone *)NULL); 672 if (now.tv_sec - sep->se_time.tv_sec > 673 CNT_INTVL) { 674 sep->se_time = now; 675 sep->se_count = 1; 676 } else { 677 syslog(LOG_ERR, 678 "%s/%s server failing (looping), service terminated", 679 sep->se_service, sep->se_proto); 680 if (sep->se_accept && 681 sep->se_socktype == SOCK_STREAM) 682 close(ctrl); 683 close_sep(sep); 684 free_conn(conn); 685 sigsetmask(0L); 686 if (!timingout) { 687 timingout = 1; 688 alarm(RETRYTIME); 689 } 690 continue; 691 } 692 } 693 pid = fork(); 694 } 695 if (pid < 0) { 696 syslog(LOG_ERR, "fork: %m"); 697 if (sep->se_accept && 698 sep->se_socktype == SOCK_STREAM) 699 close(ctrl); 700 free_conn(conn); 701 sigsetmask(0L); 702 sleep(1); 703 continue; 704 } 705 if (pid) { 706 addchild_conn(conn, pid); 707 addchild(sep, pid); 708 } 709 sigsetmask(0L); 710 if (pid == 0) { 711 if (dofork) { 712 if (debug) 713 warnx("+ closing from %d", maxsock); 714 for (tmpint = maxsock; tmpint > 2; tmpint--) 715 if (tmpint != ctrl) 716 (void) close(tmpint); 717 sigaction(SIGALRM, &saalrm, (struct sigaction *)0); 718 sigaction(SIGCHLD, &sachld, (struct sigaction *)0); 719 sigaction(SIGHUP, &sahup, (struct sigaction *)0); 720 /* SIGPIPE reset before exec */ 721 } 722 /* 723 * Call tcpmux to find the real service to exec. 724 */ 725 if (sep->se_bi && 726 sep->se_bi->bi_fn == (bi_fn_t *) tcpmux) { 727 sep = tcpmux(ctrl); 728 if (sep == NULL) { 729 close(ctrl); 730 _exit(0); 731 } 732 } 733 if (ISWRAP(sep)) { 734 inetd_setproctitle("wrapping", ctrl); 735 service = sep->se_server_name ? 736 sep->se_server_name : sep->se_service; 737 request_init(&req, RQ_DAEMON, service, RQ_FILE, ctrl, NULL); 738 fromhost(&req); 739 deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY; 740 allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY; 741 denied = !hosts_access(&req); 742 if (denied) { 743 syslog(deny_severity, 744 "refused connection from %.500s, service %s (%s%s)", 745 eval_client(&req), service, sep->se_proto, 746 (((struct sockaddr *)req.client->sin)->sa_family == AF_INET6 && !IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)req.client->sin)->sin6_addr)) ? "6" : ""); 747 if (sep->se_socktype != SOCK_STREAM) 748 recv(ctrl, buf, sizeof (buf), 0); 749 if (dofork) { 750 sleep(1); 751 _exit(0); 752 } 753 } 754 if (log) { 755 syslog(allow_severity, 756 "connection from %.500s, service %s (%s%s)", 757 eval_client(&req), service, sep->se_proto, 758 (((struct sockaddr *)req.client->sin)->sa_family == AF_INET6 && !IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)req.client->sin)->sin6_addr)) ? "6" : ""); 759 } 760 } 761 if (sep->se_bi) { 762 (*sep->se_bi->bi_fn)(ctrl, sep); 763 } else { 764 if (debug) 765 warnx("%d execl %s", 766 getpid(), sep->se_server); 767 dup2(ctrl, 0); 768 close(ctrl); 769 dup2(0, 1); 770 dup2(0, 2); 771 if ((pwd = getpwnam(sep->se_user)) == NULL) { 772 syslog(LOG_ERR, 773 "%s/%s: %s: no such user", 774 sep->se_service, sep->se_proto, 775 sep->se_user); 776 if (sep->se_socktype != SOCK_STREAM) 777 recv(0, buf, sizeof (buf), 0); 778 _exit(EX_NOUSER); 779 } 780 grp = NULL; 781 if ( sep->se_group != NULL 782 && (grp = getgrnam(sep->se_group)) == NULL 783 ) { 784 syslog(LOG_ERR, 785 "%s/%s: %s: no such group", 786 sep->se_service, sep->se_proto, 787 sep->se_group); 788 if (sep->se_socktype != SOCK_STREAM) 789 recv(0, buf, sizeof (buf), 0); 790 _exit(EX_NOUSER); 791 } 792 if (grp != NULL) 793 pwd->pw_gid = grp->gr_gid; 794#ifdef LOGIN_CAP 795 if ((lc = login_getclass(sep->se_class)) == NULL) { 796 /* error syslogged by getclass */ 797 syslog(LOG_ERR, 798 "%s/%s: %s: login class error", 799 sep->se_service, sep->se_proto, 800 sep->se_class); 801 if (sep->se_socktype != SOCK_STREAM) 802 recv(0, buf, sizeof (buf), 0); 803 _exit(EX_NOUSER); 804 } 805#endif 806 if (setsid() < 0) { 807 syslog(LOG_ERR, 808 "%s: can't setsid(): %m", 809 sep->se_service); 810 /* _exit(EX_OSERR); not fatal yet */ 811 } 812#ifdef LOGIN_CAP 813 if (setusercontext(lc, pwd, pwd->pw_uid, 814 LOGIN_SETALL) != 0) { 815 syslog(LOG_ERR, 816 "%s: can't setusercontext(..%s..): %m", 817 sep->se_service, sep->se_user); 818 _exit(EX_OSERR); 819 } 820#else 821 if (pwd->pw_uid) { 822 if (setlogin(sep->se_user) < 0) { 823 syslog(LOG_ERR, 824 "%s: can't setlogin(%s): %m", 825 sep->se_service, sep->se_user); 826 /* _exit(EX_OSERR); not yet */ 827 } 828 if (setgid(pwd->pw_gid) < 0) { 829 syslog(LOG_ERR, 830 "%s: can't set gid %d: %m", 831 sep->se_service, pwd->pw_gid); 832 _exit(EX_OSERR); 833 } 834 (void) initgroups(pwd->pw_name, 835 pwd->pw_gid); 836 if (setuid(pwd->pw_uid) < 0) { 837 syslog(LOG_ERR, 838 "%s: can't set uid %d: %m", 839 sep->se_service, pwd->pw_uid); 840 _exit(EX_OSERR); 841 } 842 } 843#endif 844 sigaction(SIGPIPE, &sapipe, 845 (struct sigaction *)0); 846 execv(sep->se_server, sep->se_argv); 847 syslog(LOG_ERR, 848 "cannot execute %s: %m", sep->se_server); 849 if (sep->se_socktype != SOCK_STREAM) 850 recv(0, buf, sizeof (buf), 0); 851 } 852 if (dofork) 853 _exit(0); 854 } 855 if (sep->se_accept && sep->se_socktype == SOCK_STREAM) 856 close(ctrl); 857 } 858 } 859} 860 861/* 862 * Add a signal flag to the signal flag queue for later handling 863 */ 864 865void 866flag_signal(int c) 867{ 868 char ch = c; 869 870 if (write(signalpipe[1], &ch, 1) != 1) { 871 syslog(LOG_ERR, "write: %m"); 872 _exit(EX_OSERR); 873 } 874} 875 876/* 877 * Record a new child pid for this service. If we've reached the 878 * limit on children, then stop accepting incoming requests. 879 */ 880 881void 882addchild(struct servtab *sep, pid_t pid) 883{ 884 if (sep->se_maxchild <= 0) 885 return; 886#ifdef SANITY_CHECK 887 if (sep->se_numchild >= sep->se_maxchild) { 888 syslog(LOG_ERR, "%s: %d >= %d", 889 __FUNCTION__, sep->se_numchild, sep->se_maxchild); 890 exit(EX_SOFTWARE); 891 } 892#endif 893 sep->se_pids[sep->se_numchild++] = pid; 894 if (sep->se_numchild == sep->se_maxchild) 895 disable(sep); 896} 897 898/* 899 * Some child process has exited. See if it's on somebody's list. 900 */ 901 902void 903flag_reapchild(int signo __unused) 904{ 905 flag_signal('C'); 906} 907 908void 909reapchild(void) 910{ 911 int k, status; 912 pid_t pid; 913 struct servtab *sep; 914 915 for (;;) { 916 pid = wait3(&status, WNOHANG, (struct rusage *)0); 917 if (pid <= 0) 918 break; 919 if (debug) 920 warnx("%d reaped, status %#x", pid, status); 921 for (sep = servtab; sep; sep = sep->se_next) { 922 for (k = 0; k < sep->se_numchild; k++) 923 if (sep->se_pids[k] == pid) 924 break; 925 if (k == sep->se_numchild) 926 continue; 927 if (sep->se_numchild == sep->se_maxchild) 928 enable(sep); 929 sep->se_pids[k] = sep->se_pids[--sep->se_numchild]; 930 if (status) 931 syslog(LOG_WARNING, 932 "%s[%d]: exit status 0x%x", 933 sep->se_server, pid, status); 934 break; 935 } 936 reapchild_conn(pid); 937 } 938} 939 940void 941flag_config(int signo __unused) 942{ 943 flag_signal('H'); 944} 945 946void 947config(void) 948{ 949 struct servtab *sep, *new, **sepp; 950 long omask; 951 int new_nomapped; 952 953 if (!setconfig()) { 954 syslog(LOG_ERR, "%s: %m", CONFIG); 955 return; 956 } 957 for (sep = servtab; sep; sep = sep->se_next) 958 sep->se_checked = 0; 959 while ((new = getconfigent())) { 960 if (getpwnam(new->se_user) == NULL) { 961 syslog(LOG_ERR, 962 "%s/%s: no such user '%s', service ignored", 963 new->se_service, new->se_proto, new->se_user); 964 continue; 965 } 966 if (new->se_group && getgrnam(new->se_group) == NULL) { 967 syslog(LOG_ERR, 968 "%s/%s: no such group '%s', service ignored", 969 new->se_service, new->se_proto, new->se_group); 970 continue; 971 } 972#ifdef LOGIN_CAP 973 if (login_getclass(new->se_class) == NULL) { 974 /* error syslogged by getclass */ 975 syslog(LOG_ERR, 976 "%s/%s: %s: login class error, service ignored", 977 new->se_service, new->se_proto, new->se_class); 978 continue; 979 } 980#endif 981 new_nomapped = new->se_nomapped; 982 for (sep = servtab; sep; sep = sep->se_next) 983 if (strcmp(sep->se_service, new->se_service) == 0 && 984 strcmp(sep->se_proto, new->se_proto) == 0 && 985 sep->se_rpc == new->se_rpc && 986 sep->se_socktype == new->se_socktype && 987 sep->se_family == new->se_family) 988 break; 989 if (sep != 0) { 990 int i; 991 992#define SWAP(t,a, b) { t c = a; a = b; b = c; } 993 omask = sigblock(SIGBLOCK); 994 if (sep->se_nomapped != new->se_nomapped) { 995 /* for rpc keep old nommaped till unregister */ 996 if (!sep->se_rpc) 997 sep->se_nomapped = new->se_nomapped; 998 sep->se_reset = 1; 999 } 1000 /* copy over outstanding child pids */ 1001 if (sep->se_maxchild > 0 && new->se_maxchild > 0) { 1002 new->se_numchild = sep->se_numchild; 1003 if (new->se_numchild > new->se_maxchild) 1004 new->se_numchild = new->se_maxchild; 1005 memcpy(new->se_pids, sep->se_pids, 1006 new->se_numchild * sizeof(*new->se_pids)); 1007 } 1008 SWAP(pid_t *, sep->se_pids, new->se_pids); 1009 sep->se_maxchild = new->se_maxchild; 1010 sep->se_numchild = new->se_numchild; 1011 sep->se_maxcpm = new->se_maxcpm; 1012 resize_conn(sep, new->se_maxperip); 1013 sep->se_maxperip = new->se_maxperip; 1014 sep->se_bi = new->se_bi; 1015 /* might need to turn on or off service now */ 1016 if (sep->se_fd >= 0) { 1017 if (sep->se_maxchild > 0 1018 && sep->se_numchild == sep->se_maxchild) { 1019 if (FD_ISSET(sep->se_fd, &allsock)) 1020 disable(sep); 1021 } else { 1022 if (!FD_ISSET(sep->se_fd, &allsock)) 1023 enable(sep); 1024 } 1025 } 1026 sep->se_accept = new->se_accept; 1027 SWAP(char *, sep->se_user, new->se_user); 1028 SWAP(char *, sep->se_group, new->se_group); 1029#ifdef LOGIN_CAP 1030 SWAP(char *, sep->se_class, new->se_class); 1031#endif 1032 SWAP(char *, sep->se_server, new->se_server); 1033 SWAP(char *, sep->se_server_name, new->se_server_name); 1034 for (i = 0; i < MAXARGV; i++) 1035 SWAP(char *, sep->se_argv[i], new->se_argv[i]); 1036#ifdef IPSEC 1037 SWAP(char *, sep->se_policy, new->se_policy); 1038 ipsecsetup(sep); 1039#endif 1040 sigsetmask(omask); 1041 freeconfig(new); 1042 if (debug) 1043 print_service("REDO", sep); 1044 } else { 1045 sep = enter(new); 1046 if (debug) 1047 print_service("ADD ", sep); 1048 } 1049 sep->se_checked = 1; 1050 if (ISMUX(sep)) { 1051 sep->se_fd = -1; 1052 continue; 1053 } 1054 switch (sep->se_family) { 1055 case AF_INET: 1056 if (no_v4bind != 0) { 1057 sep->se_fd = -1; 1058 continue; 1059 } 1060 break; 1061#ifdef INET6 1062 case AF_INET6: 1063 if (no_v6bind != 0) { 1064 sep->se_fd = -1; 1065 continue; 1066 } 1067 break; 1068#endif 1069 } 1070 if (!sep->se_rpc) { 1071 if (sep->se_family != AF_UNIX) { 1072 sp = getservbyname(sep->se_service, sep->se_proto); 1073 if (sp == 0) { 1074 syslog(LOG_ERR, "%s/%s: unknown service", 1075 sep->se_service, sep->se_proto); 1076 sep->se_checked = 0; 1077 continue; 1078 } 1079 } 1080 switch (sep->se_family) { 1081 case AF_INET: 1082 if (sp->s_port != sep->se_ctrladdr4.sin_port) { 1083 sep->se_ctrladdr4.sin_port = 1084 sp->s_port; 1085 sep->se_reset = 1; 1086 } 1087 break; 1088#ifdef INET6 1089 case AF_INET6: 1090 if (sp->s_port != 1091 sep->se_ctrladdr6.sin6_port) { 1092 sep->se_ctrladdr6.sin6_port = 1093 sp->s_port; 1094 sep->se_reset = 1; 1095 } 1096 break; 1097#endif 1098 } 1099 if (sep->se_reset != 0 && sep->se_fd >= 0) 1100 close_sep(sep); 1101 } else { 1102 rpc = getrpcbyname(sep->se_service); 1103 if (rpc == 0) { 1104 syslog(LOG_ERR, "%s/%s unknown RPC service", 1105 sep->se_service, sep->se_proto); 1106 if (sep->se_fd != -1) 1107 (void) close(sep->se_fd); 1108 sep->se_fd = -1; 1109 continue; 1110 } 1111 if (sep->se_reset != 0 || 1112 rpc->r_number != sep->se_rpc_prog) { 1113 if (sep->se_rpc_prog) 1114 unregisterrpc(sep); 1115 sep->se_rpc_prog = rpc->r_number; 1116 if (sep->se_fd != -1) 1117 (void) close(sep->se_fd); 1118 sep->se_fd = -1; 1119 } 1120 sep->se_nomapped = new_nomapped; 1121 } 1122 sep->se_reset = 0; 1123 if (sep->se_fd == -1) 1124 setup(sep); 1125 } 1126 endconfig(); 1127 /* 1128 * Purge anything not looked at above. 1129 */ 1130 omask = sigblock(SIGBLOCK); 1131 sepp = &servtab; 1132 while ((sep = *sepp)) { 1133 if (sep->se_checked) { 1134 sepp = &sep->se_next; 1135 continue; 1136 } 1137 *sepp = sep->se_next; 1138 if (sep->se_fd >= 0) 1139 close_sep(sep); 1140 if (debug) 1141 print_service("FREE", sep); 1142 if (sep->se_rpc && sep->se_rpc_prog > 0) 1143 unregisterrpc(sep); 1144 freeconfig(sep); 1145 free(sep); 1146 } 1147 (void) sigsetmask(omask); 1148} 1149 1150void 1151unregisterrpc(struct servtab *sep) 1152{ 1153 u_int i; 1154 struct servtab *sepp; 1155 long omask; 1156 struct netconfig *netid4, *netid6; 1157 1158 omask = sigblock(SIGBLOCK); 1159 netid4 = sep->se_socktype == SOCK_DGRAM ? udpconf : tcpconf; 1160 netid6 = sep->se_socktype == SOCK_DGRAM ? udp6conf : tcp6conf; 1161 if (sep->se_family == AF_INET) 1162 netid6 = NULL; 1163 else if (sep->se_nomapped) 1164 netid4 = NULL; 1165 /* 1166 * Conflict if same prog and protocol - In that case one should look 1167 * to versions, but it is not interesting: having separate servers for 1168 * different versions does not work well. 1169 * Therefore one do not unregister if there is a conflict. 1170 * There is also transport conflict if destroying INET when INET46 1171 * exists, or destroying INET46 when INET exists 1172 */ 1173 for (sepp = servtab; sepp; sepp = sepp->se_next) { 1174 if (sepp == sep) 1175 continue; 1176 if (sepp->se_checked == 0 || 1177 !sepp->se_rpc || 1178 strcmp(sep->se_proto, sepp->se_proto) != 0 || 1179 sep->se_rpc_prog != sepp->se_rpc_prog) 1180 continue; 1181 if (sepp->se_family == AF_INET) 1182 netid4 = NULL; 1183 if (sepp->se_family == AF_INET6) { 1184 netid6 = NULL; 1185 if (!sep->se_nomapped) 1186 netid4 = NULL; 1187 } 1188 if (netid4 == NULL && netid6 == NULL) 1189 return; 1190 } 1191 if (debug) 1192 print_service("UNREG", sep); 1193 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) { 1194 if (netid4) 1195 rpcb_unset(sep->se_rpc_prog, i, netid4); 1196 if (netid6) 1197 rpcb_unset(sep->se_rpc_prog, i, netid6); 1198 } 1199 if (sep->se_fd != -1) 1200 (void) close(sep->se_fd); 1201 sep->se_fd = -1; 1202 (void) sigsetmask(omask); 1203} 1204 1205void 1206flag_retry(int signo __unused) 1207{ 1208 flag_signal('A'); 1209} 1210 1211void 1212retry(void) 1213{ 1214 struct servtab *sep; 1215 1216 timingout = 0; 1217 for (sep = servtab; sep; sep = sep->se_next) 1218 if (sep->se_fd == -1 && !ISMUX(sep)) 1219 setup(sep); 1220} 1221 1222void 1223setup(struct servtab *sep) 1224{ 1225 int on = 1; 1226 1227 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 1228 if (debug) 1229 warn("socket failed on %s/%s", 1230 sep->se_service, sep->se_proto); 1231 syslog(LOG_ERR, "%s/%s: socket: %m", 1232 sep->se_service, sep->se_proto); 1233 return; 1234 } 1235#define turnon(fd, opt) \ 1236setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) 1237 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 1238 turnon(sep->se_fd, SO_DEBUG) < 0) 1239 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 1240 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 1241 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 1242#ifdef SO_PRIVSTATE 1243 if (turnon(sep->se_fd, SO_PRIVSTATE) < 0) 1244 syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m"); 1245#endif 1246 /* tftpd opens a new connection then needs more infos */ 1247 if ((sep->se_family == AF_INET6) && 1248 (strcmp(sep->se_proto, "udp") == 0) && 1249 (sep->se_accept == 0) && 1250 (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_PKTINFO, 1251 (char *)&on, sizeof (on)) < 0)) 1252 syslog(LOG_ERR, "setsockopt (IPV6_RECVPKTINFO): %m"); 1253 if (sep->se_family == AF_INET6) { 1254 int flag = sep->se_nomapped ? 1 : 0; 1255 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_V6ONLY, 1256 (char *)&flag, sizeof (flag)) < 0) 1257 syslog(LOG_ERR, "setsockopt (IPV6_V6ONLY): %m"); 1258 } 1259#undef turnon 1260 if (sep->se_type == TTCP_TYPE) 1261 if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH, 1262 (char *)&on, sizeof (on)) < 0) 1263 syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m"); 1264#ifdef IPV6_FAITH 1265 if (sep->se_type == FAITH_TYPE) { 1266 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, &on, 1267 sizeof(on)) < 0) { 1268 syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m"); 1269 } 1270 } 1271#endif 1272#ifdef IPSEC 1273 ipsecsetup(sep); 1274#endif 1275 if (sep->se_family == AF_UNIX) { 1276 (void) unlink(sep->se_ctrladdr_un.sun_path); 1277 umask(0777); /* Make socket with conservative permissions */ 1278 } 1279 if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr, 1280 sep->se_ctrladdr_size) < 0) { 1281 if (debug) 1282 warn("bind failed on %s/%s", 1283 sep->se_service, sep->se_proto); 1284 syslog(LOG_ERR, "%s/%s: bind: %m", 1285 sep->se_service, sep->se_proto); 1286 (void) close(sep->se_fd); 1287 sep->se_fd = -1; 1288 if (!timingout) { 1289 timingout = 1; 1290 alarm(RETRYTIME); 1291 } 1292 if (sep->se_family == AF_UNIX) 1293 umask(mask); 1294 return; 1295 } 1296 if (sep->se_family == AF_UNIX) { 1297 /* Ick - fch{own,mod} don't work on Unix domain sockets */ 1298 if (chown(sep->se_service, sep->se_sockuid, sep->se_sockgid) < 0) 1299 syslog(LOG_ERR, "chown socket: %m"); 1300 if (chmod(sep->se_service, sep->se_sockmode) < 0) 1301 syslog(LOG_ERR, "chmod socket: %m"); 1302 umask(mask); 1303 } 1304 if (sep->se_rpc) { 1305 u_int i; 1306 socklen_t len = sep->se_ctrladdr_size; 1307 struct netconfig *netid, *netid2 = NULL; 1308 struct sockaddr_in sock; 1309 struct netbuf nbuf, nbuf2; 1310 1311 if (getsockname(sep->se_fd, 1312 (struct sockaddr*)&sep->se_ctrladdr, &len) < 0){ 1313 syslog(LOG_ERR, "%s/%s: getsockname: %m", 1314 sep->se_service, sep->se_proto); 1315 (void) close(sep->se_fd); 1316 sep->se_fd = -1; 1317 return; 1318 } 1319 nbuf.buf = &sep->se_ctrladdr; 1320 nbuf.len = sep->se_ctrladdr.sa_len; 1321 if (sep->se_family == AF_INET) 1322 netid = sep->se_socktype==SOCK_DGRAM? udpconf:tcpconf; 1323 else { 1324 netid = sep->se_socktype==SOCK_DGRAM? udp6conf:tcp6conf; 1325 if (!sep->se_nomapped) { /* INET and INET6 */ 1326 netid2 = netid==udp6conf? udpconf:tcpconf; 1327 memset(&sock, 0, sizeof sock); /* ADDR_ANY */ 1328 nbuf2.buf = &sock; 1329 nbuf2.len = sock.sin_len = sizeof sock; 1330 sock.sin_family = AF_INET; 1331 sock.sin_port = sep->se_ctrladdr6.sin6_port; 1332 } 1333 } 1334 if (debug) 1335 print_service("REG ", sep); 1336 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) { 1337 rpcb_unset(sep->se_rpc_prog, i, netid); 1338 rpcb_set(sep->se_rpc_prog, i, netid, &nbuf); 1339 if (netid2) { 1340 rpcb_unset(sep->se_rpc_prog, i, netid2); 1341 rpcb_set(sep->se_rpc_prog, i, netid2, &nbuf2); 1342 } 1343 } 1344 } 1345 if (sep->se_socktype == SOCK_STREAM) 1346 listen(sep->se_fd, 64); 1347 enable(sep); 1348 if (debug) { 1349 warnx("registered %s on %d", 1350 sep->se_server, sep->se_fd); 1351 } 1352} 1353 1354#ifdef IPSEC 1355void 1356ipsecsetup(sep) 1357 struct servtab *sep; 1358{ 1359 char *buf; 1360 char *policy_in = NULL; 1361 char *policy_out = NULL; 1362 int level; 1363 int opt; 1364 1365 switch (sep->se_family) { 1366 case AF_INET: 1367 level = IPPROTO_IP; 1368 opt = IP_IPSEC_POLICY; 1369 break; 1370#ifdef INET6 1371 case AF_INET6: 1372 level = IPPROTO_IPV6; 1373 opt = IPV6_IPSEC_POLICY; 1374 break; 1375#endif 1376 default: 1377 return; 1378 } 1379 1380 if (!sep->se_policy || sep->se_policy[0] == '\0') { 1381 static char def_in[] = "in entrust", def_out[] = "out entrust"; 1382 policy_in = def_in; 1383 policy_out = def_out; 1384 } else { 1385 if (!strncmp("in", sep->se_policy, 2)) 1386 policy_in = sep->se_policy; 1387 else if (!strncmp("out", sep->se_policy, 3)) 1388 policy_out = sep->se_policy; 1389 else { 1390 syslog(LOG_ERR, "invalid security policy \"%s\"", 1391 sep->se_policy); 1392 return; 1393 } 1394 } 1395 1396 if (policy_in != NULL) { 1397 buf = ipsec_set_policy(policy_in, strlen(policy_in)); 1398 if (buf != NULL) { 1399 if (setsockopt(sep->se_fd, level, opt, 1400 buf, ipsec_get_policylen(buf)) < 0 && 1401 debug != 0) 1402 warnx("%s/%s: ipsec initialization failed; %s", 1403 sep->se_service, sep->se_proto, 1404 policy_in); 1405 free(buf); 1406 } else 1407 syslog(LOG_ERR, "invalid security policy \"%s\"", 1408 policy_in); 1409 } 1410 if (policy_out != NULL) { 1411 buf = ipsec_set_policy(policy_out, strlen(policy_out)); 1412 if (buf != NULL) { 1413 if (setsockopt(sep->se_fd, level, opt, 1414 buf, ipsec_get_policylen(buf)) < 0 && 1415 debug != 0) 1416 warnx("%s/%s: ipsec initialization failed; %s", 1417 sep->se_service, sep->se_proto, 1418 policy_out); 1419 free(buf); 1420 } else 1421 syslog(LOG_ERR, "invalid security policy \"%s\"", 1422 policy_out); 1423 } 1424} 1425#endif 1426 1427/* 1428 * Finish with a service and its socket. 1429 */ 1430void 1431close_sep(struct servtab *sep) 1432{ 1433 if (sep->se_fd >= 0) { 1434 if (FD_ISSET(sep->se_fd, &allsock)) 1435 disable(sep); 1436 (void) close(sep->se_fd); 1437 sep->se_fd = -1; 1438 } 1439 sep->se_count = 0; 1440 sep->se_numchild = 0; /* forget about any existing children */ 1441} 1442 1443int 1444matchservent(const char *name1, const char *name2, const char *proto) 1445{ 1446 char **alias, *p; 1447 struct servent *se; 1448 1449 if (strcmp(proto, "unix") == 0) { 1450 if ((p = strrchr(name1, '/')) != NULL) 1451 name1 = p + 1; 1452 if ((p = strrchr(name2, '/')) != NULL) 1453 name2 = p + 1; 1454 } 1455 if (strcmp(name1, name2) == 0) 1456 return(1); 1457 if ((se = getservbyname(name1, proto)) != NULL) { 1458 if (strcmp(name2, se->s_name) == 0) 1459 return(1); 1460 for (alias = se->s_aliases; *alias; alias++) 1461 if (strcmp(name2, *alias) == 0) 1462 return(1); 1463 } 1464 return(0); 1465} 1466 1467struct servtab * 1468enter(struct servtab *cp) 1469{ 1470 struct servtab *sep; 1471 long omask; 1472 1473 sep = (struct servtab *)malloc(sizeof (*sep)); 1474 if (sep == (struct servtab *)0) { 1475 syslog(LOG_ERR, "malloc: %m"); 1476 exit(EX_OSERR); 1477 } 1478 *sep = *cp; 1479 sep->se_fd = -1; 1480 omask = sigblock(SIGBLOCK); 1481 sep->se_next = servtab; 1482 servtab = sep; 1483 sigsetmask(omask); 1484 return (sep); 1485} 1486 1487void 1488enable(struct servtab *sep) 1489{ 1490 if (debug) 1491 warnx( 1492 "enabling %s, fd %d", sep->se_service, sep->se_fd); 1493#ifdef SANITY_CHECK 1494 if (sep->se_fd < 0) { 1495 syslog(LOG_ERR, 1496 "%s: %s: bad fd", __FUNCTION__, sep->se_service); 1497 exit(EX_SOFTWARE); 1498 } 1499 if (ISMUX(sep)) { 1500 syslog(LOG_ERR, 1501 "%s: %s: is mux", __FUNCTION__, sep->se_service); 1502 exit(EX_SOFTWARE); 1503 } 1504 if (FD_ISSET(sep->se_fd, &allsock)) { 1505 syslog(LOG_ERR, 1506 "%s: %s: not off", __FUNCTION__, sep->se_service); 1507 exit(EX_SOFTWARE); 1508 } 1509 nsock++; 1510#endif 1511 FD_SET(sep->se_fd, &allsock); 1512 if (sep->se_fd > maxsock) 1513 maxsock = sep->se_fd; 1514} 1515 1516void 1517disable(struct servtab *sep) 1518{ 1519 if (debug) 1520 warnx( 1521 "disabling %s, fd %d", sep->se_service, sep->se_fd); 1522#ifdef SANITY_CHECK 1523 if (sep->se_fd < 0) { 1524 syslog(LOG_ERR, 1525 "%s: %s: bad fd", __FUNCTION__, sep->se_service); 1526 exit(EX_SOFTWARE); 1527 } 1528 if (ISMUX(sep)) { 1529 syslog(LOG_ERR, 1530 "%s: %s: is mux", __FUNCTION__, sep->se_service); 1531 exit(EX_SOFTWARE); 1532 } 1533 if (!FD_ISSET(sep->se_fd, &allsock)) { 1534 syslog(LOG_ERR, 1535 "%s: %s: not on", __FUNCTION__, sep->se_service); 1536 exit(EX_SOFTWARE); 1537 } 1538 if (nsock == 0) { 1539 syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__); 1540 exit(EX_SOFTWARE); 1541 } 1542 nsock--; 1543#endif 1544 FD_CLR(sep->se_fd, &allsock); 1545 if (sep->se_fd == maxsock) 1546 maxsock--; 1547} 1548 1549FILE *fconfig = NULL; 1550struct servtab serv; 1551char line[LINE_MAX]; 1552 1553int 1554setconfig(void) 1555{ 1556 1557 if (fconfig != NULL) { 1558 fseek(fconfig, 0L, SEEK_SET); 1559 return (1); 1560 } 1561 fconfig = fopen(CONFIG, "r"); 1562 return (fconfig != NULL); 1563} 1564 1565void 1566endconfig(void) 1567{ 1568 if (fconfig) { 1569 (void) fclose(fconfig); 1570 fconfig = NULL; 1571 } 1572} 1573 1574struct servtab * 1575getconfigent(void) 1576{ 1577 struct servtab *sep = &serv; 1578 int argc; 1579 char *cp, *arg, *s; 1580 char *versp; 1581 static char TCPMUX_TOKEN[] = "tcpmux/"; 1582#define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) 1583#ifdef IPSEC 1584 char *policy; 1585#endif 1586 int v4bind; 1587#ifdef INET6 1588 int v6bind; 1589#endif 1590 int i; 1591 1592#ifdef IPSEC 1593 policy = NULL; 1594#endif 1595more: 1596 v4bind = 0; 1597#ifdef INET6 1598 v6bind = 0; 1599#endif 1600 while ((cp = nextline(fconfig)) != NULL) { 1601#ifdef IPSEC 1602 /* lines starting with #@ is not a comment, but the policy */ 1603 if (cp[0] == '#' && cp[1] == '@') { 1604 char *p; 1605 for (p = cp + 2; p && *p && isspace(*p); p++) 1606 ; 1607 if (*p == '\0') { 1608 if (policy) 1609 free(policy); 1610 policy = NULL; 1611 } else if (ipsec_get_policylen(p) >= 0) { 1612 if (policy) 1613 free(policy); 1614 policy = newstr(p); 1615 } else { 1616 syslog(LOG_ERR, 1617 "%s: invalid ipsec policy \"%s\"", 1618 CONFIG, p); 1619 exit(EX_CONFIG); 1620 } 1621 } 1622#endif 1623 if (*cp == '#' || *cp == '\0') 1624 continue; 1625 break; 1626 } 1627 if (cp == NULL) 1628 return ((struct servtab *)0); 1629 /* 1630 * clear the static buffer, since some fields (se_ctrladdr, 1631 * for example) don't get initialized here. 1632 */ 1633 memset(sep, 0, sizeof *sep); 1634 arg = skip(&cp); 1635 if (cp == NULL) { 1636 /* got an empty line containing just blanks/tabs. */ 1637 goto more; 1638 } 1639 if (arg[0] == ':') { /* :user:group:perm: */ 1640 char *user, *group, *perm; 1641 struct passwd *pw; 1642 struct group *gr; 1643 user = arg+1; 1644 if ((group = strchr(user, ':')) == NULL) { 1645 syslog(LOG_ERR, "no group after user '%s'", user); 1646 goto more; 1647 } 1648 *group++ = '\0'; 1649 if ((perm = strchr(group, ':')) == NULL) { 1650 syslog(LOG_ERR, "no mode after group '%s'", group); 1651 goto more; 1652 } 1653 *perm++ = '\0'; 1654 if ((pw = getpwnam(user)) == NULL) { 1655 syslog(LOG_ERR, "no such user '%s'", user); 1656 goto more; 1657 } 1658 sep->se_sockuid = pw->pw_uid; 1659 if ((gr = getgrnam(group)) == NULL) { 1660 syslog(LOG_ERR, "no such user '%s'", group); 1661 goto more; 1662 } 1663 sep->se_sockgid = gr->gr_gid; 1664 sep->se_sockmode = strtol(perm, &arg, 8); 1665 if (*arg != ':') { 1666 syslog(LOG_ERR, "bad mode '%s'", perm); 1667 goto more; 1668 } 1669 *arg++ = '\0'; 1670 } else { 1671 sep->se_sockuid = euid; 1672 sep->se_sockgid = egid; 1673 sep->se_sockmode = 0200; 1674 } 1675 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) { 1676 char *c = arg + MUX_LEN; 1677 if (*c == '+') { 1678 sep->se_type = MUXPLUS_TYPE; 1679 c++; 1680 } else 1681 sep->se_type = MUX_TYPE; 1682 sep->se_service = newstr(c); 1683 } else { 1684 sep->se_service = newstr(arg); 1685 sep->se_type = NORM_TYPE; 1686 } 1687 arg = sskip(&cp); 1688 if (strcmp(arg, "stream") == 0) 1689 sep->se_socktype = SOCK_STREAM; 1690 else if (strcmp(arg, "dgram") == 0) 1691 sep->se_socktype = SOCK_DGRAM; 1692 else if (strcmp(arg, "rdm") == 0) 1693 sep->se_socktype = SOCK_RDM; 1694 else if (strcmp(arg, "seqpacket") == 0) 1695 sep->se_socktype = SOCK_SEQPACKET; 1696 else if (strcmp(arg, "raw") == 0) 1697 sep->se_socktype = SOCK_RAW; 1698 else 1699 sep->se_socktype = -1; 1700 1701 arg = sskip(&cp); 1702 if (strncmp(arg, "tcp", 3) == 0) { 1703 sep->se_proto = newstr(strsep(&arg, "/")); 1704 if (arg != NULL) { 1705 if (strcmp(arg, "ttcp") == 0) 1706 sep->se_type = TTCP_TYPE; 1707 else if (strcmp(arg, "faith") == 0) 1708 sep->se_type = FAITH_TYPE; 1709 } 1710 } else { 1711 if (sep->se_type == NORM_TYPE && 1712 strncmp(arg, "faith/", 6) == 0) { 1713 arg += 6; 1714 sep->se_type = FAITH_TYPE; 1715 } 1716 sep->se_proto = newstr(arg); 1717 } 1718 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 1719 memmove(sep->se_proto, sep->se_proto + 4, 1720 strlen(sep->se_proto) + 1 - 4); 1721 sep->se_rpc = 1; 1722 sep->se_rpc_prog = sep->se_rpc_lowvers = 1723 sep->se_rpc_lowvers = 0; 1724 memcpy(&sep->se_ctrladdr4, bind_sa4, 1725 sizeof(sep->se_ctrladdr4)); 1726 if ((versp = rindex(sep->se_service, '/'))) { 1727 *versp++ = '\0'; 1728 switch (sscanf(versp, "%u-%u", 1729 &sep->se_rpc_lowvers, 1730 &sep->se_rpc_highvers)) { 1731 case 2: 1732 break; 1733 case 1: 1734 sep->se_rpc_highvers = 1735 sep->se_rpc_lowvers; 1736 break; 1737 default: 1738 syslog(LOG_ERR, 1739 "bad RPC version specifier; %s", 1740 sep->se_service); 1741 freeconfig(sep); 1742 goto more; 1743 } 1744 } 1745 else { 1746 sep->se_rpc_lowvers = 1747 sep->se_rpc_highvers = 1; 1748 } 1749 } 1750 sep->se_nomapped = 0; 1751 if (strcmp(sep->se_proto, "unix") == 0) { 1752 sep->se_family = AF_UNIX; 1753 } else { 1754 while (isdigit(sep->se_proto[strlen(sep->se_proto) - 1])) { 1755#ifdef INET6 1756 if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') { 1757 sep->se_proto[strlen(sep->se_proto) - 1] = '\0'; 1758 v6bind = 1; 1759 continue; 1760 } 1761#endif 1762 if (sep->se_proto[strlen(sep->se_proto) - 1] == '4') { 1763 sep->se_proto[strlen(sep->se_proto) - 1] = '\0'; 1764 v4bind = 1; 1765 continue; 1766 } 1767 /* illegal version num */ 1768 syslog(LOG_ERR, "bad IP version for %s", sep->se_proto); 1769 freeconfig(sep); 1770 goto more; 1771 } 1772#ifdef INET6 1773 if (v6bind != 0 && no_v6bind != 0) { 1774 syslog(LOG_INFO, "IPv6 bind is ignored for %s", 1775 sep->se_service); 1776 if (v4bind && no_v4bind == 0) 1777 v6bind = 0; 1778 else { 1779 freeconfig(sep); 1780 goto more; 1781 } 1782 } 1783 if (v6bind != 0) { 1784 sep->se_family = AF_INET6; 1785 if (v4bind == 0 || no_v4bind != 0) 1786 sep->se_nomapped = 1; 1787 } else 1788#endif 1789 { /* default to v4 bind if not v6 bind */ 1790 if (no_v4bind != 0) { 1791 syslog(LOG_NOTICE, "IPv4 bind is ignored for %s", 1792 sep->se_service); 1793 freeconfig(sep); 1794 goto more; 1795 } 1796 sep->se_family = AF_INET; 1797 } 1798 } 1799 /* init ctladdr */ 1800 switch(sep->se_family) { 1801 case AF_INET: 1802 memcpy(&sep->se_ctrladdr4, bind_sa4, 1803 sizeof(sep->se_ctrladdr4)); 1804 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr4); 1805 break; 1806#ifdef INET6 1807 case AF_INET6: 1808 memcpy(&sep->se_ctrladdr6, bind_sa6, 1809 sizeof(sep->se_ctrladdr6)); 1810 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr6); 1811 break; 1812#endif 1813 case AF_UNIX: 1814 if (strlen(sep->se_service) >= sizeof(sep->se_ctrladdr_un.sun_path)) { 1815 syslog(LOG_ERR, 1816 "domain socket pathname too long for service %s", 1817 sep->se_service); 1818 goto more; 1819 } 1820 memset(&sep->se_ctrladdr, 0, sizeof(sep->se_ctrladdr)); 1821 sep->se_ctrladdr_un.sun_family = sep->se_family; 1822 sep->se_ctrladdr_un.sun_len = strlen(sep->se_service); 1823 strcpy(sep->se_ctrladdr_un.sun_path, sep->se_service); 1824 sep->se_ctrladdr_size = SUN_LEN(&sep->se_ctrladdr_un); 1825 } 1826 arg = sskip(&cp); 1827 if (!strncmp(arg, "wait", 4)) 1828 sep->se_accept = 0; 1829 else if (!strncmp(arg, "nowait", 6)) 1830 sep->se_accept = 1; 1831 else { 1832 syslog(LOG_ERR, 1833 "%s: bad wait/nowait for service %s", 1834 CONFIG, sep->se_service); 1835 goto more; 1836 } 1837 sep->se_maxchild = -1; 1838 sep->se_maxcpm = -1; 1839 sep->se_maxperip = -1; 1840 if ((s = strchr(arg, '/')) != NULL) { 1841 char *eptr; 1842 u_long val; 1843 1844 val = strtoul(s + 1, &eptr, 10); 1845 if (eptr == s + 1 || val > MAX_MAXCHLD) { 1846 syslog(LOG_ERR, 1847 "%s: bad max-child for service %s", 1848 CONFIG, sep->se_service); 1849 goto more; 1850 } 1851 if (debug) 1852 if (!sep->se_accept && val != 1) 1853 warnx("maxchild=%lu for wait service %s" 1854 " not recommended", val, sep->se_service); 1855 sep->se_maxchild = val; 1856 if (*eptr == '/') 1857 sep->se_maxcpm = strtol(eptr + 1, &eptr, 10); 1858 if (*eptr == '/') 1859 sep->se_maxperip = strtol(eptr + 1, &eptr, 10); 1860 /* 1861 * explicitly do not check for \0 for future expansion / 1862 * backwards compatibility 1863 */ 1864 } 1865 if (ISMUX(sep)) { 1866 /* 1867 * Silently enforce "nowait" mode for TCPMUX services 1868 * since they don't have an assigned port to listen on. 1869 */ 1870 sep->se_accept = 1; 1871 if (strcmp(sep->se_proto, "tcp")) { 1872 syslog(LOG_ERR, 1873 "%s: bad protocol for tcpmux service %s", 1874 CONFIG, sep->se_service); 1875 goto more; 1876 } 1877 if (sep->se_socktype != SOCK_STREAM) { 1878 syslog(LOG_ERR, 1879 "%s: bad socket type for tcpmux service %s", 1880 CONFIG, sep->se_service); 1881 goto more; 1882 } 1883 } 1884 sep->se_user = newstr(sskip(&cp)); 1885#ifdef LOGIN_CAP 1886 if ((s = strrchr(sep->se_user, '/')) != NULL) { 1887 *s = '\0'; 1888 sep->se_class = newstr(s + 1); 1889 } else 1890 sep->se_class = newstr(RESOURCE_RC); 1891#endif 1892 if ((s = strrchr(sep->se_user, ':')) != NULL) { 1893 *s = '\0'; 1894 sep->se_group = newstr(s + 1); 1895 } else 1896 sep->se_group = NULL; 1897 sep->se_server = newstr(sskip(&cp)); 1898 if ((sep->se_server_name = rindex(sep->se_server, '/'))) 1899 sep->se_server_name++; 1900 if (strcmp(sep->se_server, "internal") == 0) { 1901 struct biltin *bi; 1902 1903 for (bi = biltins; bi->bi_service; bi++) 1904 if (bi->bi_socktype == sep->se_socktype && 1905 matchservent(bi->bi_service, sep->se_service, 1906 sep->se_proto)) 1907 break; 1908 if (bi->bi_service == 0) { 1909 syslog(LOG_ERR, "internal service %s unknown", 1910 sep->se_service); 1911 goto more; 1912 } 1913 sep->se_accept = 1; /* force accept mode for built-ins */ 1914 sep->se_bi = bi; 1915 } else 1916 sep->se_bi = NULL; 1917 if (sep->se_maxperip < 0) 1918 sep->se_maxperip = maxperip; 1919 if (sep->se_maxcpm < 0) 1920 sep->se_maxcpm = maxcpm; 1921 if (sep->se_maxchild < 0) { /* apply default max-children */ 1922 if (sep->se_bi && sep->se_bi->bi_maxchild >= 0) 1923 sep->se_maxchild = sep->se_bi->bi_maxchild; 1924 else if (sep->se_accept) 1925 sep->se_maxchild = maxchild > 0 ? maxchild : 0; 1926 else 1927 sep->se_maxchild = 1; 1928 } 1929 if (sep->se_maxchild > 0) { 1930 sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids)); 1931 if (sep->se_pids == NULL) { 1932 syslog(LOG_ERR, "malloc: %m"); 1933 exit(EX_OSERR); 1934 } 1935 } 1936 argc = 0; 1937 for (arg = skip(&cp); cp; arg = skip(&cp)) 1938 if (argc < MAXARGV) { 1939 sep->se_argv[argc++] = newstr(arg); 1940 } else { 1941 syslog(LOG_ERR, 1942 "%s: too many arguments for service %s", 1943 CONFIG, sep->se_service); 1944 goto more; 1945 } 1946 while (argc <= MAXARGV) 1947 sep->se_argv[argc++] = NULL; 1948 for (i = 0; i < PERIPSIZE; ++i) 1949 LIST_INIT(&sep->se_conn[i]); 1950#ifdef IPSEC 1951 sep->se_policy = policy ? newstr(policy) : NULL; 1952#endif 1953 return (sep); 1954} 1955 1956void 1957freeconfig(struct servtab *cp) 1958{ 1959 int i; 1960 1961 if (cp->se_service) 1962 free(cp->se_service); 1963 if (cp->se_proto) 1964 free(cp->se_proto); 1965 if (cp->se_user) 1966 free(cp->se_user); 1967 if (cp->se_group) 1968 free(cp->se_group); 1969#ifdef LOGIN_CAP 1970 if (cp->se_class) 1971 free(cp->se_class); 1972#endif 1973 if (cp->se_server) 1974 free(cp->se_server); 1975 if (cp->se_pids) 1976 free(cp->se_pids); 1977 for (i = 0; i < MAXARGV; i++) 1978 if (cp->se_argv[i]) 1979 free(cp->se_argv[i]); 1980 free_connlist(cp); 1981#ifdef IPSEC 1982 if (cp->se_policy) 1983 free(cp->se_policy); 1984#endif 1985} 1986 1987 1988/* 1989 * Safe skip - if skip returns null, log a syntax error in the 1990 * configuration file and exit. 1991 */ 1992char * 1993sskip(char **cpp) 1994{ 1995 char *cp; 1996 1997 cp = skip(cpp); 1998 if (cp == NULL) { 1999 syslog(LOG_ERR, "%s: syntax error", CONFIG); 2000 exit(EX_DATAERR); 2001 } 2002 return (cp); 2003} 2004 2005char * 2006skip(char **cpp) 2007{ 2008 char *cp = *cpp; 2009 char *start; 2010 char quote = '\0'; 2011 2012again: 2013 while (*cp == ' ' || *cp == '\t') 2014 cp++; 2015 if (*cp == '\0') { 2016 int c; 2017 2018 c = getc(fconfig); 2019 (void) ungetc(c, fconfig); 2020 if (c == ' ' || c == '\t') 2021 if ((cp = nextline(fconfig))) 2022 goto again; 2023 *cpp = (char *)0; 2024 return ((char *)0); 2025 } 2026 if (*cp == '"' || *cp == '\'') 2027 quote = *cp++; 2028 start = cp; 2029 if (quote) 2030 while (*cp && *cp != quote) 2031 cp++; 2032 else 2033 while (*cp && *cp != ' ' && *cp != '\t') 2034 cp++; 2035 if (*cp != '\0') 2036 *cp++ = '\0'; 2037 *cpp = cp; 2038 return (start); 2039} 2040 2041char * 2042nextline(FILE *fd) 2043{ 2044 char *cp; 2045 2046 if (fgets(line, sizeof (line), fd) == NULL) 2047 return ((char *)0); 2048 cp = strchr(line, '\n'); 2049 if (cp) 2050 *cp = '\0'; 2051 return (line); 2052} 2053 2054char * 2055newstr(const char *cp) 2056{ 2057 char *cr; 2058 2059 if ((cr = strdup(cp != NULL ? cp : ""))) 2060 return (cr); 2061 syslog(LOG_ERR, "strdup: %m"); 2062 exit(EX_OSERR); 2063} 2064 2065void 2066inetd_setproctitle(const char *a, int s) 2067{ 2068 socklen_t size; 2069 struct sockaddr_storage ss; 2070 char buf[80], pbuf[INET6_ADDRSTRLEN]; 2071 2072 size = sizeof(ss); 2073 if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) { 2074 getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf), 2075 NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID); 2076 (void) sprintf(buf, "%s [%s]", a, pbuf); 2077 } else 2078 (void) sprintf(buf, "%s", a); 2079 setproctitle("%s", buf); 2080} 2081 2082int 2083check_loop(const struct sockaddr *sa, const struct servtab *sep) 2084{ 2085 struct servtab *se2; 2086 char pname[INET6_ADDRSTRLEN]; 2087 2088 for (se2 = servtab; se2; se2 = se2->se_next) { 2089 if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM) 2090 continue; 2091 2092 switch (se2->se_family) { 2093 case AF_INET: 2094 if (((const struct sockaddr_in *)sa)->sin_port == 2095 se2->se_ctrladdr4.sin_port) 2096 goto isloop; 2097 continue; 2098#ifdef INET6 2099 case AF_INET6: 2100 if (((const struct sockaddr_in *)sa)->sin_port == 2101 se2->se_ctrladdr4.sin_port) 2102 goto isloop; 2103 continue; 2104#endif 2105 default: 2106 continue; 2107 } 2108 isloop: 2109 getnameinfo(sa, sa->sa_len, pname, sizeof(pname), NULL, 0, 2110 NI_NUMERICHOST|NI_WITHSCOPEID); 2111 syslog(LOG_WARNING, "%s/%s:%s/%s loop request REFUSED from %s", 2112 sep->se_service, sep->se_proto, 2113 se2->se_service, se2->se_proto, 2114 pname); 2115 return 1; 2116 } 2117 return 0; 2118} 2119 2120/* 2121 * print_service: 2122 * Dump relevant information to stderr 2123 */ 2124void 2125print_service(const char *action, const struct servtab *sep) 2126{ 2127 fprintf(stderr, 2128 "%s: %s proto=%s accept=%d max=%d user=%s group=%s" 2129#ifdef LOGIN_CAP 2130 "class=%s" 2131#endif 2132 " builtin=%p server=%s" 2133#ifdef IPSEC 2134 " policy=\"%s\"" 2135#endif 2136 "\n", 2137 action, sep->se_service, sep->se_proto, 2138 sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group, 2139#ifdef LOGIN_CAP 2140 sep->se_class, 2141#endif 2142 (void *) sep->se_bi, sep->se_server 2143#ifdef IPSEC 2144 , (sep->se_policy ? sep->se_policy : "") 2145#endif 2146 ); 2147} 2148 2149#define CPMHSIZE 256 2150#define CPMHMASK (CPMHSIZE-1) 2151#define CHTGRAN 10 2152#define CHTSIZE 6 2153 2154typedef struct CTime { 2155 unsigned long ct_Ticks; 2156 int ct_Count; 2157} CTime; 2158 2159typedef struct CHash { 2160 union { 2161 struct in_addr c4_Addr; 2162 struct in6_addr c6_Addr; 2163 } cu_Addr; 2164#define ch_Addr4 cu_Addr.c4_Addr 2165#define ch_Addr6 cu_Addr.c6_Addr 2166 int ch_Family; 2167 time_t ch_LTime; 2168 char *ch_Service; 2169 CTime ch_Times[CHTSIZE]; 2170} CHash; 2171 2172CHash CHashAry[CPMHSIZE]; 2173 2174int 2175cpmip(const struct servtab *sep, int ctrl) 2176{ 2177 struct sockaddr_storage rss; 2178 socklen_t rssLen = sizeof(rss); 2179 int r = 0; 2180 2181 /* 2182 * If getpeername() fails, just let it through (if logging is 2183 * enabled the condition is caught elsewhere) 2184 */ 2185 2186 if (sep->se_maxcpm > 0 && 2187 getpeername(ctrl, (struct sockaddr *)&rss, &rssLen) == 0 ) { 2188 time_t t = time(NULL); 2189 int hv = 0xABC3D20F; 2190 int i; 2191 int cnt = 0; 2192 CHash *chBest = NULL; 2193 unsigned int ticks = t / CHTGRAN; 2194 struct sockaddr_in *sin4; 2195#ifdef INET6 2196 struct sockaddr_in6 *sin6; 2197#endif 2198 2199 sin4 = (struct sockaddr_in *)&rss; 2200#ifdef INET6 2201 sin6 = (struct sockaddr_in6 *)&rss; 2202#endif 2203 { 2204 char *p; 2205 int addrlen; 2206 2207 switch (rss.ss_family) { 2208 case AF_INET: 2209 p = (char *)&sin4->sin_addr; 2210 addrlen = sizeof(struct in_addr); 2211 break; 2212#ifdef INET6 2213 case AF_INET6: 2214 p = (char *)&sin6->sin6_addr; 2215 addrlen = sizeof(struct in6_addr); 2216 break; 2217#endif 2218 default: 2219 /* should not happen */ 2220 return -1; 2221 } 2222 2223 for (i = 0; i < addrlen; ++i, ++p) { 2224 hv = (hv << 5) ^ (hv >> 23) ^ *p; 2225 } 2226 hv = (hv ^ (hv >> 16)); 2227 } 2228 for (i = 0; i < 5; ++i) { 2229 CHash *ch = &CHashAry[(hv + i) & CPMHMASK]; 2230 2231 if (rss.ss_family == AF_INET && 2232 ch->ch_Family == AF_INET && 2233 sin4->sin_addr.s_addr == ch->ch_Addr4.s_addr && 2234 ch->ch_Service && strcmp(sep->se_service, 2235 ch->ch_Service) == 0) { 2236 chBest = ch; 2237 break; 2238 } 2239#ifdef INET6 2240 if (rss.ss_family == AF_INET6 && 2241 ch->ch_Family == AF_INET6 && 2242 IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, 2243 &ch->ch_Addr6) != 0 && 2244 ch->ch_Service && strcmp(sep->se_service, 2245 ch->ch_Service) == 0) { 2246 chBest = ch; 2247 break; 2248 } 2249#endif 2250 if (chBest == NULL || ch->ch_LTime == 0 || 2251 ch->ch_LTime < chBest->ch_LTime) { 2252 chBest = ch; 2253 } 2254 } 2255 if ((rss.ss_family == AF_INET && 2256 (chBest->ch_Family != AF_INET || 2257 sin4->sin_addr.s_addr != chBest->ch_Addr4.s_addr)) || 2258 chBest->ch_Service == NULL || 2259 strcmp(sep->se_service, chBest->ch_Service) != 0) { 2260 chBest->ch_Family = sin4->sin_family; 2261 chBest->ch_Addr4 = sin4->sin_addr; 2262 if (chBest->ch_Service) 2263 free(chBest->ch_Service); 2264 chBest->ch_Service = strdup(sep->se_service); 2265 bzero(chBest->ch_Times, sizeof(chBest->ch_Times)); 2266 } 2267#ifdef INET6 2268 if ((rss.ss_family == AF_INET6 && 2269 (chBest->ch_Family != AF_INET6 || 2270 IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, 2271 &chBest->ch_Addr6) == 0)) || 2272 chBest->ch_Service == NULL || 2273 strcmp(sep->se_service, chBest->ch_Service) != 0) { 2274 chBest->ch_Family = sin6->sin6_family; 2275 chBest->ch_Addr6 = sin6->sin6_addr; 2276 if (chBest->ch_Service) 2277 free(chBest->ch_Service); 2278 chBest->ch_Service = strdup(sep->se_service); 2279 bzero(chBest->ch_Times, sizeof(chBest->ch_Times)); 2280 } 2281#endif 2282 chBest->ch_LTime = t; 2283 { 2284 CTime *ct = &chBest->ch_Times[ticks % CHTSIZE]; 2285 if (ct->ct_Ticks != ticks) { 2286 ct->ct_Ticks = ticks; 2287 ct->ct_Count = 0; 2288 } 2289 ++ct->ct_Count; 2290 } 2291 for (i = 0; i < CHTSIZE; ++i) { 2292 CTime *ct = &chBest->ch_Times[i]; 2293 if (ct->ct_Ticks <= ticks && 2294 ct->ct_Ticks >= ticks - CHTSIZE) { 2295 cnt += ct->ct_Count; 2296 } 2297 } 2298 if (cnt * (CHTSIZE * CHTGRAN) / 60 > sep->se_maxcpm) { 2299 char pname[INET6_ADDRSTRLEN]; 2300 2301 getnameinfo((struct sockaddr *)&rss, 2302 ((struct sockaddr *)&rss)->sa_len, 2303 pname, sizeof(pname), NULL, 0, 2304 NI_NUMERICHOST|NI_WITHSCOPEID); 2305 r = -1; 2306 syslog(LOG_ERR, 2307 "%s from %s exceeded counts/min (limit %d/min)", 2308 sep->se_service, pname, 2309 sep->se_maxcpm); 2310 } 2311 } 2312 return(r); 2313} 2314 2315static struct conninfo * 2316search_conn(struct servtab *sep, int ctrl) 2317{ 2318 struct sockaddr_storage ss; 2319 socklen_t sslen = sizeof(ss); 2320 struct conninfo *conn; 2321 int hv; 2322 char pname[NI_MAXHOST], pname2[NI_MAXHOST]; 2323 2324 if (sep->se_maxperip <= 0) 2325 return NULL; 2326 2327 /* 2328 * If getpeername() fails, just let it through (if logging is 2329 * enabled the condition is caught elsewhere) 2330 */ 2331 if (getpeername(ctrl, (struct sockaddr *)&ss, &sslen) != 0) 2332 return NULL; 2333 2334 switch (ss.ss_family) { 2335 case AF_INET: 2336 hv = hashval((char *)&((struct sockaddr_in *)&ss)->sin_addr, 2337 sizeof(struct in_addr)); 2338 break; 2339#ifdef INET6 2340 case AF_INET6: 2341 hv = hashval((char *)&((struct sockaddr_in6 *)&ss)->sin6_addr, 2342 sizeof(struct in6_addr)); 2343 break; 2344#endif 2345 default: 2346 /* 2347 * Since we only support AF_INET and AF_INET6, just 2348 * let other than AF_INET and AF_INET6 through. 2349 */ 2350 return NULL; 2351 } 2352 2353 if (getnameinfo((struct sockaddr *)&ss, sslen, pname, sizeof(pname), 2354 NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) != 0) 2355 return NULL; 2356 2357 LIST_FOREACH(conn, &sep->se_conn[hv], co_link) { 2358 if (getnameinfo((struct sockaddr *)&conn->co_addr, 2359 conn->co_addr.ss_len, pname2, sizeof(pname2), NULL, 0, 2360 NI_NUMERICHOST | NI_WITHSCOPEID) == 0 && 2361 strcmp(pname, pname2) == 0) 2362 break; 2363 } 2364 2365 if (conn == NULL) { 2366 if ((conn = malloc(sizeof(struct conninfo))) == NULL) { 2367 syslog(LOG_ERR, "malloc: %m"); 2368 exit(EX_OSERR); 2369 } 2370 conn->co_proc = malloc(sep->se_maxperip * sizeof(*conn->co_proc)); 2371 if (conn->co_proc == NULL) { 2372 syslog(LOG_ERR, "malloc: %m"); 2373 exit(EX_OSERR); 2374 } 2375 memcpy(&conn->co_addr, (struct sockaddr *)&ss, sslen); 2376 conn->co_numchild = 0; 2377 LIST_INSERT_HEAD(&sep->se_conn[hv], conn, co_link); 2378 } 2379 2380 /* 2381 * Since a child process is not invoked yet, we cannot 2382 * determine a pid of a child. So, co_proc and co_numchild 2383 * should be filled leter. 2384 */ 2385 2386 return conn; 2387} 2388 2389static int 2390room_conn(struct servtab *sep, struct conninfo *conn) 2391{ 2392 char pname[NI_MAXHOST]; 2393 2394 if (conn->co_numchild >= sep->se_maxperip) { 2395 getnameinfo((struct sockaddr *)&conn->co_addr, 2396 conn->co_addr.ss_len, pname, sizeof(pname), NULL, 0, 2397 NI_NUMERICHOST | NI_WITHSCOPEID); 2398 syslog(LOG_ERR, "%s from %s exceeded counts (limit %d)", 2399 sep->se_service, pname, sep->se_maxperip); 2400 return 0; 2401 } 2402 return 1; 2403} 2404 2405static void 2406addchild_conn(struct conninfo *conn, pid_t pid) 2407{ 2408 struct procinfo *proc; 2409 2410 if (conn == NULL) 2411 return; 2412 2413 if ((proc = search_proc(pid, 1)) != NULL) { 2414 if (proc->pr_conn != NULL) { 2415 syslog(LOG_ERR, 2416 "addchild_conn: child already on process list"); 2417 exit(EX_OSERR); 2418 } 2419 proc->pr_conn = conn; 2420 } 2421 2422 conn->co_proc[conn->co_numchild++] = proc; 2423} 2424 2425static void 2426reapchild_conn(pid_t pid) 2427{ 2428 struct procinfo *proc; 2429 struct conninfo *conn; 2430 int i; 2431 2432 if ((proc = search_proc(pid, 0)) == NULL) 2433 return; 2434 if ((conn = proc->pr_conn) == NULL) 2435 return; 2436 for (i = 0; i < conn->co_numchild; ++i) 2437 if (conn->co_proc[i] == proc) { 2438 conn->co_proc[i] = conn->co_proc[--conn->co_numchild]; 2439 break; 2440 } 2441 free_proc(proc); 2442 free_conn(conn); 2443} 2444 2445static void 2446resize_conn(struct servtab *sep, int maxpip) 2447{ 2448 struct conninfo *conn; 2449 int i, j; 2450 2451 if (sep->se_maxperip <= 0) 2452 return; 2453 if (maxpip <= 0) { 2454 free_connlist(sep); 2455 return; 2456 } 2457 for (i = 0; i < PERIPSIZE; ++i) { 2458 LIST_FOREACH(conn, &sep->se_conn[i], co_link) { 2459 for (j = maxpip; j < conn->co_numchild; ++j) 2460 free_proc(conn->co_proc[j]); 2461 conn->co_proc = realloc(conn->co_proc, 2462 maxpip * sizeof(*conn->co_proc)); 2463 if (conn->co_proc == NULL) { 2464 syslog(LOG_ERR, "realloc: %m"); 2465 exit(EX_OSERR); 2466 } 2467 if (conn->co_numchild > maxpip) 2468 conn->co_numchild = maxpip; 2469 } 2470 } 2471} 2472 2473static void 2474free_connlist(struct servtab *sep) 2475{ 2476 struct conninfo *conn; 2477 int i, j; 2478 2479 for (i = 0; i < PERIPSIZE; ++i) { 2480 while ((conn = LIST_FIRST(&sep->se_conn[i])) != NULL) { 2481 for (j = 0; j < conn->co_numchild; ++j) 2482 free_proc(conn->co_proc[j]); 2483 conn->co_numchild = 0; 2484 free_conn(conn); 2485 } 2486 } 2487} 2488 2489static void 2490free_conn(struct conninfo *conn) 2491{ 2492 if (conn == NULL) 2493 return; 2494 if (conn->co_numchild <= 0) { 2495 LIST_REMOVE(conn, co_link); 2496 free(conn->co_proc); 2497 free(conn); 2498 } 2499} 2500 2501static struct procinfo * 2502search_proc(pid_t pid, int add) 2503{ 2504 struct procinfo *proc; 2505 int hv; 2506 2507 hv = hashval((char *)&pid, sizeof(pid)); 2508 LIST_FOREACH(proc, &proctable[hv], pr_link) { 2509 if (proc->pr_pid == pid) 2510 break; 2511 } 2512 if (proc == NULL && add) { 2513 if ((proc = malloc(sizeof(struct procinfo))) == NULL) { 2514 syslog(LOG_ERR, "malloc: %m"); 2515 exit(EX_OSERR); 2516 } 2517 proc->pr_pid = pid; 2518 proc->pr_conn = NULL; 2519 LIST_INSERT_HEAD(&proctable[hv], proc, pr_link); 2520 } 2521 return proc; 2522} 2523 2524static void 2525free_proc(struct procinfo *proc) 2526{ 2527 if (proc == NULL) 2528 return; 2529 LIST_REMOVE(proc, pr_link); 2530 free(proc); 2531} 2532 2533static int 2534hashval(char *p, int len) 2535{ 2536 int i, hv = 0xABC3D20F; 2537 2538 for (i = 0; i < len; ++i, ++p) 2539 hv = (hv << 5) ^ (hv >> 23) ^ *p; 2540 hv = (hv ^ (hv >> 16)) & (PERIPSIZE - 1); 2541 return hv; 2542} 2543