inetd.c revision 1.133
1/* $NetBSD: inetd.c,v 1.133 2021/09/03 19:33:51 rillig 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 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33/* 34 * Copyright (c) 1983, 1991, 1993, 1994 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 */ 61 62#include <sys/cdefs.h> 63#ifndef lint 64__COPYRIGHT("@(#) Copyright (c) 1983, 1991, 1993, 1994\ 65 The Regents of the University of California. All rights reserved."); 66#if 0 67static char sccsid[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94"; 68#else 69__RCSID("$NetBSD: inetd.c,v 1.133 2021/09/03 19:33:51 rillig Exp $"); 70#endif 71#endif /* not lint */ 72 73/* 74 * Inetd - Internet super-server 75 * 76 * This program invokes all internet services as needed. Connection-oriented 77 * services are invoked each time a connection is made, by creating a process. 78 * This process is passed the connection as file descriptor 0 and is expected 79 * to do a getpeername to find out the source host and port. 80 * 81 * Datagram oriented services are invoked when a datagram 82 * arrives; a process is created and passed a pending message 83 * on file descriptor 0. Datagram servers may either connect 84 * to their peer, freeing up the original socket for inetd 85 * to receive further messages on, or ``take over the socket'', 86 * processing all arriving datagrams and, eventually, timing 87 * out. The first type of server is said to be ``multi-threaded''; 88 * the second type of server ``single-threaded''. 89 * 90 * Inetd uses a configuration file which is read at startup 91 * and, possibly, at some later time in response to a hangup signal. 92 * The configuration file is ``free format'' with fields given in the 93 * order shown below. Continuation lines for an entry must being with 94 * a space or tab. All fields must be present in each entry. 95 * 96 * service name must be in /etc/services or must 97 * name a tcpmux service 98 * socket type[:accf[,arg]] stream/dgram/raw/rdm/seqpacket, 99 only stream can name an accept filter 100 * protocol must be in /etc/protocols 101 * wait/nowait[:max] single-threaded/multi-threaded, max # 102 * user[:group] user/group to run daemon as 103 * server program full path name 104 * server program arguments maximum of MAXARGV (64) 105 * 106 * For RPC services 107 * service name/version must be in /etc/rpc 108 * socket type stream/dgram/raw/rdm/seqpacket 109 * protocol must be in /etc/protocols 110 * wait/nowait[:max] single-threaded/multi-threaded 111 * user[:group] user to run daemon as 112 * server program full path name 113 * server program arguments maximum of MAXARGV (64) 114 * 115 * For non-RPC services, the "service name" can be of the form 116 * hostaddress:servicename, in which case the hostaddress is used 117 * as the host portion of the address to listen on. If hostaddress 118 * consists of a single `*' character, INADDR_ANY is used. 119 * 120 * A line can also consist of just 121 * hostaddress: 122 * where hostaddress is as in the preceding paragraph. Such a line must 123 * have no further fields; the specified hostaddress is remembered and 124 * used for all further lines that have no hostaddress specified, 125 * until the next such line (or EOF). (This is why * is provided to 126 * allow explicit specification of INADDR_ANY.) A line 127 * *: 128 * is implicitly in effect at the beginning of the file. 129 * 130 * The hostaddress specifier may (and often will) contain dots; 131 * the service name must not. 132 * 133 * For RPC services, host-address specifiers are accepted and will 134 * work to some extent; however, because of limitations in the 135 * portmapper interface, it will not work to try to give more than 136 * one line for any given RPC service, even if the host-address 137 * specifiers are different. 138 * 139 * TCP services without official port numbers are handled with the 140 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for 141 * requests. When a connection is made from a foreign host, the service 142 * requested is passed to tcpmux, which looks it up in the servtab list 143 * and returns the proper entry for the service. Tcpmux returns a 144 * negative reply if the service doesn't exist, otherwise the invoked 145 * server is expected to return the positive reply if the service type in 146 * inetd.conf file has the prefix "tcpmux/". If the service type has the 147 * prefix "tcpmux/+", tcpmux will return the positive reply for the 148 * process; this is for compatibility with older server code, and also 149 * allows you to invoke programs that use stdin/stdout without putting any 150 * special server code in them. Services that use tcpmux are "nowait" 151 * because they do not have a well-known port and hence cannot listen 152 * for new requests. 153 * 154 * Comment lines are indicated by a `#' in column 1. 155 * 156 * #ifdef IPSEC 157 * Comment lines that start with "#@" denote IPsec policy string, as described 158 * in ipsec_set_policy(3). This will affect all the following items in 159 * inetd.conf(8). To reset the policy, just use "#@" line. By default, 160 * there's no IPsec policy. 161 * #endif 162 */ 163 164/* 165 * Here's the scoop concerning the user:group feature: 166 * 167 * 1) set-group-option off. 168 * 169 * a) user = root: NO setuid() or setgid() is done 170 * 171 * b) other: setuid() 172 * setgid(primary group as found in passwd) 173 * initgroups(name, primary group) 174 * 175 * 2) set-group-option on. 176 * 177 * a) user = root: NO setuid() 178 * setgid(specified group) 179 * NO initgroups() 180 * 181 * b) other: setuid() 182 * setgid(specified group) 183 * initgroups(name, specified group) 184 * 185 */ 186 187#include <sys/param.h> 188#include <sys/stat.h> 189#include <sys/ioctl.h> 190#include <sys/wait.h> 191#include <sys/resource.h> 192#include <sys/event.h> 193#include <sys/socket.h> 194 195 196#ifndef NO_RPC 197#define RPC 198#endif 199 200#include <net/if.h> 201 202#ifdef RPC 203#include <rpc/rpc.h> 204#include <rpc/rpcb_clnt.h> 205#include <netconfig.h> 206#endif 207 208#include <ctype.h> 209#include <err.h> 210#include <errno.h> 211#include <fcntl.h> 212#include <glob.h> 213#include <grp.h> 214#include <libgen.h> 215#include <pwd.h> 216#include <signal.h> 217#include <stdio.h> 218#include <stdlib.h> 219#include <string.h> 220#include <syslog.h> 221#include <unistd.h> 222#include <util.h> 223#include <ifaddrs.h> 224 225#include "inetd.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 CNT_INTVL ((time_t)60) /* servers in CNT_INTVL sec. */ 246#define RETRYTIME (60*10) /* retry after bind or server fail */ 247 248int debug; 249#ifdef LIBWRAP 250int lflag; 251#endif 252int maxsock; 253int kq; 254int options; 255int timingout; 256const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; 257 258#ifndef OPEN_MAX 259#define OPEN_MAX 64 260#endif 261 262/* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ 263#define FD_MARGIN (8) 264rlim_t rlim_ofile_cur = OPEN_MAX; 265 266struct rlimit rlim_ofile; 267 268struct kevent changebuf[64]; 269size_t changes; 270 271struct servtab *servtab; 272 273static void chargen_dg(int, struct servtab *); 274static void chargen_stream(int, struct servtab *); 275static void close_sep(struct servtab *); 276static void config(void); 277static void daytime_dg(int, struct servtab *); 278static void daytime_stream(int, struct servtab *); 279static void discard_dg(int, struct servtab *); 280static void discard_stream(int, struct servtab *); 281static void echo_dg(int, struct servtab *); 282static void echo_stream(int, struct servtab *); 283static void endconfig(void); 284static struct servtab *enter(struct servtab *); 285static struct servtab *getconfigent(char **); 286__dead static void goaway(void); 287static void machtime_dg(int, struct servtab *); 288static void machtime_stream(int, struct servtab *); 289#ifdef DEBUG_ENABLE 290static void print_service(const char *, struct servtab *); 291#endif 292static void reapchild(void); 293static void retry(void); 294static void run_service(int, struct servtab *, int); 295static void setup(struct servtab *); 296static char *skip(char **); 297static void tcpmux(int, struct servtab *); 298__dead static void usage(void); 299static void register_rpc(struct servtab *); 300static void unregister_rpc(struct servtab *); 301static void bump_nofile(void); 302static void inetd_setproctitle(char *, int); 303static void initring(void); 304static uint32_t machtime(void); 305static int port_good_dg(struct sockaddr *); 306static int dg_broadcast(struct in_addr *); 307static int my_kevent(const struct kevent *, size_t, struct kevent *, size_t); 308static struct kevent *allocchange(void); 309static int get_line(int, char *, int); 310static void spawn(struct servtab *, int); 311static struct servtab init_servtab(void); 312static int rl_process(struct servtab *, int); 313static struct se_ip_list_node *rl_add(struct servtab *, char *); 314static void rl_reset(struct servtab *, time_t); 315static struct se_ip_list_node *rl_try_get_ip(struct servtab *, char *); 316static void include_configs(char *); 317static int glob_error(const char *, int); 318static void read_glob_configs(char *); 319static void prepare_next_config(const char*); 320static bool is_same_service(const struct servtab *, const struct servtab *); 321static char *gen_file_pattern(const char *, const char *); 322static bool check_no_reinclude(const char *); 323static void include_matched_path(char *); 324static void purge_unchecked(void); 325static void config_root(void); 326static void clear_ip_list(struct servtab *); 327static time_t rl_time(void); 328static void rl_get_name(struct servtab *, int, char *); 329static void rl_drop_connection(struct servtab *, int); 330 331struct biltin { 332 const char *bi_service; /* internally provided service name */ 333 int bi_socktype; /* type of socket supported */ 334 short bi_fork; /* 1 if should fork before call */ 335 short bi_wait; /* 1 if should wait for child */ 336 void (*bi_fn)(int, struct servtab *); 337 /* function which performs it */ 338} biltins[] = { 339 /* Echo received data */ 340 { "echo", SOCK_STREAM, 1, 0, echo_stream }, 341 { "echo", SOCK_DGRAM, 0, 0, echo_dg }, 342 343 /* Internet /dev/null */ 344 { "discard", SOCK_STREAM, 1, 0, discard_stream }, 345 { "discard", SOCK_DGRAM, 0, 0, discard_dg }, 346 347 /* Return 32 bit time since 1970 */ 348 { "time", SOCK_STREAM, 0, 0, machtime_stream }, 349 { "time", SOCK_DGRAM, 0, 0, machtime_dg }, 350 351 /* Return human-readable time */ 352 { "daytime", SOCK_STREAM, 0, 0, daytime_stream }, 353 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg }, 354 355 /* Familiar character generator */ 356 { "chargen", SOCK_STREAM, 1, 0, chargen_stream }, 357 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg }, 358 359 { "tcpmux", SOCK_STREAM, 1, 0, tcpmux }, 360 361 { NULL, 0, 0, 0, NULL } 362}; 363 364/* list of "bad" ports. I.e. ports that are most obviously used for 365 * "cycling packets" denial of service attacks. See /etc/services. 366 * List must end with port number "0". 367 */ 368 369u_int16_t bad_ports[] = { 7, 9, 13, 19, 37, 0 }; 370 371 372#define NUMINT (sizeof(intab) / sizeof(struct inent)) 373const char *CONFIG = _PATH_INETDCONF; 374 375static int my_signals[] = 376 { SIGALRM, SIGHUP, SIGCHLD, SIGTERM, SIGINT, SIGPIPE }; 377 378int 379main(int argc, char *argv[]) 380{ 381 int ch, n, reload = 1; 382 383 while ((ch = getopt(argc, argv, 384#ifdef LIBWRAP 385 "dl" 386#else 387 "d" 388#endif 389 )) != -1) 390 switch(ch) { 391 case 'd': 392 debug = 1; 393 options |= SO_DEBUG; 394 break; 395#ifdef LIBWRAP 396 case 'l': 397 lflag = 1; 398 break; 399#endif 400 case '?': 401 default: 402 usage(); 403 } 404 argc -= optind; 405 argv += optind; 406 407 if (argc > 0) 408 CONFIG = argv[0]; 409 410 if (!debug) 411 daemon(0, 0); 412 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); 413 pidfile(NULL); 414 415 kq = kqueue(); 416 if (kq < 0) { 417 syslog(LOG_ERR, "kqueue: %m"); 418 return (EXIT_FAILURE); 419 } 420 421 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) { 422 syslog(LOG_ERR, "getrlimit: %m"); 423 } else { 424 rlim_ofile_cur = rlim_ofile.rlim_cur; 425 if (rlim_ofile_cur == RLIM_INFINITY) /* ! */ 426 rlim_ofile_cur = OPEN_MAX; 427 } 428 429 for (n = 0; n < (int)__arraycount(my_signals); n++) { 430 int signum; 431 432 signum = my_signals[n]; 433 if (signum != SIGCHLD) 434 (void) signal(signum, SIG_IGN); 435 436 if (signum != SIGPIPE) { 437 struct kevent *ev; 438 439 ev = allocchange(); 440 EV_SET(ev, signum, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 441 0, 0, 0); 442 } 443 } 444 445 for (;;) { 446 int ctrl; 447 struct kevent eventbuf[64], *ev; 448 struct servtab *sep; 449 450 if (reload) { 451 reload = 0; 452 config_root(); 453 } 454 455 n = my_kevent(changebuf, changes, eventbuf, __arraycount(eventbuf)); 456 changes = 0; 457 458 for (ev = eventbuf; n > 0; ev++, n--) { 459 if (ev->filter == EVFILT_SIGNAL) { 460 switch (ev->ident) { 461 case SIGALRM: 462 retry(); 463 break; 464 case SIGCHLD: 465 reapchild(); 466 break; 467 case SIGTERM: 468 case SIGINT: 469 goaway(); 470 break; 471 case SIGHUP: 472 reload = 1; 473 break; 474 } 475 continue; 476 } 477 if (ev->filter != EVFILT_READ) 478 continue; 479 sep = (struct servtab *)ev->udata; 480 /* Paranoia */ 481 if ((int)ev->ident != sep->se_fd) 482 continue; 483 DPRINTF(SERV_FMT ": service requested" , SERV_PARAMS(sep)); 484 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 485 /* XXX here do the libwrap check-before-accept*/ 486 ctrl = accept(sep->se_fd, NULL, NULL); 487 DPRINTF(SERV_FMT ": accept, ctrl fd %d", 488 SERV_PARAMS(sep), ctrl); 489 if (ctrl < 0) { 490 if (errno != EINTR) 491 syslog(LOG_WARNING, 492 SERV_FMT ": accept: %m", 493 SERV_PARAMS(sep)); 494 continue; 495 } 496 } else 497 ctrl = sep->se_fd; 498 spawn(sep, ctrl); 499 } 500 } 501} 502 503static void 504spawn(struct servtab *sep, int ctrl) 505{ 506 int dofork; 507 pid_t pid; 508 509 pid = 0; 510#ifdef LIBWRAP_INTERNAL 511 dofork = 1; 512#else 513 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 514#endif 515 if (dofork) { 516 if (rl_process(sep, ctrl)) { 517 return; 518 } 519 pid = fork(); 520 if (pid < 0) { 521 syslog(LOG_ERR, "fork: %m"); 522 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 523 close(ctrl); 524 sleep(1); 525 return; 526 } 527 if (pid != 0 && sep->se_wait) { 528 struct kevent *ev; 529 530 sep->se_wait = pid; 531 ev = allocchange(); 532 EV_SET(ev, sep->se_fd, EVFILT_READ, 533 EV_DELETE, 0, 0, 0); 534 } 535 if (pid == 0) { 536 size_t n; 537 538 for (n = 0; n < __arraycount(my_signals); n++) 539 (void) signal(my_signals[n], SIG_DFL); 540 if (debug) 541 setsid(); 542 } 543 } 544 if (pid == 0) { 545 run_service(ctrl, sep, dofork); 546 if (dofork) 547 exit(0); 548 } 549 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 550 close(ctrl); 551} 552 553static void 554run_service(int ctrl, struct servtab *sep, int didfork) 555{ 556 struct passwd *pwd; 557 struct group *grp = NULL; /* XXX gcc */ 558 char buf[NI_MAXSERV]; 559 struct servtab *s; 560#ifdef LIBWRAP 561 char abuf[BUFSIZ]; 562 struct request_info req; 563 int denied; 564 char *service = NULL; /* XXX gcc */ 565#endif 566 567#ifdef LIBWRAP 568#ifndef LIBWRAP_INTERNAL 569 if (sep->se_bi == 0) 570#endif 571 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 572 request_init(&req, RQ_DAEMON, sep->se_argv[0] ? 573 sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL); 574 fromhost(&req); 575 denied = !hosts_access(&req); 576 if (denied || lflag) { 577 if (getnameinfo(&sep->se_ctrladdr, 578 (socklen_t)sep->se_ctrladdr.sa_len, NULL, 0, 579 buf, sizeof(buf), 0) != 0) { 580 /* shouldn't happen */ 581 (void)snprintf(buf, sizeof buf, "%d", 582 ntohs(sep->se_ctrladdr_in.sin_port)); 583 } 584 service = buf; 585 if (req.client->sin) { 586 sockaddr_snprintf(abuf, sizeof(abuf), "%a", 587 req.client->sin); 588 } else { 589 strcpy(abuf, "(null)"); 590 } 591 } 592 if (denied) { 593 syslog(deny_severity, 594 "refused connection from %.500s(%s), service %s (%s)", 595 eval_client(&req), abuf, service, sep->se_proto); 596 goto reject; 597 } 598 if (lflag) { 599 syslog(allow_severity, 600 "connection from %.500s(%s), service %s (%s)", 601 eval_client(&req), abuf, service, sep->se_proto); 602 } 603 } 604#endif /* LIBWRAP */ 605 606 if (sep->se_bi) { 607 if (didfork) { 608 for (s = servtab; s; s = s->se_next) 609 if (s->se_fd != -1 && s->se_fd != ctrl) { 610 close(s->se_fd); 611 s->se_fd = -1; 612 } 613 } 614 (*sep->se_bi->bi_fn)(ctrl, sep); 615 } else { 616 if ((pwd = getpwnam(sep->se_user)) == NULL) { 617 syslog(LOG_ERR, "%s/%s: %s: No such user", 618 sep->se_service, sep->se_proto, sep->se_user); 619 goto reject; 620 } 621 if (sep->se_group && 622 (grp = getgrnam(sep->se_group)) == NULL) { 623 syslog(LOG_ERR, "%s/%s: %s: No such group", 624 sep->se_service, sep->se_proto, sep->se_group); 625 goto reject; 626 } 627 if (pwd->pw_uid) { 628 if (sep->se_group) 629 pwd->pw_gid = grp->gr_gid; 630 if (setgid(pwd->pw_gid) < 0) { 631 syslog(LOG_ERR, 632 "%s/%s: can't set gid %d: %m", sep->se_service, 633 sep->se_proto, pwd->pw_gid); 634 goto reject; 635 } 636 (void) initgroups(pwd->pw_name, 637 pwd->pw_gid); 638 if (setuid(pwd->pw_uid) < 0) { 639 syslog(LOG_ERR, 640 "%s/%s: can't set uid %d: %m", sep->se_service, 641 sep->se_proto, pwd->pw_uid); 642 goto reject; 643 } 644 } else if (sep->se_group) { 645 (void) setgid((gid_t)grp->gr_gid); 646 } 647 DPRINTF("%d execl %s", 648 getpid(), sep->se_server); 649 /* Set our control descriptor to not close-on-exec... */ 650 if (fcntl(ctrl, F_SETFD, 0) < 0) 651 syslog(LOG_ERR, "fcntl (%d, F_SETFD, 0): %m", ctrl); 652 /* ...and dup it to stdin, stdout, and stderr. */ 653 if (ctrl != 0) { 654 dup2(ctrl, 0); 655 close(ctrl); 656 ctrl = 0; 657 } 658 dup2(0, 1); 659 dup2(0, 2); 660 if (rlim_ofile.rlim_cur != rlim_ofile_cur && 661 setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) 662 syslog(LOG_ERR, "setrlimit: %m"); 663 execv(sep->se_server, sep->se_argv); 664 syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server); 665 reject: 666 if (sep->se_socktype != SOCK_STREAM) 667 recv(ctrl, buf, sizeof (buf), 0); 668 _exit(EXIT_FAILURE); 669 } 670} 671 672static void 673reapchild(void) 674{ 675 int status; 676 pid_t pid; 677 struct servtab *sep; 678 679 for (;;) { 680 pid = wait3(&status, WNOHANG, NULL); 681 if (pid <= 0) 682 break; 683 DPRINTF("%d reaped, status %#x", pid, status); 684 for (sep = servtab; sep != NULL; sep = sep->se_next) 685 if (sep->se_wait == pid) { 686 struct kevent *ev; 687 688 if (WIFEXITED(status) && WEXITSTATUS(status)) 689 syslog(LOG_WARNING, 690 "%s: exit status %u", 691 sep->se_server, WEXITSTATUS(status)); 692 else if (WIFSIGNALED(status)) 693 syslog(LOG_WARNING, 694 "%s: exit signal %u", 695 sep->se_server, WTERMSIG(status)); 696 sep->se_wait = 1; 697 ev = allocchange(); 698 EV_SET(ev, sep->se_fd, EVFILT_READ, 699 EV_ADD | EV_ENABLE, 0, 0, (intptr_t)sep); 700 DPRINTF("restored %s, fd %d", 701 sep->se_service, sep->se_fd); 702 } 703 } 704} 705 706size_t line_number; 707 708/* 709 * Recursively merge loaded service definitions with any defined 710 * in the current or included config files. 711 */ 712static void 713config(void) 714{ 715 struct servtab *sep, *cp; 716 /* 717 * Current position in line, used with key-values notation, 718 * saves cp across getconfigent calls. 719 */ 720 char *current_pos; 721 size_t n; 722 723 /* open config file from beginning */ 724 fconfig = fopen(CONFIG, "r"); 725 if(fconfig == NULL) { 726 syslog(LOG_ERR, "%s: %m", CONFIG); 727 return; 728 } 729 730 /* First call to nextline will advance line_number to 1 */ 731 line_number = 0; 732 733 /* Start parsing at the beginning of the first line */ 734 current_pos = nextline(fconfig); 735 736 while ((cp = getconfigent(¤t_pos)) != NULL) { 737 /* Find an already existing service definition */ 738 for (sep = servtab; sep != NULL; sep = sep->se_next) 739 if (is_same_service(sep, cp)) 740 break; 741 if (sep != NULL) { 742 int i; 743 744#define SWAP(type, a, b) {type c = a; a = b; b = c;} 745 746 /* 747 * sep->se_wait may be holding the pid of a daemon 748 * that we're waiting for. If so, don't overwrite 749 * it unless the config file explicitly says don't 750 * wait. 751 */ 752 if (cp->se_bi == 0 && 753 (sep->se_wait == 1 || cp->se_wait == 0)) 754 sep->se_wait = cp->se_wait; 755 SWAP(char *, sep->se_user, cp->se_user); 756 SWAP(char *, sep->se_group, cp->se_group); 757 SWAP(char *, sep->se_server, cp->se_server); 758 for (i = 0; i < MAXARGV; i++) 759 SWAP(char *, sep->se_argv[i], cp->se_argv[i]); 760#ifdef IPSEC 761 SWAP(char *, sep->se_policy, cp->se_policy); 762#endif 763 SWAP(service_type, cp->se_type, sep->se_type); 764 SWAP(size_t, cp->se_service_max, sep->se_service_max); 765 SWAP(size_t, cp->se_ip_max, sep->se_ip_max); 766#undef SWAP 767 if (isrpcservice(sep)) 768 unregister_rpc(sep); 769 sep->se_rpcversl = cp->se_rpcversl; 770 sep->se_rpcversh = cp->se_rpcversh; 771 freeconfig(cp); 772#ifdef DEBUG_ENABLE 773 if (debug) 774 print_service("REDO", sep); 775#endif 776 } else { 777 sep = enter(cp); 778#ifdef DEBUG_ENABLE 779 if (debug) 780 print_service("ADD ", sep); 781#endif 782 } 783 sep->se_checked = 1; 784 785 /* 786 * Remainder of config(void) checks validity of servtab options 787 * and sets up the service by setting up sockets (in setup(servtab)). 788 */ 789 switch (sep->se_family) { 790 case AF_LOCAL: 791 if (sep->se_fd != -1) 792 break; 793 n = strlen(sep->se_service); 794 if (n >= sizeof(sep->se_ctrladdr_un.sun_path)) { 795 syslog(LOG_ERR, "%s/%s: address too long", 796 sep->se_service, sep->se_proto); 797 sep->se_checked = 0; 798 continue; 799 } 800 (void)unlink(sep->se_service); 801 strlcpy(sep->se_ctrladdr_un.sun_path, 802 sep->se_service, n + 1); 803 sep->se_ctrladdr_un.sun_family = AF_LOCAL; 804 sep->se_ctrladdr_size = (socklen_t)(n + 805 sizeof(sep->se_ctrladdr_un) - 806 sizeof(sep->se_ctrladdr_un.sun_path)); 807 if (!ISMUX(sep)) 808 setup(sep); 809 break; 810 case AF_INET: 811#ifdef INET6 812 case AF_INET6: 813#endif 814 { 815 struct addrinfo hints, *res; 816 char *host; 817 const char *port; 818 int error; 819 int s; 820 821 /* check if the family is supported */ 822 s = socket(sep->se_family, SOCK_DGRAM, 0); 823 if (s < 0) { 824 syslog(LOG_WARNING, 825 "%s/%s: %s: the address family is not " 826 "supported by the kernel", 827 sep->se_service, sep->se_proto, 828 sep->se_hostaddr); 829 sep->se_checked = 0; 830 continue; 831 } 832 close(s); 833 834 memset(&hints, 0, sizeof(hints)); 835 hints.ai_family = sep->se_family; 836 hints.ai_socktype = sep->se_socktype; 837 hints.ai_flags = AI_PASSIVE; 838 if (!strcmp(sep->se_hostaddr, "*")) 839 host = NULL; 840 else 841 host = sep->se_hostaddr; 842 if (isrpcservice(sep) || ISMUX(sep)) 843 port = "0"; 844 else 845 port = sep->se_service; 846 error = getaddrinfo(host, port, &hints, &res); 847 if (error) { 848 if (error == EAI_SERVICE) { 849 /* gai_strerror not friendly enough */ 850 syslog(LOG_WARNING, SERV_FMT ": " 851 "unknown service", 852 SERV_PARAMS(sep)); 853 } else { 854 syslog(LOG_ERR, SERV_FMT ": %s: %s", 855 SERV_PARAMS(sep), 856 sep->se_hostaddr, 857 gai_strerror(error)); 858 } 859 sep->se_checked = 0; 860 continue; 861 } 862 if (res->ai_next) { 863 syslog(LOG_ERR, 864 SERV_FMT ": %s: resolved to multiple addr", 865 SERV_PARAMS(sep), 866 sep->se_hostaddr); 867 sep->se_checked = 0; 868 freeaddrinfo(res); 869 continue; 870 } 871 memcpy(&sep->se_ctrladdr, res->ai_addr, 872 res->ai_addrlen); 873 if (ISMUX(sep)) { 874 sep->se_fd = -1; 875 freeaddrinfo(res); 876 continue; 877 } 878 sep->se_ctrladdr_size = res->ai_addrlen; 879 freeaddrinfo(res); 880#ifdef RPC 881 if (isrpcservice(sep)) { 882 struct rpcent *rp; 883 884 sep->se_rpcprog = atoi(sep->se_service); 885 if (sep->se_rpcprog == 0) { 886 rp = getrpcbyname(sep->se_service); 887 if (rp == 0) { 888 syslog(LOG_ERR, 889 SERV_FMT 890 ": unknown service", 891 SERV_PARAMS(sep)); 892 sep->se_checked = 0; 893 continue; 894 } 895 sep->se_rpcprog = rp->r_number; 896 } 897 if (sep->se_fd == -1 && !ISMUX(sep)) 898 setup(sep); 899 if (sep->se_fd != -1) 900 register_rpc(sep); 901 } else 902#endif 903 { 904 if (sep->se_fd >= 0) 905 close_sep(sep); 906 if (sep->se_fd == -1 && !ISMUX(sep)) 907 setup(sep); 908 } 909 } 910 } 911 } 912 endconfig(); 913} 914 915static void 916retry(void) 917{ 918 struct servtab *sep; 919 920 timingout = 0; 921 for (sep = servtab; sep != NULL; sep = sep->se_next) { 922 if (sep->se_fd == -1 && !ISMUX(sep)) { 923 switch (sep->se_family) { 924 case AF_LOCAL: 925 case AF_INET: 926#ifdef INET6 927 case AF_INET6: 928#endif 929 setup(sep); 930 if (sep->se_fd >= 0 && isrpcservice(sep)) 931 register_rpc(sep); 932 break; 933 } 934 } 935 } 936} 937 938static void 939goaway(void) 940{ 941 struct servtab *sep; 942 943 for (sep = servtab; sep != NULL; sep = sep->se_next) { 944 if (sep->se_fd == -1) 945 continue; 946 947 switch (sep->se_family) { 948 case AF_LOCAL: 949 (void)unlink(sep->se_service); 950 break; 951 case AF_INET: 952#ifdef INET6 953 case AF_INET6: 954#endif 955 if (sep->se_wait == 1 && isrpcservice(sep)) 956 unregister_rpc(sep); 957 break; 958 } 959 (void)close(sep->se_fd); 960 sep->se_fd = -1; 961 } 962 exit(0); 963} 964 965static void 966setup(struct servtab *sep) 967{ 968 int on = 1; 969#ifdef INET6 970 int off = 0; 971#endif 972 struct kevent *ev; 973 974 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 975 DPRINTF("socket failed on " SERV_FMT ": %s", 976 SERV_PARAMS(sep), strerror(errno)); 977 syslog(LOG_ERR, "%s/%s: socket: %m", 978 sep->se_service, sep->se_proto); 979 return; 980 } 981 /* Set all listening sockets to close-on-exec. */ 982 if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) { 983 syslog(LOG_ERR, SERV_FMT ": fcntl(F_SETFD, FD_CLOEXEC): %m", 984 SERV_PARAMS(sep)); 985 close(sep->se_fd); 986 sep->se_fd = -1; 987 return; 988 } 989 990#define turnon(fd, opt) \ 991setsockopt(fd, SOL_SOCKET, opt, &on, (socklen_t)sizeof(on)) 992 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 993 turnon(sep->se_fd, SO_DEBUG) < 0) 994 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 995 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 996 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 997#undef turnon 998 999 /* Set the socket buffer sizes, if specified. */ 1000 if (sep->se_sndbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET, 1001 SO_SNDBUF, &sep->se_sndbuf, (socklen_t)sizeof(sep->se_sndbuf)) < 0) 1002 syslog(LOG_ERR, "setsockopt (SO_SNDBUF %d): %m", 1003 sep->se_sndbuf); 1004 if (sep->se_rcvbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET, 1005 SO_RCVBUF, &sep->se_rcvbuf, (socklen_t)sizeof(sep->se_rcvbuf)) < 0) 1006 syslog(LOG_ERR, "setsockopt (SO_RCVBUF %d): %m", 1007 sep->se_rcvbuf); 1008#ifdef INET6 1009 if (sep->se_family == AF_INET6) { 1010 int *v; 1011 v = (sep->se_type == FAITH_TYPE) ? &on : &off; 1012 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, 1013 v, (socklen_t)sizeof(*v)) < 0) 1014 syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m"); 1015 } 1016#endif 1017#ifdef IPSEC 1018 /* Avoid setting a policy if a policy specifier doesn't exist. */ 1019 if (sep->se_policy != NULL) { 1020 int e = ipsecsetup(sep->se_family, sep->se_fd, sep->se_policy); 1021 if (e < 0) { 1022 syslog(LOG_ERR, SERV_FMT ": ipsec setup failed", 1023 SERV_PARAMS(sep)); 1024 (void)close(sep->se_fd); 1025 sep->se_fd = -1; 1026 return; 1027 } 1028 } 1029#endif 1030 1031 if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) { 1032 DPRINTF(SERV_FMT ": bind failed: %s", 1033 SERV_PARAMS(sep), strerror(errno)); 1034 syslog(LOG_ERR, SERV_FMT ": bind: %m", 1035 SERV_PARAMS(sep)); 1036 (void) close(sep->se_fd); 1037 sep->se_fd = -1; 1038 if (!timingout) { 1039 timingout = 1; 1040 alarm(RETRYTIME); 1041 } 1042 return; 1043 } 1044 if (sep->se_socktype == SOCK_STREAM) 1045 listen(sep->se_fd, 10); 1046 1047 /* Set the accept filter, if specified. To be done after listen.*/ 1048 if (sep->se_accf.af_name[0] != 0 && setsockopt(sep->se_fd, SOL_SOCKET, 1049 SO_ACCEPTFILTER, &sep->se_accf, 1050 (socklen_t)sizeof(sep->se_accf)) < 0) 1051 syslog(LOG_ERR, "setsockopt(SO_ACCEPTFILTER %s): %m", 1052 sep->se_accf.af_name); 1053 1054 ev = allocchange(); 1055 EV_SET(ev, sep->se_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 1056 (intptr_t)sep); 1057 if (sep->se_fd > maxsock) { 1058 maxsock = sep->se_fd; 1059 if (maxsock > (int)(rlim_ofile_cur - FD_MARGIN)) 1060 bump_nofile(); 1061 } 1062 DPRINTF(SERV_FMT ": registered on fd %d", SERV_PARAMS(sep), sep->se_fd); 1063} 1064 1065/* 1066 * Finish with a service and its socket. 1067 */ 1068static void 1069close_sep(struct servtab *sep) 1070{ 1071 1072 if (sep->se_fd >= 0) { 1073 (void) close(sep->se_fd); 1074 sep->se_fd = -1; 1075 } 1076 sep->se_count = 0; 1077 if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) { 1078 clear_ip_list(sep); 1079 } 1080} 1081 1082static void 1083register_rpc(struct servtab *sep) 1084{ 1085#ifdef RPC 1086 struct netbuf nbuf; 1087 struct sockaddr_storage ss; 1088 struct netconfig *nconf; 1089 socklen_t socklen; 1090 int n; 1091 1092 if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) { 1093 syslog(LOG_ERR, "%s: getnetconfigent failed", 1094 sep->se_proto); 1095 return; 1096 } 1097 socklen = sizeof ss; 1098 if (getsockname(sep->se_fd, (struct sockaddr *)(void *)&ss, &socklen) < 0) { 1099 syslog(LOG_ERR, SERV_FMT ": getsockname: %m", 1100 SERV_PARAMS(sep)); 1101 return; 1102 } 1103 1104 nbuf.buf = &ss; 1105 nbuf.len = ss.ss_len; 1106 nbuf.maxlen = sizeof (struct sockaddr_storage); 1107 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1108 DPRINTF("rpcb_set: %u %d %s %s", 1109 sep->se_rpcprog, n, nconf->nc_netid, 1110 taddr2uaddr(nconf, &nbuf)); 1111 (void)rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf); 1112 if (!rpcb_set((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf, &nbuf)) 1113 syslog(LOG_ERR, "rpcb_set: %u %d %s %s%s", 1114 sep->se_rpcprog, n, nconf->nc_netid, 1115 taddr2uaddr(nconf, &nbuf), clnt_spcreateerror("")); 1116 } 1117#endif /* RPC */ 1118} 1119 1120static void 1121unregister_rpc(struct servtab *sep) 1122{ 1123#ifdef RPC 1124 int n; 1125 struct netconfig *nconf; 1126 1127 if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) { 1128 syslog(LOG_ERR, "%s: getnetconfigent failed", 1129 sep->se_proto); 1130 return; 1131 } 1132 1133 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1134 DPRINTF("rpcb_unset(%u, %d, %s)", 1135 sep->se_rpcprog, n, nconf->nc_netid); 1136 if (!rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf)) 1137 syslog(LOG_ERR, "rpcb_unset(%u, %d, %s) failed\n", 1138 sep->se_rpcprog, n, nconf->nc_netid); 1139 } 1140#endif /* RPC */ 1141} 1142 1143 1144static struct servtab * 1145enter(struct servtab *cp) 1146{ 1147 struct servtab *sep; 1148 1149 sep = malloc(sizeof (*sep)); 1150 if (sep == NULL) { 1151 syslog(LOG_ERR, "Out of memory."); 1152 exit(EXIT_FAILURE); 1153 } 1154 *sep = *cp; 1155 sep->se_fd = -1; 1156 sep->se_rpcprog = -1; 1157 sep->se_next = servtab; 1158 servtab = sep; 1159 return (sep); 1160} 1161 1162FILE *fconfig; 1163/* Temporary storage for new servtab */ 1164static struct servtab serv; 1165/* Current line from current config file */ 1166static char line[LINE_MAX]; 1167char *defhost; 1168#ifdef IPSEC 1169char *policy; 1170#endif 1171 1172static void 1173endconfig(void) 1174{ 1175 if (fconfig != NULL) { 1176 (void) fclose(fconfig); 1177 fconfig = NULL; 1178 } 1179 if (defhost != NULL) { 1180 free(defhost); 1181 defhost = NULL; 1182 } 1183 1184#ifdef IPSEC 1185 if (policy != NULL) { 1186 free(policy); 1187 policy = NULL; 1188 } 1189#endif 1190 1191} 1192 1193#define LOG_EARLY_ENDCONF() \ 1194 ERR("Exiting %s early. Some services will be unavailable", CONFIG) 1195 1196#define LOG_TOO_FEW_ARGS() \ 1197 ERR("Expected more arguments") 1198 1199/* Parse the next service and apply any directives, and returns it as servtab */ 1200static struct servtab * 1201getconfigent(char **current_pos) 1202{ 1203 struct servtab *sep = &serv; 1204 int argc, val; 1205 char *cp, *cp0, *arg, *buf0, *buf1, *sz0, *sz1; 1206 static char TCPMUX_TOKEN[] = "tcpmux/"; 1207#define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) 1208 char *hostdelim; 1209 1210 /* 1211 * Pre-condition: current_pos points into line, 1212 * line contains config line. Continue where the last getconfigent left off. 1213 * Allows for multiple service definitions per line. 1214 */ 1215 cp = *current_pos; 1216 1217 if (false) { 1218 /* 1219 * Go to the next line, but only after attemting to read the current 1220 * one! Keep reading until we find a valid definition or EOF. 1221 */ 1222more: 1223 cp = nextline(fconfig); 1224 } 1225 1226 if (cp == NULL) { 1227 /* EOF or I/O error, let config() know to exit the file */ 1228 return NULL; 1229 } 1230 1231 /* Comments and IPsec policies */ 1232 if (cp[0] == '#') { 1233#ifdef IPSEC 1234 /* lines starting with #@ is not a comment, but the policy */ 1235 if (cp[1] == '@') { 1236 char *p; 1237 for (p = cp + 2; p && *p && isspace((unsigned char)*p); p++) 1238 ; 1239 if (*p == '\0') { 1240 if (policy) 1241 free(policy); 1242 policy = NULL; 1243 } else { 1244 if (ipsecsetup_test(p) < 0) { 1245 ERR("Invalid IPsec policy \"%s\"", p); 1246 LOG_EARLY_ENDCONF(); 1247 /* 1248 * Stop reading the current config to prevent services 1249 * from being run without IPsec. 1250 */ 1251 return NULL; 1252 } else { 1253 if (policy) 1254 free(policy); 1255 policy = newstr(p); 1256 } 1257 } 1258 } 1259#endif 1260 1261 goto more; 1262 } 1263 1264 /* Parse next token: listen-addr/hostname, service-spec, .include */ 1265 arg = skip(&cp); 1266 1267 if (cp == NULL) { 1268 goto more; 1269 } 1270 1271 if(arg[0] == '.') { 1272 if (strcmp(&arg[1], "include") == 0) { 1273 /* include directive */ 1274 arg = skip(&cp); 1275 if(arg == NULL) { 1276 LOG_TOO_FEW_ARGS(); 1277 return NULL; 1278 } 1279 include_configs(arg); 1280 goto more; 1281 } else { 1282 ERR("Unknown directive '%s'", &arg[1]); 1283 goto more; 1284 } 1285 } 1286 1287 /* After this point, we might need to store data in a servtab */ 1288 *sep = init_servtab(); 1289 1290 /* Check for a host name. */ 1291 hostdelim = strrchr(arg, ':'); 1292 if (hostdelim) { 1293 *hostdelim = '\0'; 1294 if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') { 1295 hostdelim[-1] = '\0'; 1296 sep->se_hostaddr = newstr(arg + 1); 1297 } else 1298 sep->se_hostaddr = newstr(arg); 1299 arg = hostdelim + 1; 1300 /* 1301 * If the line is of the form `host:', then just change the 1302 * default host for the following lines. 1303 */ 1304 if (*arg == '\0') { 1305 arg = skip(&cp); 1306 if (cp == NULL) { 1307 free(defhost); 1308 defhost = sep->se_hostaddr; 1309 goto more; 1310 } 1311 } 1312 } else { 1313 /* No host address found, set it to NULL to indicate absence */ 1314 sep->se_hostaddr = NULL; 1315 } 1316 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) { 1317 char *c = arg + MUX_LEN; 1318 if (*c == '+') { 1319 sep->se_type = MUXPLUS_TYPE; 1320 c++; 1321 } else 1322 sep->se_type = MUX_TYPE; 1323 sep->se_service = newstr(c); 1324 } else { 1325 sep->se_service = newstr(arg); 1326 sep->se_type = NORM_TYPE; 1327 } 1328 1329 DPRINTCONF("Found service definition '%s'", sep->se_service); 1330 1331 /* on/off/socktype */ 1332 arg = skip(&cp); 1333 if (arg == NULL) { 1334 LOG_TOO_FEW_ARGS(); 1335 freeconfig(sep); 1336 goto more; 1337 } 1338 1339 /* Check for new v2 syntax */ 1340 if (strcmp(arg, "on") == 0 || strncmp(arg, "on#", 3) == 0) { 1341 1342 if (arg[2] == '#') { 1343 cp = nextline(fconfig); 1344 } 1345 1346 switch(parse_syntax_v2(sep, &cp)) { 1347 case V2_SUCCESS: 1348 *current_pos = cp; 1349 return sep; 1350 case V2_SKIP: 1351 /* Skip invalid definitions, freeconfig is called in parse_v2.c */ 1352 *current_pos = cp; 1353 freeconfig(sep); 1354 goto more; 1355 case V2_ERROR: 1356 /* 1357 * Unrecoverable error, stop reading. freeconfig is called 1358 * in parse_v2.c 1359 */ 1360 LOG_EARLY_ENDCONF(); 1361 freeconfig(sep); 1362 return NULL; 1363 } 1364 } else if (strcmp(arg, "off") == 0 || strncmp(arg, "off#", 4) == 0) { 1365 1366 if (arg[3] == '#') { 1367 cp = nextline(fconfig); 1368 } 1369 1370 /* Parse syntax the same as with 'on', but ignore the result */ 1371 switch(parse_syntax_v2(sep, &cp)) { 1372 case V2_SUCCESS: 1373 case V2_SKIP: 1374 *current_pos = cp; 1375 freeconfig(sep); 1376 goto more; 1377 case V2_ERROR: 1378 /* Unrecoverable error, stop reading */ 1379 LOG_EARLY_ENDCONF(); 1380 freeconfig(sep); 1381 return NULL; 1382 } 1383 } else { 1384 /* continue parsing v1 */ 1385 parse_socktype(arg, sep); 1386 if (sep->se_socktype == SOCK_STREAM) { 1387 parse_accept_filter(arg, sep); 1388 } 1389 if (sep->se_hostaddr == NULL) { 1390 /* Set host to current default */ 1391 sep->se_hostaddr = newstr(defhost); 1392 } 1393 } 1394 1395 /* protocol */ 1396 arg = skip(&cp); 1397 if (arg == NULL) { 1398 LOG_TOO_FEW_ARGS(); 1399 freeconfig(sep); 1400 goto more; 1401 } 1402 if (sep->se_type == NORM_TYPE && 1403 strncmp(arg, "faith/", strlen("faith/")) == 0) { 1404 arg += strlen("faith/"); 1405 sep->se_type = FAITH_TYPE; 1406 } 1407 sep->se_proto = newstr(arg); 1408 1409#define MALFORMED(arg) \ 1410do { \ 1411 ERR("%s: malformed buffer size option `%s'", \ 1412 sep->se_service, (arg)); \ 1413 freeconfig(sep); \ 1414 goto more; \ 1415 /*NOTREACHED*/ \ 1416} while (/*CONSTCOND*/0) 1417 1418#define GETVAL(arg) \ 1419do { \ 1420 if (!isdigit((unsigned char)*(arg))) \ 1421 MALFORMED(arg); \ 1422 val = (int)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 ERR("%s: invalid buffer size `%s'", \ 1433 sep->se_service, (arg)); \ 1434 freeconfig(sep); \ 1435 goto more; \ 1436 } \ 1437 /*NOTREACHED*/ \ 1438} while (/*CONSTCOND*/0) 1439 1440#define ASSIGN(arg) \ 1441do { \ 1442 if (strcmp((arg), "sndbuf") == 0) \ 1443 sep->se_sndbuf = val; \ 1444 else if (strcmp((arg), "rcvbuf") == 0) \ 1445 sep->se_rcvbuf = val; \ 1446 else \ 1447 MALFORMED((arg)); \ 1448} while (/*CONSTCOND*/0) 1449 1450 /* 1451 * Extract the send and receive buffer sizes before parsing 1452 * the protocol. 1453 */ 1454 sep->se_sndbuf = sep->se_rcvbuf = 0; 1455 buf0 = buf1 = sz0 = sz1 = NULL; 1456 if ((buf0 = strchr(sep->se_proto, ',')) != NULL) { 1457 /* Not meaningful for Tcpmux services. */ 1458 if (ISMUX(sep)) { 1459 ERR("%s: can't specify buffer sizes for " 1460 "tcpmux services", sep->se_service); 1461 goto more; 1462 } 1463 1464 /* Skip the , */ 1465 *buf0++ = '\0'; 1466 1467 /* Check to see if another socket buffer size was specified. */ 1468 if ((buf1 = strchr(buf0, ',')) != NULL) { 1469 /* Skip the , */ 1470 *buf1++ = '\0'; 1471 1472 /* Make sure a 3rd one wasn't specified. */ 1473 if (strchr(buf1, ',') != NULL) { 1474 ERR("%s: too many buffer sizes", sep->se_service); 1475 goto more; 1476 } 1477 1478 /* Locate the size. */ 1479 if ((sz1 = strchr(buf1, '=')) == NULL) 1480 MALFORMED(buf1); 1481 1482 /* Skip the = */ 1483 *sz1++ = '\0'; 1484 } 1485 1486 /* Locate the size. */ 1487 if ((sz0 = strchr(buf0, '=')) == NULL) 1488 MALFORMED(buf0); 1489 1490 /* Skip the = */ 1491 *sz0++ = '\0'; 1492 1493 GETVAL(sz0); 1494 ASSIGN(buf0); 1495 1496 if (buf1 != NULL) { 1497 GETVAL(sz1); 1498 ASSIGN(buf1); 1499 } 1500 } 1501 1502#undef ASSIGN 1503#undef GETVAL 1504#undef MALFORMED 1505 1506 if (parse_protocol(sep)) { 1507 freeconfig(sep); 1508 goto more; 1509 } 1510 1511 /* wait/nowait:max */ 1512 arg = skip(&cp); 1513 if (arg == NULL) { 1514 LOG_TOO_FEW_ARGS(); 1515 freeconfig(sep); 1516 goto more; 1517 } 1518 1519 /* Rate limiting parsing */ { 1520 char *cp1; 1521 if ((cp1 = strchr(arg, ':')) == NULL) 1522 cp1 = strchr(arg, '.'); 1523 if (cp1 != NULL) { 1524 int rstatus; 1525 *cp1++ = '\0'; 1526 sep->se_service_max = (size_t)strtou(cp1, NULL, 10, 0, 1527 SERVTAB_COUNT_MAX, &rstatus); 1528 1529 if (rstatus != 0) { 1530 if (rstatus != ERANGE) { 1531 /* For compatibility with atoi parsing */ 1532 sep->se_service_max = 0; 1533 } 1534 1535 WRN("Improper \"max\" value '%s', " 1536 "using '%zu' instead: %s", 1537 cp1, 1538 sep->se_service_max, 1539 strerror(rstatus)); 1540 } 1541 1542 } else 1543 sep->se_service_max = TOOMANY; 1544 } 1545 if (parse_wait(sep, strcmp(arg, "wait") == 0)) { 1546 freeconfig(sep); 1547 goto more; 1548 } 1549 1550 /* Parse user:group token */ 1551 arg = skip(&cp); 1552 if(arg == NULL) { 1553 LOG_TOO_FEW_ARGS(); 1554 freeconfig(sep); 1555 goto more; 1556 } 1557 char* separator = strchr(arg, ':'); 1558 if (separator == NULL) { 1559 /* Backwards compatibility, allow dot instead of colon */ 1560 separator = strchr(arg, '.'); 1561 } 1562 1563 if (separator == NULL) { 1564 /* Only user was specified */ 1565 sep->se_group = NULL; 1566 } else { 1567 *separator = '\0'; 1568 sep->se_group = newstr(separator + 1); 1569 } 1570 1571 sep->se_user = newstr(arg); 1572 1573 /* Parser server-program (path to binary or "internal") */ 1574 arg = skip(&cp); 1575 if (arg == NULL) { 1576 LOG_TOO_FEW_ARGS(); 1577 freeconfig(sep); 1578 goto more; 1579 } 1580 if (parse_server(sep, arg)) { 1581 freeconfig(sep); 1582 goto more; 1583 } 1584 1585 argc = 0; 1586 for (arg = skip(&cp); cp; arg = skip(&cp)) { 1587 if (argc < MAXARGV) 1588 sep->se_argv[argc++] = newstr(arg); 1589 } 1590 while (argc <= MAXARGV) 1591 sep->se_argv[argc++] = NULL; 1592#ifdef IPSEC 1593 sep->se_policy = policy ? newstr(policy) : NULL; 1594#endif 1595 /* getconfigent read a positional service def, move to next line */ 1596 *current_pos = nextline(fconfig); 1597 return (sep); 1598} 1599 1600void 1601freeconfig(struct servtab *cp) 1602{ 1603 int i; 1604 1605 if (cp->se_hostaddr) 1606 free(cp->se_hostaddr); 1607 if (cp->se_service) 1608 free(cp->se_service); 1609 if (cp->se_proto) 1610 free(cp->se_proto); 1611 if (cp->se_user) 1612 free(cp->se_user); 1613 if(cp->se_group) 1614 free(cp->se_group); 1615 if (cp->se_server) 1616 free(cp->se_server); 1617 for (i = 0; i < MAXARGV; i++) 1618 if (cp->se_argv[i]) 1619 free(cp->se_argv[i]); 1620#ifdef IPSEC 1621 if (cp->se_policy) 1622 free(cp->se_policy); 1623#endif 1624} 1625 1626/* 1627 * Get next token *in the current service definition* from config file. 1628 * Allows multi-line parse if single space or single tab-indented. 1629 * Things in quotes are considered single token. 1630 * Advances cp to next token. 1631 */ 1632static char * 1633skip(char **cpp) 1634{ 1635 char *cp = *cpp; 1636 char *start; 1637 char quote; 1638 1639 if (*cpp == NULL) 1640 return (NULL); 1641 1642again: 1643 while (*cp == ' ' || *cp == '\t') 1644 cp++; 1645 if (*cp == '\0') { 1646 int c; 1647 1648 c = getc(fconfig); 1649 (void) ungetc(c, fconfig); 1650 if (c == ' ' || c == '\t') 1651 if ((cp = nextline(fconfig)) != NULL) 1652 goto again; 1653 *cpp = NULL; 1654 return (NULL); 1655 } 1656 start = cp; 1657 /* Parse shell-style quotes */ 1658 quote = '\0'; 1659 while (*cp && (quote || (*cp != ' ' && *cp != '\t'))) { 1660 if (*cp == '\'' || *cp == '"') { 1661 if (quote && *cp != quote) 1662 cp++; 1663 else { 1664 if (quote) 1665 quote = '\0'; 1666 else 1667 quote = *cp; 1668 memmove(cp, cp+1, strlen(cp)); 1669 } 1670 } else 1671 cp++; 1672 } 1673 if (*cp != '\0') 1674 *cp++ = '\0'; 1675 *cpp = cp; 1676 return (start); 1677} 1678 1679char * 1680nextline(FILE *fd) 1681{ 1682 char *cp; 1683 1684 if (fgets(line, (int)sizeof(line), fd) == NULL) { 1685 if (ferror(fd)) { 1686 ERR("Error when reading next line: %s", strerror(errno)); 1687 } 1688 return NULL; 1689 } 1690 cp = strchr(line, '\n'); 1691 if (cp) 1692 *cp = '\0'; 1693 line_number++; 1694 return line; 1695} 1696 1697char * 1698newstr(const char *cp) 1699{ 1700 char *dp; 1701 if ((dp = strdup((cp != NULL) ? cp : "")) != NULL) 1702 return (dp); 1703 syslog(LOG_ERR, "strdup: %m"); 1704 exit(EXIT_FAILURE); 1705 /*NOTREACHED*/ 1706} 1707 1708static void 1709inetd_setproctitle(char *a, int s) 1710{ 1711 socklen_t size; 1712 struct sockaddr_storage ss; 1713 char hbuf[NI_MAXHOST]; 1714 const char *hp; 1715 struct sockaddr *sa; 1716 1717 size = sizeof(ss); 1718 sa = (struct sockaddr *)(void *)&ss; 1719 if (getpeername(s, sa, &size) == 0) { 1720 if (getnameinfo(sa, size, hbuf, (socklen_t)sizeof(hbuf), NULL, 1721 0, niflags) != 0) 1722 hp = "?"; 1723 else 1724 hp = hbuf; 1725 setproctitle("-%s [%s]", a, hp); 1726 } else 1727 setproctitle("-%s", a); 1728} 1729 1730static void 1731bump_nofile(void) 1732{ 1733#define FD_CHUNK 32 1734 struct rlimit rl; 1735 1736 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1737 syslog(LOG_ERR, "getrlimit: %m"); 1738 return; 1739 } 1740 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1741 if (rl.rlim_cur <= rlim_ofile_cur) { 1742 syslog(LOG_ERR, 1743 "bump_nofile: cannot extend file limit, max = %d", 1744 (int)rl.rlim_cur); 1745 return; 1746 } 1747 1748 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1749 syslog(LOG_ERR, "setrlimit: %m"); 1750 return; 1751 } 1752 1753 rlim_ofile_cur = rl.rlim_cur; 1754 return; 1755} 1756 1757/* 1758 * Internet services provided internally by inetd: 1759 */ 1760#define BUFSIZE 4096 1761 1762/* ARGSUSED */ 1763static void 1764echo_stream(int s, struct servtab *sep) /* Echo service -- echo data back */ 1765{ 1766 char buffer[BUFSIZE]; 1767 ssize_t i; 1768 1769 inetd_setproctitle(sep->se_service, s); 1770 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1771 write(s, buffer, (size_t)i) > 0) 1772 ; 1773} 1774 1775/* ARGSUSED */ 1776static void 1777echo_dg(int s, struct servtab *sep) /* Echo service -- echo data back */ 1778{ 1779 char buffer[BUFSIZE]; 1780 ssize_t i; 1781 socklen_t size; 1782 struct sockaddr_storage ss; 1783 struct sockaddr *sa; 1784 1785 sa = (struct sockaddr *)(void *)&ss; 1786 size = sizeof(ss); 1787 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, sa, &size)) < 0) 1788 return; 1789 if (port_good_dg(sa)) 1790 (void) sendto(s, buffer, (size_t)i, 0, sa, size); 1791} 1792 1793/* ARGSUSED */ 1794static void 1795discard_stream(int s, struct servtab *sep) /* Discard service -- ignore data */ 1796{ 1797 char buffer[BUFSIZE]; 1798 1799 inetd_setproctitle(sep->se_service, s); 1800 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1801 errno == EINTR) 1802 ; 1803} 1804 1805/* ARGSUSED */ 1806static void 1807discard_dg(int s, struct servtab *sep) /* Discard service -- ignore data */ 1808 1809{ 1810 char buffer[BUFSIZE]; 1811 1812 (void) read(s, buffer, sizeof(buffer)); 1813} 1814 1815#define LINESIZ 72 1816char ring[128]; 1817char *endring; 1818 1819static void 1820initring(void) 1821{ 1822 int i; 1823 1824 endring = ring; 1825 1826 for (i = 0; i <= 128; ++i) 1827 if (isprint(i)) 1828 *endring++ = (char)i; 1829} 1830 1831/* ARGSUSED */ 1832static void 1833chargen_stream(int s, struct servtab *sep) /* Character generator */ 1834{ 1835 size_t len; 1836 char *rs, text[LINESIZ+2]; 1837 1838 inetd_setproctitle(sep->se_service, s); 1839 1840 if (!endring) { 1841 initring(); 1842 rs = ring; 1843 } 1844 1845 text[LINESIZ] = '\r'; 1846 text[LINESIZ + 1] = '\n'; 1847 for (rs = ring;;) { 1848 if ((len = (size_t)(endring - rs)) >= LINESIZ) 1849 memmove(text, rs, LINESIZ); 1850 else { 1851 memmove(text, rs, len); 1852 memmove(text + len, ring, LINESIZ - len); 1853 } 1854 if (++rs == endring) 1855 rs = ring; 1856 if (write(s, text, sizeof(text)) != sizeof(text)) 1857 break; 1858 } 1859} 1860 1861/* ARGSUSED */ 1862static void 1863chargen_dg(int s, struct servtab *sep) /* Character generator */ 1864{ 1865 struct sockaddr_storage ss; 1866 struct sockaddr *sa; 1867 static char *rs; 1868 size_t len; 1869 socklen_t size; 1870 char text[LINESIZ+2]; 1871 1872 if (endring == 0) { 1873 initring(); 1874 rs = ring; 1875 } 1876 1877 sa = (struct sockaddr *)(void *)&ss; 1878 size = sizeof(ss); 1879 if (recvfrom(s, text, sizeof(text), 0, sa, &size) < 0) 1880 return; 1881 1882 if (!port_good_dg(sa)) 1883 return; 1884 1885 if ((len = (size_t)(endring - rs)) >= LINESIZ) 1886 memmove(text, rs, LINESIZ); 1887 else { 1888 memmove(text, rs, len); 1889 memmove(text + len, ring, LINESIZ - len); 1890 } 1891 if (++rs == endring) 1892 rs = ring; 1893 text[LINESIZ] = '\r'; 1894 text[LINESIZ + 1] = '\n'; 1895 (void) sendto(s, text, sizeof(text), 0, sa, size); 1896} 1897 1898/* 1899 * Return a machine readable date and time, in the form of the 1900 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1901 * returns the number of seconds since midnight, Jan 1, 1970, 1902 * we must add 2208988800 seconds to this figure to make up for 1903 * some seventy years Bell Labs was asleep. 1904 */ 1905 1906static uint32_t 1907machtime(void) 1908{ 1909 struct timeval tv; 1910 1911 if (gettimeofday(&tv, NULL) < 0) { 1912 DPRINTF("Unable to get time of day"); 1913 return (0); 1914 } 1915#define OFFSET ((uint32_t)25567 * 24*60*60) 1916 return (htonl((uint32_t)(tv.tv_sec + OFFSET))); 1917#undef OFFSET 1918} 1919 1920/* ARGSUSED */ 1921static void 1922machtime_stream(int s, struct servtab *sep) 1923{ 1924 uint32_t result; 1925 1926 result = machtime(); 1927 (void) write(s, &result, sizeof(result)); 1928} 1929 1930/* ARGSUSED */ 1931void 1932machtime_dg(int s, struct servtab *sep) 1933{ 1934 uint32_t result; 1935 struct sockaddr_storage ss; 1936 struct sockaddr *sa; 1937 socklen_t size; 1938 1939 sa = (struct sockaddr *)(void *)&ss; 1940 size = sizeof(ss); 1941 if (recvfrom(s, &result, sizeof(result), 0, sa, &size) < 0) 1942 return; 1943 if (!port_good_dg(sa)) 1944 return; 1945 result = machtime(); 1946 (void)sendto(s, &result, sizeof(result), 0, sa, size); 1947} 1948 1949/* ARGSUSED */ 1950static void 1951daytime_stream(int s,struct servtab *sep) 1952/* Return human-readable time of day */ 1953{ 1954 char buffer[256]; 1955 time_t clk; 1956 int len; 1957 1958 clk = time((time_t *) 0); 1959 1960 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk)); 1961 (void) write(s, buffer, (size_t)len); 1962} 1963 1964/* ARGSUSED */ 1965void 1966daytime_dg(int s, struct servtab *sep) 1967/* Return human-readable time of day */ 1968{ 1969 char buffer[256]; 1970 time_t clk; 1971 struct sockaddr_storage ss; 1972 struct sockaddr *sa; 1973 socklen_t size; 1974 int len; 1975 1976 clk = time((time_t *) 0); 1977 1978 sa = (struct sockaddr *)(void *)&ss; 1979 size = sizeof(ss); 1980 if (recvfrom(s, buffer, sizeof(buffer), 0, sa, &size) < 0) 1981 return; 1982 if (!port_good_dg(sa)) 1983 return; 1984 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk)); 1985 (void) sendto(s, buffer, (size_t)len, 0, sa, size); 1986} 1987 1988#ifdef DEBUG_ENABLE 1989/* 1990 * print_service: 1991 * Dump relevant information to stderr 1992 */ 1993static void 1994print_service(const char *action, struct servtab *sep) 1995{ 1996 1997 if (isrpcservice(sep)) 1998 fprintf(stderr, 1999 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s" 2000#ifdef IPSEC 2001 " policy=\"%s\"" 2002#endif 2003 "\n", 2004 action, sep->se_service, 2005 sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto, 2006 sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group, 2007 (long)sep->se_bi, sep->se_server 2008#ifdef IPSEC 2009 , (sep->se_policy ? sep->se_policy : "") 2010#endif 2011 ); 2012 else 2013 fprintf(stderr, 2014 "%s: %s:%s proto=%s%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s" 2015#ifdef IPSEC 2016 " policy=%s" 2017#endif 2018 "\n", 2019 action, sep->se_hostaddr, sep->se_service, 2020 sep->se_type == FAITH_TYPE ? "faith/" : "", 2021 sep->se_proto, 2022 sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group, 2023 (long)sep->se_bi, sep->se_server 2024#ifdef IPSEC 2025 , (sep->se_policy ? sep->se_policy : "") 2026#endif 2027 ); 2028} 2029#endif 2030 2031static void 2032usage(void) 2033{ 2034#ifdef LIBWRAP 2035 (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname()); 2036#else 2037 (void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname()); 2038#endif 2039 exit(EXIT_FAILURE); 2040} 2041 2042 2043/* 2044 * Based on TCPMUX.C by Mark K. Lottor November 1988 2045 * sri-nic::ps:<mkl>tcpmux.c 2046 */ 2047 2048static int /* # of characters upto \r,\n or \0 */ 2049get_line(int fd, char *buf, int len) 2050{ 2051 int count = 0; 2052 ssize_t n; 2053 2054 do { 2055 n = read(fd, buf, (size_t)(len - count)); 2056 if (n == 0) 2057 return (count); 2058 if (n < 0) 2059 return (-1); 2060 while (--n >= 0) { 2061 if (*buf == '\r' || *buf == '\n' || *buf == '\0') 2062 return (count); 2063 count++; 2064 buf++; 2065 } 2066 } while (count < len); 2067 return (count); 2068} 2069 2070#define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ 2071 2072#define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) 2073 2074static void 2075tcpmux(int ctrl, struct servtab *sep) 2076{ 2077 char service[MAX_SERV_LEN+1]; 2078 int len; 2079 2080 /* Get requested service name */ 2081 if ((len = get_line(ctrl, service, MAX_SERV_LEN)) < 0) { 2082 strwrite(ctrl, "-Error reading service name\r\n"); 2083 goto reject; 2084 } 2085 service[len] = '\0'; 2086 2087 DPRINTF("tcpmux: %s: service requested", service); 2088 2089 /* 2090 * Help is a required command, and lists available services, 2091 * one per line. 2092 */ 2093 if (!strcasecmp(service, "help")) { 2094 strwrite(ctrl, "+Available services:\r\n"); 2095 strwrite(ctrl, "help\r\n"); 2096 for (sep = servtab; sep != NULL; sep = sep->se_next) { 2097 if (!ISMUX(sep)) 2098 continue; 2099 (void)write(ctrl, sep->se_service, 2100 strlen(sep->se_service)); 2101 strwrite(ctrl, "\r\n"); 2102 } 2103 goto reject; 2104 } 2105 2106 /* Try matching a service in inetd.conf with the request */ 2107 for (sep = servtab; sep != NULL; sep = sep->se_next) { 2108 if (!ISMUX(sep)) 2109 continue; 2110 if (!strcasecmp(service, sep->se_service)) { 2111 if (ISMUXPLUS(sep)) 2112 strwrite(ctrl, "+Go\r\n"); 2113 run_service(ctrl, sep, 1 /* forked */); 2114 return; 2115 } 2116 } 2117 strwrite(ctrl, "-Service not available\r\n"); 2118reject: 2119 _exit(EXIT_FAILURE); 2120} 2121 2122/* 2123 * check if the address/port where send data to is one of the obvious ports 2124 * that are used for denial of service attacks like two echo ports 2125 * just echoing data between them 2126 */ 2127static int 2128port_good_dg(struct sockaddr *sa) 2129{ 2130 struct in_addr in; 2131 struct sockaddr_in *sin; 2132#ifdef INET6 2133 struct in6_addr *in6; 2134 struct sockaddr_in6 *sin6; 2135#endif 2136 u_int16_t port; 2137 int i; 2138 char hbuf[NI_MAXHOST]; 2139 2140 switch (sa->sa_family) { 2141 case AF_INET: 2142 sin = (struct sockaddr_in *)(void *)sa; 2143 in.s_addr = ntohl(sin->sin_addr.s_addr); 2144 port = ntohs(sin->sin_port); 2145#ifdef INET6 2146 v4chk: 2147#endif 2148 if (IN_MULTICAST(in.s_addr)) 2149 goto bad; 2150 switch ((in.s_addr & 0xff000000) >> 24) { 2151 case 0: case 127: case 255: 2152 goto bad; 2153 } 2154 if (dg_broadcast(&in)) 2155 goto bad; 2156 break; 2157#ifdef INET6 2158 case AF_INET6: 2159 sin6 = (struct sockaddr_in6 *)(void *)sa; 2160 in6 = &sin6->sin6_addr; 2161 port = ntohs(sin6->sin6_port); 2162 if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6)) 2163 goto bad; 2164 if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) { 2165 memcpy(&in, &in6->s6_addr[12], sizeof(in)); 2166 in.s_addr = ntohl(in.s_addr); 2167 goto v4chk; 2168 } 2169 break; 2170#endif 2171 default: 2172 /* XXX unsupported af, is it safe to assume it to be safe? */ 2173 return (1); 2174 } 2175 2176 for (i = 0; bad_ports[i] != 0; i++) { 2177 if (port == bad_ports[i]) 2178 goto bad; 2179 } 2180 2181 return (1); 2182 2183bad: 2184 if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0, 2185 niflags) != 0) 2186 strlcpy(hbuf, "?", sizeof(hbuf)); 2187 syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d", 2188 hbuf, port); 2189 return (0); 2190} 2191 2192/* XXX need optimization */ 2193static int 2194dg_broadcast(struct in_addr *in) 2195{ 2196 struct ifaddrs *ifa, *ifap; 2197 struct sockaddr_in *sin; 2198 2199 if (getifaddrs(&ifap) < 0) 2200 return (0); 2201 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 2202 if (ifa->ifa_addr->sa_family != AF_INET || 2203 (ifa->ifa_flags & IFF_BROADCAST) == 0) 2204 continue; 2205 sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr; 2206 if (sin->sin_addr.s_addr == in->s_addr) { 2207 freeifaddrs(ifap); 2208 return (1); 2209 } 2210 } 2211 freeifaddrs(ifap); 2212 return (0); 2213} 2214 2215static int 2216my_kevent(const struct kevent *changelist, size_t nchanges, 2217 struct kevent *eventlist, size_t nevents) 2218{ 2219 int result; 2220 2221 while ((result = kevent(kq, changelist, nchanges, eventlist, nevents, 2222 NULL)) < 0) 2223 if (errno != EINTR) { 2224 syslog(LOG_ERR, "kevent: %m"); 2225 exit(EXIT_FAILURE); 2226 } 2227 2228 return (result); 2229} 2230 2231static struct kevent * 2232allocchange(void) 2233{ 2234 if (changes == __arraycount(changebuf)) { 2235 (void) my_kevent(changebuf, __arraycount(changebuf), NULL, 0); 2236 changes = 0; 2237 } 2238 2239 return (&changebuf[changes++]); 2240} 2241 2242static void 2243config_root(void) 2244{ 2245 struct servtab *sep; 2246 /* Uncheck services */ 2247 for (sep = servtab; sep != NULL; sep = sep->se_next) { 2248 sep->se_checked = 0; 2249 } 2250 defhost = newstr("*"); 2251#ifdef IPSEC 2252 policy = NULL; 2253#endif 2254 fconfig = NULL; 2255 config(); 2256 purge_unchecked(); 2257} 2258 2259static void 2260purge_unchecked(void) 2261{ 2262 struct servtab *sep, **sepp = &servtab; 2263 int servtab_count = 0; 2264 while ((sep = *sepp) != NULL) { 2265 if (sep->se_checked) { 2266 sepp = &sep->se_next; 2267 servtab_count++; 2268 continue; 2269 } 2270 *sepp = sep->se_next; 2271 if (sep->se_fd >= 0) 2272 close_sep(sep); 2273 if (isrpcservice(sep)) 2274 unregister_rpc(sep); 2275 if (sep->se_family == AF_LOCAL) 2276 (void)unlink(sep->se_service); 2277#ifdef DEBUG_ENABLE 2278 if (debug) 2279 print_service("FREE", sep); 2280#endif 2281 freeconfig(sep); 2282 free(sep); 2283 } 2284 DPRINTF("%d service(s) loaded.", servtab_count); 2285} 2286 2287static bool 2288is_same_service(const struct servtab *sep, const struct servtab *cp) 2289{ 2290 return 2291 strcmp(sep->se_service, cp->se_service) == 0 && 2292 strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 && 2293 strcmp(sep->se_proto, cp->se_proto) == 0 && 2294 sep->se_family == cp->se_family && 2295 ISMUX(sep) == ISMUX(cp); 2296} 2297 2298int 2299parse_protocol(struct servtab *sep) 2300{ 2301 int val; 2302 2303 if (strcmp(sep->se_proto, "unix") == 0) { 2304 sep->se_family = AF_LOCAL; 2305 } else { 2306 val = (int)strlen(sep->se_proto); 2307 if (!val) { 2308 ERR("%s: invalid protocol specified", 2309 sep->se_service); 2310 return -1; 2311 } 2312 val = sep->se_proto[val - 1]; 2313 switch (val) { 2314 case '4': /*tcp4 or udp4*/ 2315 sep->se_family = AF_INET; 2316 break; 2317#ifdef INET6 2318 case '6': /*tcp6 or udp6*/ 2319 sep->se_family = AF_INET6; 2320 break; 2321#endif 2322 default: 2323 /* Use 'default' IP version which is IPv4, may eventually be 2324 * changed to AF_INET6 */ 2325 sep->se_family = AF_INET; 2326 break; 2327 } 2328 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 2329#ifdef RPC 2330 char *cp1, *ccp; 2331 cp1 = strchr(sep->se_service, '/'); 2332 if (cp1 == 0) { 2333 ERR("%s: no rpc version", 2334 sep->se_service); 2335 return -1; 2336 } 2337 *cp1++ = '\0'; 2338 sep->se_rpcversl = sep->se_rpcversh = 2339 (int)strtol(cp1, &ccp, 0); 2340 if (ccp == cp1) { 2341 badafterall: 2342 ERR("%s/%s: bad rpc version", 2343 sep->se_service, cp1); 2344 return -1; 2345 } 2346 if (*ccp == '-') { 2347 cp1 = ccp + 1; 2348 sep->se_rpcversh = (int)strtol(cp1, &ccp, 0); 2349 if (ccp == cp1) 2350 goto badafterall; 2351 } 2352#else 2353 ERR("%s: rpc services not supported", 2354 sep->se_service); 2355 return -1; 2356#endif /* RPC */ 2357 } 2358 } 2359 return 0; 2360} 2361 2362int 2363parse_wait(struct servtab *sep, int wait) 2364{ 2365 if (!ISMUX(sep)) { 2366 sep->se_wait = wait; 2367 return 0; 2368 } 2369 /* 2370 * Silently enforce "nowait" for TCPMUX services since 2371 * they don't have an assigned port to listen on. 2372 */ 2373 sep->se_wait = 0; 2374 2375 if (strncmp(sep->se_proto, "tcp", 3)) { 2376 ERR("bad protocol for tcpmux service %s", 2377 sep->se_service); 2378 return -1; 2379 } 2380 if (sep->se_socktype != SOCK_STREAM) { 2381 ERR("bad socket type for tcpmux service %s", 2382 sep->se_service); 2383 return -1; 2384 } 2385 return 0; 2386} 2387 2388int 2389parse_server(struct servtab *sep, const char *arg){ 2390 sep->se_server = newstr(arg); 2391 if (strcmp(sep->se_server, "internal") != 0) { 2392 sep->se_bi = NULL; 2393 return 0; 2394 } 2395 struct biltin *bi; 2396 2397 for (bi = biltins; bi->bi_service; bi++) 2398 if (bi->bi_socktype == sep->se_socktype && 2399 strcmp(bi->bi_service, sep->se_service) == 0) 2400 break; 2401 if (bi->bi_service == NULL) { 2402 ERR("Internal service %s unknown", 2403 sep->se_service); 2404 return -1; 2405 } 2406 sep->se_bi = bi; 2407 sep->se_wait = bi->bi_wait; 2408 return 0; 2409} 2410 2411/* TODO test to make sure accept filter still works */ 2412void 2413parse_accept_filter(char *arg, struct servtab *sep) { 2414 char *accf, *accf_arg; 2415 /* one and only one accept filter */ 2416 accf = strchr(arg, ':'); 2417 if (!accf) 2418 return; 2419 if (accf != strrchr(arg, ':') || *(accf + 1) == '\0') { 2420 /* more than one || nothing beyond */ 2421 sep->se_socktype = -1; 2422 return; 2423 } 2424 2425 accf++; /* skip delimiter */ 2426 strlcpy(sep->se_accf.af_name, accf, sizeof(sep->se_accf.af_name)); 2427 accf_arg = strchr(accf, ','); 2428 if (!accf_arg) /* zero or one arg, no more */ 2429 return; 2430 2431 if (strrchr(accf, ',') != accf_arg) { 2432 sep->se_socktype = -1; 2433 } else { 2434 accf_arg++; 2435 strlcpy(sep->se_accf.af_arg, accf_arg, 2436 sizeof(sep->se_accf.af_arg)); 2437 } 2438} 2439 2440void 2441parse_socktype(char* arg, struct servtab* sep) 2442{ 2443 /* stream socket may have an accept filter, only check first chars */ 2444 if (strncmp(arg, "stream", sizeof("stream") - 1) == 0) 2445 sep->se_socktype = SOCK_STREAM; 2446 else if (strcmp(arg, "dgram") == 0) 2447 sep->se_socktype = SOCK_DGRAM; 2448 else if (strcmp(arg, "rdm") == 0) 2449 sep->se_socktype = SOCK_RDM; 2450 else if (strcmp(arg, "seqpacket") == 0) 2451 sep->se_socktype = SOCK_SEQPACKET; 2452 else if (strcmp(arg, "raw") == 0) 2453 sep->se_socktype = SOCK_RAW; 2454 else 2455 sep->se_socktype = -1; 2456} 2457 2458static struct servtab 2459init_servtab(void) 2460{ 2461 /* This does not set every field to default. See enter() as well */ 2462 return (struct servtab) { 2463 /* 2464 * Set se_max to non-zero so uninitialized value is not 2465 * a valid value. Useful in v2 syntax parsing. 2466 */ 2467 .se_service_max = SERVTAB_UNSPEC_SIZE_T, 2468 .se_ip_max = SERVTAB_UNSPEC_SIZE_T, 2469 .se_wait = SERVTAB_UNSPEC_VAL, 2470 .se_socktype = SERVTAB_UNSPEC_VAL 2471 /* All other fields initialized to 0 or null */ 2472 }; 2473} 2474 2475/* Include directives bookkeeping structure */ 2476struct file_list { 2477 /* Absolute path used for checking for circular references */ 2478 char *abs; 2479 /* Pointer to the absolute path of the parent config file, 2480 * on the stack */ 2481 struct file_list *next; 2482} *file_list_head; 2483 2484static void 2485include_configs(char *pattern) 2486{ 2487 /* Allocate global per-config state on the thread stack */ 2488 const char* save_CONFIG; 2489 FILE *save_fconfig; 2490 size_t save_line_number; 2491 char *save_defhost; 2492 struct file_list new_file; 2493#ifdef IPSEC 2494 char *save_policy; 2495#endif 2496 2497 /* Store current globals on the stack */ 2498 save_CONFIG = CONFIG; 2499 save_fconfig = fconfig; 2500 save_line_number = line_number; 2501 save_defhost = defhost; 2502 new_file.abs = realpath(CONFIG, NULL); 2503 new_file.next = file_list_head; 2504#ifdef IPSEC 2505 save_policy = policy; 2506#endif 2507 /* Put new_file at the top of the config stack */ 2508 file_list_head = &new_file; 2509 read_glob_configs(pattern); 2510 free((void *)new_file.abs); 2511 /* Pop new_file off the stack */ 2512 file_list_head = new_file.next; 2513 2514 /* Restore global per-config state */ 2515 CONFIG = save_CONFIG; 2516 fconfig = save_fconfig; 2517 line_number = save_line_number; 2518 defhost = save_defhost; 2519#ifdef IPSEC 2520 policy = save_policy; 2521#endif 2522} 2523 2524static void 2525prepare_next_config(const char *file_name) 2526{ 2527 /* Setup new state that is normally only done in main */ 2528 CONFIG = file_name; 2529 2530 /* Inherit default host and IPsec policy */ 2531 defhost = newstr(defhost); 2532 2533#ifdef IPSEC 2534 policy = (policy == NULL) ? NULL : newstr(policy); 2535#endif 2536} 2537 2538static void 2539read_glob_configs(char *pattern) { 2540 glob_t results; 2541 char *full_pattern; 2542 int glob_result; 2543 full_pattern = gen_file_pattern(CONFIG, pattern); 2544 2545 DPRINTCONF("Found include directive '%s'", full_pattern); 2546 2547 glob_result = glob(full_pattern, GLOB_NOSORT, glob_error, &results); 2548 switch(glob_result) { 2549 case 0: 2550 /* No glob errors */ 2551 break; 2552 case GLOB_ABORTED: 2553 ERR("Error while searching for include files"); 2554 break; 2555 case GLOB_NOMATCH: 2556 /* It's fine if no files were matched. */ 2557 DPRINTCONF("No files matched pattern '%s'", full_pattern); 2558 break; 2559 case GLOB_NOSPACE: 2560 ERR("Error when searching for include files: %s", 2561 strerror(errno)); 2562 break; 2563 default: 2564 ERR("Unknown glob(3) error %d", errno); 2565 break; 2566 } 2567 free(full_pattern); 2568 2569 for (size_t i = 0; i < results.gl_pathc; i++) { 2570 include_matched_path(results.gl_pathv[i]); 2571 } 2572 2573 globfree(&results); 2574} 2575 2576static void 2577include_matched_path(char *glob_path) 2578{ 2579 struct stat sb; 2580 char *tmp; 2581 2582 if (lstat(glob_path, &sb)) { 2583 ERR("Error calling stat on path '%s': %s", glob_path, 2584 strerror(errno)); 2585 return; 2586 } 2587 2588 if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) { 2589 DPRINTCONF("'%s' is not a file.", glob_path); 2590 ERR("The matched path '%s' is not a regular file", glob_path); 2591 return; 2592 } 2593 2594 DPRINTCONF("Include '%s'", glob_path); 2595 2596 if (S_ISLNK(sb.st_mode)) { 2597 tmp = glob_path; 2598 glob_path = realpath(tmp, NULL); 2599 } 2600 2601 /* Ensure the file is not being reincluded .*/ 2602 if (check_no_reinclude(glob_path)) { 2603 prepare_next_config(glob_path); 2604 config(); 2605 } else { 2606 DPRINTCONF("File '%s' already included in current include " 2607 "chain", glob_path); 2608 WRN("Including file '%s' would cause a circular " 2609 "dependency", glob_path); 2610 } 2611 2612 if (S_ISLNK(sb.st_mode)) { 2613 free(glob_path); 2614 glob_path = tmp; 2615 } 2616} 2617 2618static bool 2619check_no_reinclude(const char *glob_path) 2620{ 2621 struct file_list *cur = file_list_head; 2622 char *abs_path = realpath(glob_path, NULL); 2623 2624 if (abs_path == NULL) { 2625 ERR("Error checking real path for '%s': %s", 2626 glob_path, strerror(errno)); 2627 return false; 2628 } 2629 2630 DPRINTCONF("Absolute path '%s'", abs_path); 2631 2632 for (cur = file_list_head; cur != NULL; cur = cur->next) { 2633 if (strcmp(cur->abs, abs_path) == 0) { 2634 /* file included more than once */ 2635 /* TODO relative or abs path for logging error? */ 2636 free(abs_path); 2637 return false; 2638 } 2639 } 2640 free(abs_path); 2641 return true; 2642} 2643 2644/* Resolve the pattern relative to the config file the pattern is from */ 2645static char * 2646gen_file_pattern(const char *cur_config, const char *pattern) 2647{ 2648 if (pattern[0] == '/') { 2649 /* Absolute paths don't need any normalization */ 2650 return newstr(pattern); 2651 } 2652 2653 /* pattern is relative */ 2654 /* Find the end of the file's directory */ 2655 size_t i, last = 0; 2656 for (i = 0; cur_config[i] != '\0'; i++) { 2657 if (cur_config[i] == '/') { 2658 last = i; 2659 } 2660 } 2661 2662 if (last == 0) { 2663 /* cur_config is just a filename, pattern already correct */ 2664 return newstr(pattern); 2665 } 2666 2667 /* Relativize pattern to cur_config file's directory */ 2668 char *full_pattern = malloc(last + 1 + strlen(pattern) + 1); 2669 if (full_pattern == NULL) { 2670 syslog(LOG_ERR, "Out of memory."); 2671 exit(EXIT_FAILURE); 2672 } 2673 memcpy(full_pattern, cur_config, last); 2674 full_pattern[last] = '/'; 2675 strcpy(&full_pattern[last + 1], pattern); 2676 return full_pattern; 2677} 2678 2679static int 2680glob_error(const char *path, int error) 2681{ 2682 WRN("Error while resolving path '%s': %s", path, strerror(error)); 2683 return 0; 2684} 2685 2686/* Return 0 on allow, -1 if connection should be blocked */ 2687static int 2688rl_process(struct servtab *sep, int ctrl) 2689{ 2690 struct se_ip_list_node *node; 2691 time_t now = 0; /* 0 prevents GCC from complaining */ 2692 bool istimevalid = false; 2693 char hbuf[NI_MAXHOST]; 2694 2695 DPRINTF(SERV_FMT ": processing rate-limiting", 2696 SERV_PARAMS(sep)); 2697 DPRINTF(SERV_FMT ": se_service_max " 2698 "%zu and se_count %zu", SERV_PARAMS(sep), 2699 sep->se_service_max, sep->se_count); 2700 2701 /* se_count is incremented if rl_process will return 0 */ 2702 if (sep->se_count == 0) { 2703 now = rl_time(); 2704 sep->se_time = now; 2705 istimevalid = true; 2706 } 2707 2708 if (sep->se_count >= sep->se_service_max) { 2709 if(!istimevalid) { 2710 now = rl_time(); 2711 istimevalid = true; 2712 } 2713 2714 if (now - sep->se_time > CNT_INTVL) { 2715 rl_reset(sep, now); 2716 } else { 2717 syslog(LOG_ERR, 2718 SERV_FMT ": max spawn rate (%zu in %ji seconds) " 2719 "already met, closing until end of timeout in " 2720 "%ju seconds", 2721 SERV_PARAMS(sep), 2722 sep->se_service_max, 2723 (intmax_t)CNT_INTVL, 2724 (uintmax_t)RETRYTIME); 2725 2726 DPRINTF(SERV_FMT ": service not started", 2727 SERV_PARAMS(sep)); 2728 2729 rl_drop_connection(sep, ctrl); 2730 2731 /* Close the server for 10 minutes */ 2732 close_sep(sep); 2733 if (!timingout) { 2734 timingout = 1; 2735 alarm(RETRYTIME); 2736 } 2737 2738 return -1; 2739 } 2740 } 2741 2742 if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) { 2743 rl_get_name(sep, ctrl, hbuf); 2744 node = rl_try_get_ip(sep, hbuf); 2745 if(node == NULL) { 2746 node = rl_add(sep, hbuf); 2747 } 2748 2749 DPRINTF( 2750 SERV_FMT ": se_ip_max %zu and ip_count %zu", 2751 SERV_PARAMS(sep), sep->se_ip_max, node->count); 2752 2753 if (node->count >= sep->se_ip_max) { 2754 if (!istimevalid) { 2755 /* 2756 * Only get the clock time if we didn't 2757 * already 2758 */ 2759 now = rl_time(); 2760 istimevalid = true; 2761 } 2762 2763 if (now - sep->se_time > CNT_INTVL) { 2764 rl_reset(sep, now); 2765 node = rl_add(sep, hbuf); 2766 } else { 2767 if (debug && node->count == sep->se_ip_max) { 2768 /* 2769 * Only log first failed request to 2770 * prevent DoS attack writing to system 2771 * log 2772 */ 2773 syslog(LOG_ERR, SERV_FMT 2774 ": max ip spawn rate (%zu in " 2775 "%ji seconds) for " 2776 "%." TOSTRING(NI_MAXHOST) "s " 2777 "already met; service not started", 2778 SERV_PARAMS(sep), 2779 sep->se_ip_max, 2780 (intmax_t)CNT_INTVL, 2781 node->address); 2782 } 2783 2784 DPRINTF(SERV_FMT ": service not started", 2785 SERV_PARAMS(sep)); 2786 2787 rl_drop_connection(sep, ctrl); 2788 /* 2789 * Increment so debug-syslog message will 2790 * trigger only once 2791 */ 2792 node->count++; 2793 return -1; 2794 } 2795 } 2796 node->count++; 2797 } 2798 2799 DPRINTF(SERV_FMT ": running service ", SERV_PARAMS(sep)); 2800 2801 sep->se_count++; 2802 return 0; 2803} 2804 2805/* Get the remote's IP address in textual form into hbuf of size NI_MAXHOST */ 2806static void 2807rl_get_name(struct servtab *sep, int ctrl, char *hbuf) 2808{ 2809 struct sockaddr_storage addr; 2810 socklen_t len = sizeof(struct sockaddr_storage); 2811 switch (sep->se_socktype) { 2812 case SOCK_STREAM: 2813 if (getpeername(ctrl, (struct sockaddr *)&addr, &len)) { 2814 /* error, log it and skip ip rate limiting */ 2815 syslog(LOG_ERR, 2816 SERV_FMT " failed to get peer name of the " 2817 "connection", SERV_PARAMS(sep)); 2818 exit(EXIT_FAILURE); 2819 } 2820 break; 2821 case SOCK_DGRAM: { 2822 struct msghdr header = { 2823 .msg_name = &addr, 2824 .msg_namelen = sizeof(struct sockaddr_storage), 2825 /* scatter/gather and control info is null */ 2826 }; 2827 ssize_t count; 2828 2829 /* Peek so service can still get the packet */ 2830 count = recvmsg(ctrl, &header, MSG_PEEK); 2831 if (count == -1) { 2832 syslog(LOG_ERR, 2833 "failed to get dgram source address: %s; exiting", 2834 strerror(errno)); 2835 exit(EXIT_FAILURE); 2836 } 2837 break; 2838 } 2839 default: 2840 DPRINTF(SERV_FMT ": ip_max rate limiting not supported for " 2841 "socktype", SERV_PARAMS(sep)); 2842 syslog(LOG_ERR, SERV_FMT 2843 ": ip_max rate limiting not supported for socktype", 2844 SERV_PARAMS(sep)); 2845 exit(EXIT_FAILURE); 2846 } 2847 2848 if (getnameinfo((struct sockaddr *)&addr, 2849 addr.ss_len, hbuf, 2850 NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) { 2851 /* error, log it and skip ip rate limiting */ 2852 syslog(LOG_ERR, 2853 SERV_FMT ": failed to get name info of the incoming " 2854 "connection; exiting", 2855 SERV_PARAMS(sep)); 2856 exit(EXIT_FAILURE); 2857 } 2858} 2859 2860static void 2861rl_drop_connection(struct servtab *sep, int ctrl) 2862{ 2863 2864 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 2865 /* 2866 * If the fd isn't a listen socket, 2867 * close the individual connection too. 2868 */ 2869 close(ctrl); 2870 return; 2871 } 2872 if (sep->se_socktype != SOCK_DGRAM) { 2873 return; 2874 } 2875 /* 2876 * Drop the single datagram the service would have 2877 * consumed if nowait. If this is a wait service, this 2878 * will consume 1 datagram, and further received packets 2879 * will be removed in the same way. 2880 */ 2881 struct msghdr header = { 2882 /* All fields null, just consume one message */ 2883 }; 2884 ssize_t count; 2885 2886 count = recvmsg(ctrl, &header, 0); 2887 if (count == -1) { 2888 syslog(LOG_ERR, 2889 SERV_FMT ": failed to consume nowait dgram: %s", 2890 SERV_PARAMS(sep), strerror(errno)); 2891 exit(EXIT_FAILURE); 2892 } 2893 DPRINTF(SERV_FMT ": dropped dgram message", 2894 SERV_PARAMS(sep)); 2895} 2896 2897static time_t 2898rl_time(void) 2899{ 2900 struct timespec time; 2901 if(clock_gettime(CLOCK_MONOTONIC, &time) == -1) { 2902 syslog(LOG_ERR, "clock_gettime for rate limiting failed: %s; " 2903 "exiting", strerror(errno)); 2904 /* Exit inetd if rate limiting fails */ 2905 exit(EXIT_FAILURE); 2906 } 2907 return time.tv_sec; 2908} 2909 2910static struct se_ip_list_node* 2911rl_add(struct servtab *sep, char* ip) 2912{ 2913 DPRINTF( 2914 SERV_FMT ": add ip %s to rate limiting tracking", 2915 SERV_PARAMS(sep), ip); 2916 2917 /* 2918 * TODO memory could be saved by using a variable length malloc 2919 * with only the length of ip instead of the existing address field 2920 * NI_MAXHOST in length. 2921 */ 2922 struct se_ip_list_node* temp = malloc(sizeof(*temp)); 2923 if (temp == NULL) { 2924 syslog(LOG_ERR, "Out of memory."); 2925 exit(EXIT_FAILURE); 2926 } 2927 temp->count = 0; 2928 temp->next = NULL; 2929 strlcpy(temp->address, ip, sizeof(temp->address)); 2930 2931 if (sep->se_ip_list_head == NULL) { 2932 /* List empty, insert as head */ 2933 sep->se_ip_list_head = temp; 2934 } else { 2935 /* List not empty, insert as head, point next to prev head */ 2936 temp->next = sep->se_ip_list_head; 2937 sep->se_ip_list_head = temp; 2938 } 2939 2940 return temp; 2941} 2942 2943static void 2944rl_reset(struct servtab *sep, time_t now) 2945{ 2946 DPRINTF(SERV_FMT ": %ji seconds passed; resetting rate limiting ", 2947 SERV_PARAMS(sep), (intmax_t)(now - sep->se_time)); 2948 2949 sep->se_count = 0; 2950 sep->se_time = now; 2951 if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) { 2952 clear_ip_list(sep); 2953 } 2954} 2955 2956static void 2957clear_ip_list(struct servtab *sep) { 2958 struct se_ip_list_node *curr, *next; 2959 curr = sep->se_ip_list_head; 2960 2961 while (curr != NULL) { 2962 next = curr->next; 2963 free(curr); 2964 curr = next; 2965 } 2966 sep->se_ip_list_head = NULL; 2967} 2968 2969static struct se_ip_list_node * 2970rl_try_get_ip(struct servtab *sep, char *ip) 2971{ 2972 struct se_ip_list_node *curr; 2973 2974 DPRINTF( 2975 SERV_FMT ": look up ip %s for ip_max rate limiting", 2976 SERV_PARAMS(sep), ip); 2977 2978 for (curr = sep->se_ip_list_head; curr != NULL; curr = curr->next) { 2979 if (!strncmp(curr->address, ip, NI_MAXHOST)) { 2980 /* IP addr match */ 2981 return curr; 2982 } 2983 } 2984 return NULL; 2985} 2986