dovecot-2.0-pigeonhole: ManageSieve: implemented dynamic capabil...

pigeonhole at rename-it.nl pigeonhole at rename-it.nl
Wed May 5 17:04:37 EEST 2010


details:   http://hg.rename-it.nl/dovecot-2.0-pigeonhole/rev/696c2dd83063
changeset: 1271:696c2dd83063
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Wed May 05 16:04:31 2010 +0200
description:
ManageSieve: implemented dynamic capability determination at login.

diffstat:

 src/managesieve-login/Makefile.am                  |    3 +-
 src/managesieve-login/managesieve-login-settings.c |  199 ++++++++++++++++++++++++-
 src/managesieve-login/managesieve-login-settings.h |    5 +
 src/managesieve/main.c                             |   23 ++-
 src/managesieve/managesieve-client.c               |   15 +
 src/managesieve/managesieve-client.h               |    2 +
 6 files changed, 237 insertions(+), 10 deletions(-)

diffs (truncated from 393 to 300 lines):

diff -r f37d17b61b8d -r 696c2dd83063 src/managesieve-login/Makefile.am
--- a/src/managesieve-login/Makefile.am	Wed May 05 15:43:54 2010 +0200
+++ b/src/managesieve-login/Makefile.am	Wed May 05 16:04:31 2010 +0200
@@ -16,9 +16,9 @@
 
 libmanagesieve_login_settings_la_SOURCES = \
 	managesieve-login-settings.c
+libmanagesieve_login_settings_la_CFLAGS = $(AM_CFLAGS) -D_CONFIG_PLUGIN -DPKG_LIBEXECDIR=\""$(dovecot_pkglibexecdir)"\"
 
 libs = \
-	managesieve-login-settings.lo \
 	$(top_srcdir)/src/lib-managesieve/libmanagesieve.a
 
 managesieve_login_LDADD = $(libs) $(LIBDOVECOT_LOGIN) $(LIBDOVECOT)
@@ -27,6 +27,7 @@
 managesieve_login_SOURCES = \
 	client.c \
 	client-authenticate.c \
+	managesieve-login-settings.c \
 	managesieve-proxy.c
 
 noinst_HEADERS = \
diff -r f37d17b61b8d -r 696c2dd83063 src/managesieve-login/managesieve-login-settings.c
--- a/src/managesieve-login/managesieve-login-settings.c	Wed May 05 15:43:54 2010 +0200
+++ b/src/managesieve-login/managesieve-login-settings.c	Wed May 05 16:04:31 2010 +0200
@@ -2,15 +2,27 @@
  */
 
 #include "lib.h"
+#include "str.h"
 #include "buffer.h"
+#include "env-util.h"
+#include "fd-close-on-exec.h"
+#include "execv-const.h"
 #include "settings-parser.h"
 #include "service-settings.h"
 #include "login-settings.h"
 #include "managesieve-login-settings.h"
 
 #include <stddef.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sysexits.h>
 
 /* <settings checks> */
+#ifdef _CONFIG_PLUGIN
+static bool managesieve_login_settings_verify
+	(void *_set, pool_t pool, const char **error_r);
+#endif
+
 static struct inet_listener_settings managesieve_login_inet_listeners_array[] = {
     { "managesieve", "", 4190, FALSE },
 };
@@ -54,13 +66,15 @@
 static const struct setting_define managesieve_login_setting_defines[] = {
 	DEF(SET_STR, managesieve_implementation_string),
 	DEF(SET_STR, managesieve_sieve_capability),
+	DEF(SET_STR, managesieve_notify_capability),
 
 	SETTING_DEFINE_LIST_END
 };
 
 static const struct managesieve_login_settings managesieve_login_default_settings = {
 	.managesieve_implementation_string = PACKAGE_NAME,
-	.managesieve_sieve_capability = ""
+	.managesieve_sieve_capability = "",
+	.managesieve_notify_capability = ""
 };
 
 static const struct setting_parser_info *managesieve_login_setting_dependencies[] = {
@@ -79,7 +93,11 @@
 	.parent_offset = (size_t)-1,
 	.parent = NULL,
 
-	.check_func = NULL,
+	/* Only compiled in the doveconf plugin */
+#ifdef _CONFIG_PLUGIN
+	.check_func = managesieve_login_settings_verify,
+#endif
+
 	.dependencies = managesieve_login_setting_dependencies
 };
 
