1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
--- a/inetd.c
+++ b/inetd.c
@@ -169,6 +169,11 @@
#define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
#define RETRYTIME (60*10) /* retry after bind or server fail */
+#ifdef LIBWRAP
+# include <tcpd.h>
+int lflag = 0;
+#endif
+
int debug = 0;
int maxsock;
int toomany = TOOMANY;
@@ -309,7 +314,7 @@ main(int argc, char *argv[], char *envp[
initsetproctitle(argc, argv, envp);
- while ((ch = getopt(argc, argv, "dER:")) != -1)
+ while ((ch = getopt(argc, argv, "dElR:")) != -1)
switch (ch) {
case 'd':
debug = 1;
@@ -317,6 +322,15 @@ main(int argc, char *argv[], char *envp[
case 'E':
keepenv = 1;
break;
+ case 'l':
+#ifdef LIBWRAP
+ lflag = 1;
+ break;
+#else
+ fprintf(stderr, "%s: libwrap support not enabled",
+ progname);
+ exit(1);
+#endif
case 'R': { /* invocation rate */
char *p;
int val;
@@ -334,7 +348,7 @@ main(int argc, char *argv[], char *envp[
case '?':
default:
fprintf(stderr,
- "usage: inetd [-dE] [-R rate] [configuration_file]\n");
+ "usage: inetd [-dEl] [-R rate] [configuration_file]\n");
exit(1);
}
argc -= optind;
@@ -1800,6 +1814,47 @@ spawn(int ctrl, short events, void *xsep
event_del(&sep->se_event);
}
if (pid == 0) {
+#ifdef LIBWRAP
+ if (lflag && !sep->se_wait && !sep->se_bi && sep->se_socktype == SOCK_STREAM) {
+ struct request_info req;
+ char *service;
+
+ /* do not execute tcpd if it is in the config */
+ if (strcmp(sep->se_server, "/usr/sbin/tcpd") == 0) {
+ char *p, *name;
+
+ free(sep->se_server);
+ name = sep->se_server = sep->se_argv[0];
+ for (p = name; *p; p++)
+ if (*p == '/')
+ name = p + 1;
+ sep->se_argv[0] = newstr(name);
+ }
+
+ request_init(&req, RQ_DAEMON, sep->se_argv[0],
+ RQ_FILE, ctrl, NULL);
+ fromhost(&req);
+ if (getnameinfo(&sep->se_ctrladdr,
+ sizeof(sep->se_ctrladdr), NULL, 0, buf,
+ sizeof(buf), 0) != 0) {
+ /* shouldn't happen */
+ snprintf(buf, sizeof buf, "%d",
+ ntohs(sep->se_ctrladdr_in.sin_port));
+ }
+ service = buf;
+ if (!hosts_access(&req)) {
+ syslog(deny_severity, "refused connection"
+ " from %.500s, service %s (%s)",
+ eval_client(&req), service, sep->se_proto);
+ if (sep->se_socktype != SOCK_STREAM)
+ recv(0, buf, sizeof (buf), 0);
+ exit(1);
+ }
+ syslog(allow_severity,
+ "connection from %.500s, service %s (%s)",
+ eval_client(&req), service, sep->se_proto);
+ }
+#endif
if (sep->se_bi)
(*sep->se_bi->bi_fn)(ctrl, sep);
else {
--- a/inetd.8
+++ b/inetd.8
@@ -39,6 +39,7 @@
.Nm inetd
.Op Fl d
.Op Fl E
+.Op Fl l
.Op Fl R Ar rate
.Op Ar configuration_file
.Sh DESCRIPTION
@@ -66,6 +67,13 @@ from laundering the environment. Withou
potentially harmful environment variables, including
.Pa PATH ,
will be removed and not inherited by services.
+.It Fl l
+Turns on libwrap connection logging and access control.
+Internal services cannot be wrapped. When enabled,
+.Pa /usr/sbin/tcpd
+is silently not executed even if present in
+.Pa /etc/inetd.conf
+and instead libwrap is called directly by inetd.
.It Fl R Ar rate
Specify the maximum number of times a service can be invoked
in one minute; the default is 256.
@@ -336,6 +344,23 @@ rereads its configuration file when it r
.Dv SIGHUP .
Services may be added, deleted or modified when the configuration file
is reread.
+.Ss libwrap
+Support for
+.Tn TCP
+wrappers is included with
+.Nm
+to provide built-in tcpd-like access control functionality.
+An external tcpd program is not needed.
+You do not need to change the
+.Pa /etc/inetd.conf
+server-program entry to enable this capability.
+.Nm
+uses
+.Pa /etc/hosts.allow
+and
+.Pa /etc/hosts.deny
+for access control facility configurations, as described in
+.Xr hosts_access 5 .
.Ss IPv6 TCP/UDP behavior
If you wish to run a server for IPv4 and IPv6 traffic,
you'll need to run two separate processes for the same server program,
|