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