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