dovecot-2.0: Added support for tcpwrappers and potentially other...

dovecot at dovecot.org dovecot at dovecot.org
Sat Feb 6 19:46:45 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/51a978045f47
changeset: 10647:51a978045f47
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Feb 06 19:46:40 2010 +0200
description:
Added support for tcpwrappers and potentially other login access checks.

diffstat:

12 files changed, 434 insertions(+), 1 deletion(-)
.hgignore                         |    2 
configure.in                      |   27 +++++++
doc/example-config/dovecot.conf   |    3 
src/login-common/Makefile.am      |    2 
src/login-common/access-lookup.c  |  119 ++++++++++++++++++++++++++++++++++
src/login-common/access-lookup.h  |   11 +++
src/login-common/login-settings.c |    2 
src/login-common/login-settings.h |    1 
src/login-common/main.c           |  100 +++++++++++++++++++++++++++++
src/util/Makefile.am              |   10 ++
src/util/tcpwrap-settings.c       |   32 +++++++++
src/util/tcpwrap.c                |  126 +++++++++++++++++++++++++++++++++++++

diffs (truncated from 601 to 300 lines):

diff -r d4fd28f07507 -r 51a978045f47 .hgignore
--- a/.hgignore	Sat Feb 06 17:31:14 2010 +0200
+++ b/.hgignore	Sat Feb 06 19:46:40 2010 +0200
@@ -60,6 +60,7 @@ src/config/doveconf
 src/config/doveconf
 src/lda/dovecot-lda
 src/dict/dict
+src/dns/dns-client
 src/doveadm/doveadm
 src/dsync/dsync
 src/imap-login/imap-login
@@ -84,6 +85,7 @@ src/util/maildirlock
 src/util/maildirlock
 src/util/rawlog
 src/util/script
+src/util/tcpwrap
 src/plugins/quota/rquota_xdr.c
 src/plugins/quota/rquota.h
 
diff -r d4fd28f07507 -r 51a978045f47 configure.in
--- a/configure.in	Sat Feb 06 17:31:14 2010 +0200
+++ b/configure.in	Sat Feb 06 19:46:40 2010 +0200
@@ -168,6 +168,11 @@ AC_ARG_WITH(libcap,
 [  --with-libcap           Build with libcap support (Dropping capabilities).],
   TEST_WITH(libcap, $withval),
   want_libcap=auto)
+
+AC_ARG_WITH(libwrap,
+[  --with-libwrap          Build with libwrap, ie. TCP-wrappers (auto)],
+  TEST_WITH(libwrap, $withval),
+  want_libwrap=auto)
 
 AC_ARG_WITH(ssl,
 [  --with-ssl=gnutls|openssl Build with GNUTLS or OpenSSL (default)],
@@ -328,6 +333,28 @@ if test $want_libcap != no; then
     fi
   ])
 fi
