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