chiark / gitweb /
socket: add optional libwrap support
authorLennart Poettering <lennart@poettering.net>
Wed, 16 Jun 2010 13:41:29 +0000 (15:41 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 16 Jun 2010 13:41:29 +0000 (15:41 +0200)
Makefile.am
configure.ac
m4/acx_libwrap.m4 [new file with mode: 0644]
src/dbus-socket.c
src/load-fragment.c
src/logger.c
src/socket.c
src/socket.h
src/tcpwrap.c [new file with mode: 0644]
src/tcpwrap.h [new file with mode: 0644]

index e50ae82040655c6e25b0b2ef1267d774cd04d9b9..c78968fc0369aed780bce84fa52bb4d27f0f3b8f 100644 (file)
@@ -241,7 +241,8 @@ COMMON_SOURCES = \
        src/specifier.c \
        src/unit-name.c \
        src/fdset.c \
        src/specifier.c \
        src/unit-name.c \
        src/fdset.c \
-       src/namespace.c
+       src/namespace.c \
+       src/tcpwrap.c
 
 EXTRA_DIST += \
        ${COMMON_SOURCES:.c=.h} \
 
 EXTRA_DIST += \
        ${COMMON_SOURCES:.c=.h} \
@@ -288,7 +289,8 @@ systemd_CFLAGS = \
 systemd_LDADD = \
        $(DBUS_LIBS) \
        $(UDEV_LIBS) \
 systemd_LDADD = \
        $(DBUS_LIBS) \
        $(UDEV_LIBS) \
-       $(CGROUP_LIBS)
+       $(CGROUP_LIBS) \
+       $(LIBWRAP_LIBS)
 
 test_engine_SOURCES = \
        $(COMMON_SOURCES) \
 
 test_engine_SOURCES = \
        $(COMMON_SOURCES) \
@@ -325,7 +327,11 @@ test_daemon_SOURCES = \
 systemd_logger_SOURCES = \
        $(BASIC_SOURCES) \
        src/logger.c \
 systemd_logger_SOURCES = \
        $(BASIC_SOURCES) \
        src/logger.c \
-       src/sd-daemon.c
+       src/sd-daemon.c \
+       src/tcpwrap.c
+
+systemd_logger_LDADD = \
+       $(LIBWRAP_LIBS)
 
 systemd_initctl_SOURCES = \
        $(BASIC_SOURCES) \
 
 systemd_initctl_SOURCES = \
        $(BASIC_SOURCES) \
index 02618ae637a79c0a8983a2632a12fb3e251ae81f..ae2520044223e9fd097edcb05aebec183ec4a031 100644 (file)
@@ -108,6 +108,30 @@ PKG_CHECK_MODULES(CGROUP, [ libcgroup >= 0.36 ])
 AC_SUBST(CGROUP_CFLAGS)
 AC_SUBST(CGROUP_LIBS)
 
 AC_SUBST(CGROUP_CFLAGS)
 AC_SUBST(CGROUP_LIBS)
 
+AC_ARG_ENABLE([tcpwrap],
+        AS_HELP_STRING([--disable-tcpwrap],[Disable optional TCP wrappers support]),
+                [case "${enableval}" in
+                        yes) tcpwrap=yes ;;
+                        no) tcpwrap=no ;;
+                        *) AC_MSG_ERROR(bad value ${enableval} for --disable-tcpwrap) ;;
+                esac],
+                [tcpwrap=auto])
+
+if test "x${tcpwrap}" != xno ; then
+        ACX_LIBWRAP
+        if test "x${LIBWRAP_LIBS}" = x ; then
+                if test "x$tcpwrap" = xyes ; then
+                        AC_MSG_ERROR([*** TCP wrappers support not found])
+                fi
+        else
+                tcpwrap=yes
+        fi
+else
+    LIBWRAP_LIBS=
+fi
+
+AC_SUBST(LIBWRAP_LIBS)
+
 have_gtk=no
 AC_ARG_ENABLE(gtk, AS_HELP_STRING([--disable-gtk], [disable GTK tools]))
 if test "x$enable_gtk" != "xno"; then
 have_gtk=no
 AC_ARG_ENABLE(gtk, AS_HELP_STRING([--disable-gtk], [disable GTK tools]))
 if test "x$enable_gtk" != "xno"; then
@@ -312,6 +336,7 @@ echo "
         Syslog service:          ${SPECIAL_SYSLOG_SERVICE}
         D-Bus service:           ${SPECIAL_DBUS_SERVICE}
         Gtk:                     ${have_gtk}
         Syslog service:          ${SPECIAL_SYSLOG_SERVICE}
         D-Bus service:           ${SPECIAL_DBUS_SERVICE}
         Gtk:                     ${have_gtk}
+        tcpwrap:                 ${tcpwrap}
         prefix:                  ${prefix}
         root dir:                ${with_rootdir}
         udev rules dir:          ${with_udevrulesdir}
         prefix:                  ${prefix}
         root dir:                ${with_rootdir}
         udev rules dir:          ${with_udevrulesdir}
