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