+
+have_libwrap=no
+if test $want_libwrap != no; then
+  AC_CHECK_HEADER(tcpd.h, [
+    AC_CHECK_LIB(wrap, request_init, [
+      AC_DEFINE(HAVE_LIBWRAP,, Define if you have libwrap)
+      LIBWRAP_LIBS=-lwrap
+      AC_SUBST(LIBWRAP_LIBS)
+      have_libwrap=yes
+    ], [
+      if test "$want_libwrap" = "yes"; then
+	AC_ERROR([Can't build with libwrap support: libwrap not found])
+      fi
+    ])
+    LIBS=$old_LIBS
+  ], [
+    if test "$want_libwrap" = "yes"; then
+      AC_ERROR([Can't build with libwrap support: tcpd.h not found])
+    fi
+  ])
+fi
+AM_CONDITIONAL(TCPWRAPPERS, test "$have_libwrap" = "yes")
 
 AC_DEFINE(PACKAGE_WEBPAGE, "http://www.dovecot.org/", Support URL)
 
diff -r d4fd28f07507 -r 51a978045f47 doc/example-config/dovecot.conf
--- a/doc/example-config/dovecot.conf	Sat Feb 06 17:31:14 2010 +0200
+++ b/doc/example-config/dovecot.conf	Sat Feb 06 19:46:40 2010 +0200
@@ -46,6 +46,9 @@
 # these networks. Typically you'd specify your IMAP proxy servers here.
 #login_trusted_networks =
 
+# Sepace separated list of login access check sockets (e.g. tcpwrap)
+#login_access_sockets = 
+
 # Show more verbose process titles (in ps). Currently shows user name and
 # IP address. Useful for seeing who are actually using the IMAP processes
 # (eg. shared mailboxes or if same uid is used for multiple accounts).
diff -r d4fd28f07507 -r 51a978045f47 src/login-common/Makefile.am
--- a/src/login-common/Makefile.am	Sat Feb 06 17:31:14 2010 +0200
+++ b/src/login-common/Makefile.am	Sat Feb 06 19:46:40 2010 +0200
@@ -9,6 +9,7 @@ AM_CPPFLAGS = \
 	-DPKG_STATEDIR=\""$(statedir)"\"
 
 liblogin_la_SOURCES = \
+	access-lookup.c \
 	client-common.c \
 	client-common-auth.c \
 	login-proxy.c \
@@ -24,6 +25,7 @@ liblogin_la_LIBADD = \
 	$(SSL_LIBS)
 
 headers = \
+	access-lookup.h \
 	client-common.h \
 	login-common.h \
 	login-proxy.h \
diff -r d4fd28f07507 -r 51a978045f47 src/login-common/access-lookup.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/login-common/access-lookup.c	Sat Feb 06 19:46:40 2010 +0200
@@ -0,0 +1,119 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "network.h"
+#include "fdpass.h"
+#include "access-lookup.h"
+
+#include <unistd.h>
+
+#define ACCESS_LOOKUP_TIMEOUT_MSECS (1000*60)
+
+struct access_lookup {
+	int refcount;
+
+	int fd;
+	char *path;
+
+	struct io *io;
+	struct timeout *to;
+
+	access_lookup_callback_t *callback;
+	void *context;
+};
+
+static void access_lookup_input(struct access_lookup *lookup)
+{
+	unsigned char buf[3];
+	ssize_t ret;
+	bool success = FALSE;
+
+	ret = read(lookup->fd, buf, sizeof(buf));
+	if (ret < 0) {
+		i_error("read(%s) failed: %m", lookup->path);
+	} else if (ret == 0) {
+		/* connection close -> no success */
+	} else if (ret == 2 && buf[0] == '0' && buf[1] == '\n') {
+		/* no success */
+	} else if (ret == 2 && buf[0] == '1' && buf[1] == '\n') {
+		success = TRUE;
+	} else {
+		i_error("access(%s): Invalid input", lookup->path);
+	}
+
+	lookup->refcount++;
+	lookup->callback(success, lookup->context);
+	if (lookup->refcount > 1)
+		access_lookup_destroy(&lookup);
+	access_lookup_destroy(&lookup);
+}
+
+static void access_lookup_timeout(struct access_lookup *lookup)
+{
+	i_error("access(%s): Timed out while waiting for reply", lookup->path);
+
+	lookup->refcount++;
+	lookup->callback(FALSE, lookup->context);
+	if (lookup->refcount > 1)
+		access_lookup_destroy(&lookup);
+	access_lookup_destroy(&lookup);
+}
+
+struct access_lookup *
+access_lookup(const char *path, int client_fd, const char *daemon_name,
+	      access_lookup_callback_t *callback, void *context)
+{
+	struct access_lookup *lookup;
+	const char *cmd;
+	ssize_t ret;
+	int fd;
+
+	fd = net_connect_unix(path);
+	if (fd == -1) {
+		i_error("connect(%s) failed: %m", path);
+		return NULL;
+	}
+
+	cmd = t_strconcat(daemon_name, "\n", NULL);
+	ret = fd_send(fd, client_fd, cmd, strlen(cmd));
+	if (ret != (ssize_t)strlen(cmd)) {
+		if (ret < 0)
+			i_error("fd_send(%s) failed: %m", path);
+		else
+			i_error("fd_send(%s) didn't write enough bytes", path);
+		(void)close(fd);
+		return NULL;
+	}
+
+	lookup = i_new(struct access_lookup, 1);
+	lookup->refcount = 1;
+	lookup->fd = fd;
+	lookup->path = i_strdup(path);
+	lookup->io = io_add(fd, IO_READ, access_lookup_input, lookup);
+	lookup->to = timeout_add(ACCESS_LOOKUP_TIMEOUT_MSECS,
+				 access_lookup_timeout, lookup);
+	lookup->callback = callback;
+	lookup->context = context;
+	return lookup;
+}
+
+void access_lookup_destroy(struct access_lookup **_lookup)
+{
+	struct access_lookup *lookup = *_lookup;
+
+	i_assert(lookup->refcount > 0);
+	if (--lookup->refcount > 0)
+		return;
+
+	*_lookup = NULL;
+
+	if (lookup->to != NULL)
+		timeout_remove(&lookup->to);
+	io_remove(&lookup->io);
+	if (close(lookup->fd) < 0)
+		i_error("close(%s) failed: %m", lookup->path);
+
+	i_free(lookup->path);
+	i_free(lookup);
+}
diff -r d4fd28f07507 -r 51a978045f47 src/login-common/access-lookup.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/login-common/access-lookup.h	Sat Feb 06 19:46:40 2010 +0200
@@ -0,0 +1,11 @@
+#ifndef ACCESS_LOOKUP_H
+#define ACCESS_LOOKUP_H
+
+typedef void access_lookup_callback_t(bool success, void *context);
+
+struct access_lookup *
+access_lookup(const char *path, int client_fd, const char *daemon_name,
+	      access_lookup_callback_t *callback, void *context);
+void access_lookup_destroy(struct access_lookup **lookup);
+
+#endif
diff -r d4fd28f07507 -r 51a978045f47 src/login-common/login-settings.c
--- a/src/login-common/login-settings.c	Sat Feb 06 17:31:14 2010 +0200
+++ b/src/login-common/login-settings.c	Sat Feb 06 19:46:40 2010 +0200
@@ -21,6 +21,7 @@ static const struct setting_define login
 	DEF(SET_STR_VARS, login_greeting),
 	DEF(SET_STR, login_log_format_elements),
 	DEF(SET_STR, login_log_format),
+	DEF(SET_STR, login_access_sockets),
 
 	DEF(SET_ENUM, ssl),
 	DEF(SET_STR, ssl_ca),
@@ -50,6 +51,7 @@ static const struct login_settings login
 	.login_greeting = PACKAGE_NAME" ready.",
 	.login_log_format_elements = "user=<%u> method=%m rip=%r lip=%l %c",
 	.login_log_format = "%$: %s",
+	.login_access_sockets = "",
 
 	.ssl = "yes:no:required",
 	.ssl_ca = "",
diff -r d4fd28f07507 -r 51a978045f47 src/login-common/login-settings.h
--- a/src/login-common/login-settings.h	Sat Feb 06 17:31:14 2010 +0200
+++ b/src/login-common/login-settings.h	Sat Feb 06 19:46:40 2010 +0200
@@ -7,6 +7,7 @@ struct login_settings {
 	const char *login_trusted_networks;
 	const char *login_greeting;
 	const char *login_log_format_elements, *login_log_format;
+	const char *login_access_sockets;
 
 	const char *ssl;
 	const char *ssl_ca;
diff -r d4fd28f07507 -r 51a978045f47 src/login-common/main.c
--- a/src/login-common/main.c	Sat Feb 06 17:31:14 2010 +0200
+++ b/src/login-common/main.c	Sat Feb 06 19:46:40 2010 +0200
@@ -10,6 +10,7 @@
 #include "master-service.h"
 #include "master-interface.h"
 #include "client-common.h"
+#include "access-lookup.h"
 #include "anvil-client.h"
 #include "auth-client.h"
 #include "ssl-proxy.h"
@@ -19,6 +20,14 @@
 #include <unistd.h>
 #include <syslog.h>
 
+struct login_access_lookup {
+	struct master_service_connection conn;
+	struct io *io;
+
+	char **sockets, **next_socket;
+	struct access_lookup *access;
+};
+
 struct auth_client *auth_client;
 struct master_auth *master_auth;
 bool closing_down;
@@ -29,6 +38,8 @@ void **global_other_settings;
 
 static bool shutting_down = FALSE;
 static bool ssl_connections = FALSE;
+
+static void login_access_lookup_next(struct login_access_lookup *lookup);
 
 void login_refresh_proctitle(void)
 {
@@ -62,7 +73,8 @@ static void login_die(void)
 	}


More information about the dovecot-cvs mailing list