diff --git a/m4/acx_libwrap.m4 b/m4/acx_libwrap.m4
new file mode 100644 (file)
index 0000000..e160214
--- /dev/null
@@ -0,0 +1,19 @@
+AC_DEFUN([ACX_LIBWRAP], [
+LIBWRAP_LIBS=
+saved_LIBS="$LIBS"
+LIBS="$LIBS -lwrap"
+AC_MSG_CHECKING([for tcpwrap library and headers])
+AC_LINK_IFELSE(
+AC_LANG_PROGRAM(
+[#include <tcpd.h>
+#include <syslog.h>
+int allow_severity = LOG_INFO;
+int deny_severity = LOG_WARNING;],
+[struct request_info *req;
+return hosts_access (req);]),
+[AC_DEFINE(HAVE_LIBWRAP, [], [Have tcpwrap?])
+LIBWRAP_LIBS="-lwrap"
+AC_MSG_RESULT(yes)],
+[AC_MSG_RESULT(no)])
+LIBS="$saved_LIBS"
+])
index 426af2b4cf77f161da4d4efd0d23c2a54b13420d..fa8419114043a009823f46eef1358658036ecda6 100644 (file)
@@ -37,6 +37,7 @@
         "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
         "  <property name=\"SocketMode\" type=\"u\" access=\"read\"/>\n" \
         "  <property name=\"Accept\" type=\"b\" access=\"read\"/>\n"    \
         "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
         "  <property name=\"SocketMode\" type=\"u\" access=\"read\"/>\n" \
         "  <property name=\"Accept\" type=\"b\" access=\"read\"/>\n"    \
+        "  <property name=\"TCPWrapName\" type=\"s\" access=\"read\"/>\n" \
         " </interface>\n"                                               \
 
 #define INTROSPECTION                                                   \
         " </interface>\n"                                               \
 
 #define INTROSPECTION                                                   \
@@ -66,6 +67,7 @@ DBusHandlerResult bus_socket_message_handler(Unit *u, DBusMessage *message) {
                 { "org.freedesktop.systemd1.Socket", "DirectoryMode", bus_property_append_mode,     "u", &u->socket.directory_mode },
                 { "org.freedesktop.systemd1.Socket", "SocketMode",    bus_property_append_mode,     "u", &u->socket.socket_mode },
                 { "org.freedesktop.systemd1.Socket", "Accept",        bus_property_append_bool,     "b", &u->socket.accept },
                 { "org.freedesktop.systemd1.Socket", "DirectoryMode", bus_property_append_mode,     "u", &u->socket.directory_mode },
                 { "org.freedesktop.systemd1.Socket", "SocketMode",    bus_property_append_mode,     "u", &u->socket.socket_mode },
                 { "org.freedesktop.systemd1.Socket", "Accept",        bus_property_append_bool,     "b", &u->socket.accept },
+                { "org.freedesktop.systemd1.Socket", "TCPWrapName",   bus_property_append_string,   "s", u->socket.tcpwrap_name },
                 { NULL, NULL, NULL, NULL, NULL }
         };
 
                 { NULL, NULL, NULL, NULL, NULL }
         };
 
index cf1434eb1e1d4ec5b258bd1fee43ec2c1073fad8..94a637541f54b0fd028accfc3f007e3975fb54a9 100644 (file)
@@ -1444,6 +1444,7 @@ static int load_from_path(Unit *u, const char *path) {
                 { "SocketMode",             config_parse_mode,            &u->socket.socket_mode,                          "Socket"  },
                 { "KillMode",               config_parse_kill_mode,       &u->socket.kill_mode,                            "Socket"  },
                 { "Accept",                 config_parse_bool,            &u->socket.accept,                               "Socket"  },
                 { "SocketMode",             config_parse_mode,            &u->socket.socket_mode,                          "Socket"  },
                 { "KillMode",               config_parse_kill_mode,       &u->socket.kill_mode,                            "Socket"  },
                 { "Accept",                 config_parse_bool,            &u->socket.accept,                               "Socket"  },
+                { "TCPWrapName",            config_parse_string,          &u->socket.tcpwrap_name,                         "Socket"  },
                 EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
 
                 { "What",                   config_parse_string,          &u->mount.parameters_fragment.what,              "Mount"   },
                 EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
 
                 { "What",                   config_parse_string,          &u->mount.parameters_fragment.what,              "Mount"   },
index 48eee6cd12958bcc5617b2cf69abc0480a7fe6ea..de4dfad38603c680f02f4d62ef14e94de49aec80 100644 (file)
@@ -36,6 +36,7 @@
 #include "log.h"
 #include "list.h"
 #include "sd-daemon.h"
 #include "log.h"
 #include "list.h"
 #include "sd-daemon.h"
+#include "tcpwrap.h"
 
 #define STREAM_BUFFER 2048
 #define STREAMS_MAX 256
 
 #define STREAM_BUFFER 2048
 #define STREAMS_MAX 256
@@ -340,6 +341,11 @@ static int stream_new(Server *s, int server_fd) {
                 return 0;
         }
 
                 return 0;
         }
 
