1 /* $OpenBSD: inetd.c,v 1.154 2016/08/25 05:23:19 tedu Exp $ */ 2 3 /* 4 * Copyright (c) 1983,1991 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Inetd - Internet super-server 34 * 35 * This program invokes all internet services as needed. 36 * connection-oriented services are invoked each time a 37 * connection is made, by creating a process. This process 38 * is passed the connection as file descriptor 0 and is 39 * expected to do a getpeername to find out the source host 40 * and port. 41 * 42 * Datagram oriented services are invoked when a datagram 43 * arrives; a process is created and passed a pending message 44 * on file descriptor 0. Datagram servers may either connect 45 * to their peer, freeing up the original socket for inetd 46 * to receive further messages on, or ``take over the socket'', 47 * processing all arriving datagrams and, eventually, timing 48 * out. The first type of server is said to be ``multi-threaded''; 49 * the second type of server ``single-threaded''. 50 * 51 * Inetd uses a configuration file which is read at startup 52 * and, possibly, at some later time in response to a hangup signal. 53 * The configuration file is ``free format'' with fields given in the 54 * order shown below. Continuation lines for an entry must begin with 55 * a space or tab. All fields must be present in each entry. 56 * 57 * service name must be in /etc/services 58 * socket type stream/dgram/raw/rdm/seqpacket 59 * protocol must be in /etc/protocols 60 * wait/nowait[.max] single-threaded/multi-threaded, max # 61 * user[.group] or user[:group] user/group to run daemon as 62 * server program full path name 63 * server program arguments maximum of MAXARGS (20) 64 * 65 * For RPC services 66 * service name/version must be in /etc/rpc 67 * socket type stream/dgram/raw/rdm/seqpacket 68 * protocol must be in /etc/protocols 69 * wait/nowait[.max] single-threaded/multi-threaded 70 * user[.group] or user[:group] user to run daemon as 71 * server program full path name 72 * server program arguments maximum of MAXARGS (20) 73 * 74 * For non-RPC services, the "service name" can be of the form 75 * hostaddress:servicename, in which case the hostaddress is used 76 * as the host portion of the address to listen on. If hostaddress 77 * consists of a single `*' character, INADDR_ANY is used. 78 * 79 * A line can also consist of just 80 * hostaddress: 81 * where hostaddress is as in the preceding paragraph. Such a line must 82 * have no further fields; the specified hostaddress is remembered and 83 * used for all further lines that have no hostaddress specified, 84 * until the next such line (or EOF). (This is why * is provided to 85 * allow explicit specification of INADDR_ANY.) A line 86 * *: 87 * is implicitly in effect at the beginning of the file. 88 * 89 * The hostaddress specifier may (and often will) contain dots; 90 * the service name must not. 91 * 92 * For RPC services, host-address specifiers are accepted and will 93 * work to some extent; however, because of limitations in the 94 * portmapper interface, it will not work to try to give more than 95 * one line for any given RPC service, even if the host-address 96 * specifiers are different. 97 * 98 * Comment lines are indicated by a `#' in column 1. 99 */ 100 101 /* 102 * Here's the scoop concerning the user[.:]group feature: 103 * 104 * 1) set-group-option off. 105 * 106 * a) user = root: NO setuid() or setgid() is done 107 * 108 * b) other: setgid(primary group as found in passwd) 109 * initgroups(name, primary group) 110 * setuid() 111 * 112 * 2) set-group-option on. 113 * 114 * a) user = root: setgid(specified group) 115 * NO initgroups() 116 * NO setuid() 117 * 118 * b) other: setgid(specified group) 119 * initgroups(name, specified group) 120 * setuid() 121 * 122 */ 123 124 #include <sys/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 v4chk: 448 if (IN_MULTICAST(in.s_addr)) 449 goto bad; 450 switch ((in.s_addr & 0xff000000) >> 24) { 451 case 0: case 127: case 255: 452 goto bad; 453 } 454 if (dg_broadcast(&in)) 455 goto bad; 456 break; 457 case AF_INET6: 458 in6 = &((struct sockaddr_in6 *)sa)->sin6_addr; 459 port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port); 460 if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6)) 461 goto bad; 462 /* 463 * OpenBSD does not support IPv4 mapped address (RFC2553 464 * inbound behavior) at all. We should drop it. 465 */ 466 if (IN6_IS_ADDR_V4MAPPED(in6)) 467 goto bad; 468 if (IN6_IS_ADDR_V4COMPAT(in6)) { 469 memcpy(&in, &in6->s6_addr[12], sizeof(in)); 470 in.s_addr = ntohl(in.s_addr); 471 goto v4chk; 472 } 473 break; 474 default: 475 /* Unsupported AF */ 476 goto bad; 477 } 478 479 if (port < IPPORT_RESERVED || port == NFS_PORT) 480 goto bad; 481 482 return (0); 483 484 bad: 485 return (1); 486 } 487 488 int 489 dg_broadcast(struct in_addr *in) 490 { 491 struct ifaddrs *ifa, *ifap; 492 struct sockaddr_in *sin; 493 494 if (getifaddrs(&ifap) < 0) 495 return (0); 496 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 497 if (ifa->ifa_addr->sa_family != AF_INET || 498 (ifa->ifa_flags & IFF_BROADCAST) == 0) 499 continue; 500 sin = (struct sockaddr_in *)ifa->ifa_broadaddr; 501 if (sin->sin_addr.s_addr == in->s_addr) { 502 freeifaddrs(ifap); 503 return (1); 504 } 505 } 506 freeifaddrs(ifap); 507 return (0); 508 } 509 510 void 511 reap(int sig, short event, void *arg) 512 { 513 struct servtab *sep; 514 int status; 515 pid_t pid; 516 517 if (debug) 518 fprintf(stderr, "reaping asked for\n"); 519 520 for (;;) { 521 if ((pid = wait3(&status, WNOHANG, NULL)) <= 0) { 522 if (pid == -1 && errno == EINTR) 523 continue; 524 break; 525 } 526 if (debug) 527 fprintf(stderr, "%ld reaped, status %x\n", 528 (long)pid, status); 529 for (sep = servtab; sep; sep = sep->se_next) 530 if (sep->se_wait == pid) { 531 if (WIFEXITED(status) && WEXITSTATUS(status)) 532 syslog(LOG_WARNING, 533 "%s: exit status %d", 534 sep->se_server, WEXITSTATUS(status)); 535 else if (WIFSIGNALED(status)) 536 syslog(LOG_WARNING, 537 "%s: exit signal %d", 538 sep->se_server, WTERMSIG(status)); 539 sep->se_wait = 1; 540 event_add(&sep->se_event, NULL); 541 if (debug) 542 fprintf(stderr, "restored %s, fd %d\n", 543 sep->se_service, sep->se_fd); 544 } 545 } 546 } 547 548 void 549 config(int sig, short event, void *arg) 550 { 551 struct servtab *sep, *cp, **sepp; 552 int add; 553 char protoname[11]; 554 555 if (!setconfig()) { 556 syslog(LOG_ERR, "%s: %m", CONFIG); 557 exit(1); 558 } 559 for (sep = servtab; sep; sep = sep->se_next) 560 sep->se_checked = 0; 561 cp = getconfigent(); 562 while (cp != NULL) { 563 for (sep = servtab; sep; sep = sep->se_next) 564 if (matchconf(sep, cp)) 565 break; 566 add = 0; 567 if (sep != NULL) { 568 int i; 569 570 #define SWAP(type, a, b) {type c=(type)a; a=(type)b; b=(type)c;} 571 572 /* 573 * sep->se_wait may be holding the pid of a daemon 574 * that we're waiting for. If so, don't overwrite 575 * it unless the config file explicitly says don't 576 * wait. 577 */ 578 if (cp->se_bi == 0 && 579 (sep->se_wait == 1 || cp->se_wait == 0)) 580 sep->se_wait = cp->se_wait; 581 SWAP(int, cp->se_max, sep->se_max); 582 SWAP(char *, sep->se_user, cp->se_user); 583 SWAP(char *, sep->se_group, cp->se_group); 584 SWAP(char *, sep->se_server, cp->se_server); 585 for (i = 0; i < MAXARGV; i++) 586 SWAP(char *, sep->se_argv[i], cp->se_argv[i]); 587 #undef SWAP 588 if (isrpcservice(sep)) 589 unregister_rpc(sep); 590 sep->se_rpcversl = cp->se_rpcversl; 591 sep->se_rpcversh = cp->se_rpcversh; 592 freeconfig(cp); 593 add = 1; 594 } else { 595 sep = enter(cp); 596 } 597 sep->se_checked = 1; 598 599 switch (sep->se_family) { 600 case AF_UNIX: 601 if (sep->se_fd != -1) 602 break; 603 sep->se_ctrladdr_size = 604 strlcpy(sep->se_ctrladdr_un.sun_path, 605 sep->se_service, 606 sizeof sep->se_ctrladdr_un.sun_path); 607 if (sep->se_ctrladdr_size >= 608 sizeof sep->se_ctrladdr_un.sun_path) { 609 syslog(LOG_WARNING, "%s/%s: UNIX domain socket " 610 "path too long", sep->se_service, 611 sep->se_proto); 612 goto serv_unknown; 613 } 614 sep->se_ctrladdr_un.sun_family = AF_UNIX; 615 sep->se_ctrladdr_size += 616 1 + sizeof sep->se_ctrladdr_un.sun_family; 617 (void)unlink(sep->se_service); 618 setup(sep); 619 break; 620 case AF_INET: 621 sep->se_ctrladdr_in.sin_family = AF_INET; 622 /* se_ctrladdr_in was set in getconfigent */ 623 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in; 624 625 if (isrpcservice(sep)) { 626 struct rpcent *rp; 627 628 sep->se_rpcprog = strtonum(sep->se_service, 629 1, USHRT_MAX, NULL); 630 if (sep->se_rpcprog == 0) { 631 rp = getrpcbyname(sep->se_service); 632 if (rp == 0) { 633 syslog(LOG_ERR, 634 "%s: unknown rpc service", 635 sep->se_service); 636 goto serv_unknown; 637 } 638 sep->se_rpcprog = rp->r_number; 639 } 640 if (sep->se_fd == -1) 641 setup(sep); 642 if (sep->se_fd != -1) 643 register_rpc(sep); 644 } else { 645 u_short port = htons(strtonum(sep->se_service, 646 1, USHRT_MAX, NULL)); 647 648 if (!port) { 649 (void)strlcpy(protoname, sep->se_proto, 650 sizeof(protoname)); 651 if (isdigit((unsigned char) 652 protoname[strlen(protoname) - 1])) 653 protoname[strlen(protoname) - 1] = '\0'; 654 sp = getservbyname(sep->se_service, 655 protoname); 656 if (sp == 0) { 657 syslog(LOG_ERR, 658 "%s/%s: unknown service", 659 sep->se_service, sep->se_proto); 660 goto serv_unknown; 661 } 662 port = sp->s_port; 663 } 664 if (port != sep->se_ctrladdr_in.sin_port) { 665 sep->se_ctrladdr_in.sin_port = port; 666 if (sep->se_fd != -1) { 667 event_del(&sep->se_event); 668 (void) close(sep->se_fd); 669 } 670 sep->se_fd = -1; 671 } 672 if (sep->se_fd == -1) 673 setup(sep); 674 } 675 break; 676 case AF_INET6: 677 sep->se_ctrladdr_in6.sin6_family = AF_INET6; 678 /* se_ctrladdr_in was set in getconfigent */ 679 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in6; 680 681 if (isrpcservice(sep)) { 682 struct rpcent *rp; 683 684 sep->se_rpcprog = strtonum(sep->se_service, 685 1, USHRT_MAX, NULL); 686 if (sep->se_rpcprog == 0) { 687 rp = getrpcbyname(sep->se_service); 688 if (rp == 0) { 689 syslog(LOG_ERR, 690 "%s: unknown rpc service", 691 sep->se_service); 692 goto serv_unknown; 693 } 694 sep->se_rpcprog = rp->r_number; 695 } 696 if (sep->se_fd == -1) 697 setup(sep); 698 if (sep->se_fd != -1) 699 register_rpc(sep); 700 } else { 701 u_short port = htons(strtonum(sep->se_service, 702 1, USHRT_MAX, NULL)); 703 704 if (!port) { 705 (void)strlcpy(protoname, sep->se_proto, 706 sizeof(protoname)); 707 if (isdigit((unsigned char) 708 protoname[strlen(protoname) - 1])) 709 protoname[strlen(protoname) - 1] = '\0'; 710 sp = getservbyname(sep->se_service, 711 protoname); 712 if (sp == 0) { 713 syslog(LOG_ERR, 714 "%s/%s: unknown service", 715 sep->se_service, sep->se_proto); 716 goto serv_unknown; 717 } 718 port = sp->s_port; 719 } 720 if (port != sep->se_ctrladdr_in6.sin6_port) { 721 sep->se_ctrladdr_in6.sin6_port = port; 722 if (sep->se_fd != -1) { 723 event_del(&sep->se_event); 724 (void) close(sep->se_fd); 725 } 726 sep->se_fd = -1; 727 } 728 if (sep->se_fd == -1) 729 setup(sep); 730 } 731 break; 732 } 733 serv_unknown: 734 if (cp->se_next != NULL) { 735 struct servtab *tmp = cp; 736 737 cp = cp->se_next; 738 free(tmp); 739 } else { 740 free(cp); 741 cp = getconfigent(); 742 } 743 if (debug) 744 print_service(add ? "REDO" : "ADD", sep); 745 } 746 endconfig(); 747 /* 748 * Purge anything not looked at above. 749 */ 750 sepp = &servtab; 751 while ((sep = *sepp)) { 752 if (sep->se_checked) { 753 sepp = &sep->se_next; 754 continue; 755 } 756 *sepp = sep->se_next; 757 if (sep->se_fd != -1) { 758 event_del(&sep->se_event); 759 (void) close(sep->se_fd); 760 } 761 if (isrpcservice(sep)) 762 unregister_rpc(sep); 763 if (sep->se_family == AF_UNIX) 764 (void)unlink(sep->se_service); 765 if (debug) 766 print_service("FREE", sep); 767 freeconfig(sep); 768 free(sep); 769 } 770 } 771 772 void 773 retry(int sig, short events, void *arg) 774 { 775 struct servtab *sep; 776 777 timingout = 0; 778 for (sep = servtab; sep; sep = sep->se_next) { 779 if (sep->se_fd == -1) { 780 switch (sep->se_family) { 781 case AF_UNIX: 782 case AF_INET: 783 case AF_INET6: 784 setup(sep); 785 if (sep->se_fd != -1 && isrpcservice(sep)) 786 register_rpc(sep); 787 break; 788 } 789 } 790 } 791 } 792 793 void 794 die(int sig, short events, void *arg) 795 { 796 struct servtab *sep; 797 798 for (sep = servtab; sep; sep = sep->se_next) { 799 if (sep->se_fd == -1) 800 continue; 801 802 switch (sep->se_family) { 803 case AF_UNIX: 804 (void)unlink(sep->se_service); 805 break; 806 case AF_INET: 807 case AF_INET6: 808 if (sep->se_wait == 1 && isrpcservice(sep)) 809 unregister_rpc(sep); 810 break; 811 } 812 (void)close(sep->se_fd); 813 } 814 exit(0); 815 } 816 817 void 818 setup(struct servtab *sep) 819 { 820 int on = 1; 821 int r; 822 mode_t mask = 0; 823 824 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 825 syslog(LOG_ERR, "%s/%s: socket: %m", 826 sep->se_service, sep->se_proto); 827 return; 828 } 829 #define turnon(fd, opt) \ 830 setsockopt(fd, SOL_SOCKET, opt, &on, sizeof (on)) 831 if (strncmp(sep->se_proto, "tcp", 3) == 0 && debug && 832 turnon(sep->se_fd, SO_DEBUG) < 0) 833 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 834 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 835 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 836 #undef turnon 837 if (isrpcservice(sep)) { 838 struct passwd *pwd; 839 840 /* 841 * for RPC services, attempt to use a reserved port 842 * if they are going to be running as root. 843 * 844 * Also, zero out the port for all RPC services; let bind() 845 * find one. 846 */ 847 sep->se_ctrladdr_in.sin_port = 0; 848 if (sep->se_user && (pwd = getpwnam(sep->se_user)) && 849 pwd->pw_uid == 0 && uid == 0) 850 r = bindresvport(sep->se_fd, &sep->se_ctrladdr_in); 851 else { 852 r = bind(sep->se_fd, &sep->se_ctrladdr, 853 sep->se_ctrladdr_size); 854 if (r == 0) { 855 socklen_t len = sep->se_ctrladdr_size; 856 int saveerrno = errno; 857 858 /* update se_ctrladdr_in.sin_port */ 859 r = getsockname(sep->se_fd, &sep->se_ctrladdr, 860 &len); 861 if (r <= 0) 862 errno = saveerrno; 863 } 864 } 865 } else { 866 if (sep->se_family == AF_UNIX) 867 mask = umask(0111); 868 r = bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size); 869 if (sep->se_family == AF_UNIX) 870 umask(mask); 871 } 872 if (r < 0) { 873 syslog(LOG_ERR, "%s/%s: bind: %m", 874 sep->se_service, sep->se_proto); 875 (void) close(sep->se_fd); 876 sep->se_fd = -1; 877 if (!timingout) { 878 timingout = 1; 879 alarm(RETRYTIME); 880 } 881 return; 882 } 883 if (sep->se_socktype == SOCK_STREAM) 884 listen(sep->se_fd, 10); 885 886 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 887 event_set(&sep->se_event, sep->se_fd, EV_READ|EV_PERSIST, 888 gettcp, sep); 889 } else { 890 event_set(&sep->se_event, sep->se_fd, EV_READ|EV_PERSIST, 891 spawn, sep); 892 } 893 894 event_add(&sep->se_event, NULL); 895 896 if (sep->se_fd > maxsock) { 897 maxsock = sep->se_fd; 898 if (maxsock > rlim_nofile_cur - FD_MARGIN) 899 bump_nofile(); 900 } 901 } 902 903 void 904 register_rpc(struct servtab *sep) 905 { 906 socklen_t n; 907 struct sockaddr_in sin; 908 struct protoent *pp; 909 910 if ((pp = getprotobyname(sep->se_proto+4)) == NULL) { 911 syslog(LOG_ERR, "%s: getproto: %m", 912 sep->se_proto); 913 return; 914 } 915 n = sizeof sin; 916 if (getsockname(sep->se_fd, (struct sockaddr *)&sin, &n) < 0) { 917 syslog(LOG_ERR, "%s/%s: getsockname: %m", 918 sep->se_service, sep->se_proto); 919 return; 920 } 921 922 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 923 if (debug) 924 fprintf(stderr, "pmap_set: %u %u %u %u\n", 925 sep->se_rpcprog, n, pp->p_proto, 926 ntohs(sin.sin_port)); 927 (void)pmap_unset(sep->se_rpcprog, n); 928 if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port))) 929 syslog(LOG_ERR, "%s %s: pmap_set: %u %u %u %u: %m", 930 sep->se_service, sep->se_proto, 931 sep->se_rpcprog, n, pp->p_proto, 932 ntohs(sin.sin_port)); 933 } 934 } 935 936 void 937 unregister_rpc(struct servtab *sep) 938 { 939 int n; 940 941 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 942 if (debug) 943 fprintf(stderr, "pmap_unset(%u, %u)\n", 944 sep->se_rpcprog, n); 945 if (!pmap_unset(sep->se_rpcprog, n)) 946 syslog(LOG_ERR, "pmap_unset(%u, %u)", 947 sep->se_rpcprog, n); 948 } 949 } 950 951 952 struct servtab * 953 enter(struct servtab *cp) 954 { 955 struct servtab *sep; 956 957 sep = malloc(sizeof (*sep)); 958 if (sep == NULL) { 959 syslog(LOG_ERR, "Out of memory."); 960 exit(1); 961 } 962 *sep = *cp; 963 sep->se_fd = -1; 964 sep->se_rpcprog = -1; 965 sep->se_next = servtab; 966 servtab = sep; 967 return (sep); 968 } 969 970 int 971 matchconf(struct servtab *old, struct servtab *new) 972 { 973 if (strcmp(old->se_service, new->se_service) != 0) 974 return (0); 975 976 if (strcmp(old->se_hostaddr, new->se_hostaddr) != 0) 977 return (0); 978 979 if (strcmp(old->se_proto, new->se_proto) != 0) 980 return (0); 981 982 /* 983 * If the new servtab is bound to a specific address, check that the 984 * old servtab is bound to the same entry. If the new service is not 985 * bound to a specific address then the check of se_hostaddr above 986 * is sufficient. 987 */ 988 989 if (old->se_family == AF_INET && new->se_family == AF_INET && 990 bcmp(&old->se_ctrladdr_in.sin_addr, 991 &new->se_ctrladdr_in.sin_addr, 992 sizeof(new->se_ctrladdr_in.sin_addr)) != 0) 993 return (0); 994 995 if (old->se_family == AF_INET6 && new->se_family == AF_INET6 && 996 bcmp(&old->se_ctrladdr_in6.sin6_addr, 997 &new->se_ctrladdr_in6.sin6_addr, 998 sizeof(new->se_ctrladdr_in6.sin6_addr)) != 0) 999 return (0); 1000 if (old->se_family == AF_INET6 && new->se_family == AF_INET6 && 1001 old->se_ctrladdr_in6.sin6_scope_id != 1002 new->se_ctrladdr_in6.sin6_scope_id) 1003 return (0); 1004 1005 return (1); 1006 } 1007 1008 FILE *fconfig = NULL; 1009 char line[1024]; 1010 char *defhost; 1011 char *skip(char **, int); 1012 char *nextline(FILE *); 1013 char *newstr(char *); 1014 struct servtab *dupconfig(struct servtab *); 1015 1016 int 1017 setconfig(void) 1018 { 1019 free(defhost); 1020 defhost = newstr("*"); 1021 if (fconfig != NULL) { 1022 fseek(fconfig, 0L, SEEK_SET); 1023 return (1); 1024 } 1025 fconfig = fopen(CONFIG, "r"); 1026 return (fconfig != NULL); 1027 } 1028 1029 void 1030 endconfig(void) 1031 { 1032 if (fconfig) { 1033 (void) fclose(fconfig); 1034 fconfig = NULL; 1035 } 1036 if (defhost) { 1037 free(defhost); 1038 defhost = 0; 1039 } 1040 } 1041 1042 struct servtab * 1043 getconfigent(void) 1044 { 1045 struct servtab *sep, *tsep; 1046 char *arg, *cp, *hostdelim, *s; 1047 int argc; 1048 1049 sep = calloc(1, sizeof(struct servtab)); 1050 if (sep == NULL) { 1051 syslog(LOG_ERR, "calloc: %m"); 1052 exit(1); 1053 } 1054 more: 1055 freeconfig(sep); 1056 1057 while ((cp = nextline(fconfig)) && *cp == '#') 1058 ; 1059 if (cp == NULL) { 1060 free(sep); 1061 return (NULL); 1062 } 1063 1064 memset(sep, 0, sizeof *sep); 1065 arg = skip(&cp, 0); 1066 if (arg == NULL) { 1067 /* A blank line. */ 1068 goto more; 1069 } 1070 1071 /* Check for a host name. */ 1072 hostdelim = strrchr(arg, ':'); 1073 if (hostdelim) { 1074 *hostdelim = '\0'; 1075 if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') { 1076 hostdelim[-1] = '\0'; 1077 sep->se_hostaddr = newstr(arg + 1); 1078 } else if (hostdelim == arg) 1079 sep->se_hostaddr = newstr("*"); 1080 else 1081 sep->se_hostaddr = newstr(arg); 1082 arg = hostdelim + 1; 1083 /* 1084 * If the line is of the form `host:', then just change the 1085 * default host for the following lines. 1086 */ 1087 if (*arg == '\0') { 1088 arg = skip(&cp, 0); 1089 if (cp == NULL) { 1090 free(defhost); 1091 defhost = newstr(sep->se_hostaddr); 1092 goto more; 1093 } 1094 } 1095 } else 1096 sep->se_hostaddr = newstr(defhost); 1097 1098 sep->se_service = newstr(arg); 1099 if ((arg = skip(&cp, 1)) == NULL) 1100 goto more; 1101 1102 if (strcmp(arg, "stream") == 0) 1103 sep->se_socktype = SOCK_STREAM; 1104 else if (strcmp(arg, "dgram") == 0) 1105 sep->se_socktype = SOCK_DGRAM; 1106 else if (strcmp(arg, "rdm") == 0) 1107 sep->se_socktype = SOCK_RDM; 1108 else if (strcmp(arg, "seqpacket") == 0) 1109 sep->se_socktype = SOCK_SEQPACKET; 1110 else if (strcmp(arg, "raw") == 0) 1111 sep->se_socktype = SOCK_RAW; 1112 else 1113 sep->se_socktype = -1; 1114 1115 if ((arg = skip(&cp, 1)) == NULL) 1116 goto more; 1117 1118 sep->se_proto = newstr(arg); 1119 1120 if (strcmp(sep->se_proto, "unix") == 0) { 1121 sep->se_family = AF_UNIX; 1122 } else { 1123 int s; 1124 1125 sep->se_family = AF_INET; 1126 if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') 1127 sep->se_family = AF_INET6; 1128 1129 /* check if the family is supported */ 1130 s = socket(sep->se_family, SOCK_DGRAM, 0); 1131 if (s < 0) { 1132 syslog(LOG_WARNING, "%s/%s: %s: the address family is " 1133 "not supported by the kernel", sep->se_service, 1134 sep->se_proto, sep->se_hostaddr); 1135 goto more; 1136 } 1137 close(s); 1138 1139 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 1140 char *cp, *ccp; 1141 long l; 1142 1143 cp = strchr(sep->se_service, '/'); 1144 if (cp == 0) { 1145 syslog(LOG_ERR, "%s: no rpc version", 1146 sep->se_service); 1147 goto more; 1148 } 1149 *cp++ = '\0'; 1150 l = strtol(cp, &ccp, 0); 1151 if (ccp == cp || l < 0 || l > INT_MAX) { 1152 badafterall: 1153 syslog(LOG_ERR, "%s/%s: bad rpc version", 1154 sep->se_service, cp); 1155 goto more; 1156 } 1157 sep->se_rpcversl = sep->se_rpcversh = l; 1158 if (*ccp == '-') { 1159 cp = ccp + 1; 1160 l = strtol(cp, &ccp, 0); 1161 if (ccp == cp || l < 0 || l > INT_MAX || 1162 l < sep->se_rpcversl || *ccp) 1163 goto badafterall; 1164 sep->se_rpcversh = l; 1165 } else if (*ccp != '\0') 1166 goto badafterall; 1167 } 1168 } 1169 arg = skip(&cp, 1); 1170 if (arg == NULL) 1171 goto more; 1172 1173 s = strchr(arg, '.'); 1174 if (s) { 1175 char *p; 1176 1177 *s++ = '\0'; 1178 sep->se_max = strtoul(s, &p, 0); 1179 if (sep->se_max < 1 || *p) { 1180 syslog(LOG_ERR, 1181 "%s: illegal max field \"%s\", setting to %d", 1182 sep->se_service, s, toomany); 1183 sep->se_max = toomany; 1184 } 1185 } else 1186 sep->se_max = toomany; 1187 1188 sep->se_wait = strcmp(arg, "wait") == 0; 1189 if ((arg = skip(&cp, 1)) == NULL) 1190 goto more; 1191 sep->se_user = newstr(arg); 1192 arg = strchr(sep->se_user, '.'); 1193 if (arg == NULL) 1194 arg = strchr(sep->se_user, ':'); 1195 if (arg) { 1196 *arg++ = '\0'; 1197 sep->se_group = newstr(arg); 1198 } 1199 if ((arg = skip(&cp, 1)) == NULL) 1200 goto more; 1201 1202 sep->se_server = newstr(arg); 1203 if (strcmp(sep->se_server, "internal") == 0) { 1204 struct biltin *bi; 1205 1206 for (bi = biltins; bi->bi_service; bi++) 1207 if (bi->bi_socktype == sep->se_socktype && 1208 strcmp(bi->bi_service, sep->se_service) == 0) 1209 break; 1210 if (bi->bi_service == 0) { 1211 syslog(LOG_ERR, "internal service %s unknown", 1212 sep->se_service); 1213 goto more; 1214 } 1215 sep->se_bi = bi; 1216 sep->se_wait = bi->bi_wait; 1217 } else 1218 sep->se_bi = NULL; 1219 argc = 0; 1220 for (arg = skip(&cp, 0); cp; arg = skip(&cp, 0)) { 1221 if (argc < MAXARGV) 1222 sep->se_argv[argc++] = newstr(arg); 1223 } 1224 if (argc == 0 && sep->se_bi == NULL) { 1225 if ((arg = strrchr(sep->se_server, '/')) != NULL) 1226 arg++; 1227 else 1228 arg = sep->se_server; 1229 sep->se_argv[argc++] = newstr(arg); 1230 } 1231 while (argc <= MAXARGV) 1232 sep->se_argv[argc++] = NULL; 1233 1234 /* 1235 * Resolve each hostname in the se_hostaddr list (if any) 1236 * and create a new entry for each resolved address. 1237 */ 1238 if (sep->se_hostaddr != NULL && strcmp(sep->se_proto, "unix") != 0) { 1239 struct addrinfo hints, *res0, *res; 1240 char *host, *hostlist0, *hostlist, *port; 1241 int error; 1242 1243 hostlist = hostlist0 = sep->se_hostaddr; 1244 sep->se_hostaddr = NULL; 1245 sep->se_checked = -1; 1246 while ((host = strsep(&hostlist, ",")) != NULL) { 1247 if (*host == '\0') 1248 continue; 1249 1250 memset(&hints, 0, sizeof(hints)); 1251 hints.ai_family = sep->se_family; 1252 hints.ai_socktype = sep->se_socktype; 1253 hints.ai_flags = AI_PASSIVE; 1254 port = "0"; 1255 error = getaddrinfo(strcmp(host, "*") ? host : NULL, 1256 port, &hints, &res0); 1257 if (error) { 1258 syslog(LOG_ERR, "%s/%s: %s: %s", 1259 sep->se_service, sep->se_proto, 1260 host, gai_strerror(error)); 1261 continue; 1262 } 1263 for (res = res0; res; res = res->ai_next) { 1264 if (res->ai_addrlen > 1265 sizeof(sep->se_ctrladdr_storage)) 1266 continue; 1267 /* 1268 * If sep is unused, store host in there. 1269 * Otherwise, dup a new entry and prepend it. 1270 */ 1271 if (sep->se_checked == -1) { 1272 sep->se_checked = 0; 1273 } else { 1274 tsep = dupconfig(sep); 1275 tsep->se_next = sep; 1276 sep = tsep; 1277 } 1278 sep->se_hostaddr = newstr(host); 1279 memcpy(&sep->se_ctrladdr_storage, 1280 res->ai_addr, res->ai_addrlen); 1281 sep->se_ctrladdr_size = res->ai_addrlen; 1282 } 1283 freeaddrinfo(res0); 1284 } 1285 free(hostlist0); 1286 if (sep->se_checked == -1) 1287 goto more; /* no resolvable names/addresses */ 1288 } 1289 1290 return (sep); 1291 } 1292 1293 void 1294 freeconfig(struct servtab *cp) 1295 { 1296 int i; 1297 1298 free(cp->se_hostaddr); 1299 cp->se_hostaddr = NULL; 1300 free(cp->se_service); 1301 cp->se_service = NULL; 1302 free(cp->se_proto); 1303 cp->se_proto = NULL; 1304 free(cp->se_user); 1305 cp->se_user = NULL; 1306 free(cp->se_group); 1307 cp->se_group = NULL; 1308 free(cp->se_server); 1309 cp->se_server = NULL; 1310 for (i = 0; i < MAXARGV; i++) { 1311 free(cp->se_argv[i]); 1312 cp->se_argv[i] = NULL; 1313 } 1314 } 1315 1316 char * 1317 skip(char **cpp, int report) 1318 { 1319 char *cp = *cpp; 1320 char *start; 1321 1322 erp: 1323 if (*cpp == NULL) { 1324 if (report) 1325 syslog(LOG_ERR, "syntax error in inetd config file"); 1326 return (NULL); 1327 } 1328 1329 again: 1330 while (*cp == ' ' || *cp == '\t') 1331 cp++; 1332 if (*cp == '\0') { 1333 int c; 1334 1335 c = getc(fconfig); 1336 (void) ungetc(c, fconfig); 1337 if (c == ' ' || c == '\t') 1338 if ((cp = nextline(fconfig))) 1339 goto again; 1340 *cpp = NULL; 1341 goto erp; 1342 } 1343 start = cp; 1344 while (*cp && *cp != ' ' && *cp != '\t') 1345 cp++; 1346 if (*cp != '\0') 1347 *cp++ = '\0'; 1348 if ((*cpp = cp) == NULL) 1349 goto erp; 1350 1351 return (start); 1352 } 1353 1354 char * 1355 nextline(FILE *fd) 1356 { 1357 if (fgets(line, sizeof (line), fd) == NULL) 1358 return (NULL); 1359 line[strcspn(line, "\n")] = '\0'; 1360 return (line); 1361 } 1362 1363 char * 1364 newstr(char *cp) 1365 { 1366 if ((cp = strdup(cp ? cp : ""))) 1367 return(cp); 1368 syslog(LOG_ERR, "strdup: %m"); 1369 exit(1); 1370 } 1371 1372 struct servtab * 1373 dupconfig(struct servtab *sep) 1374 { 1375 struct servtab *newtab; 1376 int argc; 1377 1378 newtab = calloc(1, sizeof(struct servtab)); 1379 1380 if (newtab == NULL) { 1381 syslog(LOG_ERR, "calloc: %m"); 1382 exit(1); 1383 } 1384 1385 newtab->se_service = sep->se_service ? newstr(sep->se_service) : NULL; 1386 newtab->se_socktype = sep->se_socktype; 1387 newtab->se_family = sep->se_family; 1388 newtab->se_proto = sep->se_proto ? newstr(sep->se_proto) : NULL; 1389 newtab->se_rpcprog = sep->se_rpcprog; 1390 newtab->se_rpcversl = sep->se_rpcversl; 1391 newtab->se_rpcversh = sep->se_rpcversh; 1392 newtab->se_wait = sep->se_wait; 1393 newtab->se_user = sep->se_user ? newstr(sep->se_user) : NULL; 1394 newtab->se_group = sep->se_group ? newstr(sep->se_group) : NULL; 1395 newtab->se_bi = sep->se_bi; 1396 newtab->se_server = sep->se_server ? newstr(sep->se_server) : 0; 1397 1398 for (argc = 0; argc <= MAXARGV; argc++) 1399 newtab->se_argv[argc] = sep->se_argv[argc] ? 1400 newstr(sep->se_argv[argc]) : NULL; 1401 newtab->se_max = sep->se_max; 1402 1403 return (newtab); 1404 } 1405 1406 void 1407 inetd_setproctitle(char *a, int s) 1408 { 1409 socklen_t size; 1410 struct sockaddr_storage ss; 1411 char hbuf[NI_MAXHOST]; 1412 1413 size = sizeof(ss); 1414 if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) { 1415 if (getnameinfo((struct sockaddr *)&ss, size, hbuf, 1416 sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) 1417 setproctitle("-%s [%s]", a, hbuf); 1418 else 1419 setproctitle("-%s [?]", a); 1420 } else 1421 setproctitle("-%s", a); 1422 } 1423 1424 int 1425 bump_nofile(void) 1426 { 1427 #define FD_CHUNK 32 1428 1429 struct rlimit rl; 1430 1431 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1432 syslog(LOG_ERR, "getrlimit: %m"); 1433 return -1; 1434 } 1435 rl.rlim_cur = MINIMUM(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1436 rl.rlim_cur = MINIMUM(FD_SETSIZE, rl.rlim_cur + FD_CHUNK); 1437 if (rl.rlim_cur <= rlim_nofile_cur) { 1438 syslog(LOG_ERR, 1439 "bump_nofile: cannot extend file limit, max = %d", 1440 (int)rl.rlim_cur); 1441 return -1; 1442 } 1443 1444 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1445 syslog(LOG_ERR, "setrlimit: %m"); 1446 return -1; 1447 } 1448 1449 rlim_nofile_cur = rl.rlim_cur; 1450 return 0; 1451 } 1452 1453 /* 1454 * Internet services provided internally by inetd: 1455 */ 1456 #define BUFSIZE 4096 1457 1458 void 1459 echo_stream(int s, struct servtab *sep) 1460 { 1461 char buffer[BUFSIZE]; 1462 int i; 1463 1464 inetd_setproctitle(sep->se_service, s); 1465 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1466 write(s, buffer, i) > 0) 1467 ; 1468 exit(0); 1469 } 1470 1471 void 1472 echo_dg(int s, struct servtab *sep) 1473 { 1474 char buffer[BUFSIZE]; 1475 int i; 1476 socklen_t size; 1477 struct sockaddr_storage ss; 1478 1479 size = sizeof(ss); 1480 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, 1481 (struct sockaddr *)&ss, &size)) < 0) 1482 return; 1483 if (dg_badinput((struct sockaddr *)&ss)) 1484 return; 1485 (void) sendto(s, buffer, i, 0, (struct sockaddr *)&ss, size); 1486 } 1487 1488 void 1489 discard_stream(int s, struct servtab *sep) 1490 { 1491 char buffer[BUFSIZE]; 1492 1493 inetd_setproctitle(sep->se_service, s); 1494 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1495 errno == EINTR) 1496 ; 1497 exit(0); 1498 } 1499 1500 void 1501 discard_dg(int s, struct servtab *sep) 1502 { 1503 char buffer[BUFSIZE]; 1504 1505 (void) read(s, buffer, sizeof(buffer)); 1506 } 1507 1508 #include <ctype.h> 1509 #define LINESIZ 72 1510 char ring[128]; 1511 char *endring; 1512 1513 void 1514 initring(void) 1515 { 1516 int i; 1517 1518 endring = ring; 1519 1520 for (i = 0; i <= sizeof ring; ++i) 1521 if (isprint((unsigned char)i)) 1522 *endring++ = i; 1523 } 1524 1525 void 1526 chargen_stream(int s, struct servtab *sep) 1527 { 1528 char *rs; 1529 int len; 1530 char text[LINESIZ+2]; 1531 1532 inetd_setproctitle(sep->se_service, s); 1533 1534 if (!endring) { 1535 initring(); 1536 rs = ring; 1537 } 1538 1539 text[LINESIZ] = '\r'; 1540 text[LINESIZ + 1] = '\n'; 1541 for (rs = ring;;) { 1542 if ((len = endring - rs) >= LINESIZ) 1543 memmove(text, rs, LINESIZ); 1544 else { 1545 memmove(text, rs, len); 1546 memmove(text + len, ring, LINESIZ - len); 1547 } 1548 if (++rs == endring) 1549 rs = ring; 1550 if (write(s, text, sizeof(text)) != sizeof(text)) 1551 break; 1552 } 1553 exit(0); 1554 } 1555 1556 void 1557 chargen_dg(int s, struct servtab *sep) 1558 { 1559 struct sockaddr_storage ss; 1560 static char *rs; 1561 int len; 1562 socklen_t size; 1563 char text[LINESIZ+2]; 1564 1565 if (endring == 0) { 1566 initring(); 1567 rs = ring; 1568 } 1569 1570 size = sizeof(ss); 1571 if (recvfrom(s, text, sizeof(text), 0, (struct sockaddr *)&ss, 1572 &size) < 0) 1573 return; 1574 if (dg_badinput((struct sockaddr *)&ss)) 1575 return; 1576 1577 if ((len = endring - rs) >= LINESIZ) 1578 memmove(text, rs, LINESIZ); 1579 else { 1580 memmove(text, rs, len); 1581 memmove(text + len, ring, LINESIZ - len); 1582 } 1583 if (++rs == endring) 1584 rs = ring; 1585 text[LINESIZ] = '\r'; 1586 text[LINESIZ + 1] = '\n'; 1587 (void) sendto(s, text, sizeof(text), 0, (struct sockaddr *)&ss, size); 1588 } 1589 1590 /* 1591 * Return a machine readable date and time, in the form of the 1592 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1593 * returns the number of seconds since midnight, Jan 1, 1970, 1594 * we must add 2208988800 seconds to this figure to make up for 1595 * some seventy years Bell Labs was asleep. 1596 */ 1597 u_int32_t 1598 machtime(void) 1599 { 1600 struct timeval tv; 1601 1602 if (gettimeofday(&tv, NULL) < 0) 1603 return (0L); 1604 1605 return (htonl((u_int32_t)tv.tv_sec + 2208988800UL)); 1606 } 1607 1608 void 1609 machtime_stream(int s, struct servtab *sep) 1610 { 1611 u_int32_t result; 1612 1613 result = machtime(); 1614 (void) write(s, &result, sizeof(result)); 1615 } 1616 1617 void 1618 machtime_dg(int s, struct servtab *sep) 1619 { 1620 u_int32_t result; 1621 struct sockaddr_storage ss; 1622 socklen_t size; 1623 1624 size = sizeof(ss); 1625 if (recvfrom(s, &result, sizeof(result), 0, 1626 (struct sockaddr *)&ss, &size) < 0) 1627 return; 1628 if (dg_badinput((struct sockaddr *)&ss)) 1629 return; 1630 result = machtime(); 1631 (void) sendto(s, &result, sizeof(result), 0, 1632 (struct sockaddr *)&ss, size); 1633 } 1634 1635 /* Return human-readable time of day */ 1636 void 1637 daytime_stream(int s, struct servtab *sep) 1638 { 1639 char buffer[256]; 1640 time_t clock; 1641 1642 clock = time(NULL); 1643 1644 (void) snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1645 (void) write(s, buffer, strlen(buffer)); 1646 } 1647 1648 /* Return human-readable time of day */ 1649 void 1650 daytime_dg(int s, struct servtab *sep) 1651 { 1652 char buffer[256]; 1653 time_t clock; 1654 struct sockaddr_storage ss; 1655 socklen_t size; 1656 1657 clock = time(NULL); 1658 1659 size = sizeof(ss); 1660 if (recvfrom(s, buffer, sizeof(buffer), 0, (struct sockaddr *)&ss, 1661 &size) < 0) 1662 return; 1663 if (dg_badinput((struct sockaddr *)&ss)) 1664 return; 1665 (void) snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1666 (void) sendto(s, buffer, strlen(buffer), 0, (struct sockaddr *)&ss, 1667 size); 1668 } 1669 1670 /* 1671 * print_service: 1672 * Dump relevant information to stderr 1673 */ 1674 void 1675 print_service(char *action, struct servtab *sep) 1676 { 1677 if (strcmp(sep->se_hostaddr, "*") == 0) 1678 fprintf(stderr, "%s: %s ", action, sep->se_service); 1679 else 1680 fprintf(stderr, "%s: %s:%s ", action, sep->se_hostaddr, 1681 sep->se_service); 1682 1683 if (isrpcservice(sep)) 1684 fprintf(stderr, "rpcprog=%d, rpcvers=%d/%d, proto=%s,", 1685 sep->se_rpcprog, sep->se_rpcversh, 1686 sep->se_rpcversl, sep->se_proto); 1687 else 1688 fprintf(stderr, "proto=%s,", sep->se_proto); 1689 1690 fprintf(stderr, 1691 " wait.max=%d.%d user:group=%s:%s builtin=%lx server=%s\n", 1692 sep->se_wait, sep->se_max, sep->se_user, 1693 sep->se_group ? sep->se_group : "wheel", 1694 (long)sep->se_bi, sep->se_server); 1695 } 1696 1697 void 1698 spawn(int ctrl, short events, void *xsep) 1699 { 1700 struct servtab *sep = xsep; 1701 struct passwd *pwd; 1702 int tmpint, dofork; 1703 struct group *grp = NULL; 1704 char buf[50]; 1705 pid_t pid; 1706 1707 if (debug) 1708 fprintf(stderr, "someone wants %s\n", sep->se_service); 1709 1710 pid = 0; 1711 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 1712 if (dofork) { 1713 if (sep->se_count++ == 0) 1714 (void)gettimeofday(&sep->se_time, NULL); 1715 else if (sep->se_count >= sep->se_max) { 1716 struct timeval now; 1717 1718 (void)gettimeofday(&now, NULL); 1719 if (now.tv_sec - sep->se_time.tv_sec > 1720 CNT_INTVL) { 1721 sep->se_time = now; 1722 sep->se_count = 1; 1723 } else { 1724 if (!sep->se_wait && 1725 sep->se_socktype == SOCK_STREAM) 1726 close(ctrl); 1727 if (sep->se_family == AF_INET && 1728 ntohs(sep->se_ctrladdr_in.sin_port) >= 1729 IPPORT_RESERVED) { 1730 /* 1731 * Cannot close it -- there are 1732 * thieves on the system. 1733 * Simply ignore the connection. 1734 */ 1735 --sep->se_count; 1736 return; 1737 } 1738 syslog(LOG_ERR, 1739 "%s/%s server failing (looping), service terminated", 1740 sep->se_service, sep->se_proto); 1741 if (!sep->se_wait && 1742 sep->se_socktype == SOCK_STREAM) 1743 close(ctrl); 1744 event_del(&sep->se_event); 1745 (void) close(sep->se_fd); 1746 1747 sep->se_fd = -1; 1748 sep->se_count = 0; 1749 if (!timingout) { 1750 timingout = 1; 1751 alarm(RETRYTIME); 1752 } 1753 return; 1754 } 1755 } 1756 pid = fork(); 1757 } 1758 if (pid < 0) { 1759 syslog(LOG_ERR, "fork: %m"); 1760 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 1761 close(ctrl); 1762 sleep(1); 1763 return; 1764 } 1765 1766 if (pledge("stdio rpath getpw inet proc exec id", NULL) == -1) 1767 err(1, "pledge"); 1768 1769 if (pid && sep->se_wait) { 1770 sep->se_wait = pid; 1771 event_del(&sep->se_event); 1772 } 1773 if (pid == 0) { 1774 if (sep->se_bi) 1775 (*sep->se_bi->bi_fn)(ctrl, sep); 1776 else { 1777 if ((pwd = getpwnam(sep->se_user)) == NULL) { 1778 syslog(LOG_ERR, 1779 "getpwnam: %s: No such user", 1780 sep->se_user); 1781 if (sep->se_socktype != SOCK_STREAM) 1782 recv(0, buf, sizeof (buf), 0); 1783 exit(1); 1784 } 1785 if (setsid() <0) 1786 syslog(LOG_ERR, "%s: setsid: %m", 1787 sep->se_service); 1788 if (sep->se_group && 1789 (grp = getgrnam(sep->se_group)) == NULL) { 1790 syslog(LOG_ERR, 1791 "getgrnam: %s: No such group", 1792 sep->se_group); 1793 if (sep->se_socktype != SOCK_STREAM) 1794 recv(0, buf, sizeof (buf), 0); 1795 exit(1); 1796 } 1797 if (uid != 0) { 1798 /* a user running private inetd */ 1799 if (uid != pwd->pw_uid) 1800 exit(1); 1801 } else { 1802 tmpint = LOGIN_SETALL & 1803 ~(LOGIN_SETGROUP|LOGIN_SETLOGIN); 1804 if (pwd->pw_uid) 1805 tmpint |= LOGIN_SETGROUP|LOGIN_SETLOGIN; 1806 if (sep->se_group) { 1807 pwd->pw_gid = grp->gr_gid; 1808 tmpint |= LOGIN_SETGROUP; 1809 } 1810 if (setusercontext(NULL, pwd, pwd->pw_uid, 1811 tmpint) < 0) { 1812 syslog(LOG_ERR, 1813 "%s/%s: setusercontext: %m", 1814 sep->se_service, sep->se_proto); 1815 exit(1); 1816 } 1817 } 1818 if (debug) 1819 fprintf(stderr, "%ld execv %s\n", 1820 (long)getpid(), sep->se_server); 1821 if (ctrl != STDIN_FILENO) { 1822 dup2(ctrl, STDIN_FILENO); 1823 close(ctrl); 1824 } 1825 dup2(STDIN_FILENO, STDOUT_FILENO); 1826 dup2(STDIN_FILENO, STDERR_FILENO); 1827 closelog(); 1828 closefrom(3); 1829 signal(SIGPIPE, SIG_DFL); 1830 execv(sep->se_server, sep->se_argv); 1831 if (sep->se_socktype != SOCK_STREAM) 1832 recv(0, buf, sizeof (buf), 0); 1833 syslog(LOG_ERR, "execv %s: %m", sep->se_server); 1834 exit(1); 1835 } 1836 } 1837 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 1838 close(ctrl); 1839 } 1840