@@ -88,3 +106,180 @@
 	&managesieve_login_setting_parser_info,
 	NULL
 };
+
+/* 
+ * Dynamic ManageSieve capability determination
+ *   Only compiled in the doveconf plugin 
+ */
+
+#ifdef _CONFIG_PLUGIN
+
+typedef enum { CAP_SIEVE, CAP_NOTIFY } capability_type_t;
+
+static const char *capability_sieve = NULL;
+static const char *capability_notify = NULL;
+
+void managesieve_login_settings_deinit(void)
+{
+	if ( capability_sieve != NULL )
+		i_free(capability_sieve);
+
+	if ( capability_notify != NULL )
+		i_free(capability_notify);
+}
+
+static void capability_store(capability_type_t cap_type, const char *value)
+{
+	switch ( cap_type ) {
+	case CAP_SIEVE:
+		capability_sieve = i_strdup(value);
+		break;
+	case CAP_NOTIFY:
+		capability_notify = i_strdup(value);
+		break;
+	}
+}
+
+static void capability_parse(const char *cap_string)
+{
+	capability_type_t cap_type = CAP_SIEVE;
+	const char *p = cap_string;
+	string_t *part = t_str_new(256);
+
+	if ( cap_string == NULL || *cap_string == '\0' ) {
+		i_warning("managesieve-login: capability string is empty.");
+		return;
+	}
+	
+	while ( *p != '\0' ) {
+		if ( *p == '\\' ) {
+			p++;
+			if ( *p != '\0' ) {
+				str_append_c(part, *p);
+				p++;
+			} else break;
+		} else if ( *p == ':' ) {
+			if ( strcasecmp(str_c(part), "SIEVE") == 0 )
+				cap_type = CAP_SIEVE;
+			else if ( strcasecmp(str_c(part), "NOTIFY") == 0 )
+				cap_type = CAP_NOTIFY;
+			else
+				i_warning("managesieve-login: unknown capability '%s' listed in "
+					"capability string (ignored).", str_c(part));
+			str_truncate(part, 0); 
+		} else if ( *p == ',' ) {
+			capability_store(cap_type, str_c(part));
+			str_truncate(part, 0);
+		} else {
+			/* Append character, but omit leading spaces */
+			if ( str_len(part) > 0 || *p != ' ' )
+				str_append_c(part, *p);
+		}
+		p++;
+	}
+	
+	if ( str_len(part) > 0 ) {
+		capability_store(cap_type, str_c(part));
+	}
+}
+
+static void capability_dump(void)
+{
+	char buf[4096];
+	int fd[2], status;
+	ssize_t ret;
+	unsigned int pos;
+	pid_t pid;
+
+	if ( pipe(fd) < 0 ) {
+		i_error("managesieve-login: dump-capability pipe() failed: %m");
+		return;
+	}
+	fd_close_on_exec(fd[0], TRUE);
+	fd_close_on_exec(fd[1], TRUE);
+
+	if ( (pid = fork()) == (pid_t)-1 ) {
+		(void)close(fd[0]); (void)close(fd[1]);
+		i_error("managesieve-login: dump-capability fork() failed: %m");
+		return;
+	}
+
+	if ( pid == 0 ) {
+		const char *argv[1];
+
+		/* Child */
+		(void)close(fd[0]);		
+	
+		if (dup2(fd[1], STDOUT_FILENO) < 0)
+			i_fatal("managesieve-login: dump-capability dup2() failed: %m");
+
+		env_put("DUMP_CAPABILITY=1");
+
+		argv[0] = PKG_LIBEXECDIR"/managesieve"; /* BAD */
+		execv_const(argv[0], argv);
+
+		i_fatal("managesieve-login: dump-capability execv(%s) failed: %m", argv[0]);
+	}
+
+	(void)close(fd[1]);
+
+	alarm(5);
+	if (wait(&status) == -1) {
+		i_fatal("managesieve-login: dump-capability process %d got stuck", 
+			(int)pid);
+	}
+	alarm(0);
+
+	if (status != 0) {
+		(void)close(fd[0]);
+		if (WIFSIGNALED(status)) {
+			i_error("managesieve-login: dump-capability process "
+				"killed with signal %d", WTERMSIG(status));
+		} else {
+			i_error("managesieve-login: dump-capability process returned %d",
+				WIFEXITED(status) ? WEXITSTATUS(status) : status);
+		}
+		return;
+	}
+
+	pos = 0;
+	while ((ret = read(fd[0], buf + pos, sizeof(buf) - pos)) > 0)
+		pos += ret;
+
+	if (ret < 0) {
+		i_error("managesieve-login: read(dump-capability process) failed: %m");
+		(void)close(fd[0]);
+		return;
+	}
+	(void)close(fd[0]);
+
+	if (pos == 0 || buf[pos-1] != '\n') {
+		i_error("managesieve-login: dump-capability: Couldn't read capability "
+			"(got %u bytes)", pos);
+		return;
+	}
+	buf[pos-1] = '\0';
+
+	capability_parse(buf);
+}
+
+/* <settings checks> */
+static bool managesieve_login_settings_verify
+(void *_set, pool_t pool ATTR_UNUSED, const char **error_r ATTR_UNUSED)
+{
+	struct managesieve_login_settings *set = _set;
+
+	if ( capability_sieve == NULL )
+		capability_dump();
+
+	if ( *set->managesieve_sieve_capability == '\0' )
+		set->managesieve_sieve_capability = capability_sieve;
+
+	if ( *set->managesieve_notify_capability == '\0' )
+		set->managesieve_notify_capability = capability_notify;
+	
+	return TRUE;
+}
+/* </settings checks> */
+
+#endif /* _CONFIG_PLUGIN */
diff -r f37d17b61b8d -r 696c2dd83063 src/managesieve-login/managesieve-login-settings.h
--- a/src/managesieve-login/managesieve-login-settings.h	Wed May 05 15:43:54 2010 +0200
+++ b/src/managesieve-login/managesieve-login-settings.h	Wed May 05 16:04:31 2010 +0200
@@ -7,8 +7,13 @@
 struct managesieve_login_settings {
 	const char *managesieve_implementation_string;
 	const char *managesieve_sieve_capability;
+	const char *managesieve_notify_capability;
 };
 
 extern const struct setting_parser_info *managesieve_login_settings_set_roots[];
 
+#ifdef _CONFIG_PLUGIN
+void managesieve_login_settings_deinit(void);
+#endif
+
 #endif /* __MANAGESIEVE_LOGIN_SETTINGS_H */
diff -r f37d17b61b8d -r 696c2dd83063 src/managesieve/main.c
--- a/src/managesieve/main.c	Wed May 05 15:43:54 2010 +0200
+++ b/src/managesieve/main.c	Wed May 05 16:04:31 2010 +0200
@@ -119,7 +119,7 @@
 	o_stream_unref(&output);
 }
 
-static int
+static struct client *
 client_create_from_input(const struct mail_storage_service_input *input,
 			 int fd_in, int fd_out, const buffer_t *input_buf,
 			 const char **error_r)
@@ -131,7 +131,7 @@
 
 	if (mail_storage_service_lookup_next(storage_service, input,
 					     &user, &mail_user, error_r) <= 0)
-		return -1;
+		return NULL;
 	restrict_access_allow_coredumps(TRUE);


More information about the dovecot-cvs mailing list