# HG changeset patch # User Timo Sirainen # Date 1225548319 -7200 # Node ID 4aafdbe62680592be0dce0b8906ae59b5396f881 # Parent 9d7c0ff9c2a0250f2a50872eba9e3e2a94f52d1d shared mailboxes: Cleanups, fixes and optimizations. 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 @@ } 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 @@ } 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 @@ *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 +#include #define SHARED_LIST_CONTEXT(obj) \ MODULE_CONTEXT(obj, shared_mailbox_list_module) @@ -30,6 +31,10 @@ 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 @@ return 0; } -static const char *lookup_home(const char *user) +static void shared_storage_destroy(struct mail_storage *_storage) { - const char *auth_socket; - const char *home = NULL; - struct auth_connection *conn; - struct auth_user_reply *reply; - pool_t userdb_pool; - struct ioloop *userdb_ioloop; + 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); +} - 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); +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); } - 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); + 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; + int ret; + + if (storage->auth_master_conn == NULL) + shared_storage_auth_master_init(storage); - 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); + 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 ret; +} - return home; +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 @@ }; 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 @@ } } - 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 @@ 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); @@ -232,6 +249,20 @@ 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 */ ns = p_new(user->pool, struct mail_namespace, 1); ns->type = NAMESPACE_SHARED; @@ -242,7 +273,10 @@ 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 @@ 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 @@ 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 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);