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