1 /* $OpenBSD: inetd.c,v 1.162 2020/12/30 18:41:06 benno 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 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 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/stat.h> 125 #include <sys/socket.h> 126 #include <sys/un.h> 127 #include <sys/wait.h> 128 #include <sys/time.h> 129 #include <sys/resource.h> 130 131 #include <net/if.h> 132 #include <netinet/in.h> 133 #include <arpa/inet.h> 134 135 #include <err.h> 136 #include <errno.h> 137 #include <ctype.h> 138 #include <signal.h> 139 #include <netdb.h> 140 #include <syslog.h> 141 #include <pwd.h> 142 #include <grp.h> 143 #include <stdio.h> 144 #include <stdlib.h> 145 #include <unistd.h> 146 #include <limits.h> 147 #include <string.h> 148 #include <login_cap.h> 149 #include <ifaddrs.h> 150 #include <rpc/rpc.h> 151 #include <rpc/pmap_clnt.h> 152 #include <rpcsvc/nfs_prot.h> 153 #include <event.h> 154 #include "pathnames.h" 155 156 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 157 158 #define TOOMANY 256 /* don't start more than TOOMANY */ 159 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ 160 #define RETRYTIME (60*10) /* retry after bind or server fail */ 161 162 int debug = 0; 163 int maxsock; 164 int toomany = TOOMANY; 165 int timingout; 166 struct servent *sp; 167 uid_t uid; 168 169 #ifndef OPEN_MAX 170 #define OPEN_MAX 64 171 #endif 172 173 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ 174 #define FD_MARGIN (8) 175 rlim_t rlim_nofile_cur = OPEN_MAX; 176 177 struct rlimit rlim_nofile; 178 179 struct servtab { 180 char *se_hostaddr; /* host address to listen on */ 181 char *se_service; /* name of service */ 182 int se_socktype; /* type of socket to use */ 183 int se_family; /* address family */ 184 char *se_proto; /* protocol used */ 185 int se_rpcprog; /* rpc program number */ 186 int se_rpcversl; /* rpc program lowest version */ 187 int se_rpcversh; /* rpc program highest version */ 188 #define isrpcservice(sep) ((sep)->se_rpcversl != 0) 189 pid_t se_wait; /* single threaded server */ 190 short se_checked; /* looked at during merge */ 191 char *se_user; /* user name to run as */ 192 char *se_group; /* group name to run as */ 193 struct biltin *se_bi; /* if built-in, description */ 194 char *se_server; /* server program */ 195 #define MAXARGV 20 196 char *se_argv[MAXARGV+1]; /* program arguments */ 197 int se_fd; /* open descriptor */ 198 union { 199 struct sockaddr se_un_ctrladdr; 200 struct sockaddr_in se_un_ctrladdr_in; 201 struct sockaddr_in6 se_un_ctrladdr_in6; 202 struct sockaddr_un se_un_ctrladdr_un; 203 struct sockaddr_storage se_un_ctrladdr_storage; 204 } se_un; /* bound address */ 205 #define se_ctrladdr se_un.se_un_ctrladdr 206 #define se_ctrladdr_in se_un.se_un_ctrladdr_in 207 #define se_ctrladdr_in6 se_un.se_un_ctrladdr_in6 208 #define se_ctrladdr_un se_un.se_un_ctrladdr_un 209 #define se_ctrladdr_storage se_un.se_un_ctrladdr_storage 210 int se_ctrladdr_size; 211 int se_max; /* max # of instances of this service */ 212 int se_count; /* number started since se_time */ 213 struct timeval se_time; /* start of se_count */ 214 struct servtab *se_next; 215 struct event se_event; 216 } *servtab; 217 218 void echo_stream(int, struct servtab *); 219 void discard_stream(int, struct servtab *); 220 void machtime_stream(int, struct servtab *); 221 void daytime_stream(int, struct servtab *); 222 void chargen_stream(int, struct servtab *); 223 void echo_dg(int, struct servtab *); 224 void discard_dg(int, struct servtab *); 225 void machtime_dg(int, struct servtab *); 226 void daytime_dg(int, struct servtab *); 227 void chargen_dg(int, struct servtab *); 228 229 struct biltin { 230 char *bi_service; /* internally provided service name */ 231 int bi_socktype; /* type of socket supported */ 232 short bi_fork; /* 1 if should fork before call */ 233 short bi_wait; /* 1 if should wait for child */ 234 void (*bi_fn)(int, struct servtab *); 235 } biltins[] = { 236 /* Echo received data */ 237 { "echo", SOCK_STREAM, 1, 0, echo_stream }, 238 { "echo", SOCK_DGRAM, 0, 0, echo_dg }, 239 240 /* Internet /dev/null */ 241 { "discard", SOCK_STREAM, 1, 0, discard_stream }, 242 { "discard", SOCK_DGRAM, 0, 0, discard_dg }, 243 244 /* Return 32 bit time since 1900 */ 245 { "time", SOCK_STREAM, 0, 0, machtime_stream }, 246 { "time", SOCK_DGRAM, 0, 0, machtime_dg }, 247 248 /* Return human-readable time */ 249 { "daytime", SOCK_STREAM, 0, 0, daytime_stream }, 250 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg }, 251 252 /* Familiar character generator */ 253 { "chargen", SOCK_STREAM, 1, 0, chargen_stream }, 254 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg }, 255 256 { 0 } 257 }; 258 259 struct event evsig_alrm; 260 struct event evsig_hup; 261 struct event evsig_chld; 262 struct event evsig_term; 263 struct event evsig_int; 264 265 void config(int, short, void *); 266 void reap(int, short, void *); 267 void retry(int, short, void *); 268 void die(int, short, void *); 269 270 void spawn(int, short, void *); 271 void gettcp(int, short, void *); 272 int setconfig(void); 273 void endconfig(void); 274 void register_rpc(struct servtab *); 275 void unregister_rpc(struct servtab *); 276 void freeconfig(struct servtab *); 277 void print_service(char *, struct servtab *); 278 void setup(struct servtab *); 279 struct servtab *getconfigent(void); 280 int bump_nofile(void); 281 struct servtab *enter(struct servtab *); 282 int matchconf(struct servtab *, struct servtab *); 283 int dg_broadcast(struct in_addr *in); 284 285 #define NUMINT (sizeof(intab) / sizeof(struct inent)) 286 char *CONFIG = _PATH_INETDCONF; 287 288 int dg_badinput(struct sockaddr *sa); 289 void inetd_setproctitle(char *a, int s); 290 void initring(void); 291 u_int32_t machtime(void); 292 293 int 294 main(int argc, char *argv[]) 295 { 296 int ch; 297 298 while ((ch = getopt(argc, argv, "dR:")) != -1) 299 switch (ch) { 300 case 'd': 301 debug = 1; 302 break; 303 case 'R': { /* invocation rate */ 304 char *p; 305 int val; 306 307 val = strtoul(optarg, &p, 0); 308 if (val >= 1 && *p == '\0') { 309 toomany = val; 310 break; 311 } 312 syslog(LOG_ERR, 313 "-R %s: bad value for service invocation rate", 314 optarg); 315 break; 316 } 317 case '?': 318 default: 319 fprintf(stderr, 320 "usage: inetd [-d] [-R rate] [configuration_file]\n"); 321 exit(1); 322 } 323 argc -= optind; 324 argv += optind; 325 326 uid = getuid(); 327 if (uid != 0) 328 CONFIG = NULL; 329 if (argc > 0) 330 CONFIG = argv[0]; 331 if (CONFIG == NULL) { 332 fprintf(stderr, "inetd: non-root must specify a config file\n"); 333 exit(1); 334 } 335 if (argc > 1) { 336 fprintf(stderr, "inetd: more than one argument specified\n"); 337 exit(1); 338 } 339 340 umask(022); 341 if (debug == 0) { 342 daemon(0, 0); 343 if (uid == 0) 344 (void) setlogin(""); 345 } 346 347 if (pledge("stdio rpath cpath getpw dns inet unix proc exec id", NULL) == -1) 348 err(1, "pledge"); 349 350 if (uid == 0) { 351 gid_t gid = getgid(); 352 353 /* If run by hand, ensure groups vector gets trashed */ 354 setgroups(1, &gid); 355 } 356 357 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); 358 359 if (getrlimit(RLIMIT_NOFILE, &rlim_nofile) == -1) { 360 syslog(LOG_ERR, "getrlimit: %m"); 361 } else { 362 rlim_nofile_cur = rlim_nofile.rlim_cur; 363 if (rlim_nofile_cur == RLIM_INFINITY) /* ! */ 364 rlim_nofile_cur = OPEN_MAX; 365 } 366 367 event_init(); 368 369 signal_set(&evsig_alrm, SIGALRM, retry, NULL); 370 signal_add(&evsig_alrm, NULL); 371 372 config(0, 0, NULL); 373 374 signal_set(&evsig_hup, SIGHUP, config, NULL); 375 signal_add(&evsig_hup, NULL); 376 signal_set(&evsig_chld, SIGCHLD, reap, NULL); 377 signal_add(&evsig_chld, NULL); 378 signal_set(&evsig_term, SIGTERM, die, NULL); 379 signal_add(&evsig_term, NULL); 380 signal_set(&evsig_int, SIGINT, die, NULL); 381 signal_add(&evsig_int, NULL); 382 383 signal(SIGPIPE, SIG_IGN); 384 385 event_dispatch(); 386 387 return (0); 388 } 389 390 void 391 gettcp(int fd, short events, void *xsep) 392 { 393 struct servtab *sep = xsep; 394 int ctrl; 395 396 if (debug) 397 fprintf(stderr, "someone wants %s\n", sep->se_service); 398 399 ctrl = accept(sep->se_fd, NULL, NULL); 400 if (debug) 401 fprintf(stderr, "accept, ctrl %d\n", ctrl); 402 if (ctrl == -1) { 403 if (errno != EWOULDBLOCK && errno != EINTR && 404 errno != ECONNABORTED) 405 syslog(LOG_WARNING, "accept (for %s): %m", 406 sep->se_service); 407 return; 408 } 409 if ((sep->se_family == AF_INET || sep->se_family == AF_INET6) && 410 sep->se_socktype == SOCK_STREAM) { 411 struct sockaddr_storage peer; 412 socklen_t plen = sizeof(peer); 413 char sbuf[NI_MAXSERV]; 414 415 if (getpeername(ctrl, (struct sockaddr *)&peer, &plen) == -1) { 416 syslog(LOG_WARNING, "could not getpeername"); 417 close(ctrl); 418 return; 419 } 420 if (getnameinfo((struct sockaddr *)&peer, plen, NULL, 0, 421 sbuf, sizeof(sbuf), NI_NUMERICSERV) == 0 && 422 strtonum(sbuf, 1, USHRT_MAX, NULL) == 20) { 423 /* 424 * ignore things that look like ftp bounce 425 */ 426 close(ctrl); 427 return; 428 } 429 } 430 431 spawn(ctrl, 0, sep); 432 } 433 434 int 435 dg_badinput(struct sockaddr *sa) 436 { 437 struct in_addr in; 438 struct in6_addr *in6; 439 u_int16_t port; 440 441 switch (sa->sa_family) { 442 case AF_INET: 443 in.s_addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr); 444 port = ntohs(((struct sockaddr_in *)sa)->sin_port); 445 if (IN_MULTICAST(in.s_addr)) 446 goto bad; 447 switch ((in.s_addr & 0xff000000) >> 24) { 448 case 0: case 127: case 255: 449 goto bad; 450 } 451 if (dg_broadcast(&in)) 452 goto bad; 453 break; 454 case AF_INET6: 455 in6 = &((struct sockaddr_in6 *)sa)->sin6_addr; 456 port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port); 457 if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6)) 458 goto bad; 459 /* 460 * OpenBSD does not support IPv4-mapped and 461 * IPv4-compatible IPv6 addresses (RFC2553). We should 462 * drop the packet. 463 */ 464 if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) 465 goto bad; 466 break; 467 default: 468 /* Unsupported AF */ 469 goto bad; 470 } 471 472 if (port < IPPORT_RESERVED || port == NFS_PORT) 473 goto bad; 474 475 return (0); 476 477 bad: 478 return (1); 479 } 480 481 int 482 dg_broadcast(struct in_addr *in) 483 { 484 struct ifaddrs *ifa, *ifap; 485 struct sockaddr_in *sin; 486 487 if (getifaddrs(&ifap) == -1) 488 return (0); 489 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 490 if (ifa->ifa_addr == NULL || 491 ifa->ifa_addr->sa_family != AF_INET || 492 (ifa->ifa_flags & IFF_BROADCAST) == 0) 493 continue; 494 sin = (struct sockaddr_in *)ifa->ifa_broadaddr; 495 if (sin->sin_addr.s_addr == in->s_addr) { 496 freeifaddrs(ifap); 497 return (1); 498 } 499 } 500 freeifaddrs(ifap); 501 return (0); 502 } 503 504 void 505 reap(int sig, short event, void *arg) 506 { 507 struct servtab *sep; 508 int status; 509 pid_t pid; 510 511 if (debug) 512 fprintf(stderr, "reaping asked for\n"); 513 514 for (;;) { 515 if ((pid = wait3(&status, WNOHANG, NULL)) <= 0) { 516 if (pid == -1 && errno == EINTR) 517 continue; 518 break; 519 } 520 if (debug) 521 fprintf(stderr, "%ld reaped, status %x\n", 522 (long)pid, status); 523 for (sep = servtab; sep; sep = sep->se_next) 524 if (sep->se_wait == pid) { 525 if (WIFEXITED(status) && WEXITSTATUS(status)) 526 syslog(LOG_WARNING, 527 "%s: exit status %d", 528 sep->se_server, WEXITSTATUS(status)); 529 else if (WIFSIGNALED(status)) 530 syslog(LOG_WARNING, 531 "%s: exit signal %d", 532 sep->se_server, WTERMSIG(status)); 533 sep->se_wait = 1; 534 event_add(&sep->se_event, NULL); 535 if (debug) 536 fprintf(stderr, "restored %s, fd %d\n", 537 sep->se_service, sep->se_fd); 538 } 539 } 540 } 541 542 void 543 config(int sig, short event, void *arg) 544 { 545 struct servtab *sep, *cp, **sepp; 546 int add; 547 char protoname[11]; 548 549 if (!setconfig()) { 550 syslog(LOG_ERR, "%s: %m", CONFIG); 551 exit(1); 552 } 553 for (sep = servtab; sep; sep = sep->se_next) 554 sep->se_checked = 0; 555 cp = getconfigent(); 556 while (cp != NULL) { 557 for (sep = servtab; sep; sep = sep->se_next) 558 if (matchconf(sep, cp)) 559 break; 560 add = 0; 561 if (sep != NULL) { 562 int i; 563 564 #define SWAP(type, a, b) {type c=(type)a; a=(type)b; b=(type)c;} 565 566 /* 567 * sep->se_wait may be holding the pid of a daemon 568 * that we're waiting for. If so, don't overwrite 569 * it unless the config file explicitly says don't 570 * wait. 571 */ 572 if (cp->se_bi == 0 && 573 (sep->se_wait == 1 || cp->se_wait == 0)) 574 sep->se_wait = cp->se_wait; 575 SWAP(int, cp->se_max, sep->se_max); 576 SWAP(char *, sep->se_user, cp->se_user); 577 SWAP(char *, sep->se_group, cp->se_group); 578 SWAP(char *, sep->se_server, cp->se_server); 579 for (i = 0; i < MAXARGV; i++) 580 SWAP(char *, sep->se_argv[i], cp->se_argv[i]); 581 #undef SWAP 582 if (isrpcservice(sep)) 583 unregister_rpc(sep); 584 sep->se_rpcversl = cp->se_rpcversl; 585 sep->se_rpcversh = cp->se_rpcversh; 586 freeconfig(cp); 587 add = 1; 588 } else { 589 sep = enter(cp); 590 } 591 sep->se_checked = 1; 592 593 switch (sep->se_family) { 594 case AF_UNIX: 595 if (sep->se_fd != -1) 596 break; 597 sep->se_ctrladdr_size = 598 strlcpy(sep->se_ctrladdr_un.sun_path, 599 sep->se_service, 600 sizeof sep->se_ctrladdr_un.sun_path); 601 if (sep->se_ctrladdr_size >= 602 sizeof sep->se_ctrladdr_un.sun_path) { 603 syslog(LOG_WARNING, "%s/%s: UNIX domain socket " 604 "path too long", sep->se_service, 605 sep->se_proto); 606 goto serv_unknown; 607 } 608 sep->se_ctrladdr_un.sun_family = AF_UNIX; 609 sep->se_ctrladdr_size += 610 1 + sizeof sep->se_ctrladdr_un.sun_family; 611 (void)unlink(sep->se_service); 612 setup(sep); 613 break; 614 case AF_INET: 615 sep->se_ctrladdr_in.sin_family = AF_INET; 616 /* se_ctrladdr_in was set in getconfigent */ 617 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in; 618 619 if (isrpcservice(sep)) { 620 struct rpcent *rp; 621 622 sep->se_rpcprog = strtonum(sep->se_service, 623 1, USHRT_MAX, NULL); 624 if (sep->se_rpcprog == 0) { 625 rp = getrpcbyname(sep->se_service); 626 if (rp == 0) { 627 syslog(LOG_ERR, 628 "%s: unknown rpc service", 629 sep->se_service); 630 goto serv_unknown; 631 } 632 sep->se_rpcprog = rp->r_number; 633 } 634 if (sep->se_fd == -1) 635 setup(sep); 636 if (sep->se_fd != -1) 637 register_rpc(sep); 638 } else { 639 u_short port = htons(strtonum(sep->se_service, 640 1, USHRT_MAX, NULL)); 641 642 if (!port) { 643 (void)strlcpy(protoname, sep->se_proto, 644 sizeof(protoname)); 645 if (isdigit((unsigned char) 646 protoname[strlen(protoname) - 1])) 647 protoname[strlen(protoname) - 1] = '\0'; 648 sp = getservbyname(sep->se_service, 649 protoname); 650 if (sp == 0) { 651 syslog(LOG_ERR, 652 "%s/%s: unknown service", 653 sep->se_service, sep->se_proto); 654 goto serv_unknown; 655 } 656 port = sp->s_port; 657 } 658 if (port != sep->se_ctrladdr_in.sin_port) { 659 sep->se_ctrladdr_in.sin_port = port; 660 if (sep->se_fd != -1) { 661 event_del(&sep->se_event); 662 (void) close(sep->se_fd); 663 } 664 sep->se_fd = -1; 665 } 666 if (sep->se_fd == -1) 667 setup(sep); 668 } 669 break; 670 case AF_INET6: 671 sep->se_ctrladdr_in6.sin6_family = AF_INET6; 672 /* se_ctrladdr_in was set in getconfigent */ 673 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in6; 674 675 if (isrpcservice(sep)) { 676 struct rpcent *rp; 677 678 sep->se_rpcprog = strtonum(sep->se_service, 679 1, USHRT_MAX, NULL); 680 if (sep->se_rpcprog == 0) { 681 rp = getrpcbyname(sep->se_service); 682 if (rp == 0) { 683 syslog(LOG_ERR, 684 "%s: unknown rpc service", 685 sep->se_service); 686 goto serv_unknown; 687 } 688 sep->se_rpcprog = rp->r_number; 689 } 690 if (sep->se_fd == -1) 691 setup(sep); 692 if (sep->se_fd != -1) 693 register_rpc(sep); 694 } else { 695 u_short port = htons(strtonum(sep->se_service, 696 1, USHRT_MAX, NULL)); 697 698 if (!port) { 699 (void)strlcpy(protoname, sep->se_proto, 700 sizeof(protoname)); 701 if (isdigit((unsigned char) 702 protoname[strlen(protoname) - 1])) 703 protoname[strlen(protoname) - 1] = '\0'; 704 sp = getservbyname(sep->se_service, 705 protoname); 706 if (sp == 0) { 707 syslog(LOG_ERR, 708 "%s/%s: unknown service", 709 sep->se_service, sep->se_proto); 710 goto serv_unknown; 711 } 712 port = sp->s_port; 713 } 714 if (port != sep->se_ctrladdr_in6.sin6_port) { 715 sep->se_ctrladdr_in6.sin6_port = port; 716 if (sep->se_fd != -1) { 717 event_del(&sep->se_event); 718 (void) close(sep->se_fd); 719 } 720 sep->se_fd = -1; 721 } 722 if (sep->se_fd == -1) 723 setup(sep); 724 } 725 break; 726 } 727 serv_unknown: 728 if (cp->se_next != NULL) { 729 struct servtab *tmp = cp; 730 731 cp = cp->se_next; 732 free(tmp); 733 } else { 734 free(cp); 735 cp = getconfigent(); 736 } 737 if (debug) 738 print_service(add ? "REDO" : "ADD", sep); 739 } 740 endconfig(); 741 /* 742 * Purge anything not looked at above. 743 */ 744 sepp = &servtab; 745 while ((sep = *sepp)) { 746 if (sep->se_checked) { 747 sepp = &sep->se_next; 748 continue; 749 } 750 *sepp = sep->se_next; 751 if (sep->se_fd != -1) { 752 event_del(&sep->se_event); 753 (void) close(sep->se_fd); 754 } 755 if (isrpcservice(sep)) 756 unregister_rpc(sep); 757 if (sep->se_family == AF_UNIX) 758 (void)unlink(sep->se_service); 759 if (debug) 760 print_service("FREE", sep); 761 freeconfig(sep); 762 free(sep); 763 } 764 } 765 766 void 767 retry(int sig, short events, void *arg) 768 { 769 struct servtab *sep; 770 771 timingout = 0; 772 for (sep = servtab; sep; sep = sep->se_next) { 773 if (sep->se_fd == -1) { 774 switch (sep->se_family) { 775 case AF_UNIX: 776 case AF_INET: 777 case AF_INET6: 778 setup(sep); 779 if (sep->se_fd != -1 && isrpcservice(sep)) 780 register_rpc(sep); 781 break; 782 } 783 } 784 } 785 } 786 787 void 788 die(int sig, short events, void *arg) 789 { 790 struct servtab *sep; 791 792 for (sep = servtab; sep; sep = sep->se_next) { 793 if (sep->se_fd == -1) 794 continue; 795 796 switch (sep->se_family) { 797 case AF_UNIX: 798 (void)unlink(sep->se_service); 799 break; 800 case AF_INET: 801 case AF_INET6: 802 if (sep->se_wait == 1 && isrpcservice(sep)) 803 unregister_rpc(sep); 804 break; 805 } 806 (void)close(sep->se_fd); 807 } 808 exit(0); 809 } 810 811 void 812 setup(struct servtab *sep) 813 { 814 int on = 1; 815 int r; 816 mode_t mask = 0; 817 818 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) == -1) { 819 syslog(LOG_ERR, "%s/%s: socket: %m", 820 sep->se_service, sep->se_proto); 821 return; 822 } 823 #define turnon(fd, opt) \ 824 setsockopt(fd, SOL_SOCKET, opt, &on, sizeof (on)) 825 if (strncmp(sep->se_proto, "tcp", 3) == 0 && debug && 826 turnon(sep->se_fd, SO_DEBUG) < 0) 827 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 828 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 829 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 830 #undef turnon 831 if (isrpcservice(sep)) { 832 struct passwd *pwd; 833 834 /* 835 * for RPC services, attempt to use a reserved port 836 * if they are going to be running as root. 837 * 838 * Also, zero out the port for all RPC services; let bind() 839 * find one. 840 */ 841 sep->se_ctrladdr_in.sin_port = 0; 842 if (sep->se_user && (pwd = getpwnam(sep->se_user)) && 843 pwd->pw_uid == 0 && uid == 0) 844 r = bindresvport(sep->se_fd, &sep->se_ctrladdr_in); 845 else { 846 r = bind(sep->se_fd, &sep->se_ctrladdr, 847 sep->se_ctrladdr_size); 848 if (r == 0) { 849 socklen_t len = sep->se_ctrladdr_size; 850 int saveerrno = errno; 851 852 /* update se_ctrladdr_in.sin_port */ 853 r = getsockname(sep->se_fd, &sep->se_ctrladdr, 854 &len); 855 if (r <= 0) 856 errno = saveerrno; 857 } 858 } 859 } else { 860 if (sep->se_family == AF_UNIX) 861 mask = umask(0111); 862 r = bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size); 863 if (sep->se_family == AF_UNIX) 864 umask(mask); 865 } 866 if (r == -1) { 867 syslog(LOG_ERR, "%s/%s: bind: %m", 868 sep->se_service, sep->se_proto); 869 (void) close(sep->se_fd); 870 sep->se_fd = -1; 871 if (!timingout) { 872 timingout = 1; 873 alarm(RETRYTIME); 874 } 875 return; 876 } 877 if (sep->se_socktype == SOCK_STREAM) 878 listen(sep->se_fd, 10); 879 880 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 881 event_set(&sep->se_event, sep->se_fd, EV_READ|EV_PERSIST, 882 gettcp, sep); 883 } else { 884 event_set(&sep->se_event, sep->se_fd, EV_READ|EV_PERSIST, 885 spawn, sep); 886 } 887 888 event_add(&sep->se_event, NULL); 889 890 if (sep->se_fd > maxsock) { 891 maxsock = sep->se_fd; 892 if (maxsock > rlim_nofile_cur - FD_MARGIN) 893 bump_nofile(); 894 } 895 } 896 897 void 898 register_rpc(struct servtab *sep) 899 { 900 socklen_t n; 901 struct sockaddr_in sin; 902 struct protoent *pp; 903 904 if ((pp = getprotobyname(sep->se_proto+4)) == NULL) { 905 syslog(LOG_ERR, "%s: getproto: %m", 906 sep->se_proto); 907 return; 908 } 909 n = sizeof sin; 910 if (getsockname(sep->se_fd, (struct sockaddr *)&sin, &n) == -1) { 911 syslog(LOG_ERR, "%s/%s: getsockname: %m", 912 sep->se_service, sep->se_proto); 913 return; 914 } 915 916 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 917 if (debug) 918 fprintf(stderr, "pmap_set: %u %u %u %u\n", 919 sep->se_rpcprog, n, pp->p_proto, 920 ntohs(sin.sin_port)); 921 (void)pmap_unset(sep->se_rpcprog, n); 922 if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port))) 923 syslog(LOG_ERR, "%s %s: pmap_set: %u %u %u %u: %m", 924 sep->se_service, sep->se_proto, 925 sep->se_rpcprog, n, pp->p_proto, 926 ntohs(sin.sin_port)); 927 } 928 } 929 930 void 931 unregister_rpc(struct servtab *sep) 932 { 933 int n; 934 935 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 936 if (debug) 937 fprintf(stderr, "pmap_unset(%u, %u)\n", 938 sep->se_rpcprog, n); 939 if (!pmap_unset(sep->se_rpcprog, n)) 940 syslog(LOG_ERR, "pmap_unset(%u, %u)", 941 sep->se_rpcprog, n); 942 } 943 } 944 945 946 struct servtab * 947 enter(struct servtab *cp) 948 { 949 struct servtab *sep; 950 951 sep = malloc(sizeof (*sep)); 952 if (sep == NULL) { 953 syslog(LOG_ERR, "Out of memory."); 954 exit(1); 955 } 956 *sep = *cp; 957 sep->se_fd = -1; 958 sep->se_rpcprog = -1; 959 sep->se_next = servtab; 960 servtab = sep; 961 return (sep); 962 } 963 964 int 965 matchconf(struct servtab *old, struct servtab *new) 966 { 967 if (strcmp(old->se_service, new->se_service) != 0) 968 return (0); 969 970 if (strcmp(old->se_hostaddr, new->se_hostaddr) != 0) 971 return (0); 972 973 if (strcmp(old->se_proto, new->se_proto) != 0) 974 return (0); 975 976 /* 977 * If the new servtab is bound to a specific address, check that the 978 * old servtab is bound to the same entry. If the new service is not 979 * bound to a specific address then the check of se_hostaddr above 980 * is sufficient. 981 */ 982 983 if (old->se_family == AF_INET && new->se_family == AF_INET && 984 bcmp(&old->se_ctrladdr_in.sin_addr, 985 &new->se_ctrladdr_in.sin_addr, 986 sizeof(new->se_ctrladdr_in.sin_addr)) != 0) 987 return (0); 988 989 if (old->se_family == AF_INET6 && new->se_family == AF_INET6 && 990 bcmp(&old->se_ctrladdr_in6.sin6_addr, 991 &new->se_ctrladdr_in6.sin6_addr, 992 sizeof(new->se_ctrladdr_in6.sin6_addr)) != 0) 993 return (0); 994 if (old->se_family == AF_INET6 && new->se_family == AF_INET6 && 995 old->se_ctrladdr_in6.sin6_scope_id != 996 new->se_ctrladdr_in6.sin6_scope_id) 997 return (0); 998 999 return (1); 1000 } 1001 1002 FILE *fconfig = NULL; 1003 char line[1024]; 1004 char *defhost; 1005 char *skip(char **, int); 1006 char *nextline(FILE *); 1007 char *newstr(char *); 1008 struct servtab *dupconfig(struct servtab *); 1009 1010 int 1011 setconfig(void) 1012 { 1013 free(defhost); 1014 defhost = newstr("*"); 1015 if (fconfig != NULL) { 1016 fseek(fconfig, 0L, SEEK_SET); 1017 return (1); 1018 } 1019 fconfig = fopen(CONFIG, "r"); 1020 return (fconfig != NULL); 1021 } 1022 1023 void 1024 endconfig(void) 1025 { 1026 if (fconfig) { 1027 (void) fclose(fconfig); 1028 fconfig = NULL; 1029 } 1030 if (defhost) { 1031 free(defhost); 1032 defhost = 0; 1033 } 1034 } 1035 1036 struct servtab * 1037 getconfigent(void) 1038 { 1039 struct servtab *sep, *tsep; 1040 char *arg, *cp, *hostdelim, *s; 1041 int argc; 1042 1043 sep = calloc(1, sizeof(struct servtab)); 1044 if (sep == NULL) { 1045 syslog(LOG_ERR, "calloc: %m"); 1046 exit(1); 1047 } 1048 more: 1049 freeconfig(sep); 1050 1051 while ((cp = nextline(fconfig)) && *cp == '#') 1052 ; 1053 if (cp == NULL) { 1054 free(sep); 1055 return (NULL); 1056 } 1057 1058 memset(sep, 0, sizeof *sep); 1059 arg = skip(&cp, 0); 1060 if (arg == NULL) { 1061 /* A blank line. */ 1062 goto more; 1063 } 1064 1065 /* Check for a host name. */ 1066 hostdelim = strrchr(arg, ':'); 1067 if (hostdelim) { 1068 *hostdelim = '\0'; 1069 if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') { 1070 hostdelim[-1] = '\0'; 1071 sep->se_hostaddr = newstr(arg + 1); 1072 } else if (hostdelim == arg) 1073 sep->se_hostaddr = newstr("*"); 1074 else 1075 sep->se_hostaddr = newstr(arg); 1076 arg = hostdelim + 1; 1077 /* 1078 * If the line is of the form `host:', then just change the 1079 * default host for the following lines. 1080 */ 1081 if (*arg == '\0') { 1082 arg = skip(&cp, 0); 1083 if (cp == NULL) { 1084 free(defhost); 1085 defhost = newstr(sep->se_hostaddr); 1086 goto more; 1087 } 1088 } 1089 } else 1090 sep->se_hostaddr = newstr(defhost); 1091 1092 sep->se_service = newstr(arg); 1093 if ((arg = skip(&cp, 1)) == NULL) 1094 goto more; 1095 1096 if (strcmp(arg, "stream") == 0) 1097 sep->se_socktype = SOCK_STREAM; 1098 else if (strcmp(arg, "dgram") == 0) 1099 sep->se_socktype = SOCK_DGRAM; 1100 else 1101 sep->se_socktype = -1; 1102 1103 if ((arg = skip(&cp, 1)) == NULL) 1104 goto more; 1105 1106 sep->se_proto = newstr(arg); 1107 1108 if (strcmp(sep->se_proto, "unix") == 0) { 1109 sep->se_family = AF_UNIX; 1110 } else { 1111 int s; 1112 1113 sep->se_family = AF_INET; 1114 if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') 1115 sep->se_family = AF_INET6; 1116 1117 /* check if the family is supported */ 1118 s = socket(sep->se_family, SOCK_DGRAM, 0); 1119 if (s == -1) { 1120 syslog(LOG_WARNING, "%s/%s: %s: the address family is " 1121 "not supported by the kernel", sep->se_service, 1122 sep->se_proto, sep->se_hostaddr); 1123 goto more; 1124 } 1125 close(s); 1126 1127 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 1128 char *cp, *ccp; 1129 long l; 1130 1131 cp = strchr(sep->se_service, '/'); 1132 if (cp == 0) { 1133 syslog(LOG_ERR, "%s: no rpc version", 1134 sep->se_service); 1135 goto more; 1136 } 1137 *cp++ = '\0'; 1138 l = strtol(cp, &ccp, 0); 1139 if (ccp == cp || l < 0 || l > INT_MAX) { 1140 badafterall: 1141 syslog(LOG_ERR, "%s/%s: bad rpc version", 1142 sep->se_service, cp); 1143 goto more; 1144 } 1145 sep->se_rpcversl = sep->se_rpcversh = l; 1146 if (*ccp == '-') { 1147 cp = ccp + 1; 1148 l = strtol(cp, &ccp, 0); 1149 if (ccp == cp || l < 0 || l > INT_MAX || 1150 l < sep->se_rpcversl || *ccp) 1151 goto badafterall; 1152 sep->se_rpcversh = l; 1153 } else if (*ccp != '\0') 1154 goto badafterall; 1155 } 1156 } 1157 arg = skip(&cp, 1); 1158 if (arg == NULL) 1159 goto more; 1160 1161 s = strchr(arg, '.'); 1162 if (s) { 1163 char *p; 1164 1165 *s++ = '\0'; 1166 sep->se_max = strtoul(s, &p, 0); 1167 if (sep->se_max < 1 || *p) { 1168 syslog(LOG_ERR, 1169 "%s: illegal max field \"%s\", setting to %d", 1170 sep->se_service, s, toomany); 1171 sep->se_max = toomany; 1172 } 1173 } else 1174 sep->se_max = toomany; 1175 1176 sep->se_wait = strcmp(arg, "wait") == 0; 1177 if ((arg = skip(&cp, 1)) == NULL) 1178 goto more; 1179 sep->se_user = newstr(arg); 1180 arg = strchr(sep->se_user, '.'); 1181 if (arg == NULL) 1182 arg = strchr(sep->se_user, ':'); 1183 if (arg) { 1184 *arg++ = '\0'; 1185 sep->se_group = newstr(arg); 1186 } 1187 if ((arg = skip(&cp, 1)) == NULL) 1188 goto more; 1189 1190 sep->se_server = newstr(arg); 1191 if (strcmp(sep->se_server, "internal") == 0) { 1192 struct biltin *bi; 1193 1194 for (bi = biltins; bi->bi_service; bi++) 1195 if (bi->bi_socktype == sep->se_socktype && 1196 strcmp(bi->bi_service, sep->se_service) == 0) 1197 break; 1198 if (bi->bi_service == 0) { 1199 syslog(LOG_ERR, "internal service %s unknown", 1200 sep->se_service); 1201 goto more; 1202 } 1203 sep->se_bi = bi; 1204 sep->se_wait = bi->bi_wait; 1205 } else 1206 sep->se_bi = NULL; 1207 argc = 0; 1208 for (arg = skip(&cp, 0); cp; arg = skip(&cp, 0)) { 1209 if (argc < MAXARGV) 1210 sep->se_argv[argc++] = newstr(arg); 1211 } 1212 if (argc == 0 && sep->se_bi == NULL) { 1213 if ((arg = strrchr(sep->se_server, '/')) != NULL) 1214 arg++; 1215 else 1216 arg = sep->se_server; 1217 sep->se_argv[argc++] = newstr(arg); 1218 } 1219 while (argc <= MAXARGV) 1220 sep->se_argv[argc++] = NULL; 1221 1222 /* 1223 * Resolve each hostname in the se_hostaddr list (if any) 1224 * and create a new entry for each resolved address. 1225 */ 1226 if (sep->se_hostaddr != NULL && strcmp(sep->se_proto, "unix") != 0) { 1227 struct addrinfo hints, *res0, *res; 1228 char *host, *hostlist0, *hostlist, *port; 1229 int error; 1230 1231 hostlist = hostlist0 = sep->se_hostaddr; 1232 sep->se_hostaddr = NULL; 1233 sep->se_checked = -1; 1234 while ((host = strsep(&hostlist, ",")) != NULL) { 1235 if (*host == '\0') 1236 continue; 1237 1238 memset(&hints, 0, sizeof(hints)); 1239 hints.ai_family = sep->se_family; 1240 hints.ai_socktype = sep->se_socktype; 1241 hints.ai_flags = AI_PASSIVE; 1242 port = "0"; 1243 error = getaddrinfo(strcmp(host, "*") ? host : NULL, 1244 port, &hints, &res0); 1245 if (error) { 1246 syslog(LOG_ERR, "%s/%s: %s: %s", 1247 sep->se_service, sep->se_proto, 1248 host, gai_strerror(error)); 1249 continue; 1250 } 1251 for (res = res0; res; res = res->ai_next) { 1252 /* 1253 * If sep is unused, store host in there. 1254 * Otherwise, dup a new entry and prepend it. 1255 */ 1256 if (sep->se_checked == -1) { 1257 sep->se_checked = 0; 1258 } else { 1259 tsep = dupconfig(sep); 1260 tsep->se_next = sep; 1261 sep = tsep; 1262 } 1263 sep->se_hostaddr = newstr(host); 1264 memcpy(&sep->se_ctrladdr_storage, 1265 res->ai_addr, res->ai_addrlen); 1266 sep->se_ctrladdr_size = res->ai_addrlen; 1267 } 1268 freeaddrinfo(res0); 1269 } 1270 free(hostlist0); 1271 if (sep->se_checked == -1) 1272 goto more; /* no resolvable names/addresses */ 1273 } 1274 1275 return (sep); 1276 } 1277 1278 void 1279 freeconfig(struct servtab *cp) 1280 { 1281 int i; 1282 1283 free(cp->se_hostaddr); 1284 cp->se_hostaddr = NULL; 1285 free(cp->se_service); 1286 cp->se_service = NULL; 1287 free(cp->se_proto); 1288 cp->se_proto = NULL; 1289 free(cp->se_user); 1290 cp->se_user = NULL; 1291 free(cp->se_group); 1292 cp->se_group = NULL; 1293 free(cp->se_server); 1294 cp->se_server = NULL; 1295 for (i = 0; i < MAXARGV; i++) { 1296 free(cp->se_argv[i]); 1297 cp->se_argv[i] = NULL; 1298 } 1299 } 1300 1301 char * 1302 skip(char **cpp, int report) 1303 { 1304 char *cp = *cpp; 1305 char *start; 1306 1307 erp: 1308 if (*cpp == NULL) { 1309 if (report) 1310 syslog(LOG_ERR, "syntax error in inetd config file"); 1311 return (NULL); 1312 } 1313 1314 again: 1315 while (*cp == ' ' || *cp == '\t') 1316 cp++; 1317 if (*cp == '\0') { 1318 int c; 1319 1320 c = getc(fconfig); 1321 (void) ungetc(c, fconfig); 1322 if (c == ' ' || c == '\t') 1323 if ((cp = nextline(fconfig))) 1324 goto again; 1325 *cpp = NULL; 1326 goto erp; 1327 } 1328 start = cp; 1329 while (*cp && *cp != ' ' && *cp != '\t') 1330 cp++; 1331 if (*cp != '\0') 1332 *cp++ = '\0'; 1333 if ((*cpp = cp) == NULL) 1334 goto erp; 1335 1336 return (start); 1337 } 1338 1339 char * 1340 nextline(FILE *fd) 1341 { 1342 if (fgets(line, sizeof (line), fd) == NULL) 1343 return (NULL); 1344 line[strcspn(line, "\n")] = '\0'; 1345 return (line); 1346 } 1347 1348 char * 1349 newstr(char *cp) 1350 { 1351 if ((cp = strdup(cp ? cp : ""))) 1352 return(cp); 1353 syslog(LOG_ERR, "strdup: %m"); 1354 exit(1); 1355 } 1356 1357 struct servtab * 1358 dupconfig(struct servtab *sep) 1359 { 1360 struct servtab *newtab; 1361 int argc; 1362 1363 newtab = calloc(1, sizeof(struct servtab)); 1364 1365 if (newtab == NULL) { 1366 syslog(LOG_ERR, "calloc: %m"); 1367 exit(1); 1368 } 1369 1370 newtab->se_service = sep->se_service ? newstr(sep->se_service) : NULL; 1371 newtab->se_socktype = sep->se_socktype; 1372 newtab->se_family = sep->se_family; 1373 newtab->se_proto = sep->se_proto ? newstr(sep->se_proto) : NULL; 1374 newtab->se_rpcprog = sep->se_rpcprog; 1375 newtab->se_rpcversl = sep->se_rpcversl; 1376 newtab->se_rpcversh = sep->se_rpcversh; 1377 newtab->se_wait = sep->se_wait; 1378 newtab->se_user = sep->se_user ? newstr(sep->se_user) : NULL; 1379 newtab->se_group = sep->se_group ? newstr(sep->se_group) : NULL; 1380 newtab->se_bi = sep->se_bi; 1381 newtab->se_server = sep->se_server ? newstr(sep->se_server) : 0; 1382 1383 for (argc = 0; argc <= MAXARGV; argc++) 1384 newtab->se_argv[argc] = sep->se_argv[argc] ? 1385 newstr(sep->se_argv[argc]) : NULL; 1386 newtab->se_max = sep->se_max; 1387 1388 return (newtab); 1389 } 1390 1391 void 1392 inetd_setproctitle(char *a, int s) 1393 { 1394 socklen_t size; 1395 struct sockaddr_storage ss; 1396 char hbuf[NI_MAXHOST]; 1397 1398 size = sizeof(ss); 1399 if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) { 1400 if (getnameinfo((struct sockaddr *)&ss, size, hbuf, 1401 sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) 1402 setproctitle("-%s [%s]", a, hbuf); 1403 else 1404 setproctitle("-%s [?]", a); 1405 } else 1406 setproctitle("-%s", a); 1407 } 1408 1409 int 1410 bump_nofile(void) 1411 { 1412 #define FD_CHUNK 32 1413 1414 struct rlimit rl; 1415 1416 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) { 1417 syslog(LOG_ERR, "getrlimit: %m"); 1418 return -1; 1419 } 1420 rl.rlim_cur = MINIMUM(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1421 rl.rlim_cur = MINIMUM(FD_SETSIZE, rl.rlim_cur + FD_CHUNK); 1422 if (rl.rlim_cur <= rlim_nofile_cur) { 1423 syslog(LOG_ERR, 1424 "bump_nofile: cannot extend file limit, max = %d", 1425 (int)rl.rlim_cur); 1426 return -1; 1427 } 1428 1429 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { 1430 syslog(LOG_ERR, "setrlimit: %m"); 1431 return -1; 1432 } 1433 1434 rlim_nofile_cur = rl.rlim_cur; 1435 return 0; 1436 } 1437 1438 /* 1439 * Internet services provided internally by inetd: 1440 */ 1441 #define BUFSIZE 4096 1442 1443 void 1444 echo_stream(int s, struct servtab *sep) 1445 { 1446 char buffer[BUFSIZE]; 1447 int i; 1448 1449 inetd_setproctitle(sep->se_service, s); 1450 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1451 write(s, buffer, i) > 0) 1452 ; 1453 exit(0); 1454 } 1455 1456 void 1457 echo_dg(int s, struct servtab *sep) 1458 { 1459 char buffer[BUFSIZE]; 1460 int i; 1461 socklen_t size; 1462 struct sockaddr_storage ss; 1463 1464 size = sizeof(ss); 1465 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, 1466 (struct sockaddr *)&ss, &size)) == -1) 1467 return; 1468 if (dg_badinput((struct sockaddr *)&ss)) 1469 return; 1470 (void) sendto(s, buffer, i, 0, (struct sockaddr *)&ss, size); 1471 } 1472 1473 void 1474 discard_stream(int s, struct servtab *sep) 1475 { 1476 char buffer[BUFSIZE]; 1477 1478 inetd_setproctitle(sep->se_service, s); 1479 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1480 errno == EINTR) 1481 ; 1482 exit(0); 1483 } 1484 1485 void 1486 discard_dg(int s, struct servtab *sep) 1487 { 1488 char buffer[BUFSIZE]; 1489 1490 (void) read(s, buffer, sizeof(buffer)); 1491 } 1492 1493 #include <ctype.h> 1494 #define LINESIZ 72 1495 char ring[128]; 1496 char *endring; 1497 1498 void 1499 initring(void) 1500 { 1501 int i; 1502 1503 endring = ring; 1504 1505 for (i = 0; i <= sizeof ring; ++i) 1506 if (isprint((unsigned char)i)) 1507 *endring++ = i; 1508 } 1509 1510 void 1511 chargen_stream(int s, struct servtab *sep) 1512 { 1513 char *rs; 1514 int len; 1515 char text[LINESIZ+2]; 1516 1517 inetd_setproctitle(sep->se_service, s); 1518 1519 if (!endring) { 1520 initring(); 1521 rs = ring; 1522 } 1523 1524 text[LINESIZ] = '\r'; 1525 text[LINESIZ + 1] = '\n'; 1526 for (rs = ring;;) { 1527 if ((len = endring - rs) >= LINESIZ) 1528 memmove(text, rs, LINESIZ); 1529 else { 1530 memmove(text, rs, len); 1531 memmove(text + len, ring, LINESIZ - len); 1532 } 1533 if (++rs == endring) 1534 rs = ring; 1535 if (write(s, text, sizeof(text)) != sizeof(text)) 1536 break; 1537 } 1538 exit(0); 1539 } 1540 1541 void 1542 chargen_dg(int s, struct servtab *sep) 1543 { 1544 struct sockaddr_storage ss; 1545 static char *rs; 1546 int len; 1547 socklen_t size; 1548 char text[LINESIZ+2]; 1549 1550 if (endring == 0) { 1551 initring(); 1552 rs = ring; 1553 } 1554 1555 size = sizeof(ss); 1556 if (recvfrom(s, text, sizeof(text), 0, (struct sockaddr *)&ss, 1557 &size) == -1) 1558 return; 1559 if (dg_badinput((struct sockaddr *)&ss)) 1560 return; 1561 1562 if ((len = endring - rs) >= LINESIZ) 1563 memmove(text, rs, LINESIZ); 1564 else { 1565 memmove(text, rs, len); 1566 memmove(text + len, ring, LINESIZ - len); 1567 } 1568 if (++rs == endring) 1569 rs = ring; 1570 text[LINESIZ] = '\r'; 1571 text[LINESIZ + 1] = '\n'; 1572 (void) sendto(s, text, sizeof(text), 0, (struct sockaddr *)&ss, size); 1573 } 1574 1575 /* 1576 * Return a machine readable date and time, in the form of the 1577 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1578 * returns the number of seconds since midnight, Jan 1, 1970, 1579 * we must add 2208988800 seconds to this figure to make up for 1580 * some seventy years Bell Labs was asleep. 1581 */ 1582 u_int32_t 1583 machtime(void) 1584 { 1585 struct timeval tv; 1586 1587 if (gettimeofday(&tv, NULL) == -1) 1588 return (0L); 1589 1590 return (htonl((u_int32_t)tv.tv_sec + 2208988800UL)); 1591 } 1592 1593 void 1594 machtime_stream(int s, struct servtab *sep) 1595 { 1596 u_int32_t result; 1597 1598 result = machtime(); 1599 (void) write(s, &result, sizeof(result)); 1600 } 1601 1602 void 1603 machtime_dg(int s, struct servtab *sep) 1604 { 1605 u_int32_t result; 1606 struct sockaddr_storage ss; 1607 socklen_t size; 1608 1609 size = sizeof(ss); 1610 if (recvfrom(s, &result, sizeof(result), 0, 1611 (struct sockaddr *)&ss, &size) == -1) 1612 return; 1613 if (dg_badinput((struct sockaddr *)&ss)) 1614 return; 1615 result = machtime(); 1616 (void) sendto(s, &result, sizeof(result), 0, 1617 (struct sockaddr *)&ss, size); 1618 } 1619 1620 /* Return human-readable time of day */ 1621 void 1622 daytime_stream(int s, struct servtab *sep) 1623 { 1624 char buffer[256]; 1625 time_t clock; 1626 1627 clock = time(NULL); 1628 1629 (void) snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1630 (void) write(s, buffer, strlen(buffer)); 1631 } 1632 1633 /* Return human-readable time of day */ 1634 void 1635 daytime_dg(int s, struct servtab *sep) 1636 { 1637 char buffer[256]; 1638 time_t clock; 1639 struct sockaddr_storage ss; 1640 socklen_t size; 1641 1642 clock = time(NULL); 1643 1644 size = sizeof(ss); 1645 if (recvfrom(s, buffer, sizeof(buffer), 0, (struct sockaddr *)&ss, 1646 &size) == -1) 1647 return; 1648 if (dg_badinput((struct sockaddr *)&ss)) 1649 return; 1650 (void) snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1651 (void) sendto(s, buffer, strlen(buffer), 0, (struct sockaddr *)&ss, 1652 size); 1653 } 1654 1655 /* 1656 * print_service: 1657 * Dump relevant information to stderr 1658 */ 1659 void 1660 print_service(char *action, struct servtab *sep) 1661 { 1662 if (strcmp(sep->se_hostaddr, "*") == 0) 1663 fprintf(stderr, "%s: %s ", action, sep->se_service); 1664 else 1665 fprintf(stderr, "%s: %s:%s ", action, sep->se_hostaddr, 1666 sep->se_service); 1667 1668 if (isrpcservice(sep)) 1669 fprintf(stderr, "rpcprog=%d, rpcvers=%d/%d, proto=%s,", 1670 sep->se_rpcprog, sep->se_rpcversh, 1671 sep->se_rpcversl, sep->se_proto); 1672 else 1673 fprintf(stderr, "proto=%s,", sep->se_proto); 1674 1675 fprintf(stderr, 1676 " wait.max=%d.%d user:group=%s:%s builtin=%lx server=%s\n", 1677 sep->se_wait, sep->se_max, sep->se_user, 1678 sep->se_group ? sep->se_group : "wheel", 1679 (long)sep->se_bi, sep->se_server); 1680 } 1681 1682 void 1683 spawn(int ctrl, short events, void *xsep) 1684 { 1685 struct servtab *sep = xsep; 1686 struct passwd *pwd; 1687 int tmpint, dofork; 1688 struct group *grp = NULL; 1689 char buf[50]; 1690 pid_t pid; 1691 1692 if (debug) 1693 fprintf(stderr, "someone wants %s\n", sep->se_service); 1694 1695 pid = 0; 1696 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 1697 if (dofork) { 1698 if (sep->se_count++ == 0) 1699 (void)gettimeofday(&sep->se_time, NULL); 1700 else if (sep->se_count >= sep->se_max) { 1701 struct timeval now; 1702 1703 (void)gettimeofday(&now, NULL); 1704 if (now.tv_sec - sep->se_time.tv_sec > 1705 CNT_INTVL) { 1706 sep->se_time = now; 1707 sep->se_count = 1; 1708 } else { 1709 if (!sep->se_wait && 1710 sep->se_socktype == SOCK_STREAM) 1711 close(ctrl); 1712 if (sep->se_family == AF_INET && 1713 ntohs(sep->se_ctrladdr_in.sin_port) >= 1714 IPPORT_RESERVED) { 1715 /* 1716 * Cannot close it -- there are 1717 * thieves on the system. 1718 * Simply ignore the connection. 1719 */ 1720 --sep->se_count; 1721 return; 1722 } 1723 syslog(LOG_ERR, 1724 "%s/%s server failing (looping), service terminated", 1725 sep->se_service, sep->se_proto); 1726 if (!sep->se_wait && 1727 sep->se_socktype == SOCK_STREAM) 1728 close(ctrl); 1729 event_del(&sep->se_event); 1730 (void) close(sep->se_fd); 1731 1732 sep->se_fd = -1; 1733 sep->se_count = 0; 1734 if (!timingout) { 1735 timingout = 1; 1736 alarm(RETRYTIME); 1737 } 1738 return; 1739 } 1740 } 1741 pid = fork(); 1742 } 1743 if (pid == -1) { 1744 syslog(LOG_ERR, "fork: %m"); 1745 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 1746 close(ctrl); 1747 sleep(1); 1748 return; 1749 } 1750 1751 if (pid && sep->se_wait) { 1752 sep->se_wait = pid; 1753 event_del(&sep->se_event); 1754 } 1755 if (pid == 0) { 1756 if (sep->se_bi) { 1757 if (dofork && pledge("stdio inet", NULL) == -1) 1758 err(1, "pledge"); 1759 (*sep->se_bi->bi_fn)(ctrl, sep); 1760 } else { 1761 if ((pwd = getpwnam(sep->se_user)) == NULL) { 1762 syslog(LOG_ERR, 1763 "getpwnam: %s: No such user", 1764 sep->se_user); 1765 if (sep->se_socktype != SOCK_STREAM) 1766 recv(0, buf, sizeof (buf), 0); 1767 exit(1); 1768 } 1769 if (setsid() <0) 1770 syslog(LOG_ERR, "%s: setsid: %m", 1771 sep->se_service); 1772 if (sep->se_group && 1773 (grp = getgrnam(sep->se_group)) == NULL) { 1774 syslog(LOG_ERR, 1775 "getgrnam: %s: No such group", 1776 sep->se_group); 1777 if (sep->se_socktype != SOCK_STREAM) 1778 recv(0, buf, sizeof (buf), 0); 1779 exit(1); 1780 } 1781 if (uid != 0) { 1782 /* a user running private inetd */ 1783 if (uid != pwd->pw_uid) 1784 exit(1); 1785 } else { 1786 tmpint = LOGIN_SETALL & 1787 ~(LOGIN_SETGROUP|LOGIN_SETLOGIN); 1788 if (pwd->pw_uid) 1789 tmpint |= LOGIN_SETGROUP|LOGIN_SETLOGIN; 1790 if (sep->se_group) { 1791 pwd->pw_gid = grp->gr_gid; 1792 tmpint |= LOGIN_SETGROUP; 1793 } 1794 if (setusercontext(NULL, pwd, pwd->pw_uid, 1795 tmpint) == -1) { 1796 syslog(LOG_ERR, 1797 "%s/%s: setusercontext: %m", 1798 sep->se_service, sep->se_proto); 1799 exit(1); 1800 } 1801 } 1802 if (debug) 1803 fprintf(stderr, "%ld execv %s\n", 1804 (long)getpid(), sep->se_server); 1805 if (ctrl != STDIN_FILENO) { 1806 dup2(ctrl, STDIN_FILENO); 1807 close(ctrl); 1808 } 1809 dup2(STDIN_FILENO, STDOUT_FILENO); 1810 dup2(STDIN_FILENO, STDERR_FILENO); 1811 closelog(); 1812 closefrom(3); 1813 signal(SIGPIPE, SIG_DFL); 1814 execv(sep->se_server, sep->se_argv); 1815 if (sep->se_socktype != SOCK_STREAM) 1816 recv(0, buf, sizeof (buf), 0); 1817 syslog(LOG_ERR, "execv %s: %m", sep->se_server); 1818 exit(1); 1819 } 1820 } 1821 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 1822 close(ctrl); 1823 } 1824