1 /* $NetBSD: inetd.c,v 1.39 1997/12/04 06:39:02 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1991, 1993, 1994 5 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 __COPYRIGHT("@(#) Copyright (c) 1983, 1991, 1993, 1994\n\ 39 The Regents of the University of California. All rights reserved.\n"); 40 #if 0 41 static char sccsid[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94"; 42 #else 43 __RCSID("$NetBSD: inetd.c,v 1.39 1997/12/04 06:39:02 mycroft Exp $"); 44 #endif 45 #endif /* not lint */ 46 47 /* 48 * Inetd - Internet super-server 49 * 50 * This program invokes all internet services as needed. Connection-oriented 51 * services are invoked each time a connection is made, by creating a process. 52 * This process is passed the connection as file descriptor 0 and is expected 53 * to do a getpeername to find out the source host and port. 54 * 55 * Datagram oriented services are invoked when a datagram 56 * arrives; a process is created and passed a pending message 57 * on file descriptor 0. Datagram servers may either connect 58 * to their peer, freeing up the original socket for inetd 59 * to receive further messages on, or ``take over the socket'', 60 * processing all arriving datagrams and, eventually, timing 61 * out. The first type of server is said to be ``multi-threaded''; 62 * the second type of server ``single-threaded''. 63 * 64 * Inetd uses a configuration file which is read at startup 65 * and, possibly, at some later time in response to a hangup signal. 66 * The configuration file is ``free format'' with fields given in the 67 * order shown below. Continuation lines for an entry must being with 68 * a space or tab. All fields must be present in each entry. 69 * 70 * service name must be in /etc/services or must 71 * name a tcpmux service 72 * socket type stream/dgram/raw/rdm/seqpacket 73 * protocol must be in /etc/protocols 74 * wait/nowait[.max] single-threaded/multi-threaded, max # 75 * user[.group] user/group to run daemon as 76 * server program full path name 77 * server program arguments maximum of MAXARGS (20) 78 * 79 * For RPC services 80 * service name/version must be in /etc/rpc 81 * socket type stream/dgram/raw/rdm/seqpacket 82 * protocol must be in /etc/protocols 83 * wait/nowait[.max] single-threaded/multi-threaded 84 * user[.group] user to run daemon as 85 * server program full path name 86 * server program arguments maximum of MAXARGS (20) 87 * 88 * For non-RPC services, the "service name" can be of the form 89 * hostaddress:servicename, in which case the hostaddress is used 90 * as the host portion of the address to listen on. If hostaddress 91 * consists of a single `*' character, INADDR_ANY is used. 92 * 93 * A line can also consist of just 94 * hostaddress: 95 * where hostaddress is as in the preceding paragraph. Such a line must 96 * have no further fields; the specified hostaddress is remembered and 97 * used for all further lines that have no hostaddress specified, 98 * until the next such line (or EOF). (This is why * is provided to 99 * allow explicit specification of INADDR_ANY.) A line 100 * *: 101 * is implicitly in effect at the beginning of the file. 102 * 103 * The hostaddress specifier may (and often will) contain dots; 104 * the service name must not. 105 * 106 * For RPC services, host-address specifiers are accepted and will 107 * work to some extent; however, because of limitations in the 108 * portmapper interface, it will not work to try to give more than 109 * one line for any given RPC service, even if the host-address 110 * specifiers are different. 111 * 112 * TCP services without official port numbers are handled with the 113 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for 114 * requests. When a connection is made from a foreign host, the service 115 * requested is passed to tcpmux, which looks it up in the servtab list 116 * and returns the proper entry for the service. Tcpmux returns a 117 * negative reply if the service doesn't exist, otherwise the invoked 118 * server is expected to return the positive reply if the service type in 119 * inetd.conf file has the prefix "tcpmux/". If the service type has the 120 * prefix "tcpmux/+", tcpmux will return the positive reply for the 121 * process; this is for compatibility with older server code, and also 122 * allows you to invoke programs that use stdin/stdout without putting any 123 * special server code in them. Services that use tcpmux are "nowait" 124 * because they do not have a well-known port and hence cannot listen 125 * for new requests. 126 * 127 * Comment lines are indicated by a `#' in column 1. 128 */ 129 130 /* 131 * Here's the scoop concerning the user.group feature: 132 * 133 * 1) set-group-option off. 134 * 135 * a) user = root: NO setuid() or setgid() is done 136 * 137 * b) other: setuid() 138 * setgid(primary group as found in passwd) 139 * initgroups(name, primary group) 140 * 141 * 2) set-group-option on. 142 * 143 * a) user = root: NO setuid() 144 * setgid(specified group) 145 * NO initgroups() 146 * 147 * b) other: setuid() 148 * setgid(specified group) 149 * initgroups(name, specified group) 150 * 151 */ 152 153 #include <sys/param.h> 154 #include <sys/stat.h> 155 #include <sys/ioctl.h> 156 #include <sys/socket.h> 157 #include <sys/un.h> 158 #include <sys/wait.h> 159 #include <sys/time.h> 160 #include <sys/resource.h> 161 162 #ifndef RLIMIT_NOFILE 163 #define RLIMIT_NOFILE RLIMIT_OFILE 164 #endif 165 166 #define RPC 167 168 #include <netinet/in.h> 169 #include <arpa/inet.h> 170 #ifdef RPC 171 #include <rpc/rpc.h> 172 #include <rpc/pmap_clnt.h> 173 #endif 174 175 #include <errno.h> 176 #include <fcntl.h> 177 #include <grp.h> 178 #include <netdb.h> 179 #include <pwd.h> 180 #include <signal.h> 181 #include <stdio.h> 182 #include <stdlib.h> 183 #include <string.h> 184 #include <syslog.h> 185 #include <unistd.h> 186 187 #include "pathnames.h" 188 189 #ifdef LIBWRAP 190 # include <tcpd.h> 191 #ifndef LIBWRAP_ALLOW_FACILITY 192 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH 193 #endif 194 #ifndef LIBWRAP_ALLOW_SEVERITY 195 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO 196 #endif 197 #ifndef LIBWRAP_DENY_FACILITY 198 # define LIBWRAP_DENY_FACILITY LOG_AUTH 199 #endif 200 #ifndef LIBWRAP_DENY_SEVERITY 201 # define LIBWRAP_DENY_SEVERITY LOG_WARNING 202 #endif 203 int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY; 204 int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY; 205 #endif 206 207 #define TOOMANY 40 /* don't start more than TOOMANY */ 208 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ 209 #define RETRYTIME (60*10) /* retry after bind or server fail */ 210 211 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) 212 213 int debug; 214 #ifdef LIBWRAP 215 int lflag; 216 #endif 217 int nsock, maxsock; 218 fd_set allsock; 219 int options; 220 int timingout; 221 struct servent *sp; 222 char *curdom; 223 224 #ifndef OPEN_MAX 225 #define OPEN_MAX 64 226 #endif 227 228 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ 229 #define FD_MARGIN (8) 230 typeof(((struct rlimit *)0)->rlim_cur) rlim_ofile_cur = OPEN_MAX; 231 232 #ifdef RLIMIT_NOFILE 233 struct rlimit rlim_ofile; 234 #endif 235 236 struct servtab { 237 char *se_hostaddr; /* host address to listen on */ 238 char *se_service; /* name of service */ 239 int se_socktype; /* type of socket to use */ 240 int se_family; /* address family */ 241 char *se_proto; /* protocol used */ 242 int se_rpcprog; /* rpc program number */ 243 int se_rpcversl; /* rpc program lowest version */ 244 int se_rpcversh; /* rpc program highest version */ 245 #define isrpcservice(sep) ((sep)->se_rpcversl != 0) 246 short se_wait; /* single threaded server */ 247 short se_checked; /* looked at during merge */ 248 char *se_user; /* user name to run as */ 249 char *se_group; /* group name to run as */ 250 struct biltin *se_bi; /* if built-in, description */ 251 char *se_server; /* server program */ 252 #define MAXARGV 20 253 char *se_argv[MAXARGV+1]; /* program arguments */ 254 int se_fd; /* open descriptor */ 255 int se_type; /* type */ 256 union { 257 struct sockaddr se_un_ctrladdr; 258 struct sockaddr_in se_un_ctrladdr_in; 259 struct sockaddr_un se_un_ctrladdr_un; 260 } se_un; /* bound address */ 261 #define se_ctrladdr se_un.se_un_ctrladdr 262 #define se_ctrladdr_in se_un.se_un_ctrladdr_in 263 #define se_ctrladdr_un se_un.se_un_ctrladdr_un 264 int se_ctrladdr_size; 265 int se_max; /* max # of instances of this service */ 266 int se_count; /* number started since se_time */ 267 struct timeval se_time; /* start of se_count */ 268 #ifdef MULOG 269 int se_log; 270 #define MULOG_RFC931 0x40000000 271 #endif 272 struct servtab *se_next; 273 } *servtab; 274 275 #define NORM_TYPE 0 276 #define MUX_TYPE 1 277 #define MUXPLUS_TYPE 2 278 #define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \ 279 ((sep)->se_type == MUXPLUS_TYPE)) 280 #define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE) 281 282 283 void chargen_dg __P((int, struct servtab *)); 284 void chargen_stream __P((int, struct servtab *)); 285 void close_sep __P((struct servtab *)); 286 void config __P((int)); 287 void daytime_dg __P((int, struct servtab *)); 288 void daytime_stream __P((int, struct servtab *)); 289 void discard_dg __P((int, struct servtab *)); 290 void discard_stream __P((int, struct servtab *)); 291 void echo_dg __P((int, struct servtab *)); 292 void echo_stream __P((int, struct servtab *)); 293 void endconfig __P((void)); 294 struct servtab *enter __P((struct servtab *)); 295 void freeconfig __P((struct servtab *)); 296 struct servtab *getconfigent __P((void)); 297 void goaway __P((int)); 298 void machtime_dg __P((int, struct servtab *)); 299 void machtime_stream __P((int, struct servtab *)); 300 char *newstr __P((char *)); 301 char *nextline __P((FILE *)); 302 void print_service __P((char *, struct servtab *)); 303 void reapchild __P((int)); 304 void retry __P((int)); 305 void run_service __P((int, struct servtab *)); 306 int setconfig __P((void)); 307 void setup __P((struct servtab *)); 308 char *sskip __P((char **)); 309 char *skip __P((char **)); 310 void tcpmux __P((int, struct servtab *)); 311 void usage __P((void)); 312 void logpid __P((void)); 313 void register_rpc __P((struct servtab *sep)); 314 void unregister_rpc __P((struct servtab *sep)); 315 void bump_nofile __P((void)); 316 void inetd_setproctitle __P((char *, int)); 317 void initring __P((void)); 318 long machtime __P((void)); 319 static int getline __P((int, char *, int)); 320 int main __P((int, char *[], char *[])); 321 322 struct biltin { 323 char *bi_service; /* internally provided service name */ 324 int bi_socktype; /* type of socket supported */ 325 short bi_fork; /* 1 if should fork before call */ 326 short bi_wait; /* 1 if should wait for child */ 327 void (*bi_fn) __P((int, struct servtab *)); 328 /* function which performs it */ 329 } biltins[] = { 330 /* Echo received data */ 331 { "echo", SOCK_STREAM, 1, 0, echo_stream }, 332 { "echo", SOCK_DGRAM, 0, 0, echo_dg }, 333 334 /* Internet /dev/null */ 335 { "discard", SOCK_STREAM, 1, 0, discard_stream }, 336 { "discard", SOCK_DGRAM, 0, 0, discard_dg }, 337 338 /* Return 32 bit time since 1970 */ 339 { "time", SOCK_STREAM, 0, 0, machtime_stream }, 340 { "time", SOCK_DGRAM, 0, 0, machtime_dg }, 341 342 /* Return human-readable time */ 343 { "daytime", SOCK_STREAM, 0, 0, daytime_stream }, 344 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg }, 345 346 /* Familiar character generator */ 347 { "chargen", SOCK_STREAM, 1, 0, chargen_stream }, 348 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg }, 349 350 { "tcpmux", SOCK_STREAM, 1, 0, tcpmux }, 351 352 { NULL } 353 }; 354 355 #define NUMINT (sizeof(intab) / sizeof(struct inent)) 356 char *CONFIG = _PATH_INETDCONF; 357 char **Argv; 358 char *LastArg; 359 extern char *__progname; 360 361 #ifdef sun 362 /* 363 * Sun's RPC library caches the result of `dtablesize()' 364 * This is incompatible with our "bumping" of file descriptors "on demand" 365 */ 366 int 367 _rpc_dtablesize() 368 { 369 return rlim_ofile_cur; 370 } 371 #endif 372 373 int 374 main(argc, argv, envp) 375 int argc; 376 char *argv[], *envp[]; 377 { 378 struct servtab *sep, *nsep; 379 struct sigvec sv; 380 int ch, dofork; 381 pid_t pid; 382 383 Argv = argv; 384 if (envp == 0 || *envp == 0) 385 envp = argv; 386 while (*envp) 387 envp++; 388 LastArg = envp[-1] + strlen(envp[-1]); 389 390 while ((ch = getopt(argc, argv, 391 #ifdef LIBWRAP 392 "dl" 393 #else 394 "d" 395 #endif 396 )) != -1) 397 switch(ch) { 398 case 'd': 399 debug = 1; 400 options |= SO_DEBUG; 401 break; 402 #ifdef LIBWRAP 403 case 'l': 404 lflag = 1; 405 break; 406 #endif 407 case '?': 408 default: 409 usage(); 410 } 411 argc -= optind; 412 argv += optind; 413 414 if (argc > 0) 415 CONFIG = argv[0]; 416 417 if (debug == 0) 418 daemon(0, 0); 419 openlog(__progname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 420 logpid(); 421 422 #ifdef RLIMIT_NOFILE 423 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) { 424 syslog(LOG_ERR, "getrlimit: %m"); 425 } else { 426 rlim_ofile_cur = rlim_ofile.rlim_cur; 427 if (rlim_ofile_cur == RLIM_INFINITY) /* ! */ 428 rlim_ofile_cur = OPEN_MAX; 429 } 430 #endif 431 432 memset(&sv, 0, sizeof(sv)); 433 sv.sv_mask = SIGBLOCK; 434 sv.sv_handler = retry; 435 sigvec(SIGALRM, &sv, (struct sigvec *)0); 436 config(SIGHUP); 437 sv.sv_handler = config; 438 sigvec(SIGHUP, &sv, (struct sigvec *)0); 439 sv.sv_handler = reapchild; 440 sigvec(SIGCHLD, &sv, (struct sigvec *)0); 441 sv.sv_handler = goaway; 442 sigvec(SIGTERM, &sv, (struct sigvec *)0); 443 sv.sv_handler = goaway; 444 sigvec(SIGINT, &sv, (struct sigvec *)0); 445 sv.sv_handler = SIG_IGN; 446 sigvec(SIGPIPE, &sv, (struct sigvec *)0); 447 448 { 449 /* space for daemons to overwrite environment for ps */ 450 #define DUMMYSIZE 100 451 char dummy[DUMMYSIZE]; 452 453 (void)memset(dummy, 'x', DUMMYSIZE - 1); 454 dummy[DUMMYSIZE - 1] = '\0'; 455 456 (void)setenv("inetd_dummy", dummy, 1); 457 } 458 459 for (;;) { 460 int n, ctrl; 461 fd_set readable; 462 463 if (nsock == 0) { 464 (void) sigblock(SIGBLOCK); 465 while (nsock == 0) 466 sigpause(0L); 467 (void) sigsetmask(0L); 468 } 469 readable = allsock; 470 if ((n = select(maxsock + 1, &readable, (fd_set *)0, 471 (fd_set *)0, (struct timeval *)0)) <= 0) { 472 if (n == -1 && errno != EINTR) { 473 syslog(LOG_WARNING, "select: %m"); 474 sleep(1); 475 } 476 continue; 477 } 478 for (sep = servtab; n && sep; sep = nsep) { 479 nsep = sep->se_next; 480 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) { 481 n--; 482 if (debug) 483 fprintf(stderr, "someone wants %s\n", sep->se_service); 484 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 485 /* XXX here do the libwrap check-before-accept */ 486 ctrl = accept(sep->se_fd, (struct sockaddr *)0, 487 (int *)0); 488 if (debug) 489 fprintf(stderr, "accept, ctrl %d\n", ctrl); 490 if (ctrl < 0) { 491 if (errno != EINTR) 492 syslog(LOG_WARNING, 493 "accept (for %s): %m", 494 sep->se_service); 495 continue; 496 } 497 } else 498 ctrl = sep->se_fd; 499 (void) sigblock(SIGBLOCK); 500 pid = 0; 501 #ifdef LIBWRAP_INTERNAL 502 dofork = 1; 503 #else 504 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 505 #endif 506 if (dofork) { 507 if (sep->se_count++ == 0) 508 (void)gettimeofday(&sep->se_time, 509 (struct timezone *)0); 510 else if (sep->se_count >= sep->se_max) { 511 struct timeval now; 512 513 (void)gettimeofday(&now, (struct timezone *)0); 514 if (now.tv_sec - sep->se_time.tv_sec > 515 CNT_INTVL) { 516 sep->se_time = now; 517 sep->se_count = 1; 518 } else { 519 syslog(LOG_ERR, 520 "%s/%s server failing (looping), service terminated\n", 521 sep->se_service, sep->se_proto); 522 close_sep(sep); 523 sigsetmask(0L); 524 if (!timingout) { 525 timingout = 1; 526 alarm(RETRYTIME); 527 } 528 continue; 529 } 530 } 531 pid = fork(); 532 if (pid < 0) { 533 syslog(LOG_ERR, "fork: %m"); 534 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 535 close(ctrl); 536 sigsetmask(0L); 537 sleep(1); 538 continue; 539 } 540 if (pid != 0 && sep->se_wait) { 541 sep->se_wait = pid; 542 FD_CLR(sep->se_fd, &allsock); 543 nsock--; 544 } 545 if (pid == 0 && debug) 546 setsid(); 547 } 548 sigsetmask(0L); 549 if (pid == 0) { 550 run_service(ctrl, sep); 551 if (dofork) 552 exit(0); 553 } 554 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 555 close(ctrl); 556 } 557 } 558 } 559 } 560 561 void 562 run_service(ctrl, sep) 563 int ctrl; 564 struct servtab *sep; 565 { 566 struct passwd *pwd; 567 struct group *grp = NULL; /* XXX gcc */ 568 #ifdef LIBWRAP 569 struct request_info req; 570 int denied; 571 char buf[7], *service = NULL; /* XXX gcc */ 572 #endif 573 574 #ifdef LIBWRAP 575 #ifndef LIBWRAP_INTERNAL 576 if (sep->se_bi == 0) 577 #endif 578 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 579 request_init(&req, RQ_DAEMON, sep->se_argv[0] ? 580 sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL); 581 fromhost(&req); 582 denied = !hosts_access(&req); 583 if (denied || lflag) { 584 sp = getservbyport(sep->se_ctrladdr_in.sin_port, 585 sep->se_proto); 586 if (sp == NULL) { 587 (void)snprintf(buf, sizeof buf, "%d", 588 ntohs(sep->se_ctrladdr_in.sin_port)); 589 service = buf; 590 } else 591 service = sp->s_name; 592 } 593 if (denied) { 594 syslog(deny_severity, 595 "refused connection from %.500s, service %s (%s)", 596 eval_client(&req), service, sep->se_proto); 597 goto reject; 598 } 599 if (lflag) { 600 syslog(allow_severity, 601 "connection from %.500s, service %s (%s)", 602 eval_client(&req), service, sep->se_proto); 603 } 604 } 605 #endif /* LIBWRAP */ 606 607 if (sep->se_bi) { 608 (*sep->se_bi->bi_fn)(ctrl, sep); 609 } else { 610 if ((pwd = getpwnam(sep->se_user)) == NULL) { 611 syslog(LOG_ERR, "%s/%s: %s: No such user", 612 sep->se_service, sep->se_proto, sep->se_user); 613 goto reject; 614 } 615 if (sep->se_group && 616 (grp = getgrnam(sep->se_group)) == NULL) { 617 syslog(LOG_ERR, "%s/%s: %s: No such group", 618 sep->se_service, sep->se_proto, sep->se_group); 619 goto reject; 620 } 621 if (pwd->pw_uid) { 622 if (sep->se_group) 623 pwd->pw_gid = grp->gr_gid; 624 if (setgid(pwd->pw_gid) < 0) { 625 syslog(LOG_ERR, 626 "%s/%s: can't set gid %d: %m", sep->se_service, 627 sep->se_proto, pwd->pw_gid); 628 goto reject; 629 } 630 (void) initgroups(pwd->pw_name, 631 pwd->pw_gid); 632 if (setuid(pwd->pw_uid) < 0) { 633 syslog(LOG_ERR, 634 "%s/%s: can't set uid %d: %m", sep->se_service, 635 sep->se_proto, pwd->pw_uid); 636 goto reject; 637 } 638 } else if (sep->se_group) { 639 (void) setgid((gid_t)grp->gr_gid); 640 } 641 if (debug) 642 fprintf(stderr, "%d execl %s\n", 643 getpid(), sep->se_server); 644 #ifdef MULOG 645 if (sep->se_log) 646 dolog(sep, ctrl); 647 #endif 648 /* Set our control descriptor to not close-on-exec... */ 649 if (fcntl(ctrl, F_SETFD, 0) < 0) 650 syslog(LOG_ERR, "fcntl (F_SETFD, 0): %m"); 651 /* ...and dup it to stdin, stdout, and stderr. */ 652 if (ctrl != 0) { 653 dup2(ctrl, 0); 654 close(ctrl); 655 ctrl = 0; 656 } 657 dup2(0, 1); 658 dup2(0, 2); 659 #ifdef RLIMIT_NOFILE 660 if (rlim_ofile.rlim_cur != rlim_ofile_cur && 661 setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) 662 syslog(LOG_ERR, "setrlimit: %m"); 663 #endif 664 execv(sep->se_server, sep->se_argv); 665 syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server); 666 reject: 667 if (sep->se_socktype != SOCK_STREAM) 668 recv(ctrl, buf, sizeof (buf), 0); 669 _exit(1); 670 } 671 } 672 673 void 674 reapchild(signo) 675 int signo; 676 { 677 int status; 678 pid_t pid; 679 struct servtab *sep; 680 681 for (;;) { 682 pid = wait3(&status, WNOHANG, (struct rusage *)0); 683 if (pid <= 0) 684 break; 685 if (debug) 686 fprintf(stderr, "%d reaped, status %#x\n", 687 pid, status); 688 for (sep = servtab; sep; sep = sep->se_next) 689 if (sep->se_wait == pid) { 690 if (WIFEXITED(status) && WEXITSTATUS(status)) 691 syslog(LOG_WARNING, 692 "%s: exit status 0x%x", 693 sep->se_server, WEXITSTATUS(status)); 694 else if (WIFSIGNALED(status)) 695 syslog(LOG_WARNING, 696 "%s: exit signal 0x%x", 697 sep->se_server, WTERMSIG(status)); 698 sep->se_wait = 1; 699 FD_SET(sep->se_fd, &allsock); 700 nsock++; 701 if (debug) 702 fprintf(stderr, "restored %s, fd %d\n", 703 sep->se_service, sep->se_fd); 704 } 705 } 706 } 707 708 void 709 config(signo) 710 int signo; 711 { 712 struct servtab *sep, *cp, **sepp; 713 long omask; 714 int n; 715 716 if (!setconfig()) { 717 syslog(LOG_ERR, "%s: %m", CONFIG); 718 return; 719 } 720 for (sep = servtab; sep; sep = sep->se_next) 721 sep->se_checked = 0; 722 while ((cp = getconfigent())) { 723 for (sep = servtab; sep; sep = sep->se_next) 724 if (strcmp(sep->se_service, cp->se_service) == 0 && 725 strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 && 726 strcmp(sep->se_proto, cp->se_proto) == 0 && 727 ISMUX(sep) == ISMUX(cp)) 728 break; 729 if (sep != 0) { 730 int i; 731 732 #define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;} 733 734 omask = sigblock(SIGBLOCK); 735 /* 736 * sep->se_wait may be holding the pid of a daemon 737 * that we're waiting for. If so, don't overwrite 738 * it unless the config file explicitly says don't 739 * wait. 740 */ 741 if (cp->se_bi == 0 && 742 (sep->se_wait == 1 || cp->se_wait == 0)) 743 sep->se_wait = cp->se_wait; 744 SWAP(char *, sep->se_user, cp->se_user); 745 SWAP(char *, sep->se_group, cp->se_group); 746 SWAP(char *, sep->se_server, cp->se_server); 747 for (i = 0; i < MAXARGV; i++) 748 SWAP(char *, sep->se_argv[i], cp->se_argv[i]); 749 SWAP(int, cp->se_type, sep->se_type); 750 SWAP(int, cp->se_max, sep->se_max); 751 #undef SWAP 752 if (isrpcservice(sep)) 753 unregister_rpc(sep); 754 sep->se_rpcversl = cp->se_rpcversl; 755 sep->se_rpcversh = cp->se_rpcversh; 756 sigsetmask(omask); 757 freeconfig(cp); 758 if (debug) 759 print_service("REDO", sep); 760 } else { 761 sep = enter(cp); 762 if (debug) 763 print_service("ADD ", sep); 764 } 765 sep->se_checked = 1; 766 767 switch (sep->se_family) { 768 case AF_UNIX: 769 if (sep->se_fd != -1) 770 break; 771 n = strlen(sep->se_service); 772 if (n > sizeof(sep->se_ctrladdr_un.sun_path)) { 773 syslog(LOG_ERR, "%s: address too long", 774 sep->se_service); 775 sep->se_checked = 0; 776 continue; 777 } 778 (void)unlink(sep->se_service); 779 strncpy(sep->se_ctrladdr_un.sun_path, 780 sep->se_service, n); 781 sep->se_ctrladdr_un.sun_family = AF_UNIX; 782 sep->se_ctrladdr_size = n + 783 sizeof(sep->se_ctrladdr_un) - 784 sizeof(sep->se_ctrladdr_un.sun_path); 785 if (!ISMUX(sep)) 786 setup(sep); 787 break; 788 case AF_INET: 789 sep->se_ctrladdr_in.sin_family = AF_INET; 790 if (!strcmp(sep->se_hostaddr,"*")) 791 sep->se_ctrladdr_in.sin_addr.s_addr = 792 INADDR_ANY; 793 else if (!inet_aton(sep->se_hostaddr, 794 &sep->se_ctrladdr_in.sin_addr)) { 795 /* Do we really want to support hostname lookups here? */ 796 struct hostent *hp; 797 hp = gethostbyname(sep->se_hostaddr); 798 if (hp == 0) { 799 syslog(LOG_ERR, "%s: unknown host", 800 sep->se_hostaddr); 801 sep->se_checked = 0; 802 continue; 803 } else if (hp->h_addrtype != AF_INET) { 804 syslog(LOG_ERR, 805 "%s: address isn't an Internet address", 806 sep->se_hostaddr); 807 sep->se_checked = 0; 808 continue; 809 } else if (hp->h_length != sizeof(struct in_addr)) { 810 syslog(LOG_ERR, 811 "%s: address size wrong (under DNS corruption attack?)", 812 sep->se_hostaddr); 813 sep->se_checked = 0; 814 continue; 815 } else { 816 memcpy(&sep->se_ctrladdr_in.sin_addr, 817 hp->h_addr_list[0], 818 sizeof(struct in_addr)); 819 } 820 } 821 if (ISMUX(sep)) { 822 sep->se_fd = -1; 823 continue; 824 } 825 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr_in); 826 if (isrpcservice(sep)) { 827 struct rpcent *rp; 828 829 sep->se_rpcprog = atoi(sep->se_service); 830 if (sep->se_rpcprog == 0) { 831 rp = getrpcbyname(sep->se_service); 832 if (rp == 0) { 833 syslog(LOG_ERR, 834 "%s/%s: unknown service", 835 sep->se_service, 836 sep->se_proto); 837 sep->se_checked = 0; 838 continue; 839 } 840 sep->se_rpcprog = rp->r_number; 841 } 842 if (sep->se_fd == -1 && !ISMUX(sep)) 843 setup(sep); 844 if (sep->se_fd != -1) 845 register_rpc(sep); 846 } else { 847 u_short port = htons(atoi(sep->se_service)); 848 849 if (!port) { 850 sp = getservbyname(sep->se_service, 851 sep->se_proto); 852 if (sp == 0) { 853 syslog(LOG_ERR, 854 "%s/%s: unknown service", 855 sep->se_service, 856 sep->se_proto); 857 sep->se_checked = 0; 858 continue; 859 } 860 port = sp->s_port; 861 } 862 if (port != sep->se_ctrladdr_in.sin_port) { 863 sep->se_ctrladdr_in.sin_port = port; 864 if (sep->se_fd >= 0) 865 close_sep(sep); 866 } 867 if (sep->se_fd == -1 && !ISMUX(sep)) 868 setup(sep); 869 } 870 } 871 } 872 endconfig(); 873 /* 874 * Purge anything not looked at above. 875 */ 876 omask = sigblock(SIGBLOCK); 877 sepp = &servtab; 878 while ((sep = *sepp)) { 879 if (sep->se_checked) { 880 sepp = &sep->se_next; 881 continue; 882 } 883 *sepp = sep->se_next; 884 if (sep->se_fd >= 0) 885 close_sep(sep); 886 if (isrpcservice(sep)) 887 unregister_rpc(sep); 888 if (sep->se_family == AF_UNIX) 889 (void)unlink(sep->se_service); 890 if (debug) 891 print_service("FREE", sep); 892 freeconfig(sep); 893 free((char *)sep); 894 } 895 (void) sigsetmask(omask); 896 } 897 898 void 899 retry(signo) 900 int signo; 901 { 902 struct servtab *sep; 903 904 timingout = 0; 905 for (sep = servtab; sep; sep = sep->se_next) { 906 if (sep->se_fd == -1 && !ISMUX(sep)) { 907 switch (sep->se_family) { 908 case AF_UNIX: 909 case AF_INET: 910 setup(sep); 911 if (sep->se_fd != -1 && isrpcservice(sep)) 912 register_rpc(sep); 913 break; 914 } 915 } 916 } 917 } 918 919 void 920 goaway(signo) 921 int signo; 922 { 923 struct servtab *sep; 924 925 for (sep = servtab; sep; sep = sep->se_next) { 926 if (sep->se_fd == -1) 927 continue; 928 929 switch (sep->se_family) { 930 case AF_UNIX: 931 (void)unlink(sep->se_service); 932 break; 933 case AF_INET: 934 if (sep->se_wait == 1 && isrpcservice(sep)) 935 unregister_rpc(sep); 936 break; 937 } 938 (void)close(sep->se_fd); 939 } 940 (void)unlink(_PATH_INETDPID); 941 exit(0); 942 } 943 944 void 945 setup(sep) 946 struct servtab *sep; 947 { 948 int on = 1; 949 950 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 951 if (debug) 952 fprintf(stderr, "socket failed on %s/%s: %s\n", 953 sep->se_service, sep->se_proto, strerror(errno)); 954 syslog(LOG_ERR, "%s/%s: socket: %m", 955 sep->se_service, sep->se_proto); 956 return; 957 } 958 /* Set all listening sockets to close-on-exec. */ 959 if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) 960 syslog(LOG_ERR, "fcntl (F_SETFD, FD_CLOEXEC): %m"); 961 #define turnon(fd, opt) \ 962 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) 963 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 964 turnon(sep->se_fd, SO_DEBUG) < 0) 965 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 966 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 967 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 968 #undef turnon 969 if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) { 970 if (debug) 971 fprintf(stderr, "bind failed on %s/%s: %s\n", 972 sep->se_service, sep->se_proto, strerror(errno)); 973 syslog(LOG_ERR, "%s/%s: bind: %m", 974 sep->se_service, sep->se_proto); 975 (void) close(sep->se_fd); 976 sep->se_fd = -1; 977 if (!timingout) { 978 timingout = 1; 979 alarm(RETRYTIME); 980 } 981 return; 982 } 983 if (sep->se_socktype == SOCK_STREAM) 984 listen(sep->se_fd, 10); 985 986 FD_SET(sep->se_fd, &allsock); 987 nsock++; 988 if (sep->se_fd > maxsock) { 989 maxsock = sep->se_fd; 990 if (maxsock > rlim_ofile_cur - FD_MARGIN) 991 bump_nofile(); 992 } 993 if (debug) 994 fprintf(stderr, "registered %s on %d\n", 995 sep->se_server, sep->se_fd); 996 } 997 998 /* 999 * Finish with a service and its socket. 1000 */ 1001 void 1002 close_sep(sep) 1003 struct servtab *sep; 1004 { 1005 if (sep->se_fd >= 0) { 1006 nsock--; 1007 FD_CLR(sep->se_fd, &allsock); 1008 (void) close(sep->se_fd); 1009 sep->se_fd = -1; 1010 } 1011 sep->se_count = 0; 1012 /* 1013 * Don't keep the pid of this running deamon: when reapchild() 1014 * reaps this pid, it would erroneously increment nsock. 1015 */ 1016 if (sep->se_wait > 1) 1017 sep->se_wait = 1; 1018 } 1019 1020 void 1021 register_rpc(sep) 1022 struct servtab *sep; 1023 { 1024 #ifdef RPC 1025 int n; 1026 struct sockaddr_in sin; 1027 struct protoent *pp; 1028 1029 if ((pp = getprotobyname(sep->se_proto+4)) == NULL) { 1030 syslog(LOG_ERR, "%s: getproto: %m", 1031 sep->se_proto); 1032 return; 1033 } 1034 n = sizeof sin; 1035 if (getsockname(sep->se_fd, (struct sockaddr *)&sin, &n) < 0) { 1036 syslog(LOG_ERR, "%s/%s: getsockname: %m", 1037 sep->se_service, sep->se_proto); 1038 return; 1039 } 1040 1041 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1042 if (debug) 1043 fprintf(stderr, "pmap_set: %u %u %u %u\n", 1044 sep->se_rpcprog, n, pp->p_proto, 1045 ntohs(sin.sin_port)); 1046 (void)pmap_unset(sep->se_rpcprog, n); 1047 if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port))) 1048 syslog(LOG_ERR, "pmap_set: %u %u %u %u: %m", 1049 sep->se_rpcprog, n, pp->p_proto, 1050 ntohs(sin.sin_port)); 1051 } 1052 #endif /* RPC */ 1053 } 1054 1055 void 1056 unregister_rpc(sep) 1057 struct servtab *sep; 1058 { 1059 #ifdef RPC 1060 int n; 1061 1062 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1063 if (debug) 1064 fprintf(stderr, "pmap_unset(%u, %u)\n", 1065 sep->se_rpcprog, n); 1066 if (!pmap_unset(sep->se_rpcprog, n)) 1067 syslog(LOG_ERR, "pmap_unset(%u, %u)\n", 1068 sep->se_rpcprog, n); 1069 } 1070 #endif /* RPC */ 1071 } 1072 1073 1074 struct servtab * 1075 enter(cp) 1076 struct servtab *cp; 1077 { 1078 struct servtab *sep; 1079 long omask; 1080 1081 sep = (struct servtab *)malloc(sizeof (*sep)); 1082 if (sep == (struct servtab *)0) { 1083 syslog(LOG_ERR, "Out of memory."); 1084 exit(-1); 1085 } 1086 *sep = *cp; 1087 sep->se_fd = -1; 1088 sep->se_rpcprog = -1; 1089 omask = sigblock(SIGBLOCK); 1090 sep->se_next = servtab; 1091 servtab = sep; 1092 sigsetmask(omask); 1093 return (sep); 1094 } 1095 1096 FILE *fconfig = NULL; 1097 struct servtab serv; 1098 char line[LINE_MAX]; 1099 char *defhost; 1100 1101 int 1102 setconfig() 1103 { 1104 if (defhost) free(defhost); 1105 defhost = newstr("*"); 1106 if (fconfig != NULL) { 1107 fseek(fconfig, 0L, SEEK_SET); 1108 return (1); 1109 } 1110 fconfig = fopen(CONFIG, "r"); 1111 return (fconfig != NULL); 1112 } 1113 1114 void 1115 endconfig() 1116 { 1117 if (fconfig) { 1118 (void) fclose(fconfig); 1119 fconfig = NULL; 1120 } 1121 if (defhost) { 1122 free(defhost); 1123 defhost = 0; 1124 } 1125 } 1126 1127 struct servtab * 1128 getconfigent() 1129 { 1130 struct servtab *sep = &serv; 1131 int argc; 1132 char *cp, *arg; 1133 static char TCPMUX_TOKEN[] = "tcpmux/"; 1134 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) 1135 char *hostdelim; 1136 1137 more: 1138 #ifdef MULOG 1139 while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0')) { 1140 /* Avoid use of `skip' if there is a danger of it looking 1141 * at continuation lines. 1142 */ 1143 do { 1144 cp++; 1145 } while (*cp == ' ' || *cp == '\t'); 1146 if (*cp == '\0') 1147 continue; 1148 if ((arg = skip(&cp)) == NULL) 1149 continue; 1150 if (strcmp(arg, "DOMAIN")) 1151 continue; 1152 if (curdom) 1153 free(curdom); 1154 curdom = NULL; 1155 while (*cp == ' ' || *cp == '\t') 1156 cp++; 1157 if (*cp == '\0') 1158 continue; 1159 arg = cp; 1160 while (*cp && *cp != ' ' && *cp != '\t') 1161 cp++; 1162 if (*cp != '\0') 1163 *cp++ = '\0'; 1164 curdom = newstr(arg); 1165 } 1166 #else 1167 while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0')) 1168 ; 1169 #endif 1170 if (cp == NULL) 1171 return ((struct servtab *)0); 1172 /* 1173 * clear the static buffer, since some fields (se_ctrladdr, 1174 * for example) don't get initialized here. 1175 */ 1176 memset((caddr_t)sep, 0, sizeof *sep); 1177 arg = skip(&cp); 1178 if (cp == NULL) { 1179 /* got an empty line containing just blanks/tabs. */ 1180 goto more; 1181 } 1182 /* Check for a host name. */ 1183 hostdelim = strrchr(arg, ':'); 1184 if (hostdelim) { 1185 *hostdelim = '\0'; 1186 sep->se_hostaddr = newstr(arg); 1187 arg = hostdelim + 1; 1188 /* 1189 * If the line is of the form `host:', then just change the 1190 * default host for the following lines. 1191 */ 1192 if (*arg == '\0') { 1193 arg = skip(&cp); 1194 if (cp == NULL) { 1195 free(defhost); 1196 defhost = sep->se_hostaddr; 1197 goto more; 1198 } 1199 } 1200 } else 1201 sep->se_hostaddr = newstr(defhost); 1202 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) { 1203 char *c = arg + MUX_LEN; 1204 if (*c == '+') { 1205 sep->se_type = MUXPLUS_TYPE; 1206 c++; 1207 } else 1208 sep->se_type = MUX_TYPE; 1209 sep->se_service = newstr(c); 1210 } else { 1211 sep->se_service = newstr(arg); 1212 sep->se_type = NORM_TYPE; 1213 } 1214 1215 arg = sskip(&cp); 1216 if (strcmp(arg, "stream") == 0) 1217 sep->se_socktype = SOCK_STREAM; 1218 else if (strcmp(arg, "dgram") == 0) 1219 sep->se_socktype = SOCK_DGRAM; 1220 else if (strcmp(arg, "rdm") == 0) 1221 sep->se_socktype = SOCK_RDM; 1222 else if (strcmp(arg, "seqpacket") == 0) 1223 sep->se_socktype = SOCK_SEQPACKET; 1224 else if (strcmp(arg, "raw") == 0) 1225 sep->se_socktype = SOCK_RAW; 1226 else 1227 sep->se_socktype = -1; 1228 1229 sep->se_proto = newstr(sskip(&cp)); 1230 if (strcmp(sep->se_proto, "unix") == 0) { 1231 sep->se_family = AF_UNIX; 1232 } else { 1233 sep->se_family = AF_INET; 1234 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 1235 #ifdef RPC 1236 char *cp, *ccp; 1237 cp = strchr(sep->se_service, '/'); 1238 if (cp == 0) { 1239 syslog(LOG_ERR, "%s: no rpc version", 1240 sep->se_service); 1241 goto more; 1242 } 1243 *cp++ = '\0'; 1244 sep->se_rpcversl = sep->se_rpcversh = 1245 strtol(cp, &ccp, 0); 1246 if (ccp == cp) { 1247 badafterall: 1248 syslog(LOG_ERR, "%s/%s: bad rpc version", 1249 sep->se_service, cp); 1250 goto more; 1251 } 1252 if (*ccp == '-') { 1253 cp = ccp + 1; 1254 sep->se_rpcversh = strtol(cp, &ccp, 0); 1255 if (ccp == cp) 1256 goto badafterall; 1257 } 1258 #else 1259 syslog(LOG_ERR, "%s: rpc services not suported", 1260 sep->se_service); 1261 goto more; 1262 #endif /* RPC */ 1263 } 1264 } 1265 arg = sskip(&cp); 1266 { 1267 char *cp; 1268 cp = strchr(arg, '.'); 1269 if (cp) { 1270 *cp++ = '\0'; 1271 sep->se_max = atoi(cp); 1272 } else 1273 sep->se_max = TOOMANY; 1274 } 1275 sep->se_wait = strcmp(arg, "wait") == 0; 1276 if (ISMUX(sep)) { 1277 /* 1278 * Silently enforce "nowait" for TCPMUX services since 1279 * they don't have an assigned port to listen on. 1280 */ 1281 sep->se_wait = 0; 1282 1283 if (strcmp(sep->se_proto, "tcp")) { 1284 syslog(LOG_ERR, 1285 "%s: bad protocol for tcpmux service %s", 1286 CONFIG, sep->se_service); 1287 goto more; 1288 } 1289 if (sep->se_socktype != SOCK_STREAM) { 1290 syslog(LOG_ERR, 1291 "%s: bad socket type for tcpmux service %s", 1292 CONFIG, sep->se_service); 1293 goto more; 1294 } 1295 } 1296 sep->se_user = newstr(sskip(&cp)); 1297 if ((sep->se_group = strchr(sep->se_user, '.'))) 1298 *sep->se_group++ = '\0'; 1299 sep->se_server = newstr(sskip(&cp)); 1300 if (strcmp(sep->se_server, "internal") == 0) { 1301 struct biltin *bi; 1302 1303 for (bi = biltins; bi->bi_service; bi++) 1304 if (bi->bi_socktype == sep->se_socktype && 1305 strcmp(bi->bi_service, sep->se_service) == 0) 1306 break; 1307 if (bi->bi_service == 0) { 1308 syslog(LOG_ERR, "internal service %s unknown", 1309 sep->se_service); 1310 goto more; 1311 } 1312 sep->se_bi = bi; 1313 sep->se_wait = bi->bi_wait; 1314 } else 1315 sep->se_bi = NULL; 1316 argc = 0; 1317 for (arg = skip(&cp); cp; arg = skip(&cp)) { 1318 #if MULOG 1319 char *colon; 1320 1321 if (argc == 0 && (colon = strrchr(arg, ':'))) { 1322 while (arg < colon) { 1323 int x; 1324 char *ccp; 1325 1326 switch (*arg++) { 1327 case 'l': 1328 x = 1; 1329 if (isdigit(*arg)) { 1330 x = strtol(arg, &ccp, 0); 1331 if (ccp == arg) 1332 break; 1333 arg = ccp; 1334 } 1335 sep->se_log &= ~MULOG_RFC931; 1336 sep->se_log |= x; 1337 break; 1338 case 'a': 1339 sep->se_log |= MULOG_RFC931; 1340 break; 1341 default: 1342 break; 1343 } 1344 } 1345 arg = colon + 1; 1346 } 1347 #endif 1348 if (argc < MAXARGV) 1349 sep->se_argv[argc++] = newstr(arg); 1350 } 1351 while (argc <= MAXARGV) 1352 sep->se_argv[argc++] = NULL; 1353 return (sep); 1354 } 1355 1356 void 1357 freeconfig(cp) 1358 struct servtab *cp; 1359 { 1360 int i; 1361 1362 if (cp->se_hostaddr) 1363 free(cp->se_hostaddr); 1364 if (cp->se_service) 1365 free(cp->se_service); 1366 if (cp->se_proto) 1367 free(cp->se_proto); 1368 if (cp->se_user) 1369 free(cp->se_user); 1370 /* Note: se_group is part of the newstr'ed se_user */ 1371 if (cp->se_server) 1372 free(cp->se_server); 1373 for (i = 0; i < MAXARGV; i++) 1374 if (cp->se_argv[i]) 1375 free(cp->se_argv[i]); 1376 } 1377 1378 1379 /* 1380 * Safe skip - if skip returns null, log a syntax error in the 1381 * configuration file and exit. 1382 */ 1383 char * 1384 sskip(cpp) 1385 char **cpp; 1386 { 1387 char *cp; 1388 1389 cp = skip(cpp); 1390 if (cp == NULL) { 1391 syslog(LOG_ERR, "%s: syntax error", CONFIG); 1392 exit(-1); 1393 } 1394 return (cp); 1395 } 1396 1397 char * 1398 skip(cpp) 1399 char **cpp; 1400 { 1401 char *cp = *cpp; 1402 char *start; 1403 1404 if (*cpp == NULL) 1405 return ((char *)0); 1406 1407 again: 1408 while (*cp == ' ' || *cp == '\t') 1409 cp++; 1410 if (*cp == '\0') { 1411 int c; 1412 1413 c = getc(fconfig); 1414 (void) ungetc(c, fconfig); 1415 if (c == ' ' || c == '\t') 1416 if ((cp = nextline(fconfig))) 1417 goto again; 1418 *cpp = (char *)0; 1419 return ((char *)0); 1420 } 1421 start = cp; 1422 while (*cp && *cp != ' ' && *cp != '\t') 1423 cp++; 1424 if (*cp != '\0') 1425 *cp++ = '\0'; 1426 *cpp = cp; 1427 return (start); 1428 } 1429 1430 char * 1431 nextline(fd) 1432 FILE *fd; 1433 { 1434 char *cp; 1435 1436 if (fgets(line, sizeof (line), fd) == NULL) 1437 return ((char *)0); 1438 cp = strchr(line, '\n'); 1439 if (cp) 1440 *cp = '\0'; 1441 return (line); 1442 } 1443 1444 char * 1445 newstr(cp) 1446 char *cp; 1447 { 1448 if ((cp = strdup(cp ? cp : ""))) 1449 return (cp); 1450 syslog(LOG_ERR, "strdup: %m"); 1451 exit(-1); 1452 } 1453 1454 void 1455 inetd_setproctitle(a, s) 1456 char *a; 1457 int s; 1458 { 1459 int size; 1460 char *cp; 1461 struct sockaddr_in sin; 1462 char buf[80]; 1463 1464 cp = Argv[0]; 1465 size = sizeof(sin); 1466 if (getpeername(s, (struct sockaddr *)&sin, &size) == 0) 1467 (void)snprintf(buf, sizeof buf, "-%s [%s]", a, 1468 inet_ntoa(sin.sin_addr)); 1469 else 1470 (void)snprintf(buf, sizeof buf, "-%s", a); 1471 strncpy(cp, buf, LastArg - cp); 1472 cp += strlen(cp); 1473 while (cp < LastArg) 1474 *cp++ = ' '; 1475 } 1476 1477 void 1478 logpid() 1479 { 1480 FILE *fp; 1481 1482 if ((fp = fopen(_PATH_INETDPID, "w")) != NULL) { 1483 fprintf(fp, "%u\n", getpid()); 1484 (void)fclose(fp); 1485 } 1486 } 1487 1488 void 1489 bump_nofile() 1490 { 1491 #ifdef RLIMIT_NOFILE 1492 1493 #define FD_CHUNK 32 1494 1495 struct rlimit rl; 1496 1497 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1498 syslog(LOG_ERR, "getrlimit: %m"); 1499 return; 1500 } 1501 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1502 if (rl.rlim_cur <= rlim_ofile_cur) { 1503 syslog(LOG_ERR, 1504 "bump_nofile: cannot extend file limit, max = %d", 1505 (int)rl.rlim_cur); 1506 return; 1507 } 1508 1509 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1510 syslog(LOG_ERR, "setrlimit: %m"); 1511 return; 1512 } 1513 1514 rlim_ofile_cur = rl.rlim_cur; 1515 return; 1516 1517 #else 1518 syslog(LOG_ERR, "bump_nofile: cannot extend file limit"); 1519 return; 1520 #endif 1521 } 1522 1523 /* 1524 * Internet services provided internally by inetd: 1525 */ 1526 #define BUFSIZE 4096 1527 1528 /* ARGSUSED */ 1529 void 1530 echo_stream(s, sep) /* Echo service -- echo data back */ 1531 int s; 1532 struct servtab *sep; 1533 { 1534 char buffer[BUFSIZE]; 1535 int i; 1536 1537 inetd_setproctitle(sep->se_service, s); 1538 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1539 write(s, buffer, i) > 0) 1540 ; 1541 } 1542 1543 /* ARGSUSED */ 1544 void 1545 echo_dg(s, sep) /* Echo service -- echo data back */ 1546 int s; 1547 struct servtab *sep; 1548 { 1549 char buffer[BUFSIZE]; 1550 int i, size; 1551 struct sockaddr sa; 1552 1553 size = sizeof(sa); 1554 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0) 1555 return; 1556 (void) sendto(s, buffer, i, 0, &sa, sizeof(sa)); 1557 } 1558 1559 /* ARGSUSED */ 1560 void 1561 discard_stream(s, sep) /* Discard service -- ignore data */ 1562 int s; 1563 struct servtab *sep; 1564 { 1565 char buffer[BUFSIZE]; 1566 1567 inetd_setproctitle(sep->se_service, s); 1568 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1569 errno == EINTR) 1570 ; 1571 } 1572 1573 /* ARGSUSED */ 1574 void 1575 discard_dg(s, sep) /* Discard service -- ignore data */ 1576 int s; 1577 struct servtab *sep; 1578 { 1579 char buffer[BUFSIZE]; 1580 1581 (void) read(s, buffer, sizeof(buffer)); 1582 } 1583 1584 #include <ctype.h> 1585 #define LINESIZ 72 1586 char ring[128]; 1587 char *endring; 1588 1589 void 1590 initring() 1591 { 1592 int i; 1593 1594 endring = ring; 1595 1596 for (i = 0; i <= 128; ++i) 1597 if (isprint(i)) 1598 *endring++ = i; 1599 } 1600 1601 /* ARGSUSED */ 1602 void 1603 chargen_stream(s, sep) /* Character generator */ 1604 int s; 1605 struct servtab *sep; 1606 { 1607 int len; 1608 char *rs, text[LINESIZ+2]; 1609 1610 inetd_setproctitle(sep->se_service, s); 1611 1612 if (!endring) { 1613 initring(); 1614 rs = ring; 1615 } 1616 1617 text[LINESIZ] = '\r'; 1618 text[LINESIZ + 1] = '\n'; 1619 for (rs = ring;;) { 1620 if ((len = endring - rs) >= LINESIZ) 1621 memmove(text, rs, LINESIZ); 1622 else { 1623 memmove(text, rs, len); 1624 memmove(text + len, ring, LINESIZ - len); 1625 } 1626 if (++rs == endring) 1627 rs = ring; 1628 if (write(s, text, sizeof(text)) != sizeof(text)) 1629 break; 1630 } 1631 } 1632 1633 /* ARGSUSED */ 1634 void 1635 chargen_dg(s, sep) /* Character generator */ 1636 int s; 1637 struct servtab *sep; 1638 { 1639 struct sockaddr sa; 1640 static char *rs; 1641 int len, size; 1642 char text[LINESIZ+2]; 1643 1644 if (endring == 0) { 1645 initring(); 1646 rs = ring; 1647 } 1648 1649 size = sizeof(sa); 1650 if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) 1651 return; 1652 1653 if ((len = endring - rs) >= LINESIZ) 1654 memmove(text, rs, LINESIZ); 1655 else { 1656 memmove(text, rs, len); 1657 memmove(text + len, ring, LINESIZ - len); 1658 } 1659 if (++rs == endring) 1660 rs = ring; 1661 text[LINESIZ] = '\r'; 1662 text[LINESIZ + 1] = '\n'; 1663 (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); 1664 } 1665 1666 /* 1667 * Return a machine readable date and time, in the form of the 1668 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1669 * returns the number of seconds since midnight, Jan 1, 1970, 1670 * we must add 2208988800 seconds to this figure to make up for 1671 * some seventy years Bell Labs was asleep. 1672 */ 1673 1674 long 1675 machtime() 1676 { 1677 struct timeval tv; 1678 1679 if (gettimeofday(&tv, (struct timezone *)0) < 0) { 1680 if (debug) 1681 fprintf(stderr, "Unable to get time of day\n"); 1682 return (0L); 1683 } 1684 #define OFFSET ((u_long)25567 * 24*60*60) 1685 return (htonl((long)(tv.tv_sec + OFFSET))); 1686 #undef OFFSET 1687 } 1688 1689 /* ARGSUSED */ 1690 void 1691 machtime_stream(s, sep) 1692 int s; 1693 struct servtab *sep; 1694 { 1695 long result; 1696 1697 result = machtime(); 1698 (void) write(s, (char *) &result, sizeof(result)); 1699 } 1700 1701 /* ARGSUSED */ 1702 void 1703 machtime_dg(s, sep) 1704 int s; 1705 struct servtab *sep; 1706 { 1707 long result; 1708 struct sockaddr sa; 1709 int size; 1710 1711 size = sizeof(sa); 1712 if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0) 1713 return; 1714 result = machtime(); 1715 (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa)); 1716 } 1717 1718 /* ARGSUSED */ 1719 void 1720 daytime_stream(s, sep) /* Return human-readable time of day */ 1721 int s; 1722 struct servtab *sep; 1723 { 1724 char buffer[256]; 1725 time_t clock; 1726 int len; 1727 1728 clock = time((time_t *) 0); 1729 1730 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1731 (void) write(s, buffer, len); 1732 } 1733 1734 /* ARGSUSED */ 1735 void 1736 daytime_dg(s, sep) /* Return human-readable time of day */ 1737 int s; 1738 struct servtab *sep; 1739 { 1740 char buffer[256]; 1741 time_t clock; 1742 struct sockaddr sa; 1743 int size, len; 1744 1745 clock = time((time_t *) 0); 1746 1747 size = sizeof(sa); 1748 if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) 1749 return; 1750 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1751 (void) sendto(s, buffer, len, 0, &sa, sizeof(sa)); 1752 } 1753 1754 /* 1755 * print_service: 1756 * Dump relevant information to stderr 1757 */ 1758 void 1759 print_service(action, sep) 1760 char *action; 1761 struct servtab *sep; 1762 { 1763 if (isrpcservice(sep)) 1764 fprintf(stderr, 1765 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%lx server=%s\n", 1766 action, sep->se_service, 1767 sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto, 1768 sep->se_wait, sep->se_max, sep->se_user, sep->se_group, 1769 (long)sep->se_bi, sep->se_server); 1770 else 1771 fprintf(stderr, 1772 "%s: %s proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%lx server=%s\n", 1773 action, sep->se_service, sep->se_proto, 1774 sep->se_wait, sep->se_max, sep->se_user, sep->se_group, 1775 (long)sep->se_bi, sep->se_server); 1776 } 1777 1778 void 1779 usage() 1780 { 1781 1782 #ifdef LIBWRAP 1783 (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", __progname); 1784 #else 1785 (void)fprintf(stderr, "usage: %s [-d] [conf]\n", __progname); 1786 #endif 1787 exit(1); 1788 } 1789 1790 1791 /* 1792 * Based on TCPMUX.C by Mark K. Lottor November 1988 1793 * sri-nic::ps:<mkl>tcpmux.c 1794 */ 1795 1796 static int /* # of characters upto \r,\n or \0 */ 1797 getline(fd, buf, len) 1798 int fd; 1799 char *buf; 1800 int len; 1801 { 1802 int count = 0, n; 1803 1804 do { 1805 n = read(fd, buf, len-count); 1806 if (n == 0) 1807 return (count); 1808 if (n < 0) 1809 return (-1); 1810 while (--n >= 0) { 1811 if (*buf == '\r' || *buf == '\n' || *buf == '\0') 1812 return (count); 1813 count++; 1814 buf++; 1815 } 1816 } while (count < len); 1817 return (count); 1818 } 1819 1820 #define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ 1821 1822 #define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) 1823 1824 void 1825 tcpmux(ctrl, sep) 1826 int ctrl; 1827 struct servtab *sep; 1828 { 1829 char service[MAX_SERV_LEN+1]; 1830 int len; 1831 1832 /* Get requested service name */ 1833 if ((len = getline(ctrl, service, MAX_SERV_LEN)) < 0) { 1834 strwrite(ctrl, "-Error reading service name\r\n"); 1835 goto reject; 1836 } 1837 service[len] = '\0'; 1838 1839 if (debug) 1840 fprintf(stderr, "tcpmux: someone wants %s\n", service); 1841 1842 /* 1843 * Help is a required command, and lists available services, 1844 * one per line. 1845 */ 1846 if (!strcasecmp(service, "help")) { 1847 strwrite(ctrl, "+Available services:\r\n"); 1848 strwrite(ctrl, "help\r\n"); 1849 for (sep = servtab; sep; sep = sep->se_next) { 1850 if (!ISMUX(sep)) 1851 continue; 1852 (void)write(ctrl, sep->se_service, 1853 strlen(sep->se_service)); 1854 strwrite(ctrl, "\r\n"); 1855 } 1856 goto reject; 1857 } 1858 1859 /* Try matching a service in inetd.conf with the request */ 1860 for (sep = servtab; sep; sep = sep->se_next) { 1861 if (!ISMUX(sep)) 1862 continue; 1863 if (!strcasecmp(service, sep->se_service)) { 1864 if (ISMUXPLUS(sep)) 1865 strwrite(ctrl, "+Go\r\n"); 1866 run_service(ctrl, sep); 1867 return; 1868 } 1869 } 1870 strwrite(ctrl, "-Service not available\r\n"); 1871 reject: 1872 _exit(1); 1873 } 1874 1875 1876 #ifdef MULOG 1877 dolog(sep, ctrl) 1878 struct servtab *sep; 1879 int ctrl; 1880 { 1881 struct sockaddr sa; 1882 struct sockaddr_in *sin = (struct sockaddr_in *)&sa; 1883 int len = sizeof(sa); 1884 struct hostent *hp; 1885 char *host, *dp, buf[BUFSIZ], *rfc931_name(); 1886 int connected = 1; 1887 1888 if (sep->se_family != AF_INET) 1889 return; 1890 1891 if (getpeername(ctrl, &sa, &len) < 0) { 1892 if (errno != ENOTCONN) { 1893 syslog(LOG_ERR, "getpeername: %m"); 1894 return; 1895 } 1896 if (recvfrom(ctrl, buf, sizeof(buf), MSG_PEEK, &sa, &len) < 0) { 1897 syslog(LOG_ERR, "recvfrom: %m"); 1898 return; 1899 } 1900 connected = 0; 1901 } 1902 if (sa.sa_family != AF_INET) { 1903 syslog(LOG_ERR, "unexpected address family %u", sa.sa_family); 1904 return; 1905 } 1906 1907 hp = gethostbyaddr((char *) &sin->sin_addr.s_addr, 1908 sizeof (sin->sin_addr.s_addr), AF_INET); 1909 1910 host = hp?hp->h_name:inet_ntoa(sin->sin_addr); 1911 1912 switch (sep->se_log & ~MULOG_RFC931) { 1913 case 0: 1914 return; 1915 case 1: 1916 if (curdom == NULL || *curdom == '\0') 1917 break; 1918 dp = host + strlen(host) - strlen(curdom); 1919 if (dp < host) 1920 break; 1921 if (debug) 1922 fprintf(stderr, "check \"%s\" against curdom \"%s\"\n", 1923 host, curdom); 1924 if (strcasecmp(dp, curdom) == 0) 1925 return; 1926 break; 1927 case 2: 1928 default: 1929 break; 1930 } 1931 1932 openlog("", LOG_NOWAIT, MULOG); 1933 1934 if (connected && (sep->se_log & MULOG_RFC931)) 1935 syslog(LOG_INFO, "%s@%s wants %s", 1936 rfc931_name(sin, ctrl), host, sep->se_service); 1937 else 1938 syslog(LOG_INFO, "%s wants %s", 1939 host, sep->se_service); 1940 } 1941 1942 /* 1943 * From tcp_log by 1944 * Wietse Venema, Eindhoven University of Technology, The Netherlands. 1945 */ 1946 #if 0 1947 static char sccsid[] = "@(#) rfc931.c 1.3 92/08/31 22:54:46"; 1948 #endif 1949 1950 #include <setjmp.h> 1951 1952 #define RFC931_PORT 113 /* Semi-well-known port */ 1953 #define TIMEOUT 4 1954 #define TIMEOUT2 10 1955 1956 static jmp_buf timebuf; 1957 1958 /* timeout - handle timeouts */ 1959 1960 static void timeout(sig) 1961 int sig; 1962 { 1963 longjmp(timebuf, sig); 1964 } 1965 1966 /* rfc931_name - return remote user name */ 1967 1968 char * 1969 rfc931_name(there, ctrl) 1970 struct sockaddr_in *there; /* remote link information */ 1971 int ctrl; 1972 { 1973 struct sockaddr_in here; /* local link information */ 1974 struct sockaddr_in sin; /* for talking to RFC931 daemon */ 1975 int length; 1976 int s; 1977 unsigned remote; 1978 unsigned local; 1979 static char user[256]; /* XXX */ 1980 char buf[256]; 1981 char *cp; 1982 char *result = "USER_UNKNOWN"; 1983 int len; 1984 1985 /* Find out local port number of our stdin. */ 1986 1987 length = sizeof(here); 1988 if (getsockname(ctrl, (struct sockaddr *) &here, &length) == -1) { 1989 syslog(LOG_ERR, "getsockname: %m"); 1990 return (result); 1991 } 1992 /* Set up timer so we won't get stuck. */ 1993 1994 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 1995 syslog(LOG_ERR, "socket: %m"); 1996 return (result); 1997 } 1998 1999 sin = here; 2000 sin.sin_port = htons(0); 2001 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { 2002 syslog(LOG_ERR, "bind: %m"); 2003 return (result); 2004 } 2005 2006 signal(SIGALRM, timeout); 2007 if (setjmp(timebuf)) { 2008 close(s); /* not: fclose(fp) */ 2009 return (result); 2010 } 2011 alarm(TIMEOUT); 2012 2013 /* Connect to the RFC931 daemon. */ 2014 2015 sin = *there; 2016 sin.sin_port = htons(RFC931_PORT); 2017 if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { 2018 close(s); 2019 alarm(0); 2020 return (result); 2021 } 2022 2023 /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */ 2024 (void)snprintf(buf, sizeof buf, "%u,%u\r\n", ntohs(there->sin_port), 2025 ntohs(here.sin_port)); 2026 2027 2028 for (len = 0, cp = buf; len < strlen(buf); ) { 2029 int n; 2030 2031 if ((n = write(s, cp, strlen(buf) - len)) == -1) { 2032 close(s); 2033 alarm(0); 2034 return (result); 2035 } 2036 cp += n; 2037 len += n; 2038 } 2039 2040 /* Read response */ 2041 for (cp = buf; cp < buf + sizeof(buf) - 1; ) { 2042 char c; 2043 if (read(s, &c, 1) != 1) { 2044 close(s); 2045 alarm(0); 2046 return (result); 2047 } 2048 if (c == '\n') 2049 break; 2050 *cp++ = c; 2051 } 2052 *cp = '\0'; 2053 2054 if (sscanf(buf, "%u , %u : USERID :%*[^:]:%255s", &remote, &local, user) == 3 2055 && ntohs(there->sin_port) == remote 2056 && ntohs(here.sin_port) == local) { 2057 2058 /* Strip trailing carriage return. */ 2059 if (cp = strchr(user, '\r')) 2060 *cp = 0; 2061 result = user; 2062 } 2063 2064 alarm(0); 2065 close(s); 2066 return (result); 2067 } 2068 #endif 2069