inetd.c revision 1.136
1/* $NetBSD: inetd.c,v 1.136 2021/09/03 21:02:04 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.136 2021/09/03 21:02:04 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, true, false, echo_stream }, 341 { "echo", SOCK_DGRAM, false, false, echo_dg }, 342 343 /* Internet /dev/null */ 344 { "discard", SOCK_STREAM, true, false, discard_stream }, 345 { "discard", SOCK_DGRAM, false, false, discard_dg }, 346 347 /* Return 32 bit time since 1970 */ 348 { "time", SOCK_STREAM, false, false, machtime_stream }, 349 { "time", SOCK_DGRAM, false, false, machtime_dg }, 350 351 /* Return human-readable time */ 352 { "daytime", SOCK_STREAM, false, false, daytime_stream }, 353 { "daytime", SOCK_DGRAM, false, false, daytime_dg }, 354 355 /* Familiar character generator */ 356 { "chargen", SOCK_STREAM, true, false, chargen_stream }, 357 { "chargen", SOCK_DGRAM, false, false, chargen_dg }, 358 359 { "tcpmux", SOCK_STREAM, true, false, tcpmux }, 360 361 { NULL, 0, false, false, 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 = true; 393 options |= SO_DEBUG; 394 break; 395#ifdef LIBWRAP 396 case 'l': 397 lflag = true; 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 = false; 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 = true; 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 == 0 && 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 = true; 512#else 513 dofork = (sep->se_bi == NULL || 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 == 0 && sep->se_socktype == SOCK_STREAM) 523 close(ctrl); 524 sleep(1); 525 return; 526 } 527 if (pid != 0 && sep->se_wait != 0) { 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 == 0 && 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 == 0 && sep->se_socktype == SOCK_STREAM) { 572 request_init(&req, RQ_DAEMON, sep->se_argv[0] != NULL ? 573 sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL); 574 fromhost(&req); 575 denied = hosts_access(&req) == 0; 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 != NULL) { 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 != NULL) { 607 if (didfork) { 608 for (s = servtab; s != NULL; 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 != NULL && 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 != 0) { 628 if (sep->se_group != NULL) 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 != NULL) { 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 = false; 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, "*") == 0) 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 != 0) { 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 = false; 860 continue; 861 } 862 if (res->ai_next != NULL) { 863 syslog(LOG_ERR, 864 SERV_FMT ": %s: resolved to multiple addr", 865 SERV_PARAMS(sep), 866 sep->se_hostaddr); 867 sep->se_checked = false; 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 = false; 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 = false; 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 = true; 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) == 0) 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) == 0) 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; 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 != NULL) { 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} while (false) 1416 1417#define GETVAL(arg) \ 1418do { \ 1419 if (!isdigit((unsigned char)*(arg))) \ 1420 MALFORMED(arg); \ 1421 val = (int)strtol((arg), &cp0, 10); \ 1422 if (cp0 != NULL) { \ 1423 if (cp0[1] != '\0') \ 1424 MALFORMED((arg)); \ 1425 if (cp0[0] == 'k') \ 1426 val *= 1024; \ 1427 if (cp0[0] == 'm') \ 1428 val *= 1024 * 1024; \ 1429 } \ 1430 if (val < 1) { \ 1431 ERR("%s: invalid buffer size `%s'", \ 1432 sep->se_service, (arg)); \ 1433 freeconfig(sep); \ 1434 goto more; \ 1435 } \ 1436} while (false) 1437 1438#define ASSIGN(arg) \ 1439do { \ 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 (false) 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 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 ERR("%s: too many buffer sizes", sep->se_service); 1473 goto more; 1474 } 1475 1476 /* Locate the size. */ 1477 if ((sz1 = strchr(buf1, '=')) == NULL) 1478 MALFORMED(buf1); 1479 1480 /* Skip the = */ 1481 *sz1++ = '\0'; 1482 } 1483 1484 /* Locate the size. */ 1485 if ((sz0 = strchr(buf0, '=')) == NULL) 1486 MALFORMED(buf0); 1487 1488 /* Skip the = */ 1489 *sz0++ = '\0'; 1490 1491 GETVAL(sz0); 1492 ASSIGN(buf0); 1493 1494 if (buf1 != NULL) { 1495 GETVAL(sz1); 1496 ASSIGN(buf1); 1497 } 1498 } 1499 1500#undef ASSIGN 1501#undef GETVAL 1502#undef MALFORMED 1503 1504 if (parse_protocol(sep)) { 1505 freeconfig(sep); 1506 goto more; 1507 } 1508 1509 /* wait/nowait:max */ 1510 arg = skip(&cp); 1511 if (arg == NULL) { 1512 LOG_TOO_FEW_ARGS(); 1513 freeconfig(sep); 1514 goto more; 1515 } 1516 1517 /* Rate limiting parsing */ { 1518 char *cp1; 1519 if ((cp1 = strchr(arg, ':')) == NULL) 1520 cp1 = strchr(arg, '.'); 1521 if (cp1 != NULL) { 1522 int rstatus; 1523 *cp1++ = '\0'; 1524 sep->se_service_max = (size_t)strtou(cp1, NULL, 10, 0, 1525 SERVTAB_COUNT_MAX, &rstatus); 1526 1527 if (rstatus != 0) { 1528 if (rstatus != ERANGE) { 1529 /* For compatibility with atoi parsing */ 1530 sep->se_service_max = 0; 1531 } 1532 1533 WRN("Improper \"max\" value '%s', " 1534 "using '%zu' instead: %s", 1535 cp1, 1536 sep->se_service_max, 1537 strerror(rstatus)); 1538 } 1539 1540 } else 1541 sep->se_service_max = TOOMANY; 1542 } 1543 if (parse_wait(sep, strcmp(arg, "wait") == 0)) { 1544 freeconfig(sep); 1545 goto more; 1546 } 1547 1548 /* Parse user:group token */ 1549 arg = skip(&cp); 1550 if(arg == NULL) { 1551 LOG_TOO_FEW_ARGS(); 1552 freeconfig(sep); 1553 goto more; 1554 } 1555 char* separator = strchr(arg, ':'); 1556 if (separator == NULL) { 1557 /* Backwards compatibility, allow dot instead of colon */ 1558 separator = strchr(arg, '.'); 1559 } 1560 1561 if (separator == NULL) { 1562 /* Only user was specified */ 1563 sep->se_group = NULL; 1564 } else { 1565 *separator = '\0'; 1566 sep->se_group = newstr(separator + 1); 1567 } 1568 1569 sep->se_user = newstr(arg); 1570 1571 /* Parser server-program (path to binary or "internal") */ 1572 arg = skip(&cp); 1573 if (arg == NULL) { 1574 LOG_TOO_FEW_ARGS(); 1575 freeconfig(sep); 1576 goto more; 1577 } 1578 if (parse_server(sep, arg)) { 1579 freeconfig(sep); 1580 goto more; 1581 } 1582 1583 argc = 0; 1584 for (arg = skip(&cp); cp != NULL; arg = skip(&cp)) { 1585 if (argc < MAXARGV) 1586 sep->se_argv[argc++] = newstr(arg); 1587 } 1588 while (argc <= MAXARGV) 1589 sep->se_argv[argc++] = NULL; 1590#ifdef IPSEC 1591 sep->se_policy = policy != NULL ? newstr(policy) : NULL; 1592#endif 1593 /* getconfigent read a positional service def, move to next line */ 1594 *current_pos = nextline(fconfig); 1595 return (sep); 1596} 1597 1598void 1599freeconfig(struct servtab *cp) 1600{ 1601 int i; 1602 1603 free(cp->se_hostaddr); 1604 free(cp->se_service); 1605 free(cp->se_proto); 1606 free(cp->se_user); 1607 free(cp->se_group); 1608 free(cp->se_server); 1609 for (i = 0; i < MAXARGV; i++) 1610 free(cp->se_argv[i]); 1611#ifdef IPSEC 1612 free(cp->se_policy); 1613#endif 1614} 1615 1616/* 1617 * Get next token *in the current service definition* from config file. 1618 * Allows multi-line parse if single space or single tab-indented. 1619 * Things in quotes are considered single token. 1620 * Advances cp to next token. 1621 */ 1622static char * 1623skip(char **cpp) 1624{ 1625 char *cp = *cpp; 1626 char *start; 1627 char quote; 1628 1629 if (*cpp == NULL) 1630 return (NULL); 1631 1632again: 1633 while (*cp == ' ' || *cp == '\t') 1634 cp++; 1635 if (*cp == '\0') { 1636 int c; 1637 1638 c = getc(fconfig); 1639 (void) ungetc(c, fconfig); 1640 if (c == ' ' || c == '\t') 1641 if ((cp = nextline(fconfig)) != NULL) 1642 goto again; 1643 *cpp = NULL; 1644 return (NULL); 1645 } 1646 start = cp; 1647 /* Parse shell-style quotes */ 1648 quote = '\0'; 1649 while (*cp != '\0' && (quote != '\0' || (*cp != ' ' && *cp != '\t'))) { 1650 if (*cp == '\'' || *cp == '"') { 1651 if (quote != '\0' && *cp != quote) 1652 cp++; 1653 else { 1654 if (quote != '\0') 1655 quote = '\0'; 1656 else 1657 quote = *cp; 1658 memmove(cp, cp+1, strlen(cp)); 1659 } 1660 } else 1661 cp++; 1662 } 1663 if (*cp != '\0') 1664 *cp++ = '\0'; 1665 *cpp = cp; 1666 return (start); 1667} 1668 1669char * 1670nextline(FILE *fd) 1671{ 1672 char *cp; 1673 1674 if (fgets(line, (int)sizeof(line), fd) == NULL) { 1675 if (ferror(fd) != 0) { 1676 ERR("Error when reading next line: %s", strerror(errno)); 1677 } 1678 return NULL; 1679 } 1680 cp = strchr(line, '\n'); 1681 if (cp != NULL) 1682 *cp = '\0'; 1683 line_number++; 1684 return line; 1685} 1686 1687char * 1688newstr(const char *cp) 1689{ 1690 char *dp; 1691 if ((dp = strdup((cp != NULL) ? cp : "")) != NULL) 1692 return (dp); 1693 syslog(LOG_ERR, "strdup: %m"); 1694 exit(EXIT_FAILURE); 1695 /*NOTREACHED*/ 1696} 1697 1698static void 1699inetd_setproctitle(char *a, int s) 1700{ 1701 socklen_t size; 1702 struct sockaddr_storage ss; 1703 char hbuf[NI_MAXHOST]; 1704 const char *hp; 1705 struct sockaddr *sa; 1706 1707 size = sizeof(ss); 1708 sa = (struct sockaddr *)(void *)&ss; 1709 if (getpeername(s, sa, &size) == 0) { 1710 if (getnameinfo(sa, size, hbuf, (socklen_t)sizeof(hbuf), NULL, 1711 0, niflags) != 0) 1712 hp = "?"; 1713 else 1714 hp = hbuf; 1715 setproctitle("-%s [%s]", a, hp); 1716 } else 1717 setproctitle("-%s", a); 1718} 1719 1720static void 1721bump_nofile(void) 1722{ 1723#define FD_CHUNK 32 1724 struct rlimit rl; 1725 1726 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1727 syslog(LOG_ERR, "getrlimit: %m"); 1728 return; 1729 } 1730 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1731 if (rl.rlim_cur <= rlim_ofile_cur) { 1732 syslog(LOG_ERR, 1733 "bump_nofile: cannot extend file limit, max = %d", 1734 (int)rl.rlim_cur); 1735 return; 1736 } 1737 1738 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1739 syslog(LOG_ERR, "setrlimit: %m"); 1740 return; 1741 } 1742 1743 rlim_ofile_cur = rl.rlim_cur; 1744 return; 1745} 1746 1747/* 1748 * Internet services provided internally by inetd: 1749 */ 1750#define BUFSIZE 4096 1751 1752/* ARGSUSED */ 1753static void 1754echo_stream(int s, struct servtab *sep) /* Echo service -- echo data back */ 1755{ 1756 char buffer[BUFSIZE]; 1757 ssize_t i; 1758 1759 inetd_setproctitle(sep->se_service, s); 1760 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1761 write(s, buffer, (size_t)i) > 0) 1762 ; 1763} 1764 1765/* ARGSUSED */ 1766static void 1767echo_dg(int s, struct servtab *sep) /* Echo service -- echo data back */ 1768{ 1769 char buffer[BUFSIZE]; 1770 ssize_t i; 1771 socklen_t size; 1772 struct sockaddr_storage ss; 1773 struct sockaddr *sa; 1774 1775 sa = (struct sockaddr *)(void *)&ss; 1776 size = sizeof(ss); 1777 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, sa, &size)) < 0) 1778 return; 1779 if (port_good_dg(sa)) 1780 (void) sendto(s, buffer, (size_t)i, 0, sa, size); 1781} 1782 1783/* ARGSUSED */ 1784static void 1785discard_stream(int s, struct servtab *sep) /* Discard service -- ignore data */ 1786{ 1787 char buffer[BUFSIZE]; 1788 1789 inetd_setproctitle(sep->se_service, s); 1790 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1791 errno == EINTR) 1792 ; 1793} 1794 1795/* ARGSUSED */ 1796static void 1797discard_dg(int s, struct servtab *sep) /* Discard service -- ignore data */ 1798 1799{ 1800 char buffer[BUFSIZE]; 1801 1802 (void) read(s, buffer, sizeof(buffer)); 1803} 1804 1805#define LINESIZ 72 1806char ring[128]; 1807char *endring; 1808 1809static void 1810initring(void) 1811{ 1812 int i; 1813 1814 endring = ring; 1815 1816 for (i = 0; i <= 128; ++i) 1817 if (isprint(i)) 1818 *endring++ = (char)i; 1819} 1820 1821/* ARGSUSED */ 1822static void 1823chargen_stream(int s, struct servtab *sep) /* Character generator */ 1824{ 1825 size_t len; 1826 char *rs, text[LINESIZ+2]; 1827 1828 inetd_setproctitle(sep->se_service, s); 1829 1830 if (endring == NULL) { 1831 initring(); 1832 rs = ring; 1833 } 1834 1835 text[LINESIZ] = '\r'; 1836 text[LINESIZ + 1] = '\n'; 1837 for (rs = ring;;) { 1838 if ((len = (size_t)(endring - rs)) >= LINESIZ) 1839 memmove(text, rs, LINESIZ); 1840 else { 1841 memmove(text, rs, len); 1842 memmove(text + len, ring, LINESIZ - len); 1843 } 1844 if (++rs == endring) 1845 rs = ring; 1846 if (write(s, text, sizeof(text)) != sizeof(text)) 1847 break; 1848 } 1849} 1850 1851/* ARGSUSED */ 1852static void 1853chargen_dg(int s, struct servtab *sep) /* Character generator */ 1854{ 1855 struct sockaddr_storage ss; 1856 struct sockaddr *sa; 1857 static char *rs; 1858 size_t len; 1859 socklen_t size; 1860 char text[LINESIZ+2]; 1861 1862 if (endring == 0) { 1863 initring(); 1864 rs = ring; 1865 } 1866 1867 sa = (struct sockaddr *)(void *)&ss; 1868 size = sizeof(ss); 1869 if (recvfrom(s, text, sizeof(text), 0, sa, &size) < 0) 1870 return; 1871 1872 if (!port_good_dg(sa)) 1873 return; 1874 1875 if ((len = (size_t)(endring - rs)) >= LINESIZ) 1876 memmove(text, rs, LINESIZ); 1877 else { 1878 memmove(text, rs, len); 1879 memmove(text + len, ring, LINESIZ - len); 1880 } 1881 if (++rs == endring) 1882 rs = ring; 1883 text[LINESIZ] = '\r'; 1884 text[LINESIZ + 1] = '\n'; 1885 (void) sendto(s, text, sizeof(text), 0, sa, size); 1886} 1887 1888/* 1889 * Return a machine readable date and time, in the form of the 1890 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1891 * returns the number of seconds since midnight, Jan 1, 1970, 1892 * we must add 2208988800 seconds to this figure to make up for 1893 * some seventy years Bell Labs was asleep. 1894 */ 1895 1896static uint32_t 1897machtime(void) 1898{ 1899 struct timeval tv; 1900 1901 if (gettimeofday(&tv, NULL) < 0) { 1902 DPRINTF("Unable to get time of day"); 1903 return (0); 1904 } 1905#define OFFSET ((uint32_t)25567 * 24*60*60) 1906 return (htonl((uint32_t)(tv.tv_sec + OFFSET))); 1907#undef OFFSET 1908} 1909 1910/* ARGSUSED */ 1911static void 1912machtime_stream(int s, struct servtab *sep) 1913{ 1914 uint32_t result; 1915 1916 result = machtime(); 1917 (void) write(s, &result, sizeof(result)); 1918} 1919 1920/* ARGSUSED */ 1921void 1922machtime_dg(int s, struct servtab *sep) 1923{ 1924 uint32_t result; 1925 struct sockaddr_storage ss; 1926 struct sockaddr *sa; 1927 socklen_t size; 1928 1929 sa = (struct sockaddr *)(void *)&ss; 1930 size = sizeof(ss); 1931 if (recvfrom(s, &result, sizeof(result), 0, sa, &size) < 0) 1932 return; 1933 if (!port_good_dg(sa)) 1934 return; 1935 result = machtime(); 1936 (void)sendto(s, &result, sizeof(result), 0, sa, size); 1937} 1938 1939/* ARGSUSED */ 1940static void 1941daytime_stream(int s,struct servtab *sep) 1942/* Return human-readable time of day */ 1943{ 1944 char buffer[256]; 1945 time_t clk; 1946 int len; 1947 1948 clk = time((time_t *) 0); 1949 1950 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk)); 1951 (void) write(s, buffer, (size_t)len); 1952} 1953 1954/* ARGSUSED */ 1955void 1956daytime_dg(int s, struct servtab *sep) 1957/* Return human-readable time of day */ 1958{ 1959 char buffer[256]; 1960 time_t clk; 1961 struct sockaddr_storage ss; 1962 struct sockaddr *sa; 1963 socklen_t size; 1964 int len; 1965 1966 clk = time((time_t *) 0); 1967 1968 sa = (struct sockaddr *)(void *)&ss; 1969 size = sizeof(ss); 1970 if (recvfrom(s, buffer, sizeof(buffer), 0, sa, &size) < 0) 1971 return; 1972 if (!port_good_dg(sa)) 1973 return; 1974 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk)); 1975 (void) sendto(s, buffer, (size_t)len, 0, sa, size); 1976} 1977 1978#ifdef DEBUG_ENABLE 1979/* 1980 * print_service: 1981 * Dump relevant information to stderr 1982 */ 1983static void 1984print_service(const char *action, struct servtab *sep) 1985{ 1986 1987 if (isrpcservice(sep)) 1988 fprintf(stderr, 1989 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s" 1990#ifdef IPSEC 1991 " policy=\"%s\"" 1992#endif 1993 "\n", 1994 action, sep->se_service, 1995 sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto, 1996 sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group, 1997 (long)sep->se_bi, sep->se_server 1998#ifdef IPSEC 1999 , (sep->se_policy != NULL ? sep->se_policy : "") 2000#endif 2001 ); 2002 else 2003 fprintf(stderr, 2004 "%s: %s:%s proto=%s%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s" 2005#ifdef IPSEC 2006 " policy=%s" 2007#endif 2008 "\n", 2009 action, sep->se_hostaddr, sep->se_service, 2010 sep->se_type == FAITH_TYPE ? "faith/" : "", 2011 sep->se_proto, 2012 sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group, 2013 (long)sep->se_bi, sep->se_server 2014#ifdef IPSEC 2015 , (sep->se_policy != NULL ? sep->se_policy : "") 2016#endif 2017 ); 2018} 2019#endif 2020 2021static void 2022usage(void) 2023{ 2024#ifdef LIBWRAP 2025 (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname()); 2026#else 2027 (void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname()); 2028#endif 2029 exit(EXIT_FAILURE); 2030} 2031 2032 2033/* 2034 * Based on TCPMUX.C by Mark K. Lottor November 1988 2035 * sri-nic::ps:<mkl>tcpmux.c 2036 */ 2037 2038static int /* # of characters upto \r,\n or \0 */ 2039get_line(int fd, char *buf, int len) 2040{ 2041 int count = 0; 2042 ssize_t n; 2043 2044 do { 2045 n = read(fd, buf, (size_t)(len - count)); 2046 if (n == 0) 2047 return (count); 2048 if (n < 0) 2049 return (-1); 2050 while (--n >= 0) { 2051 if (*buf == '\r' || *buf == '\n' || *buf == '\0') 2052 return (count); 2053 count++; 2054 buf++; 2055 } 2056 } while (count < len); 2057 return (count); 2058} 2059 2060#define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ 2061 2062#define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) 2063 2064static void 2065tcpmux(int ctrl, struct servtab *sep) 2066{ 2067 char service[MAX_SERV_LEN+1]; 2068 int len; 2069 2070 /* Get requested service name */ 2071 if ((len = get_line(ctrl, service, MAX_SERV_LEN)) < 0) { 2072 strwrite(ctrl, "-Error reading service name\r\n"); 2073 goto reject; 2074 } 2075 service[len] = '\0'; 2076 2077 DPRINTF("tcpmux: %s: service requested", service); 2078 2079 /* 2080 * Help is a required command, and lists available services, 2081 * one per line. 2082 */ 2083 if (strcasecmp(service, "help") == 0) { 2084 strwrite(ctrl, "+Available services:\r\n"); 2085 strwrite(ctrl, "help\r\n"); 2086 for (sep = servtab; sep != NULL; sep = sep->se_next) { 2087 if (!ISMUX(sep)) 2088 continue; 2089 (void)write(ctrl, sep->se_service, 2090 strlen(sep->se_service)); 2091 strwrite(ctrl, "\r\n"); 2092 } 2093 goto reject; 2094 } 2095 2096 /* Try matching a service in inetd.conf with the request */ 2097 for (sep = servtab; sep != NULL; sep = sep->se_next) { 2098 if (!ISMUX(sep)) 2099 continue; 2100 if (strcasecmp(service, sep->se_service) == 0) { 2101 if (ISMUXPLUS(sep)) 2102 strwrite(ctrl, "+Go\r\n"); 2103 run_service(ctrl, sep, true /* forked */); 2104 return; 2105 } 2106 } 2107 strwrite(ctrl, "-Service not available\r\n"); 2108reject: 2109 _exit(EXIT_FAILURE); 2110} 2111 2112/* 2113 * check if the address/port where send data to is one of the obvious ports 2114 * that are used for denial of service attacks like two echo ports 2115 * just echoing data between them 2116 */ 2117static int 2118port_good_dg(struct sockaddr *sa) 2119{ 2120 struct in_addr in; 2121 struct sockaddr_in *sin; 2122#ifdef INET6 2123 struct in6_addr *in6; 2124 struct sockaddr_in6 *sin6; 2125#endif 2126 u_int16_t port; 2127 int i; 2128 char hbuf[NI_MAXHOST]; 2129 2130 switch (sa->sa_family) { 2131 case AF_INET: 2132 sin = (struct sockaddr_in *)(void *)sa; 2133 in.s_addr = ntohl(sin->sin_addr.s_addr); 2134 port = ntohs(sin->sin_port); 2135#ifdef INET6 2136 v4chk: 2137#endif 2138 if (IN_MULTICAST(in.s_addr)) 2139 goto bad; 2140 switch ((in.s_addr & 0xff000000) >> 24) { 2141 case 0: case 127: case 255: 2142 goto bad; 2143 } 2144 if (dg_broadcast(&in)) 2145 goto bad; 2146 break; 2147#ifdef INET6 2148 case AF_INET6: 2149 sin6 = (struct sockaddr_in6 *)(void *)sa; 2150 in6 = &sin6->sin6_addr; 2151 port = ntohs(sin6->sin6_port); 2152 if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6)) 2153 goto bad; 2154 if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) { 2155 memcpy(&in, &in6->s6_addr[12], sizeof(in)); 2156 in.s_addr = ntohl(in.s_addr); 2157 goto v4chk; 2158 } 2159 break; 2160#endif 2161 default: 2162 /* XXX unsupported af, is it safe to assume it to be safe? */ 2163 return true; 2164 } 2165 2166 for (i = 0; bad_ports[i] != 0; i++) { 2167 if (port == bad_ports[i]) 2168 goto bad; 2169 } 2170 2171 return true; 2172 2173bad: 2174 if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0, 2175 niflags) != 0) 2176 strlcpy(hbuf, "?", sizeof(hbuf)); 2177 syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d", 2178 hbuf, port); 2179 return false; 2180} 2181 2182/* XXX need optimization */ 2183static int 2184dg_broadcast(struct in_addr *in) 2185{ 2186 struct ifaddrs *ifa, *ifap; 2187 struct sockaddr_in *sin; 2188 2189 if (getifaddrs(&ifap) < 0) 2190 return false; 2191 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 2192 if (ifa->ifa_addr->sa_family != AF_INET || 2193 (ifa->ifa_flags & IFF_BROADCAST) == 0) 2194 continue; 2195 sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr; 2196 if (sin->sin_addr.s_addr == in->s_addr) { 2197 freeifaddrs(ifap); 2198 return true; 2199 } 2200 } 2201 freeifaddrs(ifap); 2202 return false; 2203} 2204 2205static int 2206my_kevent(const struct kevent *changelist, size_t nchanges, 2207 struct kevent *eventlist, size_t nevents) 2208{ 2209 int result; 2210 2211 while ((result = kevent(kq, changelist, nchanges, eventlist, nevents, 2212 NULL)) < 0) 2213 if (errno != EINTR) { 2214 syslog(LOG_ERR, "kevent: %m"); 2215 exit(EXIT_FAILURE); 2216 } 2217 2218 return (result); 2219} 2220 2221static struct kevent * 2222allocchange(void) 2223{ 2224 if (changes == __arraycount(changebuf)) { 2225 (void) my_kevent(changebuf, __arraycount(changebuf), NULL, 0); 2226 changes = 0; 2227 } 2228 2229 return (&changebuf[changes++]); 2230} 2231 2232static void 2233config_root(void) 2234{ 2235 struct servtab *sep; 2236 /* Uncheck services */ 2237 for (sep = servtab; sep != NULL; sep = sep->se_next) { 2238 sep->se_checked = false; 2239 } 2240 defhost = newstr("*"); 2241#ifdef IPSEC 2242 policy = NULL; 2243#endif 2244 fconfig = NULL; 2245 config(); 2246 purge_unchecked(); 2247} 2248 2249static void 2250purge_unchecked(void) 2251{ 2252 struct servtab *sep, **sepp = &servtab; 2253 int servtab_count = 0; 2254 while ((sep = *sepp) != NULL) { 2255 if (sep->se_checked) { 2256 sepp = &sep->se_next; 2257 servtab_count++; 2258 continue; 2259 } 2260 *sepp = sep->se_next; 2261 if (sep->se_fd >= 0) 2262 close_sep(sep); 2263 if (isrpcservice(sep)) 2264 unregister_rpc(sep); 2265 if (sep->se_family == AF_LOCAL) 2266 (void)unlink(sep->se_service); 2267#ifdef DEBUG_ENABLE 2268 if (debug) 2269 print_service("FREE", sep); 2270#endif 2271 freeconfig(sep); 2272 free(sep); 2273 } 2274 DPRINTF("%d service(s) loaded.", servtab_count); 2275} 2276 2277static bool 2278is_same_service(const struct servtab *sep, const struct servtab *cp) 2279{ 2280 return 2281 strcmp(sep->se_service, cp->se_service) == 0 && 2282 strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 && 2283 strcmp(sep->se_proto, cp->se_proto) == 0 && 2284 sep->se_family == cp->se_family && 2285 ISMUX(sep) == ISMUX(cp); 2286} 2287 2288int 2289parse_protocol(struct servtab *sep) 2290{ 2291 int val; 2292 2293 if (strcmp(sep->se_proto, "unix") == 0) { 2294 sep->se_family = AF_LOCAL; 2295 } else { 2296 val = (int)strlen(sep->se_proto); 2297 if (val == 0) { 2298 ERR("%s: invalid protocol specified", 2299 sep->se_service); 2300 return -1; 2301 } 2302 val = sep->se_proto[val - 1]; 2303 switch (val) { 2304 case '4': /*tcp4 or udp4*/ 2305 sep->se_family = AF_INET; 2306 break; 2307#ifdef INET6 2308 case '6': /*tcp6 or udp6*/ 2309 sep->se_family = AF_INET6; 2310 break; 2311#endif 2312 default: 2313 /* Use 'default' IP version which is IPv4, may eventually be 2314 * changed to AF_INET6 */ 2315 sep->se_family = AF_INET; 2316 break; 2317 } 2318 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 2319#ifdef RPC 2320 char *cp1, *ccp; 2321 cp1 = strchr(sep->se_service, '/'); 2322 if (cp1 == 0) { 2323 ERR("%s: no rpc version", 2324 sep->se_service); 2325 return -1; 2326 } 2327 *cp1++ = '\0'; 2328 sep->se_rpcversl = sep->se_rpcversh = 2329 (int)strtol(cp1, &ccp, 0); 2330 if (ccp == cp1) { 2331 badafterall: 2332 ERR("%s/%s: bad rpc version", 2333 sep->se_service, cp1); 2334 return -1; 2335 } 2336 if (*ccp == '-') { 2337 cp1 = ccp + 1; 2338 sep->se_rpcversh = (int)strtol(cp1, &ccp, 0); 2339 if (ccp == cp1) 2340 goto badafterall; 2341 } 2342#else 2343 ERR("%s: rpc services not supported", 2344 sep->se_service); 2345 return -1; 2346#endif /* RPC */ 2347 } 2348 } 2349 return 0; 2350} 2351 2352int 2353parse_wait(struct servtab *sep, int wait) 2354{ 2355 if (!ISMUX(sep)) { 2356 sep->se_wait = wait; 2357 return 0; 2358 } 2359 /* 2360 * Silently enforce "nowait" for TCPMUX services since 2361 * they don't have an assigned port to listen on. 2362 */ 2363 sep->se_wait = 0; 2364 2365 if (strncmp(sep->se_proto, "tcp", 3)) { 2366 ERR("bad protocol for tcpmux service %s", 2367 sep->se_service); 2368 return -1; 2369 } 2370 if (sep->se_socktype != SOCK_STREAM) { 2371 ERR("bad socket type for tcpmux service %s", 2372 sep->se_service); 2373 return -1; 2374 } 2375 return 0; 2376} 2377 2378int 2379parse_server(struct servtab *sep, const char *arg){ 2380 sep->se_server = newstr(arg); 2381 if (strcmp(sep->se_server, "internal") != 0) { 2382 sep->se_bi = NULL; 2383 return 0; 2384 } 2385 struct biltin *bi; 2386 2387 for (bi = biltins; bi->bi_service; bi++) 2388 if (bi->bi_socktype == sep->se_socktype && 2389 strcmp(bi->bi_service, sep->se_service) == 0) 2390 break; 2391 if (bi->bi_service == NULL) { 2392 ERR("Internal service %s unknown", 2393 sep->se_service); 2394 return -1; 2395 } 2396 sep->se_bi = bi; 2397 sep->se_wait = bi->bi_wait; 2398 return 0; 2399} 2400 2401/* TODO test to make sure accept filter still works */ 2402void 2403parse_accept_filter(char *arg, struct servtab *sep) { 2404 char *accf, *accf_arg; 2405 /* one and only one accept filter */ 2406 accf = strchr(arg, ':'); 2407 if (accf == NULL) 2408 return; 2409 if (accf != strrchr(arg, ':') || *(accf + 1) == '\0') { 2410 /* more than one || nothing beyond */ 2411 sep->se_socktype = -1; 2412 return; 2413 } 2414 2415 accf++; /* skip delimiter */ 2416 strlcpy(sep->se_accf.af_name, accf, sizeof(sep->se_accf.af_name)); 2417 accf_arg = strchr(accf, ','); 2418 if (accf_arg == NULL) /* zero or one arg, no more */ 2419 return; 2420 2421 if (strrchr(accf, ',') != accf_arg) { 2422 sep->se_socktype = -1; 2423 } else { 2424 accf_arg++; 2425 strlcpy(sep->se_accf.af_arg, accf_arg, 2426 sizeof(sep->se_accf.af_arg)); 2427 } 2428} 2429 2430void 2431parse_socktype(char* arg, struct servtab* sep) 2432{ 2433 /* stream socket may have an accept filter, only check first chars */ 2434 if (strncmp(arg, "stream", sizeof("stream") - 1) == 0) 2435 sep->se_socktype = SOCK_STREAM; 2436 else if (strcmp(arg, "dgram") == 0) 2437 sep->se_socktype = SOCK_DGRAM; 2438 else if (strcmp(arg, "rdm") == 0) 2439 sep->se_socktype = SOCK_RDM; 2440 else if (strcmp(arg, "seqpacket") == 0) 2441 sep->se_socktype = SOCK_SEQPACKET; 2442 else if (strcmp(arg, "raw") == 0) 2443 sep->se_socktype = SOCK_RAW; 2444 else 2445 sep->se_socktype = -1; 2446} 2447 2448static struct servtab 2449init_servtab(void) 2450{ 2451 /* This does not set every field to default. See enter() as well */ 2452 return (struct servtab) { 2453 /* 2454 * Set se_max to non-zero so uninitialized value is not 2455 * a valid value. Useful in v2 syntax parsing. 2456 */ 2457 .se_service_max = SERVTAB_UNSPEC_SIZE_T, 2458 .se_ip_max = SERVTAB_UNSPEC_SIZE_T, 2459 .se_wait = SERVTAB_UNSPEC_VAL, 2460 .se_socktype = SERVTAB_UNSPEC_VAL 2461 /* All other fields initialized to 0 or null */ 2462 }; 2463} 2464 2465/* Include directives bookkeeping structure */ 2466struct file_list { 2467 /* Absolute path used for checking for circular references */ 2468 char *abs; 2469 /* Pointer to the absolute path of the parent config file, 2470 * on the stack */ 2471 struct file_list *next; 2472} *file_list_head; 2473 2474static void 2475include_configs(char *pattern) 2476{ 2477 /* Allocate global per-config state on the thread stack */ 2478 const char* save_CONFIG; 2479 FILE *save_fconfig; 2480 size_t save_line_number; 2481 char *save_defhost; 2482 struct file_list new_file; 2483#ifdef IPSEC 2484 char *save_policy; 2485#endif 2486 2487 /* Store current globals on the stack */ 2488 save_CONFIG = CONFIG; 2489 save_fconfig = fconfig; 2490 save_line_number = line_number; 2491 save_defhost = defhost; 2492 new_file.abs = realpath(CONFIG, NULL); 2493 new_file.next = file_list_head; 2494#ifdef IPSEC 2495 save_policy = policy; 2496#endif 2497 /* Put new_file at the top of the config stack */ 2498 file_list_head = &new_file; 2499 read_glob_configs(pattern); 2500 free(new_file.abs); 2501 /* Pop new_file off the stack */ 2502 file_list_head = new_file.next; 2503 2504 /* Restore global per-config state */ 2505 CONFIG = save_CONFIG; 2506 fconfig = save_fconfig; 2507 line_number = save_line_number; 2508 defhost = save_defhost; 2509#ifdef IPSEC 2510 policy = save_policy; 2511#endif 2512} 2513 2514static void 2515prepare_next_config(const char *file_name) 2516{ 2517 /* Setup new state that is normally only done in main */ 2518 CONFIG = file_name; 2519 2520 /* Inherit default host and IPsec policy */ 2521 defhost = newstr(defhost); 2522 2523#ifdef IPSEC 2524 policy = (policy == NULL) ? NULL : newstr(policy); 2525#endif 2526} 2527 2528static void 2529read_glob_configs(char *pattern) { 2530 glob_t results; 2531 char *full_pattern; 2532 int glob_result; 2533 full_pattern = gen_file_pattern(CONFIG, pattern); 2534 2535 DPRINTCONF("Found include directive '%s'", full_pattern); 2536 2537 glob_result = glob(full_pattern, GLOB_NOSORT, glob_error, &results); 2538 switch(glob_result) { 2539 case 0: 2540 /* No glob errors */ 2541 break; 2542 case GLOB_ABORTED: 2543 ERR("Error while searching for include files"); 2544 break; 2545 case GLOB_NOMATCH: 2546 /* It's fine if no files were matched. */ 2547 DPRINTCONF("No files matched pattern '%s'", full_pattern); 2548 break; 2549 case GLOB_NOSPACE: 2550 ERR("Error when searching for include files: %s", 2551 strerror(errno)); 2552 break; 2553 default: 2554 ERR("Unknown glob(3) error %d", errno); 2555 break; 2556 } 2557 free(full_pattern); 2558 2559 for (size_t i = 0; i < results.gl_pathc; i++) { 2560 include_matched_path(results.gl_pathv[i]); 2561 } 2562 2563 globfree(&results); 2564} 2565 2566static void 2567include_matched_path(char *glob_path) 2568{ 2569 struct stat sb; 2570 char *tmp; 2571 2572 if (lstat(glob_path, &sb) != 0) { 2573 ERR("Error calling stat on path '%s': %s", glob_path, 2574 strerror(errno)); 2575 return; 2576 } 2577 2578 if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) { 2579 DPRINTCONF("'%s' is not a file.", glob_path); 2580 ERR("The matched path '%s' is not a regular file", glob_path); 2581 return; 2582 } 2583 2584 DPRINTCONF("Include '%s'", glob_path); 2585 2586 if (S_ISLNK(sb.st_mode)) { 2587 tmp = glob_path; 2588 glob_path = realpath(tmp, NULL); 2589 } 2590 2591 /* Ensure the file is not being reincluded .*/ 2592 if (check_no_reinclude(glob_path)) { 2593 prepare_next_config(glob_path); 2594 config(); 2595 } else { 2596 DPRINTCONF("File '%s' already included in current include " 2597 "chain", glob_path); 2598 WRN("Including file '%s' would cause a circular " 2599 "dependency", glob_path); 2600 } 2601 2602 if (S_ISLNK(sb.st_mode)) { 2603 free(glob_path); 2604 glob_path = tmp; 2605 } 2606} 2607 2608static bool 2609check_no_reinclude(const char *glob_path) 2610{ 2611 struct file_list *cur = file_list_head; 2612 char *abs_path = realpath(glob_path, NULL); 2613 2614 if (abs_path == NULL) { 2615 ERR("Error checking real path for '%s': %s", 2616 glob_path, strerror(errno)); 2617 return false; 2618 } 2619 2620 DPRINTCONF("Absolute path '%s'", abs_path); 2621 2622 for (cur = file_list_head; cur != NULL; cur = cur->next) { 2623 if (strcmp(cur->abs, abs_path) == 0) { 2624 /* file included more than once */ 2625 /* TODO relative or abs path for logging error? */ 2626 free(abs_path); 2627 return false; 2628 } 2629 } 2630 free(abs_path); 2631 return true; 2632} 2633 2634/* Resolve the pattern relative to the config file the pattern is from */ 2635static char * 2636gen_file_pattern(const char *cur_config, const char *pattern) 2637{ 2638 if (pattern[0] == '/') { 2639 /* Absolute paths don't need any normalization */ 2640 return newstr(pattern); 2641 } 2642 2643 /* pattern is relative */ 2644 /* Find the end of the file's directory */ 2645 size_t i, last = 0; 2646 for (i = 0; cur_config[i] != '\0'; i++) { 2647 if (cur_config[i] == '/') { 2648 last = i; 2649 } 2650 } 2651 2652 if (last == 0) { 2653 /* cur_config is just a filename, pattern already correct */ 2654 return newstr(pattern); 2655 } 2656 2657 /* Relativize pattern to cur_config file's directory */ 2658 char *full_pattern = malloc(last + 1 + strlen(pattern) + 1); 2659 if (full_pattern == NULL) { 2660 syslog(LOG_ERR, "Out of memory."); 2661 exit(EXIT_FAILURE); 2662 } 2663 memcpy(full_pattern, cur_config, last); 2664 full_pattern[last] = '/'; 2665 strcpy(&full_pattern[last + 1], pattern); 2666 return full_pattern; 2667} 2668 2669static int 2670glob_error(const char *path, int error) 2671{ 2672 WRN("Error while resolving path '%s': %s", path, strerror(error)); 2673 return 0; 2674} 2675 2676/* Return 0 on allow, -1 if connection should be blocked */ 2677static int 2678rl_process(struct servtab *sep, int ctrl) 2679{ 2680 struct se_ip_list_node *node; 2681 time_t now = 0; /* 0 prevents GCC from complaining */ 2682 bool istimevalid = false; 2683 char hbuf[NI_MAXHOST]; 2684 2685 DPRINTF(SERV_FMT ": processing rate-limiting", 2686 SERV_PARAMS(sep)); 2687 DPRINTF(SERV_FMT ": se_service_max " 2688 "%zu and se_count %zu", SERV_PARAMS(sep), 2689 sep->se_service_max, sep->se_count); 2690 2691 /* se_count is incremented if rl_process will return 0 */ 2692 if (sep->se_count == 0) { 2693 now = rl_time(); 2694 sep->se_time = now; 2695 istimevalid = true; 2696 } 2697 2698 if (sep->se_count >= sep->se_service_max) { 2699 if(!istimevalid) { 2700 now = rl_time(); 2701 istimevalid = true; 2702 } 2703 2704 if (now - sep->se_time > CNT_INTVL) { 2705 rl_reset(sep, now); 2706 } else { 2707 syslog(LOG_ERR, 2708 SERV_FMT ": max spawn rate (%zu in %ji seconds) " 2709 "already met, closing until end of timeout in " 2710 "%ju seconds", 2711 SERV_PARAMS(sep), 2712 sep->se_service_max, 2713 (intmax_t)CNT_INTVL, 2714 (uintmax_t)RETRYTIME); 2715 2716 DPRINTF(SERV_FMT ": service not started", 2717 SERV_PARAMS(sep)); 2718 2719 rl_drop_connection(sep, ctrl); 2720 2721 /* Close the server for 10 minutes */ 2722 close_sep(sep); 2723 if (!timingout) { 2724 timingout = true; 2725 alarm(RETRYTIME); 2726 } 2727 2728 return -1; 2729 } 2730 } 2731 2732 if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) { 2733 rl_get_name(sep, ctrl, hbuf); 2734 node = rl_try_get_ip(sep, hbuf); 2735 if(node == NULL) { 2736 node = rl_add(sep, hbuf); 2737 } 2738 2739 DPRINTF( 2740 SERV_FMT ": se_ip_max %zu and ip_count %zu", 2741 SERV_PARAMS(sep), sep->se_ip_max, node->count); 2742 2743 if (node->count >= sep->se_ip_max) { 2744 if (!istimevalid) { 2745 /* 2746 * Only get the clock time if we didn't 2747 * already 2748 */ 2749 now = rl_time(); 2750 istimevalid = true; 2751 } 2752 2753 if (now - sep->se_time > CNT_INTVL) { 2754 rl_reset(sep, now); 2755 node = rl_add(sep, hbuf); 2756 } else { 2757 if (debug && node->count == sep->se_ip_max) { 2758 /* 2759 * Only log first failed request to 2760 * prevent DoS attack writing to system 2761 * log 2762 */ 2763 syslog(LOG_ERR, SERV_FMT 2764 ": max ip spawn rate (%zu in " 2765 "%ji seconds) for " 2766 "%." TOSTRING(NI_MAXHOST) "s " 2767 "already met; service not started", 2768 SERV_PARAMS(sep), 2769 sep->se_ip_max, 2770 (intmax_t)CNT_INTVL, 2771 node->address); 2772 } 2773 2774 DPRINTF(SERV_FMT ": service not started", 2775 SERV_PARAMS(sep)); 2776 2777 rl_drop_connection(sep, ctrl); 2778 /* 2779 * Increment so debug-syslog message will 2780 * trigger only once 2781 */ 2782 node->count++; 2783 return -1; 2784 } 2785 } 2786 node->count++; 2787 } 2788 2789 DPRINTF(SERV_FMT ": running service ", SERV_PARAMS(sep)); 2790 2791 sep->se_count++; 2792 return 0; 2793} 2794 2795/* Get the remote's IP address in textual form into hbuf of size NI_MAXHOST */ 2796static void 2797rl_get_name(struct servtab *sep, int ctrl, char *hbuf) 2798{ 2799 struct sockaddr_storage addr; 2800 socklen_t len = sizeof(struct sockaddr_storage); 2801 switch (sep->se_socktype) { 2802 case SOCK_STREAM: 2803 if (getpeername(ctrl, (struct sockaddr *)&addr, &len) != 0) { 2804 /* error, log it and skip ip rate limiting */ 2805 syslog(LOG_ERR, 2806 SERV_FMT " failed to get peer name of the " 2807 "connection", SERV_PARAMS(sep)); 2808 exit(EXIT_FAILURE); 2809 } 2810 break; 2811 case SOCK_DGRAM: { 2812 struct msghdr header = { 2813 .msg_name = &addr, 2814 .msg_namelen = sizeof(struct sockaddr_storage), 2815 /* scatter/gather and control info is null */ 2816 }; 2817 ssize_t count; 2818 2819 /* Peek so service can still get the packet */ 2820 count = recvmsg(ctrl, &header, MSG_PEEK); 2821 if (count == -1) { 2822 syslog(LOG_ERR, 2823 "failed to get dgram source address: %s; exiting", 2824 strerror(errno)); 2825 exit(EXIT_FAILURE); 2826 } 2827 break; 2828 } 2829 default: 2830 DPRINTF(SERV_FMT ": ip_max rate limiting not supported for " 2831 "socktype", SERV_PARAMS(sep)); 2832 syslog(LOG_ERR, SERV_FMT 2833 ": ip_max rate limiting not supported for socktype", 2834 SERV_PARAMS(sep)); 2835 exit(EXIT_FAILURE); 2836 } 2837 2838 if (getnameinfo((struct sockaddr *)&addr, 2839 addr.ss_len, hbuf, 2840 NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) { 2841 /* error, log it and skip ip rate limiting */ 2842 syslog(LOG_ERR, 2843 SERV_FMT ": failed to get name info of the incoming " 2844 "connection; exiting", 2845 SERV_PARAMS(sep)); 2846 exit(EXIT_FAILURE); 2847 } 2848} 2849 2850static void 2851rl_drop_connection(struct servtab *sep, int ctrl) 2852{ 2853 2854 if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) { 2855 /* 2856 * If the fd isn't a listen socket, 2857 * close the individual connection too. 2858 */ 2859 close(ctrl); 2860 return; 2861 } 2862 if (sep->se_socktype != SOCK_DGRAM) { 2863 return; 2864 } 2865 /* 2866 * Drop the single datagram the service would have 2867 * consumed if nowait. If this is a wait service, this 2868 * will consume 1 datagram, and further received packets 2869 * will be removed in the same way. 2870 */ 2871 struct msghdr header = { 2872 /* All fields null, just consume one message */ 2873 }; 2874 ssize_t count; 2875 2876 count = recvmsg(ctrl, &header, 0); 2877 if (count == -1) { 2878 syslog(LOG_ERR, 2879 SERV_FMT ": failed to consume nowait dgram: %s", 2880 SERV_PARAMS(sep), strerror(errno)); 2881 exit(EXIT_FAILURE); 2882 } 2883 DPRINTF(SERV_FMT ": dropped dgram message", 2884 SERV_PARAMS(sep)); 2885} 2886 2887static time_t 2888rl_time(void) 2889{ 2890 struct timespec time; 2891 if(clock_gettime(CLOCK_MONOTONIC, &time) == -1) { 2892 syslog(LOG_ERR, "clock_gettime for rate limiting failed: %s; " 2893 "exiting", strerror(errno)); 2894 /* Exit inetd if rate limiting fails */ 2895 exit(EXIT_FAILURE); 2896 } 2897 return time.tv_sec; 2898} 2899 2900static struct se_ip_list_node* 2901rl_add(struct servtab *sep, char* ip) 2902{ 2903 DPRINTF( 2904 SERV_FMT ": add ip %s to rate limiting tracking", 2905 SERV_PARAMS(sep), ip); 2906 2907 /* 2908 * TODO memory could be saved by using a variable length malloc 2909 * with only the length of ip instead of the existing address field 2910 * NI_MAXHOST in length. 2911 */ 2912 struct se_ip_list_node* temp = malloc(sizeof(*temp)); 2913 if (temp == NULL) { 2914 syslog(LOG_ERR, "Out of memory."); 2915 exit(EXIT_FAILURE); 2916 } 2917 temp->count = 0; 2918 temp->next = NULL; 2919 strlcpy(temp->address, ip, sizeof(temp->address)); 2920 2921 if (sep->se_ip_list_head == NULL) { 2922 /* List empty, insert as head */ 2923 sep->se_ip_list_head = temp; 2924 } else { 2925 /* List not empty, insert as head, point next to prev head */ 2926 temp->next = sep->se_ip_list_head; 2927 sep->se_ip_list_head = temp; 2928 } 2929 2930 return temp; 2931} 2932 2933static void 2934rl_reset(struct servtab *sep, time_t now) 2935{ 2936 DPRINTF(SERV_FMT ": %ji seconds passed; resetting rate limiting ", 2937 SERV_PARAMS(sep), (intmax_t)(now - sep->se_time)); 2938 2939 sep->se_count = 0; 2940 sep->se_time = now; 2941 if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) { 2942 clear_ip_list(sep); 2943 } 2944} 2945 2946static void 2947clear_ip_list(struct servtab *sep) { 2948 struct se_ip_list_node *curr, *next; 2949 curr = sep->se_ip_list_head; 2950 2951 while (curr != NULL) { 2952 next = curr->next; 2953 free(curr); 2954 curr = next; 2955 } 2956 sep->se_ip_list_head = NULL; 2957} 2958 2959static struct se_ip_list_node * 2960rl_try_get_ip(struct servtab *sep, char *ip) 2961{ 2962 struct se_ip_list_node *curr; 2963 2964 DPRINTF( 2965 SERV_FMT ": look up ip %s for ip_max rate limiting", 2966 SERV_PARAMS(sep), ip); 2967 2968 for (curr = sep->se_ip_list_head; curr != NULL; curr = curr->next) { 2969 if (!strncmp(curr->address, ip, NI_MAXHOST)) { 2970 /* IP addr match */ 2971 return curr; 2972 } 2973 } 2974 return NULL; 2975} 2976