dovecot-1.2: shared mailboxes: Cleanups, fixes and optimizations.

dovecot at dovecot.org dovecot at dovecot.org
Sat Nov 1 16:05:26 EET 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/4aafdbe62680
changeset: 8375:4aafdbe62680
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Nov 01 16:05:19 2008 +0200
description:
shared mailboxes: Cleanups, fixes and optimizations.

diffstat:

5 files changed, 103 insertions(+), 51 deletions(-)
src/lib-storage/index/dbox/dbox-storage.c       |    9 +
src/lib-storage/index/maildir/maildir-storage.c |    5 
src/lib-storage/index/mbox/mbox-storage.c       |    4 
src/lib-storage/index/shared/shared-storage.c   |  133 ++++++++++++++---------
src/lib-storage/index/shared/shared-storage.h   |    3 

diffs (279 lines):

diff -r 9d7c0ff9c2a0 -r 4aafdbe62680 src/lib-storage/index/dbox/dbox-storage.c
--- a/src/lib-storage/index/dbox/dbox-storage.c	Sat Nov 01 16:04:24 2008 +0200
+++ b/src/lib-storage/index/dbox/dbox-storage.c	Sat Nov 01 16:05:19 2008 +0200
@@ -119,8 +119,13 @@ static int dbox_create(struct mail_stora
 	} else if (mkdir_parents(list_set.root_dir,
 				 CREATE_MODE) == 0 || errno == EEXIST) {
 	} else if (errno == EACCES) {
-		*error_r = mail_storage_eacces_msg("mkdir", list_set.root_dir);
-		return -1;
+		if (_storage->ns->type != NAMESPACE_SHARED) {
+			*error_r = mail_storage_eacces_msg("mkdir",
+							   list_set.root_dir);
+			return -1;
+		}
+		/* can't create a new user, but we don't want to fail
+		   the storage creation. */
 	} else {
 		*error_r = t_strdup_printf("mkdir(%s) failed: %m",
 					   list_set.root_dir);
diff -r 9d7c0ff9c2a0 -r 4aafdbe62680 src/lib-storage/index/maildir/maildir-storage.c
--- a/src/lib-storage/index/maildir/maildir-storage.c	Sat Nov 01 16:04:24 2008 +0200
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Sat Nov 01 16:05:19 2008 +0200
@@ -317,6 +317,11 @@ static int mkdir_verify(struct mail_stor
 	} else if (errno == ENOENT) {
 		mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
 			"Mailbox was deleted while it was being created");
+	} else if (errno == EACCES && storage->ns->type == NAMESPACE_SHARED) {
+		/* shared namespace, don't log permission errors */
+		mail_storage_set_error(storage, MAIL_ERROR_PERM,
+				       MAIL_ERRSTR_NO_PERMISSION);
+		return -1;
 	} else {
 		mail_storage_set_critical(storage,
 					  "mkdir(%s) failed: %m", dir);
diff -r 9d7c0ff9c2a0 -r 4aafdbe62680 src/lib-storage/index/mbox/mbox-storage.c
--- a/src/lib-storage/index/mbox/mbox-storage.c	Sat Nov 01 16:04:24 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Sat Nov 01 16:05:19 2008 +0200
@@ -353,6 +353,10 @@ mbox_get_list_settings(struct mailbox_li
 			*error_r = t_strdup_printf("lstat(%s) failed: %m",
 						   list_set->root_dir);
 			return -1;
+		} else if (errno == ENOENT &&
+			   storage->ns->type == NAMESPACE_SHARED) {
+			/* can't create a new user, but we don't want to fail
+			   the storage creation. */
 		} else if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
 			*error_r = t_strdup_printf(
 					"Root mail directory doesn't exist: %s",
diff -r 9d7c0ff9c2a0 -r 4aafdbe62680 src/lib-storage/index/shared/shared-storage.c
--- a/src/lib-storage/index/shared/shared-storage.c	Sat Nov 01 16:04:24 2008 +0200
+++ b/src/lib-storage/index/shared/shared-storage.c	Sat Nov 01 16:05:19 2008 +0200
@@ -9,6 +9,7 @@
 #include "shared-storage.h"
 
 #include <stdlib.h>
+#include <ctype.h>
 
 #define SHARED_LIST_CONTEXT(obj) \
 	MODULE_CONTEXT(obj, shared_mailbox_list_module)
@@ -29,6 +30,10 @@ static struct mail_storage *shared_alloc
 	storage->storage = shared_storage;
 	storage->storage.pool = pool;
 	storage->storage.storage_class = &shared_storage;
+
+	storage->base_dir = p_strdup(pool, getenv("BASE_DIR"));
+	if (storage->base_dir == NULL)
+		storage->base_dir = PKG_RUNDIR;
 
 	return &storage->storage;
 }
@@ -99,47 +104,62 @@ static int shared_create(struct mail_sto
 	return 0;
 }
 
-static const char *lookup_home(const char *user)
-{
-	const char *auth_socket;
-	const char *home = NULL;
-	struct auth_connection *conn;
-	struct auth_user_reply *reply;
+static void shared_storage_destroy(struct mail_storage *_storage)
+{
+	struct shared_storage *storage = (struct shared_storage *)_storage;
+
+	if (storage->auth_master_conn != NULL)
+		auth_master_deinit(&storage->auth_master_conn);
+	index_storage_destroy(_storage);
+}
+
+static void shared_storage_auth_master_init(struct shared_storage *storage)
+{
+	const char *auth_socket_path;
+	bool debug;
+
+	auth_socket_path = getenv("AUTH_SOCKET_PATH");
+	if (auth_socket_path == NULL) {
+		auth_socket_path = t_strconcat(storage->base_dir,
+					       "/auth-master", NULL);
+	}
+
+	debug = (storage->storage.flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
+	storage->auth_master_conn = auth_master_init(auth_socket_path, debug);
+}
+
+static int
+shared_storage_lookup_home(struct shared_storage *storage,
+			   const char *user, const char **home_r)
+{
+	struct auth_user_reply reply;
 	pool_t userdb_pool;
-	struct ioloop *userdb_ioloop;
-
-	auth_socket = getenv("AUTH_SOCKET_PATH");
-	if (auth_socket == NULL) {
-		const char *base_dir = getenv("BASE_DIR");
-		if (base_dir == NULL)
-			base_dir = PKG_RUNDIR;
-		auth_socket = t_strconcat(base_dir, "/auth-master",
-					  NULL);
-	}
-
-	userdb_pool = pool_alloconly_create("userdb lookup replys", 512);
-	userdb_ioloop = io_loop_create();
-	conn = auth_master_init(auth_socket, getenv("DEBUG") != NULL);
-	reply = i_new(struct auth_user_reply, 1);
-
-	switch (auth_master_user_lookup(conn, user, "shared-storage", userdb_pool, reply)) {
-	case -1:
-		/* Some error during lookup... */
-	case 0:
-		/* User not found
-		   FIXME: It might be a good idea to handle this special case... */
-		break;
-	case 1:
-		home = i_strdup(reply->home);
-	}
-	
-	i_free(reply);
-	if (conn != NULL)
-		auth_master_deinit(conn);
-	io_loop_destroy(&userdb_ioloop);
+	int ret;
+
+	if (storage->auth_master_conn == NULL)
+		shared_storage_auth_master_init(storage);
+
+	userdb_pool = pool_alloconly_create("userdb lookup", 512);
+	ret = auth_master_user_lookup(storage->auth_master_conn, user,
+				      AUTH_SERVICE_INTERNAL,
+				      userdb_pool, &reply);
+	if (ret > 0)
+		*home_r = t_strdup(reply.home);
 	pool_unref(&userdb_pool);
-
-	return home;
+	return ret;
+}
+
+static void get_nonexisting_user_location(struct shared_storage *storage,
+					  string_t *location)
+{
+	/* user wasn't found. we'll still need to create the storage
+	   to avoid exposing which users exist and which don't. */
+	str_append(location, storage->storage_class->name);
+	str_append_c(location, ':');
+
+	/* use a reachable but non-existing path as the mail root directory */
+	str_append(location, storage->base_dir);
+	str_append(location, PKG_RUNDIR"/user-not-found");
 }
 
 int shared_storage_get_namespace(struct mail_storage *_storage,
@@ -157,9 +177,12 @@ int shared_storage_get_namespace(struct 
 	};
 	struct var_expand_table *tab;
 	struct mail_namespace *ns;
-	const char *domain = NULL, *username = NULL, *userdomain = NULL, *userhome = NULL;
+	const char *domain = NULL, *username = NULL, *userdomain = NULL;
 	const char *name, *p, *next, **dest, *error;
 	string_t *prefix, *location;
+	int ret;
+
+	*ns_r = NULL;
 
 	p = storage->ns_prefix_pattern;
 	for (name = *_name; *p != '\0';) {
@@ -207,12 +230,6 @@ int shared_storage_get_namespace(struct 
 		}
 	}
 
-	userhome = lookup_home(userdomain);
-	if (userhome == NULL) {
-		i_error("Namespace '%s': could not lookup home for user %s", _storage->ns->prefix, userdomain);
-		return -1;
-	}
-
 	/* expand the namespace prefix and see if it already exists.
 	   this should normally happen only when the mailbox is being opened */
 	tab = t_malloc(sizeof(static_tab));
@@ -220,7 +237,7 @@ int shared_storage_get_namespace(struct 
 	tab[0].value = userdomain;
 	tab[1].value = username;
 	tab[2].value = domain;
-	tab[3].value = userhome;
+
 	prefix = t_str_new(128);
 	str_append(prefix, _storage->ns->prefix);
 	var_expand(prefix, storage->ns_prefix_pattern, tab);
@@ -230,6 +247,20 @@ int shared_storage_get_namespace(struct 
 		*_name = mail_namespace_fix_sep(ns, name);
 		*ns_r = ns;
 		return 0;
+	}
+
+	if (!var_has_key(storage->location, 'h'))
+		ret = 1;
+	else {
+		/* we'll need to look up the user's home directory */
+		ret = shared_storage_lookup_home(storage, userdomain,
+						 &tab[3].value);
+		if (ret < 0) {
+			mail_storage_set_critical(_storage, "Namespace '%s': "
+				"Could not lookup home for user %s",
+				_storage->ns->prefix, userdomain);
+			return -1;
+		}
 	}
 
 	/* create the new namespace */
@@ -242,7 +273,10 @@ int shared_storage_get_namespace(struct 
 	ns->sep = _storage->ns->sep;
 
 	location = t_str_new(256);
-	var_expand(location, storage->location, tab);
+	if (ret > 0)
+		var_expand(location, storage->location, tab);
+	else
+		get_nonexisting_user_location(storage, location);
 	if (mail_storage_create(ns, NULL, str_c(location), _storage->flags,
 				_storage->lock_method, &error) < 0) {
 		mail_storage_set_critical(_storage, "Namespace '%s': %s",
@@ -301,6 +335,7 @@ static int shared_mailbox_create(struct 
 
 	if (shared_storage_get_namespace(storage, &name, &ns) < 0)
 		return -1;
+
 	ret = mail_storage_mailbox_create(ns->storage, name, directory);
 	if (ret < 0)
 		shared_mailbox_copy_error(storage, ns);
@@ -316,7 +351,7 @@ struct mail_storage shared_storage = {
 		NULL,
 		shared_alloc,
 		shared_create,
-		index_storage_destroy,
+		shared_storage_destroy,
 		NULL,
 		shared_mailbox_open,
 		shared_mailbox_create
diff -r 9d7c0ff9c2a0 -r 4aafdbe62680 src/lib-storage/index/shared/shared-storage.h
--- a/src/lib-storage/index/shared/shared-storage.h	Sat Nov 01 16:04:24 2008 +0200
+++ b/src/lib-storage/index/shared/shared-storage.h	Sat Nov 01 16:05:19 2008 +0200
@@ -10,14 +10,17 @@ struct shared_storage {
 	struct mail_storage storage;
 	union mailbox_list_module_context list_module_ctx;
 
+	const char *base_dir;
 	const char *ns_prefix_pattern;
 	const char *location;
+	struct auth_master_connection *auth_master_conn;
 
 	struct mail_storage *storage_class;
 };
 
 struct mailbox_list *shared_mailbox_list_alloc(void);
 
+/* Returns -1 = error, 0 = user doesn't exist, 1 = ok */
 int shared_storage_get_namespace(struct mail_storage *storage,
 				 const char **name,
 				 struct mail_namespace **ns_r);


More information about the dovecot-cvs mailing list