+        if (!socket_tcpwrap(fd, "systemd-logger")) {
+                close_nointr_nofail(fd);
+                return 0;
+        }
+
         if (!(stream = new0(Stream, 1))) {
                 close_nointr_nofail(fd);
                 return -ENOMEM;
         if (!(stream = new0(Stream, 1))) {
                 close_nointr_nofail(fd);
                 return -ENOMEM;
index 1852fe93755a507837ed4067c5e3af162377cad8..71f1672027d6905557f48f5f6b97da483a91dd98 100644 (file)
@@ -36,6 +36,7 @@
 #include "strv.h"
 #include "unit-name.h"
 #include "dbus-socket.h"
 #include "strv.h"
 #include "unit-name.h"
 #include "dbus-socket.h"
+#include "tcpwrap.h"
 
 static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
         [SOCKET_DEAD] = UNIT_INACTIVE,
 
 static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
         [SOCKET_DEAD] = UNIT_INACTIVE,
@@ -107,6 +108,9 @@ static void socket_done(Unit *u) {
         free(s->bind_to_device);
         s->bind_to_device = NULL;
 
         free(s->bind_to_device);
         s->bind_to_device = NULL;
 
+        free(s->tcpwrap_name);
+        s->tcpwrap_name = NULL;
+
         unit_unwatch_timer(u, &s->timer_watch);
 }
 
         unit_unwatch_timer(u, &s->timer_watch);
 }
 
@@ -305,6 +309,11 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                         "%sBindToDevice: %s\n",
                         prefix, s->bind_to_device);
 
                         "%sBindToDevice: %s\n",
                         prefix, s->bind_to_device);
 
+        if (s->tcpwrap_name)
+                fprintf(f,
+                        "%sTCPWrapName: %s\n",
+                        prefix, s->tcpwrap_name);
+
         if (s->accept)
                 fprintf(f,
                         "%sAccepted: %u\n",
         if (s->accept)
                 fprintf(f,
                         "%sAccepted: %u\n",
@@ -1212,6 +1221,12 @@ static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
 
                         break;
                 }
 
                         break;
                 }
+
+                if (s->tcpwrap_name)
+                        if (!socket_tcpwrap(cfd, s->tcpwrap_name)) {
+                                close_nointr_nofail(cfd);
+                                return;
+                        }
         }
 
         socket_enter_running(s, cfd);
         }
 
         socket_enter_running(s, cfd);
index 5a2cd06d9d66a761c2df62421c0bfd00d3e64a10..de3e913f7cd787dc8826036bb9c10c3873bb939f 100644 (file)
@@ -101,6 +101,8 @@ struct Socket {
         mode_t directory_mode;
         mode_t socket_mode;
 
         mode_t directory_mode;
         mode_t socket_mode;
 
+        char *tcpwrap_name;
+
         bool accept;
         unsigned n_accepted;
 
         bool accept;
         unsigned n_accepted;
 
diff --git a/src/tcpwrap.c b/src/tcpwrap.c
new file mode 100644 (file)
index 0000000..579aad5
--- /dev/null
@@ -0,0 +1,66 @@
+/*-*- Mode: C; c-basic-offset: 8 -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#ifdef HAVE_LIBWRAP
+#include <tcpd.h>
+#endif
+
+#include "tcpwrap.h"
+#include "log.h"
+
+bool socket_tcpwrap(int fd, const char *name) {
+#ifdef HAVE_LIBWRAP
+        struct request_info req;
+        union {
+                struct sockaddr sa;
+                struct sockaddr_in in;
+                struct sockaddr_in6 in6;
+                struct sockaddr_un un;
+                struct sockaddr_storage storage;
+        } sa_union;
+        socklen_t l = sizeof(sa_union);
+
+        if (getsockname(fd, &sa_union.sa, &l) < 0)
+                return true;
+
+        if (sa_union.sa.sa_family != AF_INET &&
+            sa_union.sa.sa_family != AF_INET6)
+                return true;
+
+        request_init(&req,
+                     RQ_DAEMON, name,
+                     RQ_FILE, fd,
+                     NULL);
+
+        fromhost(&req);
+
+        if (!hosts_access(&req)) {
+                log_warning("Connection refused by tcpwrap.");
+                return false;
+        }
+
+        log_debug("Connection accepted by tcpwrap.");
+#endif
+        return true;
+}
diff --git a/src/tcpwrap.h b/src/tcpwrap.h
new file mode 100644 (file)
index 0000000..b471696
--- /dev/null
@@ -0,0 +1,29 @@
+/*-*- Mode: C; c-basic-offset: 8 -*-*/
+
+#ifndef foolibwraphfoo
+#define foolibwraphfoo
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+
+bool socket_tcpwrap(int fd, const char *name);
+
+#endif