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