1 /* $NetBSD: inetd.c,v 1.91 2003/04/22 07:46:46 itojun Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2003 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 and by Matthias Scheler. 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 78 static char sccsid[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94"; 79 #else 80 __RCSID("$NetBSD: inetd.c,v 1.91 2003/04/22 07:46:46 itojun 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 * #ifdef IPSEC 167 * Comment lines that start with "#@" denote IPsec policy string, as described 168 * in ipsec_set_policy(3). This will affect all the following items in 169 * inetd.conf(8). To reset the policy, just use "#@" line. By default, 170 * there's no IPsec policy. 171 * #endif 172 */ 173 174 /* 175 * Here's the scoop concerning the user:group feature: 176 * 177 * 1) set-group-option off. 178 * 179 * a) user = root: NO setuid() or setgid() is done 180 * 181 * b) other: setuid() 182 * setgid(primary group as found in passwd) 183 * initgroups(name, primary group) 184 * 185 * 2) set-group-option on. 186 * 187 * a) user = root: NO setuid() 188 * setgid(specified group) 189 * NO initgroups() 190 * 191 * b) other: setuid() 192 * setgid(specified group) 193 * initgroups(name, specified group) 194 * 195 */ 196 197 #include <sys/param.h> 198 #include <sys/stat.h> 199 #include <sys/ioctl.h> 200 #include <sys/socket.h> 201 #include <sys/un.h> 202 #include <sys/wait.h> 203 #include <sys/time.h> 204 #include <sys/resource.h> 205 #include <sys/event.h> 206 207 #ifndef RLIMIT_NOFILE 208 #define RLIMIT_NOFILE RLIMIT_OFILE 209 #endif 210 211 #ifndef NO_RPC 212 #define RPC 213 #endif 214 215 #include <net/if.h> 216 217 #include <netinet/in.h> 218 #include <arpa/inet.h> 219 #ifdef RPC 220 #include <rpc/rpc.h> 221 #include <rpc/rpcb_clnt.h> 222 #include <netconfig.h> 223 #endif 224 225 #include <ctype.h> 226 #include <errno.h> 227 #include <fcntl.h> 228 #include <grp.h> 229 #include <netdb.h> 230 #include <pwd.h> 231 #include <signal.h> 232 #include <stdio.h> 233 #include <stdlib.h> 234 #include <string.h> 235 #include <syslog.h> 236 #include <unistd.h> 237 #include <util.h> 238 #include <ifaddrs.h> 239 240 #include "pathnames.h" 241 242 #ifdef IPSEC 243 #include <netinet6/ipsec.h> 244 #ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */ 245 #undef IPSEC 246 #endif 247 #include "ipsec.h" 248 #endif 249 250 #ifdef LIBWRAP 251 # include <tcpd.h> 252 #ifndef LIBWRAP_ALLOW_FACILITY 253 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH 254 #endif 255 #ifndef LIBWRAP_ALLOW_SEVERITY 256 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO 257 #endif 258 #ifndef LIBWRAP_DENY_FACILITY 259 # define LIBWRAP_DENY_FACILITY LOG_AUTH 260 #endif 261 #ifndef LIBWRAP_DENY_SEVERITY 262 # define LIBWRAP_DENY_SEVERITY LOG_WARNING 263 #endif 264 int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY; 265 int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY; 266 #endif 267 268 #define TOOMANY 40 /* don't start more than TOOMANY */ 269 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ 270 #define RETRYTIME (60*10) /* retry after bind or server fail */ 271 272 #define A_CNT(a) (sizeof (a) / sizeof (a[0])) 273 274 int debug; 275 #ifdef LIBWRAP 276 int lflag; 277 #endif 278 int maxsock; 279 int kq; 280 int options; 281 int timingout; 282 struct servent *sp; 283 char *curdom; 284 const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; 285 286 #ifndef OPEN_MAX 287 #define OPEN_MAX 64 288 #endif 289 290 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ 291 #define FD_MARGIN (8) 292 rlim_t rlim_ofile_cur = OPEN_MAX; 293 294 #ifdef RLIMIT_NOFILE 295 struct rlimit rlim_ofile; 296 #endif 297 298 struct kevent changebuf[64]; 299 size_t changes; 300 301 struct servtab { 302 char *se_hostaddr; /* host address to listen on */ 303 char *se_service; /* name of service */ 304 int se_socktype; /* type of socket to use */ 305 int se_family; /* address family */ 306 char *se_proto; /* protocol used */ 307 int se_sndbuf; /* sndbuf size */ 308 int se_rcvbuf; /* rcvbuf size */ 309 int se_rpcprog; /* rpc program number */ 310 int se_rpcversl; /* rpc program lowest version */ 311 int se_rpcversh; /* rpc program highest version */ 312 #define isrpcservice(sep) ((sep)->se_rpcversl != 0) 313 pid_t se_wait; /* single threaded server */ 314 short se_checked; /* looked at during merge */ 315 char *se_user; /* user name to run as */ 316 char *se_group; /* group name to run as */ 317 struct biltin *se_bi; /* if built-in, description */ 318 char *se_server; /* server program */ 319 #define MAXARGV 20 320 char *se_argv[MAXARGV+1]; /* program arguments */ 321 #ifdef IPSEC 322 char *se_policy; /* IPsec poilcy string */ 323 #endif 324 int se_fd; /* open descriptor */ 325 int se_type; /* type */ 326 union { 327 struct sockaddr se_un_ctrladdr; 328 struct sockaddr_in se_un_ctrladdr_in; 329 struct sockaddr_in6 se_un_ctrladdr_in6; 330 struct sockaddr_un se_un_ctrladdr_un; 331 } se_un; /* bound address */ 332 #define se_ctrladdr se_un.se_un_ctrladdr 333 #define se_ctrladdr_in se_un.se_un_ctrladdr_in 334 #define se_ctrladdr_un se_un.se_un_ctrladdr_un 335 int se_ctrladdr_size; 336 int se_max; /* max # of instances of this service */ 337 int se_count; /* number started since se_time */ 338 struct timeval se_time; /* start of se_count */ 339 #ifdef MULOG 340 int se_log; 341 #define MULOG_RFC931 0x40000000 342 #endif 343 struct servtab *se_next; 344 } *servtab; 345 346 #define NORM_TYPE 0 347 #define MUX_TYPE 1 348 #define MUXPLUS_TYPE 2 349 #define FAITH_TYPE 3 350 #define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \ 351 ((sep)->se_type == MUXPLUS_TYPE)) 352 #define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE) 353 354 355 static void chargen_dg(int, struct servtab *); 356 static void chargen_stream(int, struct servtab *); 357 static void close_sep(struct servtab *); 358 static void config(void); 359 static void daytime_dg(int, struct servtab *); 360 static void daytime_stream(int, struct servtab *); 361 static void discard_dg(int, struct servtab *); 362 static void discard_stream(int, struct servtab *); 363 static void echo_dg(int, struct servtab *); 364 static void echo_stream(int, struct servtab *); 365 static void endconfig(void); 366 static struct servtab *enter(struct servtab *); 367 static void freeconfig(struct servtab *); 368 static struct servtab *getconfigent(void); 369 static void goaway(void); 370 static void machtime_dg(int, struct servtab *); 371 static void machtime_stream(int, struct servtab *); 372 static char *newstr(char *); 373 static char *nextline(FILE *); 374 static void print_service(char *, struct servtab *); 375 static void reapchild(void); 376 static void retry(void); 377 static void run_service(int, struct servtab *); 378 static int setconfig(void); 379 static void setup(struct servtab *); 380 static char *sskip(char **); 381 static char *skip(char **); 382 static void tcpmux(int, struct servtab *); 383 static void usage(void); 384 static void register_rpc(struct servtab *); 385 static void unregister_rpc(struct servtab *); 386 static void bump_nofile(void); 387 static void inetd_setproctitle(char *, int); 388 static void initring(void); 389 static uint32_t machtime(void); 390 static int port_good_dg(struct sockaddr *); 391 static int dg_broadcast(struct in_addr *); 392 static int my_kevent(const struct kevent *, size_t, struct kevent *, 393 size_t); 394 static struct kevent * allocchange(void); 395 static int getline(int, char *, int); 396 static void spawn(struct servtab *, int); 397 #ifdef MULOG 398 static void dolog(struct servtab *, int); 399 static void timeout(int); 400 static char *rfc931_name(struct sockaddr *, int); 401 #endif 402 403 struct biltin { 404 char *bi_service; /* internally provided service name */ 405 int bi_socktype; /* type of socket supported */ 406 short bi_fork; /* 1 if should fork before call */ 407 short bi_wait; /* 1 if should wait for child */ 408 void (*bi_fn)(int, struct servtab *); 409 /* function which performs it */ 410 } biltins[] = { 411 /* Echo received data */ 412 { "echo", SOCK_STREAM, 1, 0, echo_stream }, 413 { "echo", SOCK_DGRAM, 0, 0, echo_dg }, 414 415 /* Internet /dev/null */ 416 { "discard", SOCK_STREAM, 1, 0, discard_stream }, 417 { "discard", SOCK_DGRAM, 0, 0, discard_dg }, 418 419 /* Return 32 bit time since 1970 */ 420 { "time", SOCK_STREAM, 0, 0, machtime_stream }, 421 { "time", SOCK_DGRAM, 0, 0, machtime_dg }, 422 423 /* Return human-readable time */ 424 { "daytime", SOCK_STREAM, 0, 0, daytime_stream }, 425 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg }, 426 427 /* Familiar character generator */ 428 { "chargen", SOCK_STREAM, 1, 0, chargen_stream }, 429 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg }, 430 431 { "tcpmux", SOCK_STREAM, 1, 0, tcpmux }, 432 433 { NULL } 434 }; 435 436 /* list of "bad" ports. I.e. ports that are most obviously used for 437 * "cycling packets" denial of service attacks. See /etc/services. 438 * List must end with port number "0". 439 */ 440 441 u_int16_t bad_ports[] = { 7, 9, 13, 19, 37, 0 }; 442 443 444 #define NUMINT (sizeof(intab) / sizeof(struct inent)) 445 char *CONFIG = _PATH_INETDCONF; 446 447 static int my_signals[] = 448 { SIGALRM, SIGHUP, SIGCHLD, SIGTERM, SIGINT, SIGPIPE }; 449 450 int 451 main(int argc, char *argv[]) 452 { 453 int ch, n, reload = 1; 454 455 while ((ch = getopt(argc, argv, 456 #ifdef LIBWRAP 457 "dl" 458 #else 459 "d" 460 #endif 461 )) != -1) 462 switch(ch) { 463 case 'd': 464 debug = 1; 465 options |= SO_DEBUG; 466 break; 467 #ifdef LIBWRAP 468 case 'l': 469 lflag = 1; 470 break; 471 #endif 472 case '?': 473 default: 474 usage(); 475 } 476 argc -= optind; 477 argv += optind; 478 479 if (argc > 0) 480 CONFIG = argv[0]; 481 482 if (!debug) 483 daemon(0, 0); 484 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); 485 pidfile(NULL); 486 487 kq = kqueue(); 488 if (kq < 0) { 489 syslog(LOG_ERR, "kqueue: %m"); 490 return (EXIT_FAILURE); 491 } 492 493 #ifdef RLIMIT_NOFILE 494 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) { 495 syslog(LOG_ERR, "getrlimit: %m"); 496 } else { 497 rlim_ofile_cur = rlim_ofile.rlim_cur; 498 if (rlim_ofile_cur == RLIM_INFINITY) /* ! */ 499 rlim_ofile_cur = OPEN_MAX; 500 } 501 #endif 502 503 for (n = 0; n < A_CNT(my_signals); n++) { 504 int signum; 505 506 signum = my_signals[n]; 507 (void) signal(signum, SIG_IGN); 508 509 if (signum != SIGPIPE) { 510 struct kevent *ev; 511 512 ev = allocchange(); 513 EV_SET(ev, signum, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 514 0, 0, NULL); 515 } 516 } 517 518 for (;;) { 519 int ctrl; 520 struct kevent eventbuf[64], *ev; 521 struct servtab *sep; 522 523 if (reload) { 524 reload = 0; 525 config(); 526 } 527 528 n = my_kevent(changebuf, changes, eventbuf, A_CNT(eventbuf)); 529 changes = 0; 530 531 for (ev = eventbuf; n > 0; ev++, n--) { 532 if (ev->filter == EVFILT_SIGNAL) { 533 switch (ev->ident) { 534 case SIGALRM: 535 retry(); 536 break; 537 case SIGCHLD: 538 reapchild(); 539 break; 540 case SIGTERM: 541 case SIGINT: 542 goaway(); 543 break; 544 case SIGHUP: 545 reload = 1; 546 break; 547 } 548 continue; 549 } 550 if (ev->filter != EVFILT_READ) 551 continue; 552 sep = (struct servtab *)ev->udata; 553 /* Paranoia */ 554 if (ev->ident != sep->se_fd) 555 continue; 556 if (debug) 557 fprintf(stderr, "someone wants %s\n", sep->se_service); 558 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 559 /* XXX here do the libwrap check-before-accept */ 560 ctrl = accept(sep->se_fd, NULL, NULL); 561 if (debug) 562 fprintf(stderr, "accept, ctrl %d\n", 563 ctrl); 564 if (ctrl < 0) { 565 if (errno != EINTR) 566 syslog(LOG_WARNING, 567 "accept (for %s): %m", 568 sep->se_service); 569 continue; 570 } 571 } else 572 ctrl = sep->se_fd; 573 spawn(sep, ctrl); 574 } 575 } 576 } 577 578 static void 579 spawn(struct servtab *sep, int ctrl) 580 { 581 int dofork; 582 pid_t pid; 583 584 pid = 0; 585 #ifdef LIBWRAP_INTERNAL 586 dofork = 1; 587 #else 588 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 589 #endif 590 if (dofork) { 591 if (sep->se_count++ == 0) 592 (void)gettimeofday(&sep->se_time, NULL); 593 else if (sep->se_count >= sep->se_max) { 594 struct timeval now; 595 596 (void)gettimeofday(&now, NULL); 597 if (now.tv_sec - sep->se_time.tv_sec > CNT_INTVL) { 598 sep->se_time = now; 599 sep->se_count = 1; 600 } else { 601 syslog(LOG_ERR, 602 "%s/%s server failing (looping), service terminated\n", 603 sep->se_service, sep->se_proto); 604 if (!sep->se_wait && sep->se_socktype == 605 SOCK_STREAM) 606 close(ctrl); 607 close_sep(sep); 608 if (!timingout) { 609 timingout = 1; 610 alarm(RETRYTIME); 611 } 612 return; 613 } 614 } 615 pid = fork(); 616 if (pid < 0) { 617 syslog(LOG_ERR, "fork: %m"); 618 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 619 close(ctrl); 620 sleep(1); 621 return; 622 } 623 if (pid != 0 && sep->se_wait) { 624 struct kevent *ev; 625 626 sep->se_wait = pid; 627 ev = allocchange(); 628 EV_SET(ev, sep->se_fd, EVFILT_READ, 629 EV_DELETE, 0, 0, 0); 630 } 631 if (pid == 0) { 632 int n; 633 634 for (n = 0; n < A_CNT(my_signals); n++) 635 (void) signal(my_signals[n], SIG_DFL); 636 if (debug) 637 setsid(); 638 } 639 } 640 if (pid == 0) { 641 run_service(ctrl, sep); 642 if (dofork) 643 exit(0); 644 } 645 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 646 close(ctrl); 647 } 648 649 static void 650 run_service(int ctrl, struct servtab *sep) 651 { 652 struct passwd *pwd; 653 struct group *grp = NULL; /* XXX gcc */ 654 char buf[NI_MAXSERV]; 655 #ifdef LIBWRAP 656 struct request_info req; 657 int denied; 658 char *service = NULL; /* XXX gcc */ 659 #endif 660 661 #ifdef LIBWRAP 662 #ifndef LIBWRAP_INTERNAL 663 if (sep->se_bi == 0) 664 #endif 665 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 666 request_init(&req, RQ_DAEMON, sep->se_argv[0] ? 667 sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL); 668 fromhost(&req); 669 denied = !hosts_access(&req); 670 if (denied || lflag) { 671 if (getnameinfo(&sep->se_ctrladdr, 672 sep->se_ctrladdr.sa_len, NULL, 0, 673 buf, sizeof(buf), 0) != 0) { 674 /* shouldn't happen */ 675 (void)snprintf(buf, sizeof buf, "%d", 676 ntohs(sep->se_ctrladdr_in.sin_port)); 677 } 678 service = buf; 679 } 680 if (denied) { 681 syslog(deny_severity, 682 "refused connection from %.500s, service %s (%s)", 683 eval_client(&req), service, sep->se_proto); 684 goto reject; 685 } 686 if (lflag) { 687 syslog(allow_severity, 688 "connection from %.500s, service %s (%s)", 689 eval_client(&req), service, sep->se_proto); 690 } 691 } 692 #endif /* LIBWRAP */ 693 694 if (sep->se_bi) { 695 (*sep->se_bi->bi_fn)(ctrl, sep); 696 } else { 697 if ((pwd = getpwnam(sep->se_user)) == NULL) { 698 syslog(LOG_ERR, "%s/%s: %s: No such user", 699 sep->se_service, sep->se_proto, sep->se_user); 700 goto reject; 701 } 702 if (sep->se_group && 703 (grp = getgrnam(sep->se_group)) == NULL) { 704 syslog(LOG_ERR, "%s/%s: %s: No such group", 705 sep->se_service, sep->se_proto, sep->se_group); 706 goto reject; 707 } 708 if (pwd->pw_uid) { 709 if (sep->se_group) 710 pwd->pw_gid = grp->gr_gid; 711 if (setgid(pwd->pw_gid) < 0) { 712 syslog(LOG_ERR, 713 "%s/%s: can't set gid %d: %m", sep->se_service, 714 sep->se_proto, pwd->pw_gid); 715 goto reject; 716 } 717 (void) initgroups(pwd->pw_name, 718 pwd->pw_gid); 719 if (setuid(pwd->pw_uid) < 0) { 720 syslog(LOG_ERR, 721 "%s/%s: can't set uid %d: %m", sep->se_service, 722 sep->se_proto, pwd->pw_uid); 723 goto reject; 724 } 725 } else if (sep->se_group) { 726 (void) setgid((gid_t)grp->gr_gid); 727 } 728 if (debug) 729 fprintf(stderr, "%d execl %s\n", 730 getpid(), sep->se_server); 731 #ifdef MULOG 732 if (sep->se_log) 733 dolog(sep, ctrl); 734 #endif 735 /* Set our control descriptor to not close-on-exec... */ 736 if (fcntl(ctrl, F_SETFD, 0) < 0) 737 syslog(LOG_ERR, "fcntl (F_SETFD, 0): %m"); 738 /* ...and dup it to stdin, stdout, and stderr. */ 739 if (ctrl != 0) { 740 dup2(ctrl, 0); 741 close(ctrl); 742 ctrl = 0; 743 } 744 dup2(0, 1); 745 dup2(0, 2); 746 #ifdef RLIMIT_NOFILE 747 if (rlim_ofile.rlim_cur != rlim_ofile_cur && 748 setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) 749 syslog(LOG_ERR, "setrlimit: %m"); 750 #endif 751 execv(sep->se_server, sep->se_argv); 752 syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server); 753 reject: 754 if (sep->se_socktype != SOCK_STREAM) 755 recv(ctrl, buf, sizeof (buf), 0); 756 _exit(1); 757 } 758 } 759 760 static void 761 reapchild(void) 762 { 763 int status; 764 pid_t pid; 765 struct servtab *sep; 766 767 for (;;) { 768 pid = wait3(&status, WNOHANG, NULL); 769 if (pid <= 0) 770 break; 771 if (debug) 772 (void) fprintf(stderr, "%d reaped, status %#x\n", 773 pid, status); 774 for (sep = servtab; sep != NULL; sep = sep->se_next) 775 if (sep->se_wait == pid) { 776 struct kevent *ev; 777 778 if (WIFEXITED(status) && WEXITSTATUS(status)) 779 syslog(LOG_WARNING, 780 "%s: exit status 0x%x", 781 sep->se_server, WEXITSTATUS(status)); 782 else if (WIFSIGNALED(status)) 783 syslog(LOG_WARNING, 784 "%s: exit signal 0x%x", 785 sep->se_server, WTERMSIG(status)); 786 sep->se_wait = 1; 787 ev = allocchange(); 788 EV_SET(ev, sep->se_fd, EVFILT_READ, 789 EV_ADD | EV_ENABLE, 0, 0, (intptr_t)sep); 790 if (debug) 791 fprintf(stderr, "restored %s, fd %d\n", 792 sep->se_service, sep->se_fd); 793 } 794 } 795 } 796 797 static void 798 config(void) 799 { 800 struct servtab *sep, *cp, **sepp; 801 int n; 802 803 if (!setconfig()) { 804 syslog(LOG_ERR, "%s: %m", CONFIG); 805 return; 806 } 807 for (sep = servtab; sep != NULL; sep = sep->se_next) 808 sep->se_checked = 0; 809 while ((cp = getconfigent())) { 810 for (sep = servtab; sep != NULL; sep = sep->se_next) 811 if (strcmp(sep->se_service, cp->se_service) == 0 && 812 strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 && 813 strcmp(sep->se_proto, cp->se_proto) == 0 && 814 ISMUX(sep) == ISMUX(cp)) 815 break; 816 if (sep != NULL) { 817 int i; 818 819 #define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;} 820 821 /* 822 * sep->se_wait may be holding the pid of a daemon 823 * that we're waiting for. If so, don't overwrite 824 * it unless the config file explicitly says don't 825 * wait. 826 */ 827 if (cp->se_bi == 0 && 828 (sep->se_wait == 1 || cp->se_wait == 0)) 829 sep->se_wait = cp->se_wait; 830 SWAP(char *, sep->se_user, cp->se_user); 831 SWAP(char *, sep->se_group, cp->se_group); 832 SWAP(char *, sep->se_server, cp->se_server); 833 for (i = 0; i < MAXARGV; i++) 834 SWAP(char *, sep->se_argv[i], cp->se_argv[i]); 835 #ifdef IPSEC 836 SWAP(char *, sep->se_policy, cp->se_policy); 837 #endif 838 SWAP(int, cp->se_type, sep->se_type); 839 SWAP(int, cp->se_max, sep->se_max); 840 #undef SWAP 841 if (isrpcservice(sep)) 842 unregister_rpc(sep); 843 sep->se_rpcversl = cp->se_rpcversl; 844 sep->se_rpcversh = cp->se_rpcversh; 845 freeconfig(cp); 846 if (debug) 847 print_service("REDO", sep); 848 } else { 849 sep = enter(cp); 850 if (debug) 851 print_service("ADD ", sep); 852 } 853 sep->se_checked = 1; 854 855 switch (sep->se_family) { 856 case AF_LOCAL: 857 if (sep->se_fd != -1) 858 break; 859 n = strlen(sep->se_service); 860 if (n > sizeof(sep->se_ctrladdr_un.sun_path)) { 861 syslog(LOG_ERR, "%s: address too long", 862 sep->se_service); 863 sep->se_checked = 0; 864 continue; 865 } 866 (void)unlink(sep->se_service); 867 strncpy(sep->se_ctrladdr_un.sun_path, 868 sep->se_service, n); 869 sep->se_ctrladdr_un.sun_family = AF_LOCAL; 870 sep->se_ctrladdr_size = n + 871 sizeof(sep->se_ctrladdr_un) - 872 sizeof(sep->se_ctrladdr_un.sun_path); 873 if (!ISMUX(sep)) 874 setup(sep); 875 break; 876 case AF_INET: 877 #ifdef INET6 878 case AF_INET6: 879 #endif 880 { 881 struct addrinfo hints, *res; 882 char *host, *port; 883 int error; 884 int s; 885 886 /* check if the family is supported */ 887 s = socket(sep->se_family, SOCK_DGRAM, 0); 888 if (s < 0) { 889 syslog(LOG_WARNING, 890 "%s/%s: %s: the address family is not supported by the kernel", 891 sep->se_service, sep->se_proto, 892 sep->se_hostaddr); 893 sep->se_checked = 0; 894 continue; 895 } 896 close(s); 897 898 memset(&hints, 0, sizeof(hints)); 899 hints.ai_family = sep->se_family; 900 hints.ai_socktype = sep->se_socktype; 901 hints.ai_flags = AI_PASSIVE; 902 if (!strcmp(sep->se_hostaddr, "*")) 903 host = NULL; 904 else 905 host = sep->se_hostaddr; 906 if (isrpcservice(sep) || ISMUX(sep)) 907 port = "0"; 908 else 909 port = sep->se_service; 910 error = getaddrinfo(host, port, &hints, &res); 911 if (error) { 912 if (error == EAI_SERVICE) { 913 /* gai_strerror not friendly enough */ 914 syslog(LOG_WARNING, "%s/%s: " 915 "unknown service", 916 sep->se_service, sep->se_proto); 917 } else { 918 syslog(LOG_ERR, "%s/%s: %s: %s", 919 sep->se_service, sep->se_proto, 920 sep->se_hostaddr, 921 gai_strerror(error)); 922 } 923 sep->se_checked = 0; 924 continue; 925 } 926 if (res->ai_next) { 927 syslog(LOG_ERR, 928 "%s/%s: %s: resolved to multiple addr", 929 sep->se_service, sep->se_proto, 930 sep->se_hostaddr); 931 sep->se_checked = 0; 932 freeaddrinfo(res); 933 continue; 934 } 935 memcpy(&sep->se_ctrladdr, res->ai_addr, 936 res->ai_addrlen); 937 if (ISMUX(sep)) { 938 sep->se_fd = -1; 939 freeaddrinfo(res); 940 continue; 941 } 942 sep->se_ctrladdr_size = res->ai_addrlen; 943 freeaddrinfo(res); 944 #ifdef RPC 945 if (isrpcservice(sep)) { 946 struct rpcent *rp; 947 948 sep->se_rpcprog = atoi(sep->se_service); 949 if (sep->se_rpcprog == 0) { 950 rp = getrpcbyname(sep->se_service); 951 if (rp == 0) { 952 syslog(LOG_ERR, 953 "%s/%s: unknown service", 954 sep->se_service, 955 sep->se_proto); 956 sep->se_checked = 0; 957 continue; 958 } 959 sep->se_rpcprog = rp->r_number; 960 } 961 if (sep->se_fd == -1 && !ISMUX(sep)) 962 setup(sep); 963 if (sep->se_fd != -1) 964 register_rpc(sep); 965 } else 966 #endif 967 { 968 if (sep->se_fd >= 0) 969 close_sep(sep); 970 if (sep->se_fd == -1 && !ISMUX(sep)) 971 setup(sep); 972 } 973 } 974 } 975 } 976 endconfig(); 977 /* 978 * Purge anything not looked at above. 979 */ 980 sepp = &servtab; 981 while ((sep = *sepp)) { 982 if (sep->se_checked) { 983 sepp = &sep->se_next; 984 continue; 985 } 986 *sepp = sep->se_next; 987 if (sep->se_fd >= 0) 988 close_sep(sep); 989 if (isrpcservice(sep)) 990 unregister_rpc(sep); 991 if (sep->se_family == AF_LOCAL) 992 (void)unlink(sep->se_service); 993 if (debug) 994 print_service("FREE", sep); 995 freeconfig(sep); 996 free(sep); 997 } 998 } 999 1000 static void 1001 retry(void) 1002 { 1003 struct servtab *sep; 1004 1005 timingout = 0; 1006 for (sep = servtab; sep != NULL; sep = sep->se_next) { 1007 if (sep->se_fd == -1 && !ISMUX(sep)) { 1008 switch (sep->se_family) { 1009 case AF_LOCAL: 1010 case AF_INET: 1011 #ifdef INET6 1012 case AF_INET6: 1013 #endif 1014 setup(sep); 1015 if (sep->se_fd != -1 && isrpcservice(sep)) 1016 register_rpc(sep); 1017 break; 1018 } 1019 } 1020 } 1021 } 1022 1023 static void 1024 goaway(void) 1025 { 1026 struct servtab *sep; 1027 1028 for (sep = servtab; sep != NULL; sep = sep->se_next) { 1029 if (sep->se_fd == -1) 1030 continue; 1031 1032 switch (sep->se_family) { 1033 case AF_LOCAL: 1034 (void)unlink(sep->se_service); 1035 break; 1036 case AF_INET: 1037 #ifdef INET6 1038 case AF_INET6: 1039 #endif 1040 if (sep->se_wait == 1 && isrpcservice(sep)) 1041 unregister_rpc(sep); 1042 break; 1043 } 1044 (void)close(sep->se_fd); 1045 } 1046 exit(0); 1047 } 1048 1049 static void 1050 setup(struct servtab *sep) 1051 { 1052 int on = 1, off = 0; 1053 struct kevent *ev; 1054 1055 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 1056 if (debug) 1057 fprintf(stderr, "socket failed on %s/%s: %s\n", 1058 sep->se_service, sep->se_proto, strerror(errno)); 1059 syslog(LOG_ERR, "%s/%s: socket: %m", 1060 sep->se_service, sep->se_proto); 1061 return; 1062 } 1063 /* Set all listening sockets to close-on-exec. */ 1064 if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) { 1065 syslog(LOG_ERR, "%s/%s: fcntl(F_SETFD, FD_CLOEXEC): %m", 1066 sep->se_service, sep->se_proto); 1067 close(sep->se_fd); 1068 return; 1069 } 1070 1071 #define turnon(fd, opt) \ 1072 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) 1073 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 1074 turnon(sep->se_fd, SO_DEBUG) < 0) 1075 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 1076 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 1077 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 1078 #undef turnon 1079 1080 /* Set the socket buffer sizes, if specified. */ 1081 if (sep->se_sndbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET, 1082 SO_SNDBUF, (char *)&sep->se_sndbuf, sizeof(sep->se_sndbuf)) < 0) 1083 syslog(LOG_ERR, "setsockopt (SO_SNDBUF %d): %m", 1084 sep->se_sndbuf); 1085 if (sep->se_rcvbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET, 1086 SO_RCVBUF, (char *)&sep->se_rcvbuf, sizeof(sep->se_rcvbuf)) < 0) 1087 syslog(LOG_ERR, "setsockopt (SO_RCVBUF %d): %m", 1088 sep->se_rcvbuf); 1089 #ifdef INET6 1090 if (sep->se_family == AF_INET6) { 1091 int *v; 1092 v = (sep->se_type == FAITH_TYPE) ? &on : &off; 1093 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, 1094 (char *)v, sizeof(*v)) < 0) 1095 syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m"); 1096 } 1097 #endif 1098 #ifdef IPSEC 1099 if (ipsecsetup(sep->se_family, sep->se_fd, sep->se_policy) < 0 && 1100 sep->se_policy) { 1101 syslog(LOG_ERR, "%s/%s: ipsec setup failed", 1102 sep->se_service, sep->se_proto); 1103 (void)close(sep->se_fd); 1104 sep->se_fd = -1; 1105 return; 1106 } 1107 #endif 1108 1109 if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) { 1110 if (debug) 1111 fprintf(stderr, "bind failed on %s/%s: %s\n", 1112 sep->se_service, sep->se_proto, strerror(errno)); 1113 syslog(LOG_ERR, "%s/%s: bind: %m", 1114 sep->se_service, sep->se_proto); 1115 (void) close(sep->se_fd); 1116 sep->se_fd = -1; 1117 if (!timingout) { 1118 timingout = 1; 1119 alarm(RETRYTIME); 1120 } 1121 return; 1122 } 1123 if (sep->se_socktype == SOCK_STREAM) 1124 listen(sep->se_fd, 10); 1125 1126 ev = allocchange(); 1127 EV_SET(ev, sep->se_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 1128 (intptr_t)sep); 1129 if (sep->se_fd > maxsock) { 1130 maxsock = sep->se_fd; 1131 if (maxsock > rlim_ofile_cur - FD_MARGIN) 1132 bump_nofile(); 1133 } 1134 if (debug) 1135 fprintf(stderr, "registered %s on %d\n", 1136 sep->se_server, sep->se_fd); 1137 } 1138 1139 /* 1140 * Finish with a service and its socket. 1141 */ 1142 static void 1143 close_sep(struct servtab *sep) 1144 { 1145 if (sep->se_fd >= 0) { 1146 (void) close(sep->se_fd); 1147 sep->se_fd = -1; 1148 } 1149 sep->se_count = 0; 1150 } 1151 1152 static void 1153 register_rpc(struct servtab *sep) 1154 { 1155 #ifdef RPC 1156 int n; 1157 struct netbuf nbuf; 1158 struct sockaddr_storage ss; 1159 struct netconfig *nconf; 1160 1161 if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) { 1162 syslog(LOG_ERR, "%s: getnetconfigent failed", 1163 sep->se_proto); 1164 return; 1165 } 1166 n = sizeof ss; 1167 if (getsockname(sep->se_fd, (struct sockaddr *)&ss, &n) < 0) { 1168 syslog(LOG_ERR, "%s/%s: getsockname: %m", 1169 sep->se_service, sep->se_proto); 1170 return; 1171 } 1172 1173 nbuf.buf = &ss; 1174 nbuf.len = ss.ss_len; 1175 nbuf.maxlen = sizeof (struct sockaddr_storage); 1176 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1177 if (debug) 1178 fprintf(stderr, "rpcb_set: %u %d %s %s\n", 1179 sep->se_rpcprog, n, nconf->nc_netid, 1180 taddr2uaddr(nconf, &nbuf)); 1181 (void)rpcb_unset(sep->se_rpcprog, n, nconf); 1182 if (!rpcb_set(sep->se_rpcprog, n, nconf, &nbuf)) 1183 syslog(LOG_ERR, "rpcb_set: %u %d %s %s%s", 1184 sep->se_rpcprog, n, nconf->nc_netid, 1185 taddr2uaddr(nconf, &nbuf), clnt_spcreateerror("")); 1186 } 1187 #endif /* RPC */ 1188 } 1189 1190 static void 1191 unregister_rpc(struct servtab *sep) 1192 { 1193 #ifdef RPC 1194 int n; 1195 struct netconfig *nconf; 1196 1197 if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) { 1198 syslog(LOG_ERR, "%s: getnetconfigent failed", 1199 sep->se_proto); 1200 return; 1201 } 1202 1203 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1204 if (debug) 1205 fprintf(stderr, "rpcb_unset(%u, %d, %s)\n", 1206 sep->se_rpcprog, n, nconf->nc_netid); 1207 if (!rpcb_unset(sep->se_rpcprog, n, nconf)) 1208 syslog(LOG_ERR, "rpcb_unset(%u, %d, %s) failed\n", 1209 sep->se_rpcprog, n, nconf->nc_netid); 1210 } 1211 #endif /* RPC */ 1212 } 1213 1214 1215 static struct servtab * 1216 enter(struct servtab *cp) 1217 { 1218 struct servtab *sep; 1219 1220 sep = (struct servtab *)malloc(sizeof (*sep)); 1221 if (sep == NULL) { 1222 syslog(LOG_ERR, "Out of memory."); 1223 exit(1); 1224 } 1225 *sep = *cp; 1226 sep->se_fd = -1; 1227 sep->se_rpcprog = -1; 1228 sep->se_next = servtab; 1229 servtab = sep; 1230 return (sep); 1231 } 1232 1233 FILE *fconfig = NULL; 1234 struct servtab serv; 1235 char line[LINE_MAX]; 1236 char *defhost; 1237 #ifdef IPSEC 1238 static char *policy = NULL; 1239 #endif 1240 1241 static int 1242 setconfig(void) 1243 { 1244 if (defhost) 1245 free(defhost); 1246 defhost = newstr("*"); 1247 #ifdef IPSEC 1248 if (policy) 1249 free(policy); 1250 policy = NULL; 1251 #endif 1252 if (fconfig != NULL) { 1253 fseek(fconfig, 0L, SEEK_SET); 1254 return (1); 1255 } 1256 fconfig = fopen(CONFIG, "r"); 1257 return (fconfig != NULL); 1258 } 1259 1260 static void 1261 endconfig(void) 1262 { 1263 if (fconfig != NULL) { 1264 (void) fclose(fconfig); 1265 fconfig = NULL; 1266 } 1267 if (defhost != NULL) { 1268 free(defhost); 1269 defhost = NULL; 1270 } 1271 } 1272 1273 static struct servtab * 1274 getconfigent(void) 1275 { 1276 struct servtab *sep = &serv; 1277 int argc, val; 1278 char *cp, *cp0, *arg, *buf0, *buf1, *sz0, *sz1; 1279 static char TCPMUX_TOKEN[] = "tcpmux/"; 1280 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) 1281 char *hostdelim; 1282 1283 more: 1284 while ((cp = nextline(fconfig))) { 1285 #ifdef IPSEC 1286 /* lines starting with #@ is not a comment, but the policy */ 1287 if (cp[0] == '#' && cp[1] == '@') { 1288 char *p; 1289 for (p = cp + 2; p && *p && isspace(*p); p++) 1290 ; 1291 if (*p == '\0') { 1292 if (policy) 1293 free(policy); 1294 policy = NULL; 1295 } else { 1296 if (ipsecsetup_test(p) < 0) { 1297 syslog(LOG_ERR, 1298 "%s: invalid ipsec policy \"%s\"", 1299 CONFIG, p); 1300 exit(1); 1301 } else { 1302 if (policy) 1303 free(policy); 1304 policy = newstr(p); 1305 } 1306 } 1307 } 1308 #endif 1309 if (*cp == '#' || *cp == '\0') 1310 continue; 1311 #ifdef MULOG 1312 /* Avoid use of `skip' if there is a danger of it looking 1313 * at continuation lines. 1314 */ 1315 do { 1316 cp++; 1317 } while (*cp == ' ' || *cp == '\t'); 1318 if (*cp == '\0') 1319 continue; 1320 if ((arg = skip(&cp)) == NULL) 1321 continue; 1322 if (strcmp(arg, "DOMAIN")) 1323 continue; 1324 if (curdom) 1325 free(curdom); 1326 curdom = NULL; 1327 while (*cp == ' ' || *cp == '\t') 1328 cp++; 1329 if (*cp == '\0') 1330 continue; 1331 arg = cp; 1332 while (*cp && *cp != ' ' && *cp != '\t') 1333 cp++; 1334 if (*cp != '\0') 1335 *cp++ = '\0'; 1336 curdom = newstr(arg); 1337 #endif 1338 break; 1339 } 1340 if (cp == NULL) 1341 return (NULL); 1342 /* 1343 * clear the static buffer, since some fields (se_ctrladdr, 1344 * for example) don't get initialized here. 1345 */ 1346 memset((caddr_t)sep, 0, sizeof *sep); 1347 arg = skip(&cp); 1348 if (cp == NULL) { 1349 /* got an empty line containing just blanks/tabs. */ 1350 goto more; 1351 } 1352 /* Check for a host name. */ 1353 hostdelim = strrchr(arg, ':'); 1354 if (hostdelim) { 1355 *hostdelim = '\0'; 1356 if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') { 1357 hostdelim[-1] = '\0'; 1358 sep->se_hostaddr = newstr(arg + 1); 1359 } else 1360 sep->se_hostaddr = newstr(arg); 1361 arg = hostdelim + 1; 1362 /* 1363 * If the line is of the form `host:', then just change the 1364 * default host for the following lines. 1365 */ 1366 if (*arg == '\0') { 1367 arg = skip(&cp); 1368 if (cp == NULL) { 1369 free(defhost); 1370 defhost = sep->se_hostaddr; 1371 goto more; 1372 } 1373 } 1374 } else 1375 sep->se_hostaddr = newstr(defhost); 1376 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) { 1377 char *c = arg + MUX_LEN; 1378 if (*c == '+') { 1379 sep->se_type = MUXPLUS_TYPE; 1380 c++; 1381 } else 1382 sep->se_type = MUX_TYPE; 1383 sep->se_service = newstr(c); 1384 } else { 1385 sep->se_service = newstr(arg); 1386 sep->se_type = NORM_TYPE; 1387 } 1388 1389 arg = sskip(&cp); 1390 if (strcmp(arg, "stream") == 0) 1391 sep->se_socktype = SOCK_STREAM; 1392 else if (strcmp(arg, "dgram") == 0) 1393 sep->se_socktype = SOCK_DGRAM; 1394 else if (strcmp(arg, "rdm") == 0) 1395 sep->se_socktype = SOCK_RDM; 1396 else if (strcmp(arg, "seqpacket") == 0) 1397 sep->se_socktype = SOCK_SEQPACKET; 1398 else if (strcmp(arg, "raw") == 0) 1399 sep->se_socktype = SOCK_RAW; 1400 else 1401 sep->se_socktype = -1; 1402 1403 arg = sskip(&cp); 1404 if (sep->se_type == NORM_TYPE && 1405 strncmp(arg, "faith/", strlen("faith/")) == 0) { 1406 arg += strlen("faith/"); 1407 sep->se_type = FAITH_TYPE; 1408 } 1409 sep->se_proto = newstr(arg); 1410 1411 #define MALFORMED(arg) \ 1412 do { \ 1413 syslog(LOG_ERR, "%s: malformed buffer size option `%s'", \ 1414 sep->se_service, (arg)); \ 1415 goto more; \ 1416 } while (0) 1417 1418 #define GETVAL(arg) \ 1419 do { \ 1420 if (!isdigit(*(arg))) \ 1421 MALFORMED(arg); \ 1422 val = strtol((arg), &cp0, 10); \ 1423 if (cp0 != NULL) { \ 1424 if (cp0[1] != '\0') \ 1425 MALFORMED((arg)); \ 1426 if (cp0[0] == 'k') \ 1427 val *= 1024; \ 1428 if (cp0[0] == 'm') \ 1429 val *= 1024 * 1024; \ 1430 } \ 1431 if (val < 1) { \ 1432 syslog(LOG_ERR, "%s: invalid buffer size `%s'", \ 1433 sep->se_service, (arg)); \ 1434 goto more; \ 1435 } \ 1436 } while (0) 1437 1438 #define ASSIGN(arg) \ 1439 do { \ 1440 if (strcmp((arg), "sndbuf") == 0) \ 1441 sep->se_sndbuf = val; \ 1442 else if (strcmp((arg), "rcvbuf") == 0) \ 1443 sep->se_rcvbuf = val; \ 1444 else \ 1445 MALFORMED((arg)); \ 1446 } while (0) 1447 1448 /* 1449 * Extract the send and receive buffer sizes before parsing 1450 * the protocol. 1451 */ 1452 sep->se_sndbuf = sep->se_rcvbuf = 0; 1453 buf0 = buf1 = sz0 = sz1 = NULL; 1454 if ((buf0 = strchr(sep->se_proto, ',')) != NULL) { 1455 /* Not meaningful for Tcpmux services. */ 1456 if (ISMUX(sep)) { 1457 syslog(LOG_ERR, "%s: can't specify buffer sizes for " 1458 "tcpmux services", sep->se_service); 1459 goto more; 1460 } 1461 1462 /* Skip the , */ 1463 *buf0++ = '\0'; 1464 1465 /* Check to see if another socket buffer size was specified. */ 1466 if ((buf1 = strchr(buf0, ',')) != NULL) { 1467 /* Skip the , */ 1468 *buf1++ = '\0'; 1469 1470 /* Make sure a 3rd one wasn't specified. */ 1471 if (strchr(buf1, ',') != NULL) { 1472 syslog(LOG_ERR, "%s: too many buffer sizes", 1473 sep->se_service); 1474 goto more; 1475 } 1476 1477 /* Locate the size. */ 1478 if ((sz1 = strchr(buf1, '=')) == NULL) 1479 MALFORMED(buf1); 1480 1481 /* Skip the = */ 1482 *sz1++ = '\0'; 1483 } 1484 1485 /* Locate the size. */ 1486 if ((sz0 = strchr(buf0, '=')) == NULL) 1487 MALFORMED(buf0); 1488 1489 /* Skip the = */ 1490 *sz0++ = '\0'; 1491 1492 GETVAL(sz0); 1493 ASSIGN(buf0); 1494 1495 if (buf1 != NULL) { 1496 GETVAL(sz1); 1497 ASSIGN(buf1); 1498 } 1499 } 1500 1501 #undef ASSIGN 1502 #undef GETVAL 1503 #undef MALFORMED 1504 1505 if (strcmp(sep->se_proto, "unix") == 0) { 1506 sep->se_family = AF_LOCAL; 1507 } else { 1508 val = strlen(sep->se_proto); 1509 if (!val) { 1510 syslog(LOG_ERR, "%s: invalid protocol specified", 1511 sep->se_service); 1512 goto more; 1513 } 1514 val = sep->se_proto[val - 1]; 1515 switch (val) { 1516 case '4': /*tcp4 or udp4*/ 1517 sep->se_family = AF_INET; 1518 break; 1519 #ifdef INET6 1520 case '6': /*tcp6 or udp6*/ 1521 sep->se_family = AF_INET6; 1522 break; 1523 #endif 1524 default: 1525 sep->se_family = AF_INET; /*will become AF_INET6*/ 1526 break; 1527 } 1528 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 1529 #ifdef RPC 1530 char *cp, *ccp; 1531 cp = strchr(sep->se_service, '/'); 1532 if (cp == 0) { 1533 syslog(LOG_ERR, "%s: no rpc version", 1534 sep->se_service); 1535 goto more; 1536 } 1537 *cp++ = '\0'; 1538 sep->se_rpcversl = sep->se_rpcversh = 1539 strtol(cp, &ccp, 0); 1540 if (ccp == cp) { 1541 badafterall: 1542 syslog(LOG_ERR, "%s/%s: bad rpc version", 1543 sep->se_service, cp); 1544 goto more; 1545 } 1546 if (*ccp == '-') { 1547 cp = ccp + 1; 1548 sep->se_rpcversh = strtol(cp, &ccp, 0); 1549 if (ccp == cp) 1550 goto badafterall; 1551 } 1552 #else 1553 syslog(LOG_ERR, "%s: rpc services not suported", 1554 sep->se_service); 1555 goto more; 1556 #endif /* RPC */ 1557 } 1558 } 1559 arg = sskip(&cp); 1560 { 1561 char *cp; 1562 if ((cp = strchr(arg, ':')) == NULL) 1563 cp = strchr(arg, '.'); 1564 if (cp != NULL) { 1565 *cp++ = '\0'; 1566 sep->se_max = atoi(cp); 1567 } else 1568 sep->se_max = TOOMANY; 1569 } 1570 sep->se_wait = strcmp(arg, "wait") == 0; 1571 if (ISMUX(sep)) { 1572 /* 1573 * Silently enforce "nowait" for TCPMUX services since 1574 * they don't have an assigned port to listen on. 1575 */ 1576 sep->se_wait = 0; 1577 1578 if (strncmp(sep->se_proto, "tcp", 3)) { 1579 syslog(LOG_ERR, 1580 "%s: bad protocol for tcpmux service %s", 1581 CONFIG, sep->se_service); 1582 goto more; 1583 } 1584 if (sep->se_socktype != SOCK_STREAM) { 1585 syslog(LOG_ERR, 1586 "%s: bad socket type for tcpmux service %s", 1587 CONFIG, sep->se_service); 1588 goto more; 1589 } 1590 } 1591 sep->se_user = newstr(sskip(&cp)); 1592 if ((sep->se_group = strchr(sep->se_user, ':')) != NULL) 1593 *sep->se_group++ = '\0'; 1594 else if ((sep->se_group = strchr(sep->se_user, '.')) != NULL) 1595 *sep->se_group++ = '\0'; 1596 1597 sep->se_server = newstr(sskip(&cp)); 1598 if (strcmp(sep->se_server, "internal") == 0) { 1599 struct biltin *bi; 1600 1601 for (bi = biltins; bi->bi_service; bi++) 1602 if (bi->bi_socktype == sep->se_socktype && 1603 strcmp(bi->bi_service, sep->se_service) == 0) 1604 break; 1605 if (bi->bi_service == 0) { 1606 syslog(LOG_ERR, "internal service %s unknown", 1607 sep->se_service); 1608 goto more; 1609 } 1610 sep->se_bi = bi; 1611 sep->se_wait = bi->bi_wait; 1612 } else 1613 sep->se_bi = NULL; 1614 argc = 0; 1615 for (arg = skip(&cp); cp; arg = skip(&cp)) { 1616 #if MULOG 1617 char *colon; 1618 1619 if (argc == 0 && (colon = strrchr(arg, ':'))) { 1620 while (arg < colon) { 1621 int x; 1622 char *ccp; 1623 1624 switch (*arg++) { 1625 case 'l': 1626 x = 1; 1627 if (isdigit(*arg)) { 1628 x = strtol(arg, &ccp, 0); 1629 if (ccp == arg) 1630 break; 1631 arg = ccp; 1632 } 1633 sep->se_log &= ~MULOG_RFC931; 1634 sep->se_log |= x; 1635 break; 1636 case 'a': 1637 sep->se_log |= MULOG_RFC931; 1638 break; 1639 default: 1640 break; 1641 } 1642 } 1643 arg = colon + 1; 1644 } 1645 #endif 1646 if (argc < MAXARGV) 1647 sep->se_argv[argc++] = newstr(arg); 1648 } 1649 while (argc <= MAXARGV) 1650 sep->se_argv[argc++] = NULL; 1651 #ifdef IPSEC 1652 sep->se_policy = policy ? newstr(policy) : NULL; 1653 #endif 1654 return (sep); 1655 } 1656 1657 static void 1658 freeconfig(struct servtab *cp) 1659 { 1660 int i; 1661 1662 if (cp->se_hostaddr) 1663 free(cp->se_hostaddr); 1664 if (cp->se_service) 1665 free(cp->se_service); 1666 if (cp->se_proto) 1667 free(cp->se_proto); 1668 if (cp->se_user) 1669 free(cp->se_user); 1670 /* Note: se_group is part of the newstr'ed se_user */ 1671 if (cp->se_server) 1672 free(cp->se_server); 1673 for (i = 0; i < MAXARGV; i++) 1674 if (cp->se_argv[i]) 1675 free(cp->se_argv[i]); 1676 #ifdef IPSEC 1677 if (cp->se_policy) 1678 free(cp->se_policy); 1679 #endif 1680 } 1681 1682 1683 /* 1684 * Safe skip - if skip returns null, log a syntax error in the 1685 * configuration file and exit. 1686 */ 1687 static char * 1688 sskip(char **cpp) 1689 { 1690 char *cp; 1691 1692 cp = skip(cpp); 1693 if (cp == NULL) { 1694 syslog(LOG_ERR, "%s: syntax error", CONFIG); 1695 exit(1); 1696 } 1697 return (cp); 1698 } 1699 1700 static char * 1701 skip(char **cpp) 1702 { 1703 char *cp = *cpp; 1704 char *start; 1705 1706 if (*cpp == NULL) 1707 return (NULL); 1708 1709 again: 1710 while (*cp == ' ' || *cp == '\t') 1711 cp++; 1712 if (*cp == '\0') { 1713 int c; 1714 1715 c = getc(fconfig); 1716 (void) ungetc(c, fconfig); 1717 if (c == ' ' || c == '\t') 1718 if ((cp = nextline(fconfig))) 1719 goto again; 1720 *cpp = NULL; 1721 return (NULL); 1722 } 1723 start = cp; 1724 while (*cp && *cp != ' ' && *cp != '\t') 1725 cp++; 1726 if (*cp != '\0') 1727 *cp++ = '\0'; 1728 *cpp = cp; 1729 return (start); 1730 } 1731 1732 static char * 1733 nextline(FILE *fd) 1734 { 1735 char *cp; 1736 1737 if (fgets(line, sizeof (line), fd) == NULL) 1738 return (NULL); 1739 cp = strchr(line, '\n'); 1740 if (cp) 1741 *cp = '\0'; 1742 return (line); 1743 } 1744 1745 static char * 1746 newstr(char *cp) 1747 { 1748 if ((cp = strdup((cp !=NULL )? cp : "")) != NULL) 1749 return (cp); 1750 syslog(LOG_ERR, "strdup: %m"); 1751 exit(1); 1752 } 1753 1754 static void 1755 inetd_setproctitle(char *a, int s) 1756 { 1757 socklen_t size; 1758 struct sockaddr_storage ss; 1759 char hbuf[NI_MAXHOST]; 1760 1761 size = sizeof(ss); 1762 if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) { 1763 if (getnameinfo((struct sockaddr *)&ss, size, hbuf, 1764 sizeof(hbuf), NULL, 0, niflags) == 0) 1765 setproctitle("-%s [%s]", a, hbuf); 1766 else 1767 setproctitle("-%s [?]", a); 1768 } else 1769 setproctitle("-%s", a); 1770 } 1771 1772 static void 1773 bump_nofile(void) 1774 { 1775 #ifdef RLIMIT_NOFILE 1776 1777 #define FD_CHUNK 32 1778 1779 struct rlimit rl; 1780 1781 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1782 syslog(LOG_ERR, "getrlimit: %m"); 1783 return; 1784 } 1785 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1786 if (rl.rlim_cur <= rlim_ofile_cur) { 1787 syslog(LOG_ERR, 1788 "bump_nofile: cannot extend file limit, max = %d", 1789 (int)rl.rlim_cur); 1790 return; 1791 } 1792 1793 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1794 syslog(LOG_ERR, "setrlimit: %m"); 1795 return; 1796 } 1797 1798 rlim_ofile_cur = rl.rlim_cur; 1799 return; 1800 1801 #else 1802 syslog(LOG_ERR, "bump_nofile: cannot extend file limit"); 1803 return; 1804 #endif 1805 } 1806 1807 /* 1808 * Internet services provided internally by inetd: 1809 */ 1810 #define BUFSIZE 4096 1811 1812 /* ARGSUSED */ 1813 static void 1814 echo_stream(int s, struct servtab *sep) /* Echo service -- echo data back */ 1815 { 1816 char buffer[BUFSIZE]; 1817 int i; 1818 1819 inetd_setproctitle(sep->se_service, s); 1820 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1821 write(s, buffer, i) > 0) 1822 ; 1823 } 1824 1825 /* ARGSUSED */ 1826 static void 1827 echo_dg(int s, struct servtab *sep) /* Echo service -- echo data back */ 1828 { 1829 char buffer[BUFSIZE]; 1830 int i; 1831 socklen_t size; 1832 struct sockaddr_storage ss; 1833 struct sockaddr *sa; 1834 1835 sa = (struct sockaddr *)&ss; 1836 size = sizeof(ss); 1837 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, sa, &size)) < 0) 1838 return; 1839 if (port_good_dg(sa)) 1840 (void) sendto(s, buffer, i, 0, sa, size); 1841 } 1842 1843 /* ARGSUSED */ 1844 static void 1845 discard_stream(int s, struct servtab *sep) /* Discard service -- ignore data */ 1846 { 1847 char buffer[BUFSIZE]; 1848 1849 inetd_setproctitle(sep->se_service, s); 1850 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1851 errno == EINTR) 1852 ; 1853 } 1854 1855 /* ARGSUSED */ 1856 static void 1857 discard_dg(int s, struct servtab *sep) /* Discard service -- ignore data */ 1858 1859 { 1860 char buffer[BUFSIZE]; 1861 1862 (void) read(s, buffer, sizeof(buffer)); 1863 } 1864 1865 #include <ctype.h> 1866 #define LINESIZ 72 1867 char ring[128]; 1868 char *endring; 1869 1870 static void 1871 initring(void) 1872 { 1873 int i; 1874 1875 endring = ring; 1876 1877 for (i = 0; i <= 128; ++i) 1878 if (isprint(i)) 1879 *endring++ = i; 1880 } 1881 1882 /* ARGSUSED */ 1883 static void 1884 chargen_stream(int s,struct servtab *sep) /* Character generator */ 1885 { 1886 int len; 1887 char *rs, text[LINESIZ+2]; 1888 1889 inetd_setproctitle(sep->se_service, s); 1890 1891 if (!endring) { 1892 initring(); 1893 rs = ring; 1894 } 1895 1896 text[LINESIZ] = '\r'; 1897 text[LINESIZ + 1] = '\n'; 1898 for (rs = ring;;) { 1899 if ((len = endring - rs) >= LINESIZ) 1900 memmove(text, rs, LINESIZ); 1901 else { 1902 memmove(text, rs, len); 1903 memmove(text + len, ring, LINESIZ - len); 1904 } 1905 if (++rs == endring) 1906 rs = ring; 1907 if (write(s, text, sizeof(text)) != sizeof(text)) 1908 break; 1909 } 1910 } 1911 1912 /* ARGSUSED */ 1913 static void 1914 chargen_dg(int s, struct servtab *sep) /* Character generator */ 1915 { 1916 struct sockaddr_storage ss; 1917 struct sockaddr *sa; 1918 static char *rs; 1919 int len; 1920 socklen_t size; 1921 char text[LINESIZ+2]; 1922 1923 if (endring == 0) { 1924 initring(); 1925 rs = ring; 1926 } 1927 1928 sa = (struct sockaddr *)&ss; 1929 size = sizeof(ss); 1930 if (recvfrom(s, text, sizeof(text), 0, sa, &size) < 0) 1931 return; 1932 1933 if (!port_good_dg(sa)) 1934 return; 1935 1936 if ((len = endring - rs) >= LINESIZ) 1937 memmove(text, rs, LINESIZ); 1938 else { 1939 memmove(text, rs, len); 1940 memmove(text + len, ring, LINESIZ - len); 1941 } 1942 if (++rs == endring) 1943 rs = ring; 1944 text[LINESIZ] = '\r'; 1945 text[LINESIZ + 1] = '\n'; 1946 (void) sendto(s, text, sizeof(text), 0, sa, size); 1947 } 1948 1949 /* 1950 * Return a machine readable date and time, in the form of the 1951 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1952 * returns the number of seconds since midnight, Jan 1, 1970, 1953 * we must add 2208988800 seconds to this figure to make up for 1954 * some seventy years Bell Labs was asleep. 1955 */ 1956 1957 static uint32_t 1958 machtime(void) 1959 { 1960 struct timeval tv; 1961 1962 if (gettimeofday(&tv, NULL) < 0) { 1963 if (debug) 1964 fprintf(stderr, "Unable to get time of day\n"); 1965 return (0); 1966 } 1967 #define OFFSET ((uint32_t)25567 * 24*60*60) 1968 return (htonl((uint32_t)(tv.tv_sec + OFFSET))); 1969 #undef OFFSET 1970 } 1971 1972 /* ARGSUSED */ 1973 static void 1974 machtime_stream(int s, struct servtab *sep) 1975 { 1976 uint32_t result; 1977 1978 result = machtime(); 1979 (void) write(s, (char *) &result, sizeof(result)); 1980 } 1981 1982 /* ARGSUSED */ 1983 void 1984 machtime_dg(int s, struct servtab *sep) 1985 { 1986 uint32_t result; 1987 struct sockaddr_storage ss; 1988 struct sockaddr *sa; 1989 socklen_t size; 1990 1991 sa = (struct sockaddr *)&ss; 1992 size = sizeof(ss); 1993 if (recvfrom(s, (char *)&result, sizeof(result), 0, sa, &size) < 0) 1994 return; 1995 if (!port_good_dg(sa)) 1996 return; 1997 result = machtime(); 1998 (void) sendto(s, (char *) &result, sizeof(result), 0, sa, size); 1999 } 2000 2001 /* ARGSUSED */ 2002 static void 2003 daytime_stream(int s,struct servtab *sep) 2004 /* Return human-readable time of day */ 2005 { 2006 char buffer[256]; 2007 time_t clock; 2008 int len; 2009 2010 clock = time((time_t *) 0); 2011 2012 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 2013 (void) write(s, buffer, len); 2014 } 2015 2016 /* ARGSUSED */ 2017 void 2018 daytime_dg(int s, struct servtab *sep) 2019 /* Return human-readable time of day */ 2020 { 2021 char buffer[256]; 2022 time_t clock; 2023 struct sockaddr_storage ss; 2024 struct sockaddr *sa; 2025 socklen_t size; 2026 int len; 2027 2028 clock = time((time_t *) 0); 2029 2030 sa = (struct sockaddr *)&ss; 2031 size = sizeof(ss); 2032 if (recvfrom(s, buffer, sizeof(buffer), 0, sa, &size) < 0) 2033 return; 2034 if (!port_good_dg(sa)) 2035 return; 2036 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 2037 (void) sendto(s, buffer, len, 0, sa, size); 2038 } 2039 2040 /* 2041 * print_service: 2042 * Dump relevant information to stderr 2043 */ 2044 static void 2045 print_service(char *action, struct servtab *sep) 2046 { 2047 2048 if (isrpcservice(sep)) 2049 fprintf(stderr, 2050 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait:max=%d.%d, user:group=%s:%s builtin=%lx server=%s" 2051 #ifdef IPSEC 2052 " policy=\"%s\"" 2053 #endif 2054 "\n", 2055 action, sep->se_service, 2056 sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto, 2057 sep->se_wait, sep->se_max, sep->se_user, sep->se_group, 2058 (long)sep->se_bi, sep->se_server 2059 #ifdef IPSEC 2060 , (sep->se_policy ? sep->se_policy : "") 2061 #endif 2062 ); 2063 else 2064 fprintf(stderr, 2065 "%s: %s proto=%s%s, wait:max=%d.%d, user:group=%s:%s builtin=%lx server=%s" 2066 #ifdef IPSEC 2067 " policy=%s" 2068 #endif 2069 "\n", 2070 action, sep->se_service, 2071 sep->se_type == FAITH_TYPE ? "faith/" : "", 2072 sep->se_proto, 2073 sep->se_wait, sep->se_max, sep->se_user, sep->se_group, 2074 (long)sep->se_bi, sep->se_server 2075 #ifdef IPSEC 2076 , (sep->se_policy ? sep->se_policy : "") 2077 #endif 2078 ); 2079 } 2080 2081 static void 2082 usage(void) 2083 { 2084 #ifdef LIBWRAP 2085 (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname()); 2086 #else 2087 (void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname()); 2088 #endif 2089 exit(1); 2090 } 2091 2092 2093 /* 2094 * Based on TCPMUX.C by Mark K. Lottor November 1988 2095 * sri-nic::ps:<mkl>tcpmux.c 2096 */ 2097 2098 static int /* # of characters upto \r,\n or \0 */ 2099 getline(int fd, char *buf, int len) 2100 { 2101 int count = 0, n; 2102 2103 do { 2104 n = read(fd, buf, len-count); 2105 if (n == 0) 2106 return (count); 2107 if (n < 0) 2108 return (-1); 2109 while (--n >= 0) { 2110 if (*buf == '\r' || *buf == '\n' || *buf == '\0') 2111 return (count); 2112 count++; 2113 buf++; 2114 } 2115 } while (count < len); 2116 return (count); 2117 } 2118 2119 #define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ 2120 2121 #define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) 2122 2123 static void 2124 tcpmux(int ctrl, struct servtab *sep) 2125 { 2126 char service[MAX_SERV_LEN+1]; 2127 int len; 2128 2129 /* Get requested service name */ 2130 if ((len = getline(ctrl, service, MAX_SERV_LEN)) < 0) { 2131 strwrite(ctrl, "-Error reading service name\r\n"); 2132 goto reject; 2133 } 2134 service[len] = '\0'; 2135 2136 if (debug) 2137 fprintf(stderr, "tcpmux: someone wants %s\n", service); 2138 2139 /* 2140 * Help is a required command, and lists available services, 2141 * one per line. 2142 */ 2143 if (!strcasecmp(service, "help")) { 2144 strwrite(ctrl, "+Available services:\r\n"); 2145 strwrite(ctrl, "help\r\n"); 2146 for (sep = servtab; sep != NULL; sep = sep->se_next) { 2147 if (!ISMUX(sep)) 2148 continue; 2149 (void)write(ctrl, sep->se_service, 2150 strlen(sep->se_service)); 2151 strwrite(ctrl, "\r\n"); 2152 } 2153 goto reject; 2154 } 2155 2156 /* Try matching a service in inetd.conf with the request */ 2157 for (sep = servtab; sep != NULL; sep = sep->se_next) { 2158 if (!ISMUX(sep)) 2159 continue; 2160 if (!strcasecmp(service, sep->se_service)) { 2161 if (ISMUXPLUS(sep)) 2162 strwrite(ctrl, "+Go\r\n"); 2163 run_service(ctrl, sep); 2164 return; 2165 } 2166 } 2167 strwrite(ctrl, "-Service not available\r\n"); 2168 reject: 2169 _exit(1); 2170 } 2171 2172 #ifdef MULOG 2173 void 2174 dolog(struct servtab *sep, int ctrl) 2175 { 2176 struct sockaddr_storage ss; 2177 struct sockaddr *sa = (struct sockaddr *)&ss; 2178 socklen_t len = sizeof(ss); 2179 char *host, *dp, buf[BUFSIZ]; 2180 int connected = 1; 2181 2182 switch (sep->se_family) { 2183 case AF_INET: 2184 #ifdef INET6 2185 case AF_INET6: 2186 #endif 2187 break; 2188 default: 2189 return; 2190 } 2191 2192 if (getpeername(ctrl, sa, &len) < 0) { 2193 if (errno != ENOTCONN) { 2194 syslog(LOG_ERR, "getpeername: %m"); 2195 return; 2196 } 2197 if (recvfrom(ctrl, buf, sizeof(buf), MSG_PEEK, sa, &len) < 0) { 2198 syslog(LOG_ERR, "recvfrom: %m"); 2199 return; 2200 } 2201 connected = 0; 2202 } 2203 switch (sa->sa_family) { 2204 case AF_INET: 2205 #ifdef INET6 2206 case AF_INET6: 2207 #endif 2208 break; 2209 default: 2210 syslog(LOG_ERR, "unexpected address family %u", sa->sa_family); 2211 return; 2212 } 2213 2214 if (getnameinfo(sa, len, buf, sizeof(buf), NULL, 0, 0) != 0) 2215 strcpy(buf, "?"); 2216 host = buf; 2217 2218 switch (sep->se_log & ~MULOG_RFC931) { 2219 case 0: 2220 return; 2221 case 1: 2222 if (curdom == NULL || *curdom == '\0') 2223 break; 2224 dp = host + strlen(host) - strlen(curdom); 2225 if (dp < host) 2226 break; 2227 if (debug) 2228 fprintf(stderr, "check \"%s\" against curdom \"%s\"\n", 2229 host, curdom); 2230 if (strcasecmp(dp, curdom) == 0) 2231 return; 2232 break; 2233 case 2: 2234 default: 2235 break; 2236 } 2237 2238 openlog("", LOG_NOWAIT, MULOG); 2239 2240 if (connected && (sep->se_log & MULOG_RFC931)) 2241 syslog(LOG_INFO, "%s@%s wants %s", 2242 rfc931_name(sa, ctrl), host, sep->se_service); 2243 else 2244 syslog(LOG_INFO, "%s wants %s", 2245 host, sep->se_service); 2246 } 2247 2248 /* 2249 * From tcp_log by 2250 * Wietse Venema, Eindhoven University of Technology, The Netherlands. 2251 */ 2252 #if 0 2253 static char sccsid[] = "@(#) rfc931.c 1.3 92/08/31 22:54:46"; 2254 #endif 2255 2256 #include <setjmp.h> 2257 2258 #define RFC931_PORT 113 /* Semi-well-known port */ 2259 #define TIMEOUT 4 2260 #define TIMEOUT2 10 2261 2262 static jmp_buf timebuf; 2263 2264 /* timeout - handle timeouts */ 2265 2266 static void 2267 timeout(int sig) 2268 { 2269 longjmp(timebuf, sig); 2270 } 2271 2272 /* rfc931_name - return remote user name */ 2273 2274 char * 2275 rfc931_name(struct sockaddr *there, /* remote link information */ 2276 int ctrl) 2277 { 2278 struct sockaddr_storage here; /* local link information */ 2279 struct sockaddr_storage sin; /* for talking to RFC931 daemon */ 2280 socklen_t length; 2281 int s; 2282 unsigned remote; 2283 unsigned local; 2284 static char user[256]; /* XXX */ 2285 char buf[256]; 2286 char *cp; 2287 char *result = "USER_UNKNOWN"; 2288 int len; 2289 u_int16_t myport, hisport; 2290 2291 /* Find out local port number of our stdin. */ 2292 2293 length = sizeof(here); 2294 if (getsockname(ctrl, (struct sockaddr *) &here, &length) == -1) { 2295 syslog(LOG_ERR, "getsockname: %m"); 2296 return (result); 2297 } 2298 switch (here.ss_family) { 2299 case AF_INET: 2300 myport = ((struct sockaddr_in *)&here)->sin_port; 2301 break; 2302 #ifdef INET6 2303 case AF_INET6: 2304 myport = ((struct sockaddr_in6 *)&here)->sin6_port; 2305 break; 2306 #endif 2307 } 2308 switch (there->sa_family) { 2309 case AF_INET: 2310 hisport = ((struct sockaddr_in *)&there)->sin_port; 2311 break; 2312 #ifdef INET6 2313 case AF_INET6: 2314 hisport = ((struct sockaddr_in6 *)&there)->sin6_port; 2315 break; 2316 #endif 2317 } 2318 /* Set up timer so we won't get stuck. */ 2319 2320 if ((s = socket(here.ss_family, SOCK_STREAM, 0)) == -1) { 2321 syslog(LOG_ERR, "socket: %m"); 2322 return (result); 2323 } 2324 2325 sin = here; 2326 switch (sin.ss_family) { 2327 case AF_INET: 2328 ((struct sockaddr_in *)&sin)->sin_port = htons(0); 2329 break; 2330 #ifdef INET6 2331 case AF_INET6: 2332 ((struct sockaddr_in6 *)&sin)->sin6_port = htons(0); 2333 break; 2334 #endif 2335 } 2336 if (bind(s, (struct sockaddr *) &sin, sin.ss_len) == -1) { 2337 syslog(LOG_ERR, "bind: %m"); 2338 return (result); 2339 } 2340 2341 signal(SIGALRM, timeout); 2342 if (setjmp(timebuf)) { 2343 close(s); /* not: fclose(fp) */ 2344 return (result); 2345 } 2346 alarm(TIMEOUT); 2347 2348 /* Connect to the RFC931 daemon. */ 2349 2350 memcpy(&sin, there, there->sa_len); 2351 switch (sin.ss_family) { 2352 case AF_INET: 2353 ((struct sockaddr_in *)&sin)->sin_port = htons(RFC931_PORT); 2354 break; 2355 #ifdef INET6 2356 case AF_INET6: 2357 ((struct sockaddr_in6 *)&sin)->sin6_port = htons(RFC931_PORT); 2358 break; 2359 #endif 2360 } 2361 if (connect(s, (struct sockaddr *) &sin, sin.ss_len) == -1) { 2362 close(s); 2363 alarm(0); 2364 return (result); 2365 } 2366 2367 /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */ 2368 (void)snprintf(buf, sizeof buf, "%u,%u\r\n", ntohs(hisport), 2369 ntohs(myport)); 2370 2371 for (len = 0, cp = buf; len < strlen(buf); ) { 2372 int n; 2373 2374 if ((n = write(s, cp, strlen(buf) - len)) == -1) { 2375 close(s); 2376 alarm(0); 2377 return (result); 2378 } 2379 cp += n; 2380 len += n; 2381 } 2382 2383 /* Read response */ 2384 for (cp = buf; cp < buf + sizeof(buf) - 1; ) { 2385 char c; 2386 if (read(s, &c, 1) != 1) { 2387 close(s); 2388 alarm(0); 2389 return (result); 2390 } 2391 if (c == '\n') 2392 break; 2393 *cp++ = c; 2394 } 2395 *cp = '\0'; 2396 2397 if (sscanf(buf, "%u , %u : USERID :%*[^:]:%255s", &remote, &local, 2398 user) == 3 && ntohs(hisport) == remote && ntohs(myport) == local) { 2399 /* Strip trailing carriage return. */ 2400 if ((cp = strchr(user, '\r')) != NULL) 2401 *cp = 0; 2402 result = user; 2403 } 2404 2405 alarm(0); 2406 close(s); 2407 return (result); 2408 } 2409 #endif 2410 2411 /* 2412 * check if the address/port where send data to is one of the obvious ports 2413 * that are used for denial of service attacks like two echo ports 2414 * just echoing data between them 2415 */ 2416 static int 2417 port_good_dg(struct sockaddr *sa) 2418 { 2419 struct in_addr in; 2420 #ifdef INET6 2421 struct in6_addr *in6; 2422 #endif 2423 u_int16_t port; 2424 int i, bad; 2425 char hbuf[NI_MAXHOST]; 2426 2427 bad = 0; 2428 2429 switch (sa->sa_family) { 2430 case AF_INET: 2431 in.s_addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr); 2432 port = ntohs(((struct sockaddr_in *)sa)->sin_port); 2433 v4chk: 2434 if (IN_MULTICAST(in.s_addr)) 2435 goto bad; 2436 switch ((in.s_addr & 0xff000000) >> 24) { 2437 case 0: case 127: case 255: 2438 goto bad; 2439 } 2440 if (dg_broadcast(&in)) 2441 goto bad; 2442 break; 2443 #ifdef INET6 2444 case AF_INET6: 2445 in6 = &((struct sockaddr_in6 *)sa)->sin6_addr; 2446 port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port); 2447 if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6)) 2448 goto bad; 2449 if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) { 2450 memcpy(&in, &in6->s6_addr[12], sizeof(in)); 2451 in.s_addr = ntohl(in.s_addr); 2452 goto v4chk; 2453 } 2454 break; 2455 #endif 2456 default: 2457 /* XXX unsupported af, is it safe to assume it to be safe? */ 2458 return (1); 2459 } 2460 2461 for (i = 0; bad_ports[i] != 0; i++) { 2462 if (port == bad_ports[i]) 2463 goto bad; 2464 } 2465 2466 return (1); 2467 2468 bad: 2469 if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, 2470 niflags) != 0) 2471 strcpy(hbuf, "?"); 2472 syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d", 2473 hbuf, port); 2474 return (0); 2475 } 2476 2477 /* XXX need optimization */ 2478 static int 2479 dg_broadcast(struct in_addr *in) 2480 { 2481 struct ifaddrs *ifa, *ifap; 2482 struct sockaddr_in *sin; 2483 2484 if (getifaddrs(&ifap) < 0) 2485 return (0); 2486 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 2487 if (ifa->ifa_addr->sa_family != AF_INET || 2488 (ifa->ifa_flags & IFF_BROADCAST) == 0) 2489 continue; 2490 sin = (struct sockaddr_in *)ifa->ifa_broadaddr; 2491 if (sin->sin_addr.s_addr == in->s_addr) { 2492 freeifaddrs(ifap); 2493 return (1); 2494 } 2495 } 2496 freeifaddrs(ifap); 2497 return (0); 2498 } 2499 2500 static int 2501 my_kevent(const struct kevent *changelist, size_t nchanges, 2502 struct kevent *eventlist, size_t nevents) 2503 { 2504 int result; 2505 2506 while ((result = kevent(kq, changelist, nchanges, eventlist, nevents, 2507 NULL)) < 0) 2508 if (errno != EINTR) { 2509 syslog(LOG_ERR, "kevent: %m"); 2510 exit(EXIT_FAILURE); 2511 } 2512 2513 return (result); 2514 } 2515 2516 static struct kevent * 2517 allocchange(void) 2518 { 2519 if (changes == A_CNT(changebuf)) { 2520 (void) my_kevent(changebuf, A_CNT(changebuf), NULL, 0); 2521 changes = 0; 2522 } 2523 2524 return (&changebuf[changes++]); 2525 } 2526