shared-storage.c revision c4c9be10781e1a16b3b001dc6b0461c4640da101
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "lib.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "array.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "str.h"
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde#include "ioloop.h"
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde#include "auth-master.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "var-expand.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#include "shared-storage.h"
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde#include <stdlib.h>
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen#include <ctype.h>
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen#define SHARED_LIST_CONTEXT(obj) \
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen MODULE_CONTEXT(obj, shared_mailbox_list_module)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenextern struct mail_storage shared_storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenextern struct mailbox shared_mailbox;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(shared_mailbox_list_module,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen &mailbox_list_module_register);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic struct mail_storage *shared_alloc(void)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct shared_storage *storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen pool_t pool;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen pool = pool_alloconly_create("shared storage", 256);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage = p_new(pool, struct shared_storage, 1);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage->storage = shared_storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage->storage.pool = pool;
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen storage->storage.storage_class = &shared_storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen storage->base_dir = p_strdup(pool, getenv("BASE_DIR"));
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (storage->base_dir == NULL)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen storage->base_dir = PKG_RUNDIR;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return &storage->storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic int shared_create(struct mail_storage *_storage, const char *data,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char **error_r)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct mailbox_list_settings list_set;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char *driver, *p;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen bool have_username;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* data must begin with the actual mailbox driver */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen p = strchr(data, ':');
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (p == NULL) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen driver = t_strdup_until(data, p);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage->location = p_strdup(_storage->pool, data);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage->storage_class = mail_storage_find_class(driver);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (storage->storage_class == NULL) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen driver, NULL);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen _storage->mailbox_is_file = storage->storage_class->mailbox_is_file;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen p = strchr(_storage->ns->prefix, '%');
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (p == NULL) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, p);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen _storage->ns->prefix = p_strdup_until(_storage->ns->user->pool,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen _storage->ns->prefix, p);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen have_username = FALSE;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*p != '%')
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen continue;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*++p == '\0')
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*p == 'u' || *p == 'n')
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen have_username = TRUE;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen else if (*p != 'd')
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*p != '\0') {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared namespace prefix contains unknown variables";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (!have_username) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (mailbox_list_alloc("shared", &_storage->list, error_r) < 0)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen MODULE_CONTEXT_SET_FULL(_storage->list, shared_mailbox_list_module,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen storage, &storage->list_module_ctx);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen memset(&list_set, 0, sizeof(list_set));
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen list_set.mail_storage_flags = &_storage->flags;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen list_set.lock_method = &_storage->lock_method;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mailbox_list_init(_storage->list, _storage->ns, &list_set,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_storage_get_list_flags(_storage->flags));
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainenstatic void shared_storage_destroy(struct mail_storage *_storage)
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde{
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (storage->auth_master_conn != NULL)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen auth_master_deinit(&storage->auth_master_conn);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen index_storage_destroy(_storage);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen}
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainenstatic void shared_storage_auth_master_init(struct shared_storage *storage)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen{
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen const char *auth_socket_path;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen bool debug;
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen auth_socket_path = getenv("AUTH_SOCKET_PATH");
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (auth_socket_path == NULL) {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen auth_socket_path = t_strconcat(storage->base_dir,
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen "/auth-master", NULL);
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde }
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen debug = (storage->storage.flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen storage->auth_master_conn = auth_master_init(auth_socket_path, debug);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen}
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainenstatic int
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainenshared_storage_lookup_home(struct shared_storage *storage,
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen const char *user, const char **home_r)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen{
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen struct auth_user_reply reply;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen pool_t userdb_pool;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen int ret;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (storage->auth_master_conn == NULL)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen shared_storage_auth_master_init(storage);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen userdb_pool = pool_alloconly_create("userdb lookup", 512);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen ret = auth_master_user_lookup(storage->auth_master_conn, user,
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen AUTH_SERVICE_INTERNAL,
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen userdb_pool, &reply);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (ret > 0)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen *home_r = t_strdup(reply.home);
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde pool_unref(&userdb_pool);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen return ret;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen}
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainenstatic void get_nonexisting_user_location(struct shared_storage *storage,
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen string_t *location)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen{
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* user wasn't found. we'll still need to create the storage
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen to avoid exposing which users exist and which don't. */
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen str_append(location, storage->storage_class->name);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen str_append_c(location, ':');
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* use a reachable but non-existing path as the mail root directory */
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen str_append(location, storage->base_dir);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen str_append(location, PKG_RUNDIR"/user-not-found");
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde}
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenint shared_storage_get_namespace(struct mail_storage *_storage,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char **_name,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct mail_namespace **ns_r)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct mail_user *user = _storage->ns->user;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen static struct var_expand_table static_tab[] = {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen { 'u', NULL },
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen { 'n', NULL },
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen { 'd', NULL },
c2ee17c9c263efdc9c0a339c4836c3d43f5cd3d9Sascha Wilde { 'h', NULL },
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen { '\0', NULL }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen };
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct var_expand_table *tab;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct mail_namespace *ns;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char *name, *p, *next, **dest, *error;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen string_t *prefix, *location;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen int ret;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen *ns_r = NULL;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen p = storage->ns_prefix_pattern;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen for (name = *_name; *p != '\0';) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*p != '%') {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (*p != *name)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen p++; name++;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen continue;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen switch (*++p) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen case 'd':
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest = &domain;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen case 'n':
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest = &username;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen case 'u':
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen dest = &userdomain;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen break;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen default:
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* we checked this already above */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i_unreached();
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen p++;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen next = strchr(name, *p != '\0' ? *p : _storage->ns->sep);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (next == NULL)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *dest = t_strdup_until(name, next);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen name = next;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* successfully matched the name. */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (userdomain == NULL) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i_assert(username != NULL);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen userdomain = domain == NULL ? username :
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen t_strconcat(username, "@", domain, NULL);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen } else {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen domain = strchr(userdomain, '@');
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (domain == NULL)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen username = userdomain;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen else {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen username = t_strdup_until(userdomain, domain);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen domain++;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* expand the namespace prefix and see if it already exists.
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen this should normally happen only when the mailbox is being opened */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen tab = t_malloc(sizeof(static_tab));
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen tab[0].value = userdomain;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen tab[1].value = username;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen tab[2].value = domain;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen prefix = t_str_new(128);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen str_append(prefix, _storage->ns->prefix);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen var_expand(prefix, storage->ns_prefix_pattern, tab);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (ns != NULL) {
c7194d1d3872ffb2901737e1df337cc227a3fa77Timo Sirainen *_name = mail_namespace_fix_sep(ns, name);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *ns_r = ns;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (!var_has_key(storage->location, 'h'))
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen ret = 1;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen else {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen /* we'll need to look up the user's home directory */
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen ret = shared_storage_lookup_home(storage, userdomain,
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen &tab[3].value);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (ret < 0) {
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen mail_storage_set_critical(_storage, "Namespace '%s': "
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen "Could not lookup home for user %s",
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen _storage->ns->prefix, userdomain);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen return -1;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen }
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen }
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* create the new namespace */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ns = p_new(user->pool, struct mail_namespace, 1);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ns->type = NAMESPACE_SHARED;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ns->user = user;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ns->prefix = p_strdup(user->pool, str_c(prefix));
a988c3fd9251806e38931a011aaa4006dd081cbdTimo Sirainen ns->flags = NAMESPACE_FLAG_LIST | NAMESPACE_FLAG_HIDDEN |
a988c3fd9251806e38931a011aaa4006dd081cbdTimo Sirainen NAMESPACE_FLAG_AUTOCREATED;
c7194d1d3872ffb2901737e1df337cc227a3fa77Timo Sirainen ns->sep = _storage->ns->sep;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen location = t_str_new(256);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen if (ret > 0)
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen var_expand(location, storage->location, tab);
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen else
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen get_nonexisting_user_location(storage, location);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (mail_storage_create(ns, NULL, str_c(location), _storage->flags,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen _storage->lock_method, &error) < 0) {
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen mail_storage_set_critical(_storage, "Namespace '%s': %s",
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen ns->prefix, error);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen /* FIXME: we could remove namespaces here that don't have usable
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mailboxes. otherwise the memory usage could just keep growing. */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_user_add_namespace(user, ns);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
c7194d1d3872ffb2901737e1df337cc227a3fa77Timo Sirainen *_name = mail_namespace_fix_sep(ns, name);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *ns_r = ns;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic void shared_mailbox_copy_error(struct mail_storage *shared_storage,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct mail_namespace *backend_ns)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char *str;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen enum mail_error error;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen str = mail_storage_get_last_error(backend_ns->storage, &error);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_storage_set_error(shared_storage, error, str);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic struct mailbox *
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenshared_mailbox_open(struct mail_storage *storage, const char *name,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct istream *input, enum mailbox_open_flags flags)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct mail_namespace *ns;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct mailbox *box;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (input != NULL) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen mail_storage_set_critical(storage,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen "Shared storage doesn't support streamed mailboxes");
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return NULL;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (shared_storage_get_namespace(storage, &name, &ns) < 0)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return NULL;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen /* if we call the normal mailbox_open() here the plugins will see
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen mailbox_open() called twice and they could break. */
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen box = ns->storage->storage_class->v.
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen mailbox_open(ns->storage, name, NULL, flags);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (box == NULL)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen shared_mailbox_copy_error(storage, ns);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return box;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstatic int shared_mailbox_create(struct mail_storage *storage,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const char *name, bool directory)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen struct mail_namespace *ns;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen int ret;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (shared_storage_get_namespace(storage, &name, &ns) < 0)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen ret = mail_storage_mailbox_create(ns->storage, name, directory);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (ret < 0)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen shared_mailbox_copy_error(storage, ns);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return ret;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenstruct mail_storage shared_storage = {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen MEMBER(name) SHARED_STORAGE_NAME,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen MEMBER(mailbox_is_file) FALSE, /* unknown at this point */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen NULL,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen NULL,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen shared_alloc,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen shared_create,
c4c9be10781e1a16b3b001dc6b0461c4640da101Timo Sirainen shared_storage_destroy,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen NULL,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen shared_mailbox_open,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen shared_mailbox_create
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen};