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