1 /* $OpenBSD: inetd.c,v 1.132 2009/11/02 20:03:01 otto Exp $ */ 2 3 /* 4 * Copyright (c) 1983,1991 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Inetd - Internet super-server 34 * 35 * This program invokes all internet services as needed. 36 * connection-oriented services are invoked each time a 37 * connection is made, by creating a process. This process 38 * is passed the connection as file descriptor 0 and is 39 * expected to do a getpeername to find out the source host 40 * and port. 41 * 42 * Datagram oriented services are invoked when a datagram 43 * arrives; a process is created and passed a pending message 44 * on file descriptor 0. Datagram servers may either connect 45 * to their peer, freeing up the original socket for inetd 46 * to receive further messages on, or ``take over the socket'', 47 * processing all arriving datagrams and, eventually, timing 48 * out. The first type of server is said to be ``multi-threaded''; 49 * the second type of server ``single-threaded''. 50 * 51 * Inetd uses a configuration file which is read at startup 52 * and, possibly, at some later time in response to a hangup signal. 53 * The configuration file is ``free format'' with fields given in the 54 * order shown below. Continuation lines for an entry must begin with 55 * a space or tab. All fields must be present in each entry. 56 * 57 * service name must be in /etc/services 58 * socket type stream/dgram/raw/rdm/seqpacket 59 * protocol must be in /etc/protocols 60 * wait/nowait[.max] single-threaded/multi-threaded, max # 61 * user[.group] or user[:group] user/group to run daemon as 62 * server program full path name 63 * server program arguments maximum of MAXARGS (20) 64 * 65 * For RPC services 66 * service name/version must be in /etc/rpc 67 * socket type stream/dgram/raw/rdm/seqpacket 68 * protocol must be in /etc/protocols 69 * wait/nowait[.max] single-threaded/multi-threaded 70 * user[.group] or user[:group] user to run daemon as 71 * server program full path name 72 * server program arguments maximum of MAXARGS (20) 73 * 74 * For non-RPC services, the "service name" can be of the form 75 * hostaddress:servicename, in which case the hostaddress is used 76 * as the host portion of the address to listen on. If hostaddress 77 * consists of a single `*' character, INADDR_ANY is used. 78 * 79 * A line can also consist of just 80 * hostaddress: 81 * where hostaddress is as in the preceding paragraph. Such a line must 82 * have no further fields; the specified hostaddress is remembered and 83 * used for all further lines that have no hostaddress specified, 84 * until the next such line (or EOF). (This is why * is provided to 85 * allow explicit specification of INADDR_ANY.) A line 86 * *: 87 * is implicitly in effect at the beginning of the file. 88 * 89 * The hostaddress specifier may (and often will) contain dots; 90 * the service name must not. 91 * 92 * For RPC services, host-address specifiers are accepted and will 93 * work to some extent; however, because of limitations in the 94 * portmapper interface, it will not work to try to give more than 95 * one line for any given RPC service, even if the host-address 96 * specifiers are different. 97 * 98 * Comment lines are indicated by a `#' in column 1. 99 */ 100 101 /* 102 * Here's the scoop concerning the user[.:]group feature: 103 * 104 * 1) set-group-option off. 105 * 106 * a) user = root: NO setuid() or setgid() is done 107 * 108 * b) other: setgid(primary group as found in passwd) 109 * initgroups(name, primary group) 110 * setuid() 111 * 112 * 2) set-group-option on. 113 * 114 * a) user = root: setgid(specified group) 115 * NO initgroups() 116 * NO setuid() 117 * 118 * b) other: setgid(specified group) 119 * initgroups(name, specified group) 120 * setuid() 121 * 122 */ 123 124 #include <sys/param.h> 125 #include <sys/stat.h> 126 #include <sys/ioctl.h> 127 #include <sys/socket.h> 128 #include <sys/un.h> 129 #include <sys/file.h> 130 #include <sys/wait.h> 131 #include <sys/time.h> 132 #include <sys/resource.h> 133 134 #include <net/if.h> 135 #include <netinet/in.h> 136 #include <arpa/inet.h> 137 138 #include <errno.h> 139 #include <ctype.h> 140 #include <signal.h> 141 #include <netdb.h> 142 #include <syslog.h> 143 #include <pwd.h> 144 #include <grp.h> 145 #include <stdio.h> 146 #include <stdlib.h> 147 #include <unistd.h> 148 #include <string.h> 149 #include <login_cap.h> 150 #include <ifaddrs.h> 151 #include <rpc/rpc.h> 152 #include <rpc/pmap_clnt.h> 153 #include <rpcsvc/nfs_prot.h> 154 #include "pathnames.h" 155 156 #define TOOMANY 256 /* don't start more than TOOMANY */ 157 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ 158 #define RETRYTIME (60*10) /* retry after bind or server fail */ 159 160 int debug = 0; 161 int nsock, maxsock; 162 fd_set *allsockp; 163 int allsockn; 164 int toomany = TOOMANY; 165 int options; 166 int timingout; 167 struct servent *sp; 168 uid_t uid; 169 sigset_t blockmask; 170 sigset_t emptymask; 171 172 #ifndef OPEN_MAX 173 #define OPEN_MAX 64 174 #endif 175 176 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ 177 #define FD_MARGIN (8) 178 rlim_t rlim_nofile_cur = OPEN_MAX; 179 180 struct rlimit rlim_nofile; 181 182 struct servtab { 183 char *se_hostaddr; /* host address to listen on */ 184 char *se_service; /* name of service */ 185 int se_socktype; /* type of socket to use */ 186 int se_family; /* address family */ 187 char *se_proto; /* protocol used */ 188 int se_rpcprog; /* rpc program number */ 189 int se_rpcversl; /* rpc program lowest version */ 190 int se_rpcversh; /* rpc program highest version */ 191 #define isrpcservice(sep) ((sep)->se_rpcversl != 0) 192 pid_t se_wait; /* single threaded server */ 193 short se_checked; /* looked at during merge */ 194 char *se_user; /* user name to run as */ 195 char *se_group; /* group name to run as */ 196 struct biltin *se_bi; /* if built-in, description */ 197 char *se_server; /* server program */ 198 #define MAXARGV 20 199 char *se_argv[MAXARGV+1]; /* program arguments */ 200 int se_fd; /* open descriptor */ 201 union { 202 struct sockaddr se_un_ctrladdr; 203 struct sockaddr_in se_un_ctrladdr_in; 204 struct sockaddr_in6 se_un_ctrladdr_in6; 205 struct sockaddr_un se_un_ctrladdr_un; 206 struct sockaddr_storage se_un_ctrladdr_storage; 207 } se_un; /* bound address */ 208 #define se_ctrladdr se_un.se_un_ctrladdr 209 #define se_ctrladdr_in se_un.se_un_ctrladdr_in 210 #define se_ctrladdr_in6 se_un.se_un_ctrladdr_in6 211 #define se_ctrladdr_un se_un.se_un_ctrladdr_un 212 #define se_ctrladdr_storage se_un.se_un_ctrladdr_storage 213 int se_ctrladdr_size; 214 int se_max; /* max # of instances of this service */ 215 int se_count; /* number started since se_time */ 216 struct timeval se_time; /* start of se_count */ 217 struct servtab *se_next; 218 } *servtab; 219 220 void echo_stream(int, struct servtab *); 221 void discard_stream(int, struct servtab *); 222 void machtime_stream(int, struct servtab *); 223 void daytime_stream(int, struct servtab *); 224 void chargen_stream(int, struct servtab *); 225 void echo_dg(int, struct servtab *); 226 void discard_dg(int, struct servtab *); 227 void machtime_dg(int, struct servtab *); 228 void daytime_dg(int, struct servtab *); 229 void chargen_dg(int, struct servtab *); 230 231 struct biltin { 232 char *bi_service; /* internally provided service name */ 233 int bi_socktype; /* type of socket supported */ 234 short bi_fork; /* 1 if should fork before call */ 235 short bi_wait; /* 1 if should wait for child */ 236 void (*bi_fn)(int, struct servtab *); 237 } biltins[] = { 238 /* Echo received data */ 239 { "echo", SOCK_STREAM, 1, 0, echo_stream }, 240 { "echo", SOCK_DGRAM, 0, 0, echo_dg }, 241 242 /* Internet /dev/null */ 243 { "discard", SOCK_STREAM, 1, 0, discard_stream }, 244 { "discard", SOCK_DGRAM, 0, 0, discard_dg }, 245 246 /* Return 32 bit time since 1900 */ 247 { "time", SOCK_STREAM, 0, 0, machtime_stream }, 248 { "time", SOCK_DGRAM, 0, 0, machtime_dg }, 249 250 /* Return human-readable time */ 251 { "daytime", SOCK_STREAM, 0, 0, daytime_stream }, 252 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg }, 253 254 /* Familiar character generator */ 255 { "chargen", SOCK_STREAM, 1, 0, chargen_stream }, 256 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg }, 257 258 { 0 } 259 }; 260 261 volatile sig_atomic_t wantretry; 262 volatile sig_atomic_t wantconfig; 263 volatile sig_atomic_t wantreap; 264 volatile sig_atomic_t wantdie; 265 266 void config(int); 267 void doconfig(void); 268 void reap(int); 269 void doreap(void); 270 void retry(int); 271 void doretry(void); 272 void die(int); 273 void dodie(void); 274 void logpid(void); 275 void spawn(struct servtab *, int); 276 int gettcp(struct servtab *); 277 int setconfig(void); 278 void endconfig(void); 279 void register_rpc(struct servtab *); 280 void unregister_rpc(struct servtab *); 281 void freeconfig(struct servtab *); 282 void print_service(char *, struct servtab *); 283 void setup(struct servtab *); 284 struct servtab *getconfigent(void); 285 int bump_nofile(void); 286 struct servtab *enter(struct servtab *); 287 int matchconf(struct servtab *, struct servtab *); 288 int dg_broadcast(struct in_addr *in); 289 290 #define NUMINT (sizeof(intab) / sizeof(struct inent)) 291 char *CONFIG = _PATH_INETDCONF; 292 293 void 294 fd_grow(fd_set **fdsp, int *bytes, int fd) 295 { 296 caddr_t new; 297 int newbytes; 298 299 newbytes = howmany(fd+1, NFDBITS) * sizeof(fd_mask); 300 if (newbytes > *bytes) { 301 newbytes *= 2; /* optimism */ 302 new = realloc(*fdsp, newbytes); 303 if (new == NULL) { 304 syslog(LOG_ERR, "Out of memory."); 305 exit(1); 306 } 307 memset(new + *bytes, 0, newbytes - *bytes); 308 *fdsp = (fd_set *)new; 309 *bytes = newbytes; 310 } 311 } 312 313 struct sigaction sa, sapipe; 314 315 int 316 main(int argc, char *argv[]) 317 { 318 fd_set *fdsrp = NULL; 319 int readablen = 0, ch; 320 struct servtab *sep; 321 extern char *optarg; 322 extern int optind; 323 324 while ((ch = getopt(argc, argv, "dR:")) != -1) 325 switch (ch) { 326 case 'd': 327 debug = 1; 328 options |= SO_DEBUG; 329 break; 330 case 'R': { /* invocation rate */ 331 char *p; 332 int val; 333 334 val = strtoul(optarg, &p, 0); 335 if (val >= 1 && *p == '\0') { 336 toomany = val; 337 break; 338 } 339 syslog(LOG_ERR, 340 "-R %s: bad value for service invocation rate", 341 optarg); 342 break; 343 } 344 case '?': 345 default: 346 fprintf(stderr, 347 "usage: inetd [-d] [-R rate] [configuration_file]\n"); 348 exit(1); 349 } 350 argc -= optind; 351 argv += optind; 352 353 uid = getuid(); 354 if (uid != 0) 355 CONFIG = NULL; 356 if (argc > 0) 357 CONFIG = argv[0]; 358 if (CONFIG == NULL) { 359 fprintf(stderr, "inetd: non-root must specify a config file\n"); 360 exit(1); 361 } 362 if (argc > 1) { 363 fprintf(stderr, "inetd: more than one argument specified\n"); 364 exit(1); 365 } 366 367 umask(022); 368 if (debug == 0) { 369 daemon(0, 0); 370 if (uid == 0) 371 (void) setlogin(""); 372 } 373 374 if (uid == 0) { 375 gid_t gid = getgid(); 376 377 /* If run by hand, ensure groups vector gets trashed */ 378 setgroups(1, &gid); 379 } 380 381 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); 382 logpid(); 383 384 if (getrlimit(RLIMIT_NOFILE, &rlim_nofile) < 0) { 385 syslog(LOG_ERR, "getrlimit: %m"); 386 } else { 387 rlim_nofile_cur = rlim_nofile.rlim_cur; 388 if (rlim_nofile_cur == RLIM_INFINITY) /* ! */ 389 rlim_nofile_cur = OPEN_MAX; 390 } 391 392 sigemptyset(&emptymask); 393 sigemptyset(&blockmask); 394 sigaddset(&blockmask, SIGCHLD); 395 sigaddset(&blockmask, SIGHUP); 396 sigaddset(&blockmask, SIGALRM); 397 398 memset(&sa, 0, sizeof(sa)); 399 sigemptyset(&sa.sa_mask); 400 sigaddset(&sa.sa_mask, SIGALRM); 401 sigaddset(&sa.sa_mask, SIGCHLD); 402 sigaddset(&sa.sa_mask, SIGHUP); 403 sa.sa_handler = retry; 404 sigaction(SIGALRM, &sa, NULL); 405 doconfig(); 406 sa.sa_handler = config; 407 sigaction(SIGHUP, &sa, NULL); 408 sa.sa_handler = reap; 409 sigaction(SIGCHLD, &sa, NULL); 410 sa.sa_handler = die; 411 sigaction(SIGTERM, &sa, NULL); 412 sa.sa_handler = die; 413 sigaction(SIGINT, &sa, NULL); 414 sa.sa_handler = SIG_IGN; 415 sigaction(SIGPIPE, &sa, &sapipe); 416 417 for (;;) { 418 int n, ctrl = -1; 419 420 restart: 421 if (nsock == 0) { 422 (void) sigprocmask(SIG_BLOCK, &blockmask, NULL); 423 while (nsock == 0) { 424 if (wantretry || wantconfig || wantreap || wantdie) 425 break; 426 sigsuspend(&emptymask); 427 } 428 (void) sigprocmask(SIG_SETMASK, &emptymask, NULL); 429 } 430 431 while (wantretry || wantconfig || wantreap || wantdie) { 432 if (wantretry) { 433 wantretry = 0; 434 doretry(); 435 } 436 if (wantconfig) { 437 wantconfig = 0; 438 doconfig(); 439 } 440 if (wantreap) { 441 wantreap = 0; 442 doreap(); 443 } 444 if (wantdie) 445 dodie(); 446 goto restart; 447 } 448 449 if (readablen != allsockn) { 450 if (fdsrp) 451 free(fdsrp); 452 fdsrp = (fd_set *)calloc(allsockn, 1); 453 if (fdsrp == NULL) { 454 syslog(LOG_ERR, "Out of memory."); 455 exit(1); 456 } 457 readablen = allsockn; 458 } 459 bcopy(allsockp, fdsrp, allsockn); 460 461 if ((n = select(maxsock + 1, fdsrp, NULL, NULL, NULL)) <= 0) { 462 if (n < 0 && errno != EINTR) { 463 syslog(LOG_WARNING, "select: %m"); 464 sleep(1); 465 } 466 continue; 467 } 468 469 for (sep = servtab; n && sep; sep = sep->se_next) { 470 if (sep->se_fd != -1 && 471 FD_ISSET(sep->se_fd, fdsrp)) { 472 n--; 473 if (debug) 474 fprintf(stderr, "someone wants %s\n", 475 sep->se_service); 476 if (!sep->se_wait && 477 sep->se_socktype == SOCK_STREAM) { 478 ctrl = gettcp(sep); 479 if (ctrl == -1) 480 continue; 481 } else 482 ctrl = sep->se_fd; 483 (void) sigprocmask(SIG_BLOCK, &blockmask, NULL); 484 spawn(sep, ctrl); /* spawn will unblock */ 485 } 486 } 487 } 488 } 489 490 int 491 gettcp(struct servtab *sep) 492 { 493 int ctrl; 494 495 ctrl = accept(sep->se_fd, NULL, NULL); 496 if (debug) 497 fprintf(stderr, "accept, ctrl %d\n", ctrl); 498 if (ctrl < 0) { 499 if (errno == EINTR) 500 return -1; 501 syslog(LOG_WARNING, "accept (for %s): %m", sep->se_service); 502 return -1; 503 } 504 if ((sep->se_family == AF_INET || sep->se_family == AF_INET6) && 505 sep->se_socktype == SOCK_STREAM) { 506 struct sockaddr_storage peer; 507 socklen_t plen = sizeof(peer); 508 char sbuf[NI_MAXSERV]; 509 510 if (getpeername(ctrl, (struct sockaddr *)&peer, &plen) < 0) { 511 syslog(LOG_WARNING, "could not getpeername"); 512 close(ctrl); 513 return -1; 514 } 515 if (getnameinfo((struct sockaddr *)&peer, plen, NULL, 0, 516 sbuf, sizeof(sbuf), NI_NUMERICSERV) == 0 && 517 atoi(sbuf) == 20) { 518 /* 519 * ignore things that look like ftp bounce 520 */ 521 close(ctrl); 522 return -1; 523 } 524 } 525 return (ctrl); 526 } 527 528 529 int 530 dg_badinput(struct sockaddr *sa) 531 { 532 struct in_addr in; 533 struct in6_addr *in6; 534 u_int16_t port; 535 536 switch (sa->sa_family) { 537 case AF_INET: 538 in.s_addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr); 539 port = ntohs(((struct sockaddr_in *)sa)->sin_port); 540 v4chk: 541 if (IN_MULTICAST(in.s_addr)) 542 goto bad; 543 switch ((in.s_addr & 0xff000000) >> 24) { 544 case 0: case 127: case 255: 545 goto bad; 546 } 547 if (dg_broadcast(&in)) 548 goto bad; 549 break; 550 case AF_INET6: 551 in6 = &((struct sockaddr_in6 *)sa)->sin6_addr; 552 port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port); 553 if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6)) 554 goto bad; 555 /* 556 * OpenBSD does not support IPv4 mapped address (RFC2553 557 * inbound behavior) at all. We should drop it. 558 */ 559 if (IN6_IS_ADDR_V4MAPPED(in6)) 560 goto bad; 561 if (IN6_IS_ADDR_V4COMPAT(in6)) { 562 memcpy(&in, &in6->s6_addr[12], sizeof(in)); 563 in.s_addr = ntohl(in.s_addr); 564 goto v4chk; 565 } 566 break; 567 default: 568 /* XXX unsupported af, is it safe to assume it to be safe? */ 569 return 0; 570 } 571 572 if (port < IPPORT_RESERVED || port == NFS_PORT) 573 goto bad; 574 575 return (0); 576 577 bad: 578 return (1); 579 } 580 581 int 582 dg_broadcast(struct in_addr *in) 583 { 584 struct ifaddrs *ifa, *ifap; 585 struct sockaddr_in *sin; 586 587 if (getifaddrs(&ifap) < 0) 588 return (0); 589 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 590 if (ifa->ifa_addr->sa_family != AF_INET || 591 (ifa->ifa_flags & IFF_BROADCAST) == 0) 592 continue; 593 sin = (struct sockaddr_in *)ifa->ifa_broadaddr; 594 if (sin->sin_addr.s_addr == in->s_addr) { 595 freeifaddrs(ifap); 596 return (1); 597 } 598 } 599 freeifaddrs(ifap); 600 return (0); 601 } 602 603 /* ARGSUSED */ 604 void 605 reap(int sig) 606 { 607 wantreap = 1; 608 } 609 610 void 611 doreap(void) 612 { 613 struct servtab *sep; 614 int status; 615 pid_t pid; 616 617 if (debug) 618 fprintf(stderr, "reaping asked for\n"); 619 620 for (;;) { 621 if ((pid = wait3(&status, WNOHANG, NULL)) <= 0) { 622 if (pid == -1 && errno == EINTR) 623 continue; 624 break; 625 } 626 if (debug) 627 fprintf(stderr, "%ld reaped, status %x\n", 628 (long)pid, status); 629 for (sep = servtab; sep; sep = sep->se_next) 630 if (sep->se_wait == pid) { 631 if (WIFEXITED(status) && WEXITSTATUS(status)) 632 syslog(LOG_WARNING, 633 "%s: exit status %d", 634 sep->se_server, WEXITSTATUS(status)); 635 else if (WIFSIGNALED(status)) 636 syslog(LOG_WARNING, 637 "%s: exit signal %d", 638 sep->se_server, WTERMSIG(status)); 639 sep->se_wait = 1; 640 fd_grow(&allsockp, &allsockn, sep->se_fd); 641 FD_SET(sep->se_fd, allsockp); 642 nsock++; 643 if (debug) 644 fprintf(stderr, "restored %s, fd %d\n", 645 sep->se_service, sep->se_fd); 646 } 647 } 648 } 649 650 /* ARGSUSED */ 651 void 652 config(int sig) 653 { 654 wantconfig = 1; 655 } 656 657 void 658 doconfig(void) 659 { 660 struct servtab *sep, *cp, **sepp; 661 int add; 662 char protoname[10]; 663 sigset_t omask; 664 665 if (!setconfig()) { 666 syslog(LOG_ERR, "%s: %m", CONFIG); 667 exit(1); 668 } 669 for (sep = servtab; sep; sep = sep->se_next) 670 sep->se_checked = 0; 671 cp = getconfigent(); 672 while (cp != NULL) { 673 for (sep = servtab; sep; sep = sep->se_next) 674 if (matchconf(sep, cp)) 675 break; 676 add = 0; 677 if (sep != NULL) { 678 int i; 679 680 #define SWAP(type, a, b) {type c=(type)a; a=(type)b; b=(type)c;} 681 682 sigprocmask(SIG_BLOCK, &blockmask, &omask); 683 /* 684 * sep->se_wait may be holding the pid of a daemon 685 * that we're waiting for. If so, don't overwrite 686 * it unless the config file explicitly says don't 687 * wait. 688 */ 689 if (cp->se_bi == 0 && 690 (sep->se_wait == 1 || cp->se_wait == 0)) 691 sep->se_wait = cp->se_wait; 692 SWAP(int, cp->se_max, sep->se_max); 693 SWAP(char *, sep->se_user, cp->se_user); 694 SWAP(char *, sep->se_group, cp->se_group); 695 SWAP(char *, sep->se_server, cp->se_server); 696 for (i = 0; i < MAXARGV; i++) 697 SWAP(char *, sep->se_argv[i], cp->se_argv[i]); 698 #undef SWAP 699 if (isrpcservice(sep)) 700 unregister_rpc(sep); 701 sep->se_rpcversl = cp->se_rpcversl; 702 sep->se_rpcversh = cp->se_rpcversh; 703 sigprocmask(SIG_SETMASK, &omask, NULL); 704 freeconfig(cp); 705 add = 1; 706 } else { 707 sep = enter(cp); 708 } 709 sep->se_checked = 1; 710 711 switch (sep->se_family) { 712 case AF_UNIX: 713 if (sep->se_fd != -1) 714 break; 715 sep->se_ctrladdr_size = 716 strlcpy(sep->se_ctrladdr_un.sun_path, 717 sep->se_service, 718 sizeof sep->se_ctrladdr_un.sun_path); 719 if (sep->se_ctrladdr_size >= 720 sizeof sep->se_ctrladdr_un.sun_path) { 721 syslog(LOG_WARNING, "%s/%s: UNIX domain socket " 722 "path too long", sep->se_service, 723 sep->se_proto); 724 goto serv_unknown; 725 } 726 sep->se_ctrladdr_un.sun_family = AF_UNIX; 727 sep->se_ctrladdr_size += 728 1 + sizeof sep->se_ctrladdr_un.sun_family; 729 (void)unlink(sep->se_service); 730 setup(sep); 731 break; 732 case AF_INET: 733 sep->se_ctrladdr_in.sin_family = AF_INET; 734 /* se_ctrladdr_in was set in getconfigent */ 735 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in; 736 737 if (isrpcservice(sep)) { 738 struct rpcent *rp; 739 740 sep->se_rpcprog = atoi(sep->se_service); 741 if (sep->se_rpcprog == 0) { 742 rp = getrpcbyname(sep->se_service); 743 if (rp == 0) { 744 syslog(LOG_ERR, 745 "%s: unknown rpc service", 746 sep->se_service); 747 goto serv_unknown; 748 } 749 sep->se_rpcprog = rp->r_number; 750 } 751 if (sep->se_fd == -1) 752 setup(sep); 753 if (sep->se_fd != -1) 754 register_rpc(sep); 755 } else { 756 u_short port = htons(atoi(sep->se_service)); 757 758 if (!port) { 759 /* XXX */ 760 strncpy(protoname, sep->se_proto, 761 sizeof(protoname)); 762 if (isdigit(protoname[strlen(protoname) - 1])) 763 protoname[strlen(protoname) - 1] = '\0'; 764 sp = getservbyname(sep->se_service, 765 protoname); 766 if (sp == 0) { 767 syslog(LOG_ERR, 768 "%s/%s: unknown service", 769 sep->se_service, sep->se_proto); 770 goto serv_unknown; 771 } 772 port = sp->s_port; 773 } 774 if (port != sep->se_ctrladdr_in.sin_port) { 775 sep->se_ctrladdr_in.sin_port = port; 776 if (sep->se_fd != -1) { 777 FD_CLR(sep->se_fd, allsockp); 778 nsock--; 779 (void) close(sep->se_fd); 780 } 781 sep->se_fd = -1; 782 } 783 if (sep->se_fd == -1) 784 setup(sep); 785 } 786 break; 787 case AF_INET6: 788 sep->se_ctrladdr_in6.sin6_family = AF_INET6; 789 /* se_ctrladdr_in was set in getconfigent */ 790 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in6; 791 792 if (isrpcservice(sep)) { 793 struct rpcent *rp; 794 795 sep->se_rpcprog = atoi(sep->se_service); 796 if (sep->se_rpcprog == 0) { 797 rp = getrpcbyname(sep->se_service); 798 if (rp == 0) { 799 syslog(LOG_ERR, 800 "%s: unknown rpc service", 801 sep->se_service); 802 goto serv_unknown; 803 } 804 sep->se_rpcprog = rp->r_number; 805 } 806 if (sep->se_fd == -1) 807 setup(sep); 808 if (sep->se_fd != -1) 809 register_rpc(sep); 810 } else { 811 u_short port = htons(atoi(sep->se_service)); 812 813 if (!port) { 814 /* XXX */ 815 strncpy(protoname, sep->se_proto, 816 sizeof(protoname)); 817 if (isdigit(protoname[strlen(protoname) - 1])) 818 protoname[strlen(protoname) - 1] = '\0'; 819 sp = getservbyname(sep->se_service, 820 protoname); 821 if (sp == 0) { 822 syslog(LOG_ERR, 823 "%s/%s: unknown service", 824 sep->se_service, sep->se_proto); 825 goto serv_unknown; 826 } 827 port = sp->s_port; 828 } 829 if (port != sep->se_ctrladdr_in6.sin6_port) { 830 sep->se_ctrladdr_in6.sin6_port = port; 831 if (sep->se_fd != -1) { 832 FD_CLR(sep->se_fd, allsockp); 833 nsock--; 834 (void) close(sep->se_fd); 835 } 836 sep->se_fd = -1; 837 } 838 if (sep->se_fd == -1) 839 setup(sep); 840 } 841 break; 842 } 843 serv_unknown: 844 if (cp->se_next != NULL) { 845 struct servtab *tmp = cp; 846 847 cp = cp->se_next; 848 free(tmp); 849 } else { 850 free(cp); 851 cp = getconfigent(); 852 } 853 if (debug) 854 print_service(add ? "REDO" : "ADD", sep); 855 } 856 endconfig(); 857 /* 858 * Purge anything not looked at above. 859 */ 860 sigprocmask(SIG_BLOCK, &blockmask, &omask); 861 sepp = &servtab; 862 while ((sep = *sepp)) { 863 if (sep->se_checked) { 864 sepp = &sep->se_next; 865 continue; 866 } 867 *sepp = sep->se_next; 868 if (sep->se_fd != -1) { 869 FD_CLR(sep->se_fd, allsockp); 870 nsock--; 871 (void) close(sep->se_fd); 872 } 873 if (isrpcservice(sep)) 874 unregister_rpc(sep); 875 if (sep->se_family == AF_UNIX) 876 (void)unlink(sep->se_service); 877 if (debug) 878 print_service("FREE", sep); 879 freeconfig(sep); 880 free(sep); 881 } 882 sigprocmask(SIG_SETMASK, &omask, NULL); 883 } 884 885 /* ARGSUSED */ 886 void 887 retry(int sig) 888 { 889 wantretry = 1; 890 } 891 892 void 893 doretry(void) 894 { 895 struct servtab *sep; 896 897 timingout = 0; 898 for (sep = servtab; sep; sep = sep->se_next) { 899 if (sep->se_fd == -1) { 900 switch (sep->se_family) { 901 case AF_UNIX: 902 case AF_INET: 903 case AF_INET6: 904 setup(sep); 905 if (sep->se_fd != -1 && isrpcservice(sep)) 906 register_rpc(sep); 907 break; 908 } 909 } 910 } 911 } 912 913 /* ARGSUSED */ 914 void 915 die(int sig) 916 { 917 wantdie = 1; 918 } 919 920 void 921 dodie(void) 922 { 923 struct servtab *sep; 924 925 for (sep = servtab; sep; sep = sep->se_next) { 926 if (sep->se_fd == -1) 927 continue; 928 929 switch (sep->se_family) { 930 case AF_UNIX: 931 (void)unlink(sep->se_service); 932 break; 933 case AF_INET: 934 case AF_INET6: 935 if (sep->se_wait == 1 && isrpcservice(sep)) 936 unregister_rpc(sep); 937 break; 938 } 939 (void)close(sep->se_fd); 940 } 941 (void)unlink(_PATH_INETDPID); 942 exit(0); 943 } 944 945 void 946 setup(struct servtab *sep) 947 { 948 int on = 1; 949 int r; 950 mode_t mask = 0; 951 952 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 953 syslog(LOG_ERR, "%s/%s: socket: %m", 954 sep->se_service, sep->se_proto); 955 return; 956 } 957 #define turnon(fd, opt) \ 958 setsockopt(fd, SOL_SOCKET, opt, &on, sizeof (on)) 959 if (strncmp(sep->se_proto, "tcp", 3) == 0 && (options & SO_DEBUG) && 960 turnon(sep->se_fd, SO_DEBUG) < 0) 961 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 962 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 963 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 964 #undef turnon 965 if (isrpcservice(sep)) { 966 struct passwd *pwd; 967 968 /* 969 * for RPC services, attempt to use a reserved port 970 * if they are going to be running as root. 971 * 972 * Also, zero out the port for all RPC services; let bind() 973 * find one. 974 */ 975 sep->se_ctrladdr_in.sin_port = 0; 976 if (sep->se_user && (pwd = getpwnam(sep->se_user)) && 977 pwd->pw_uid == 0 && uid == 0) 978 r = bindresvport(sep->se_fd, &sep->se_ctrladdr_in); 979 else { 980 r = bind(sep->se_fd, &sep->se_ctrladdr, 981 sep->se_ctrladdr_size); 982 if (r == 0) { 983 socklen_t len = sep->se_ctrladdr_size; 984 int saveerrno = errno; 985 986 /* update se_ctrladdr_in.sin_port */ 987 r = getsockname(sep->se_fd, &sep->se_ctrladdr, 988 &len); 989 if (r <= 0) 990 errno = saveerrno; 991 } 992 } 993 } else { 994 if (sep->se_family == AF_UNIX) 995 mask = umask(0111); 996 r = bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size); 997 if (sep->se_family == AF_UNIX) 998 umask(mask); 999 } 1000 if (r < 0) { 1001 syslog(LOG_ERR, "%s/%s: bind: %m", 1002 sep->se_service, sep->se_proto); 1003 (void) close(sep->se_fd); 1004 sep->se_fd = -1; 1005 if (!timingout) { 1006 timingout = 1; 1007 alarm(RETRYTIME); 1008 } 1009 return; 1010 } 1011 if (sep->se_socktype == SOCK_STREAM) 1012 listen(sep->se_fd, 10); 1013 1014 fd_grow(&allsockp, &allsockn, sep->se_fd); 1015 FD_SET(sep->se_fd, allsockp); 1016 nsock++; 1017 if (sep->se_fd > maxsock) { 1018 maxsock = sep->se_fd; 1019 if (maxsock > rlim_nofile_cur - FD_MARGIN) 1020 bump_nofile(); 1021 } 1022 } 1023 1024 void 1025 register_rpc(struct servtab *sep) 1026 { 1027 socklen_t n; 1028 struct sockaddr_in sin; 1029 struct protoent *pp; 1030 1031 if ((pp = getprotobyname(sep->se_proto+4)) == NULL) { 1032 syslog(LOG_ERR, "%s: getproto: %m", 1033 sep->se_proto); 1034 return; 1035 } 1036 n = sizeof sin; 1037 if (getsockname(sep->se_fd, (struct sockaddr *)&sin, &n) < 0) { 1038 syslog(LOG_ERR, "%s/%s: getsockname: %m", 1039 sep->se_service, sep->se_proto); 1040 return; 1041 } 1042 1043 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1044 if (debug) 1045 fprintf(stderr, "pmap_set: %u %u %u %u\n", 1046 sep->se_rpcprog, n, pp->p_proto, 1047 ntohs(sin.sin_port)); 1048 (void)pmap_unset(sep->se_rpcprog, n); 1049 if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port))) 1050 syslog(LOG_ERR, "%s %s: pmap_set: %u %u %u %u: %m", 1051 sep->se_service, sep->se_proto, 1052 sep->se_rpcprog, n, pp->p_proto, 1053 ntohs(sin.sin_port)); 1054 } 1055 } 1056 1057 void 1058 unregister_rpc(struct servtab *sep) 1059 { 1060 int n; 1061 1062 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1063 if (debug) 1064 fprintf(stderr, "pmap_unset(%u, %u)\n", 1065 sep->se_rpcprog, n); 1066 if (!pmap_unset(sep->se_rpcprog, n)) 1067 syslog(LOG_ERR, "pmap_unset(%u, %u)", 1068 sep->se_rpcprog, n); 1069 } 1070 } 1071 1072 1073 struct servtab * 1074 enter(struct servtab *cp) 1075 { 1076 struct servtab *sep; 1077 sigset_t omask; 1078 1079 sep = (struct servtab *)malloc(sizeof (*sep)); 1080 if (sep == NULL) { 1081 syslog(LOG_ERR, "Out of memory."); 1082 exit(1); 1083 } 1084 *sep = *cp; 1085 sep->se_fd = -1; 1086 sep->se_rpcprog = -1; 1087 sigprocmask(SIG_BLOCK, &blockmask, &omask); 1088 sep->se_next = servtab; 1089 servtab = sep; 1090 sigprocmask(SIG_SETMASK, &omask, NULL); 1091 return (sep); 1092 } 1093 1094 int 1095 matchconf(struct servtab *old, struct servtab *new) 1096 { 1097 if (strcmp(old->se_service, new->se_service) != 0) 1098 return (0); 1099 1100 if (strcmp(old->se_hostaddr, new->se_hostaddr) != 0) 1101 return (0); 1102 1103 if (strcmp(old->se_proto, new->se_proto) != 0) 1104 return (0); 1105 1106 /* 1107 * If the new servtab is bound to a specific address, check that the 1108 * old servtab is bound to the same entry. If the new service is not 1109 * bound to a specific address then the check of se_hostaddr above 1110 * is sufficient. 1111 */ 1112 1113 if (old->se_family == AF_INET && new->se_family == AF_INET && 1114 bcmp(&old->se_ctrladdr_in.sin_addr, 1115 &new->se_ctrladdr_in.sin_addr, 1116 sizeof(new->se_ctrladdr_in.sin_addr)) != 0) 1117 return (0); 1118 1119 if (old->se_family == AF_INET6 && new->se_family == AF_INET6 && 1120 bcmp(&old->se_ctrladdr_in6.sin6_addr, 1121 &new->se_ctrladdr_in6.sin6_addr, 1122 sizeof(new->se_ctrladdr_in6.sin6_addr)) != 0) 1123 return (0); 1124 if (old->se_family == AF_INET6 && new->se_family == AF_INET6 && 1125 old->se_ctrladdr_in6.sin6_scope_id != 1126 new->se_ctrladdr_in6.sin6_scope_id) 1127 return (0); 1128 1129 return (1); 1130 } 1131 1132 FILE *fconfig = NULL; 1133 char line[1024]; 1134 char *defhost; 1135 char *skip(char **, int); 1136 char *nextline(FILE *); 1137 char *newstr(char *); 1138 struct servtab *dupconfig(struct servtab *); 1139 1140 int 1141 setconfig(void) 1142 { 1143 if (defhost) 1144 free(defhost); 1145 defhost = newstr("*"); 1146 if (fconfig != NULL) { 1147 fseek(fconfig, 0L, SEEK_SET); 1148 return (1); 1149 } 1150 fconfig = fopen(CONFIG, "r"); 1151 return (fconfig != NULL); 1152 } 1153 1154 void 1155 endconfig(void) 1156 { 1157 if (fconfig) { 1158 (void) fclose(fconfig); 1159 fconfig = NULL; 1160 } 1161 if (defhost) { 1162 free(defhost); 1163 defhost = 0; 1164 } 1165 } 1166 1167 struct servtab * 1168 getconfigent(void) 1169 { 1170 struct servtab *sep, *tsep; 1171 char *arg, *cp, *hostdelim, *s; 1172 int argc; 1173 1174 sep = (struct servtab *) malloc(sizeof(struct servtab)); 1175 if (sep == NULL) { 1176 syslog(LOG_ERR, "malloc: %m"); 1177 exit(1); 1178 } 1179 1180 memset(sep, 0, sizeof *sep); 1181 more: 1182 freeconfig(sep); 1183 1184 while ((cp = nextline(fconfig)) && *cp == '#') 1185 ; 1186 if (cp == NULL) { 1187 free(sep); 1188 return (NULL); 1189 } 1190 1191 memset(sep, 0, sizeof *sep); 1192 arg = skip(&cp, 0); 1193 if (arg == NULL) { 1194 /* A blank line. */ 1195 goto more; 1196 } 1197 1198 /* Check for a host name. */ 1199 hostdelim = strrchr(arg, ':'); 1200 if (hostdelim) { 1201 *hostdelim = '\0'; 1202 if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') { 1203 hostdelim[-1] = '\0'; 1204 sep->se_hostaddr = newstr(arg + 1); 1205 } else if (hostdelim == arg) 1206 sep->se_hostaddr = newstr("*"); 1207 else 1208 sep->se_hostaddr = newstr(arg); 1209 arg = hostdelim + 1; 1210 /* 1211 * If the line is of the form `host:', then just change the 1212 * default host for the following lines. 1213 */ 1214 if (*arg == '\0') { 1215 arg = skip(&cp, 0); 1216 if (cp == NULL) { 1217 free(defhost); 1218 defhost = newstr(sep->se_hostaddr); 1219 goto more; 1220 } 1221 } 1222 } else 1223 sep->se_hostaddr = newstr(defhost); 1224 1225 sep->se_service = newstr(arg); 1226 if ((arg = skip(&cp, 1)) == NULL) 1227 goto more; 1228 1229 if (strcmp(arg, "stream") == 0) 1230 sep->se_socktype = SOCK_STREAM; 1231 else if (strcmp(arg, "dgram") == 0) 1232 sep->se_socktype = SOCK_DGRAM; 1233 else if (strcmp(arg, "rdm") == 0) 1234 sep->se_socktype = SOCK_RDM; 1235 else if (strcmp(arg, "seqpacket") == 0) 1236 sep->se_socktype = SOCK_SEQPACKET; 1237 else if (strcmp(arg, "raw") == 0) 1238 sep->se_socktype = SOCK_RAW; 1239 else 1240 sep->se_socktype = -1; 1241 1242 if ((arg = skip(&cp, 1)) == NULL) 1243 goto more; 1244 1245 sep->se_proto = newstr(arg); 1246 1247 if (strcmp(sep->se_proto, "unix") == 0) { 1248 sep->se_family = AF_UNIX; 1249 } else { 1250 int s; 1251 1252 sep->se_family = AF_INET; 1253 if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') 1254 sep->se_family = AF_INET6; 1255 1256 /* check if the family is supported */ 1257 s = socket(sep->se_family, SOCK_DGRAM, 0); 1258 if (s < 0) { 1259 syslog(LOG_WARNING, "%s/%s: %s: the address family is " 1260 "not supported by the kernel", sep->se_service, 1261 sep->se_proto, sep->se_hostaddr); 1262 goto more; 1263 } 1264 close(s); 1265 1266 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 1267 char *cp, *ccp; 1268 long l; 1269 1270 cp = strchr(sep->se_service, '/'); 1271 if (cp == 0) { 1272 syslog(LOG_ERR, "%s: no rpc version", 1273 sep->se_service); 1274 goto more; 1275 } 1276 *cp++ = '\0'; 1277 l = strtol(cp, &ccp, 0); 1278 if (ccp == cp || l < 0 || l > INT_MAX) { 1279 badafterall: 1280 syslog(LOG_ERR, "%s/%s: bad rpc version", 1281 sep->se_service, cp); 1282 goto more; 1283 } 1284 sep->se_rpcversl = sep->se_rpcversh = l; 1285 if (*ccp == '-') { 1286 cp = ccp + 1; 1287 l = strtol(cp, &ccp, 0); 1288 if (ccp == cp || l < 0 || l > INT_MAX || 1289 l < sep->se_rpcversl || *ccp) 1290 goto badafterall; 1291 sep->se_rpcversh = l; 1292 } else if (*ccp != '\0') 1293 goto badafterall; 1294 } 1295 } 1296 arg = skip(&cp, 1); 1297 if (arg == NULL) 1298 goto more; 1299 1300 s = strchr(arg, '.'); 1301 if (s) { 1302 char *p; 1303 1304 *s++ = '\0'; 1305 sep->se_max = strtoul(s, &p, 0); 1306 if (sep->se_max < 1 || *p) { 1307 syslog(LOG_ERR, 1308 "%s: illegal max field \"%s\", setting to %d", 1309 sep->se_service, s, toomany); 1310 sep->se_max = toomany; 1311 } 1312 } else 1313 sep->se_max = toomany; 1314 1315 sep->se_wait = strcmp(arg, "wait") == 0; 1316 if ((arg = skip(&cp, 1)) == NULL) 1317 goto more; 1318 sep->se_user = newstr(arg); 1319 arg = strchr(sep->se_user, '.'); 1320 if (arg == NULL) 1321 arg = strchr(sep->se_user, ':'); 1322 if (arg) { 1323 *arg++ = '\0'; 1324 sep->se_group = newstr(arg); 1325 } 1326 if ((arg = skip(&cp, 1)) == NULL) 1327 goto more; 1328 1329 sep->se_server = newstr(arg); 1330 if (strcmp(sep->se_server, "internal") == 0) { 1331 struct biltin *bi; 1332 1333 for (bi = biltins; bi->bi_service; bi++) 1334 if (bi->bi_socktype == sep->se_socktype && 1335 strcmp(bi->bi_service, sep->se_service) == 0) 1336 break; 1337 if (bi->bi_service == 0) { 1338 syslog(LOG_ERR, "internal service %s unknown", 1339 sep->se_service); 1340 goto more; 1341 } 1342 sep->se_bi = bi; 1343 sep->se_wait = bi->bi_wait; 1344 } else 1345 sep->se_bi = NULL; 1346 argc = 0; 1347 for (arg = skip(&cp, 0); cp; arg = skip(&cp, 0)) { 1348 if (argc < MAXARGV) 1349 sep->se_argv[argc++] = newstr(arg); 1350 } 1351 if (argc == 0 && sep->se_bi == NULL) { 1352 if ((arg = strrchr(sep->se_server, '/')) != NULL) 1353 arg++; 1354 else 1355 arg = sep->se_server; 1356 sep->se_argv[argc++] = newstr(arg); 1357 } 1358 while (argc <= MAXARGV) 1359 sep->se_argv[argc++] = NULL; 1360 1361 /* 1362 * Resolve each hostname in the se_hostaddr list (if any) 1363 * and create a new entry for each resolved address. 1364 */ 1365 if (sep->se_hostaddr != NULL && strcmp(sep->se_proto, "unix") != 0) { 1366 struct addrinfo hints, *res0, *res; 1367 char *host, *hostlist0, *hostlist, *port; 1368 int error; 1369 1370 hostlist = hostlist0 = sep->se_hostaddr; 1371 sep->se_hostaddr = NULL; 1372 sep->se_checked = -1; 1373 while ((host = strsep(&hostlist, ",")) != NULL) { 1374 if (*host == '\0') 1375 continue; 1376 1377 memset(&hints, 0, sizeof(hints)); 1378 hints.ai_family = sep->se_family; 1379 hints.ai_socktype = sep->se_socktype; 1380 hints.ai_flags = AI_PASSIVE; 1381 port = "0"; 1382 /* XXX shortened IPv4 syntax is now forbidden */ 1383 error = getaddrinfo(strcmp(host, "*") ? host : NULL, 1384 port, &hints, &res0); 1385 if (error) { 1386 syslog(LOG_ERR, "%s/%s: %s: %s", 1387 sep->se_service, sep->se_proto, 1388 host, gai_strerror(error)); 1389 continue; 1390 } 1391 for (res = res0; res; res = res->ai_next) { 1392 if (res->ai_addrlen > 1393 sizeof(sep->se_ctrladdr_storage)) 1394 continue; 1395 /* 1396 * If sep is unused, store host in there. 1397 * Otherwise, dup a new entry and prepend it. 1398 */ 1399 if (sep->se_checked == -1) { 1400 sep->se_checked = 0; 1401 } else { 1402 tsep = dupconfig(sep); 1403 tsep->se_next = sep; 1404 sep = tsep; 1405 } 1406 sep->se_hostaddr = newstr(host); 1407 memcpy(&sep->se_ctrladdr_storage, 1408 res->ai_addr, res->ai_addrlen); 1409 sep->se_ctrladdr_size = res->ai_addrlen; 1410 } 1411 freeaddrinfo(res0); 1412 } 1413 free(hostlist0); 1414 if (sep->se_checked == -1) 1415 goto more; /* no resolvable names/addresses */ 1416 } 1417 1418 return (sep); 1419 } 1420 1421 void 1422 freeconfig(struct servtab *cp) 1423 { 1424 int i; 1425 1426 free(cp->se_hostaddr); 1427 cp->se_hostaddr = NULL; 1428 free(cp->se_service); 1429 cp->se_service = NULL; 1430 free(cp->se_proto); 1431 cp->se_proto = NULL; 1432 free(cp->se_user); 1433 cp->se_user = NULL; 1434 free(cp->se_group); 1435 cp->se_group = NULL; 1436 free(cp->se_server); 1437 cp->se_server = NULL; 1438 for (i = 0; i < MAXARGV; i++) { 1439 free(cp->se_argv[i]); 1440 cp->se_argv[i] = NULL; 1441 } 1442 } 1443 1444 char * 1445 skip(char **cpp, int report) 1446 { 1447 char *cp = *cpp; 1448 char *start; 1449 1450 erp: 1451 if (*cpp == NULL) { 1452 if (report) 1453 syslog(LOG_ERR, "syntax error in inetd config file"); 1454 return (NULL); 1455 } 1456 1457 again: 1458 while (*cp == ' ' || *cp == '\t') 1459 cp++; 1460 if (*cp == '\0') { 1461 int c; 1462 1463 c = getc(fconfig); 1464 (void) ungetc(c, fconfig); 1465 if (c == ' ' || c == '\t') 1466 if ((cp = nextline(fconfig))) 1467 goto again; 1468 *cpp = NULL; 1469 goto erp; 1470 } 1471 start = cp; 1472 while (*cp && *cp != ' ' && *cp != '\t') 1473 cp++; 1474 if (*cp != '\0') 1475 *cp++ = '\0'; 1476 if ((*cpp = cp) == NULL) 1477 goto erp; 1478 1479 return (start); 1480 } 1481 1482 char * 1483 nextline(FILE *fd) 1484 { 1485 if (fgets(line, sizeof (line), fd) == NULL) 1486 return (NULL); 1487 line[strcspn(line, "\n")] = '\0'; 1488 return (line); 1489 } 1490 1491 char * 1492 newstr(char *cp) 1493 { 1494 if ((cp = strdup(cp ? cp : ""))) 1495 return(cp); 1496 syslog(LOG_ERR, "strdup: %m"); 1497 exit(1); 1498 } 1499 1500 struct servtab * 1501 dupconfig(struct servtab *sep) 1502 { 1503 struct servtab *newtab; 1504 int argc; 1505 1506 newtab = (struct servtab *) malloc(sizeof(struct servtab)); 1507 1508 if (newtab == NULL) { 1509 syslog(LOG_ERR, "malloc: %m"); 1510 exit(1); 1511 } 1512 1513 memset(newtab, 0, sizeof(struct servtab)); 1514 1515 newtab->se_service = sep->se_service ? newstr(sep->se_service) : NULL; 1516 newtab->se_socktype = sep->se_socktype; 1517 newtab->se_family = sep->se_family; 1518 newtab->se_proto = sep->se_proto ? newstr(sep->se_proto) : NULL; 1519 newtab->se_rpcprog = sep->se_rpcprog; 1520 newtab->se_rpcversl = sep->se_rpcversl; 1521 newtab->se_rpcversh = sep->se_rpcversh; 1522 newtab->se_wait = sep->se_wait; 1523 newtab->se_user = sep->se_user ? newstr(sep->se_user) : NULL; 1524 newtab->se_group = sep->se_group ? newstr(sep->se_group) : NULL; 1525 newtab->se_bi = sep->se_bi; 1526 newtab->se_server = sep->se_server ? newstr(sep->se_server) : 0; 1527 1528 for (argc = 0; argc <= MAXARGV; argc++) 1529 newtab->se_argv[argc] = sep->se_argv[argc] ? 1530 newstr(sep->se_argv[argc]) : NULL; 1531 newtab->se_max = sep->se_max; 1532 1533 return (newtab); 1534 } 1535 1536 void 1537 inetd_setproctitle(char *a, int s) 1538 { 1539 socklen_t size; 1540 struct sockaddr_storage ss; 1541 char hbuf[NI_MAXHOST]; 1542 1543 size = sizeof(ss); 1544 if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) { 1545 if (getnameinfo((struct sockaddr *)&ss, size, hbuf, 1546 sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) 1547 setproctitle("-%s [%s]", a, hbuf); 1548 else 1549 setproctitle("-%s [?]", a); 1550 } else 1551 setproctitle("-%s", a); 1552 } 1553 1554 void 1555 logpid(void) 1556 { 1557 FILE *fp; 1558 1559 if ((fp = fopen(_PATH_INETDPID, "w")) != NULL) { 1560 fprintf(fp, "%ld\n", (long)getpid()); 1561 (void)fclose(fp); 1562 } 1563 } 1564 1565 int 1566 bump_nofile(void) 1567 { 1568 #define FD_CHUNK 32 1569 1570 struct rlimit rl; 1571 1572 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1573 syslog(LOG_ERR, "getrlimit: %m"); 1574 return -1; 1575 } 1576 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1577 rl.rlim_cur = MIN(FD_SETSIZE, rl.rlim_cur + FD_CHUNK); 1578 if (rl.rlim_cur <= rlim_nofile_cur) { 1579 syslog(LOG_ERR, 1580 "bump_nofile: cannot extend file limit, max = %d", 1581 (int)rl.rlim_cur); 1582 return -1; 1583 } 1584 1585 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1586 syslog(LOG_ERR, "setrlimit: %m"); 1587 return -1; 1588 } 1589 1590 rlim_nofile_cur = rl.rlim_cur; 1591 return 0; 1592 } 1593 1594 /* 1595 * Internet services provided internally by inetd: 1596 */ 1597 #define BUFSIZE 4096 1598 1599 /* ARGSUSED */ 1600 void 1601 echo_stream(int s, struct servtab *sep) 1602 { 1603 char buffer[BUFSIZE]; 1604 int i; 1605 1606 inetd_setproctitle(sep->se_service, s); 1607 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1608 write(s, buffer, i) > 0) 1609 ; 1610 exit(0); 1611 } 1612 1613 /* ARGSUSED */ 1614 void 1615 echo_dg(int s, struct servtab *sep) 1616 { 1617 char buffer[BUFSIZE]; 1618 int i; 1619 socklen_t size; 1620 struct sockaddr_storage ss; 1621 1622 size = sizeof(ss); 1623 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, 1624 (struct sockaddr *)&ss, &size)) < 0) 1625 return; 1626 if (dg_badinput((struct sockaddr *)&ss)) 1627 return; 1628 (void) sendto(s, buffer, i, 0, (struct sockaddr *)&ss, size); 1629 } 1630 1631 /* ARGSUSED */ 1632 void 1633 discard_stream(int s, struct servtab *sep) 1634 { 1635 char buffer[BUFSIZE]; 1636 1637 inetd_setproctitle(sep->se_service, s); 1638 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1639 errno == EINTR) 1640 ; 1641 exit(0); 1642 } 1643 1644 /* ARGSUSED */ 1645 void 1646 discard_dg(int s, struct servtab *sep) 1647 { 1648 char buffer[BUFSIZE]; 1649 1650 (void) read(s, buffer, sizeof(buffer)); 1651 } 1652 1653 #include <ctype.h> 1654 #define LINESIZ 72 1655 char ring[128]; 1656 char *endring; 1657 1658 void 1659 initring(void) 1660 { 1661 int i; 1662 1663 endring = ring; 1664 1665 for (i = 0; i <= sizeof ring; ++i) 1666 if (isprint(i)) 1667 *endring++ = i; 1668 } 1669 1670 /* ARGSUSED */ 1671 void 1672 chargen_stream(int s, struct servtab *sep) 1673 { 1674 char *rs; 1675 int len; 1676 char text[LINESIZ+2]; 1677 1678 inetd_setproctitle(sep->se_service, s); 1679 1680 if (!endring) { 1681 initring(); 1682 rs = ring; 1683 } 1684 1685 text[LINESIZ] = '\r'; 1686 text[LINESIZ + 1] = '\n'; 1687 for (rs = ring;;) { 1688 if ((len = endring - rs) >= LINESIZ) 1689 memmove(text, rs, LINESIZ); 1690 else { 1691 memmove(text, rs, len); 1692 memmove(text + len, ring, LINESIZ - len); 1693 } 1694 if (++rs == endring) 1695 rs = ring; 1696 if (write(s, text, sizeof(text)) != sizeof(text)) 1697 break; 1698 } 1699 exit(0); 1700 } 1701 1702 /* ARGSUSED */ 1703 void 1704 chargen_dg(int s, struct servtab *sep) 1705 { 1706 struct sockaddr_storage ss; 1707 static char *rs; 1708 int len; 1709 socklen_t size; 1710 char text[LINESIZ+2]; 1711 1712 if (endring == 0) { 1713 initring(); 1714 rs = ring; 1715 } 1716 1717 size = sizeof(ss); 1718 if (recvfrom(s, text, sizeof(text), 0, (struct sockaddr *)&ss, 1719 &size) < 0) 1720 return; 1721 if (dg_badinput((struct sockaddr *)&ss)) 1722 return; 1723 1724 if ((len = endring - rs) >= LINESIZ) 1725 memmove(text, rs, LINESIZ); 1726 else { 1727 memmove(text, rs, len); 1728 memmove(text + len, ring, LINESIZ - len); 1729 } 1730 if (++rs == endring) 1731 rs = ring; 1732 text[LINESIZ] = '\r'; 1733 text[LINESIZ + 1] = '\n'; 1734 (void) sendto(s, text, sizeof(text), 0, (struct sockaddr *)&ss, size); 1735 } 1736 1737 /* 1738 * Return a machine readable date and time, in the form of the 1739 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1740 * returns the number of seconds since midnight, Jan 1, 1970, 1741 * we must add 2208988800 seconds to this figure to make up for 1742 * some seventy years Bell Labs was asleep. 1743 */ 1744 u_int32_t 1745 machtime(void) 1746 { 1747 struct timeval tv; 1748 1749 if (gettimeofday(&tv, NULL) < 0) 1750 return (0L); 1751 1752 return (htonl((u_int32_t)tv.tv_sec + 2208988800UL)); 1753 } 1754 1755 /* ARGSUSED */ 1756 void 1757 machtime_stream(s, sep) 1758 int s; 1759 struct servtab *sep; 1760 { 1761 u_int32_t result; 1762 1763 result = machtime(); 1764 (void) write(s, &result, sizeof(result)); 1765 } 1766 1767 /* ARGSUSED */ 1768 void 1769 machtime_dg(int s, struct servtab *sep) 1770 { 1771 u_int32_t result; 1772 struct sockaddr_storage ss; 1773 socklen_t size; 1774 1775 size = sizeof(ss); 1776 if (recvfrom(s, &result, sizeof(result), 0, 1777 (struct sockaddr *)&ss, &size) < 0) 1778 return; 1779 if (dg_badinput((struct sockaddr *)&ss)) 1780 return; 1781 result = machtime(); 1782 (void) sendto(s, &result, sizeof(result), 0, 1783 (struct sockaddr *)&ss, size); 1784 } 1785 1786 /* Return human-readable time of day */ 1787 /* ARGSUSED */ 1788 void 1789 daytime_stream(int s, struct servtab *sep) 1790 { 1791 char buffer[256]; 1792 time_t clock; 1793 1794 clock = time(NULL); 1795 1796 (void) snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1797 (void) write(s, buffer, strlen(buffer)); 1798 } 1799 1800 /* Return human-readable time of day */ 1801 /* ARGSUSED */ 1802 void 1803 daytime_dg(int s, struct servtab *sep) 1804 { 1805 char buffer[256]; 1806 time_t clock; 1807 struct sockaddr_storage ss; 1808 socklen_t size; 1809 1810 clock = time(NULL); 1811 1812 size = sizeof(ss); 1813 if (recvfrom(s, buffer, sizeof(buffer), 0, (struct sockaddr *)&ss, 1814 &size) < 0) 1815 return; 1816 if (dg_badinput((struct sockaddr *)&ss)) 1817 return; 1818 (void) snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1819 (void) sendto(s, buffer, strlen(buffer), 0, (struct sockaddr *)&ss, 1820 size); 1821 } 1822 1823 /* 1824 * print_service: 1825 * Dump relevant information to stderr 1826 */ 1827 void 1828 print_service(char *action, struct servtab *sep) 1829 { 1830 if (strcmp(sep->se_hostaddr, "*") == 0) 1831 fprintf(stderr, "%s: %s ", action, sep->se_service); 1832 else 1833 fprintf(stderr, "%s: %s:%s ", action, sep->se_hostaddr, 1834 sep->se_service); 1835 1836 if (isrpcservice(sep)) 1837 fprintf(stderr, "rpcprog=%d, rpcvers=%d/%d, proto=%s,", 1838 sep->se_rpcprog, sep->se_rpcversh, 1839 sep->se_rpcversl, sep->se_proto); 1840 else 1841 fprintf(stderr, "proto=%s,", sep->se_proto); 1842 1843 fprintf(stderr, 1844 " wait.max=%hd.%d user:group=%s:%s builtin=%lx server=%s\n", 1845 sep->se_wait, sep->se_max, sep->se_user, 1846 sep->se_group ? sep->se_group : "wheel", 1847 (long)sep->se_bi, sep->se_server); 1848 } 1849 1850 void 1851 spawn(struct servtab *sep, int ctrl) 1852 { 1853 struct passwd *pwd; 1854 int tmpint, dofork; 1855 struct group *grp = NULL; 1856 char buf[50]; 1857 pid_t pid; 1858 1859 pid = 0; 1860 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 1861 if (dofork) { 1862 if (sep->se_count++ == 0) 1863 (void)gettimeofday(&sep->se_time, NULL); 1864 else if (sep->se_count >= sep->se_max) { 1865 struct timeval now; 1866 1867 (void)gettimeofday(&now, NULL); 1868 if (now.tv_sec - sep->se_time.tv_sec > 1869 CNT_INTVL) { 1870 sep->se_time = now; 1871 sep->se_count = 1; 1872 } else { 1873 if (!sep->se_wait && 1874 sep->se_socktype == SOCK_STREAM) 1875 close(ctrl); 1876 if (sep->se_family == AF_INET && 1877 ntohs(sep->se_ctrladdr_in.sin_port) >= 1878 IPPORT_RESERVED) { 1879 /* 1880 * Cannot close it -- there are 1881 * thieves on the system. 1882 * Simply ignore the connection. 1883 */ 1884 --sep->se_count; 1885 sigprocmask(SIG_SETMASK, &emptymask, 1886 NULL); 1887 return; 1888 } 1889 syslog(LOG_ERR, 1890 "%s/%s server failing (looping), service terminated", 1891 sep->se_service, sep->se_proto); 1892 if (!sep->se_wait && 1893 sep->se_socktype == SOCK_STREAM) 1894 close(ctrl); 1895 FD_CLR(sep->se_fd, allsockp); 1896 (void) close(sep->se_fd); 1897 sep->se_fd = -1; 1898 sep->se_count = 0; 1899 nsock--; 1900 sigprocmask(SIG_SETMASK, &emptymask, 1901 NULL); 1902 if (!timingout) { 1903 timingout = 1; 1904 alarm(RETRYTIME); 1905 } 1906 return; 1907 } 1908 } 1909 pid = fork(); 1910 } 1911 if (pid < 0) { 1912 syslog(LOG_ERR, "fork: %m"); 1913 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 1914 close(ctrl); 1915 sigprocmask(SIG_SETMASK, &emptymask, NULL); 1916 sleep(1); 1917 return; 1918 } 1919 if (pid && sep->se_wait) { 1920 sep->se_wait = pid; 1921 FD_CLR(sep->se_fd, allsockp); 1922 nsock--; 1923 } 1924 sigprocmask(SIG_SETMASK, &emptymask, NULL); 1925 if (pid == 0) { 1926 if (sep->se_bi) 1927 (*sep->se_bi->bi_fn)(ctrl, sep); 1928 else { 1929 if ((pwd = getpwnam(sep->se_user)) == NULL) { 1930 syslog(LOG_ERR, 1931 "getpwnam: %s: No such user", 1932 sep->se_user); 1933 if (sep->se_socktype != SOCK_STREAM) 1934 recv(0, buf, sizeof (buf), 0); 1935 exit(1); 1936 } 1937 if (setsid() <0) 1938 syslog(LOG_ERR, "%s: setsid: %m", 1939 sep->se_service); 1940 if (sep->se_group && 1941 (grp = getgrnam(sep->se_group)) == NULL) { 1942 syslog(LOG_ERR, 1943 "getgrnam: %s: No such group", 1944 sep->se_group); 1945 if (sep->se_socktype != SOCK_STREAM) 1946 recv(0, buf, sizeof (buf), 0); 1947 exit(1); 1948 } 1949 if (uid != 0) { 1950 /* a user running private inetd */ 1951 if (uid != pwd->pw_uid) 1952 exit(1); 1953 } else { 1954 tmpint = LOGIN_SETALL & 1955 ~(LOGIN_SETGROUP|LOGIN_SETLOGIN); 1956 if (pwd->pw_uid) 1957 tmpint |= LOGIN_SETGROUP|LOGIN_SETLOGIN; 1958 if (sep->se_group) { 1959 pwd->pw_gid = grp->gr_gid; 1960 tmpint |= LOGIN_SETGROUP; 1961 } 1962 if (setusercontext(NULL, pwd, pwd->pw_uid, 1963 tmpint) < 0) { 1964 syslog(LOG_ERR, 1965 "%s/%s: setusercontext: %m", 1966 sep->se_service, sep->se_proto); 1967 exit(1); 1968 } 1969 } 1970 if (debug) 1971 fprintf(stderr, "%ld execv %s\n", 1972 (long)getpid(), sep->se_server); 1973 if (ctrl != STDIN_FILENO) { 1974 dup2(ctrl, STDIN_FILENO); 1975 close(ctrl); 1976 } 1977 dup2(STDIN_FILENO, STDOUT_FILENO); 1978 dup2(STDIN_FILENO, STDERR_FILENO); 1979 closelog(); 1980 closefrom(3); 1981 sigaction(SIGPIPE, &sapipe, NULL); 1982 execv(sep->se_server, sep->se_argv); 1983 if (sep->se_socktype != SOCK_STREAM) 1984 recv(0, buf, sizeof (buf), 0); 1985 syslog(LOG_ERR, "execv %s: %m", sep->se_server); 1986 exit(1); 1987 } 1988 } 1989 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 1990 close(ctrl); 1991 } 1992