shared-storage.c revision 0f5dc4da3982053036be65190e44bf28a67b1ca2
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2008-2016 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 "var-expand.h"
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen#include "index-storage.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mailbox-list-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "fail-mail-storage.h"
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen#include "shared-storage.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <ctype.h>
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen
56561d472db25ebda35ae6afdc7f7deb75c323fcTimo Sirainenextern struct mail_storage shared_storage;
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainenstatic struct mail_storage *shared_storage_alloc(void)
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen{
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainen struct shared_storage *storage;
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen pool_t pool;
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool = pool_alloconly_create("shared storage", 1024);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage = p_new(pool, struct shared_storage, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage->storage = shared_storage;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage->storage.pool = pool;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen return &storage->storage;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainenstatic int
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainenshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const char **error_r)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_storage *storage_class;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen const char *driver, *p;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen char *wildcardp, key;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool have_username;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen /* location must begin with the actual mailbox driver */
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen p = strchr(ns->set->location, ':');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (p == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return -1;
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainen }
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen driver = t_strdup_until(ns->set->location, p);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen storage->location = p_strdup(_storage->pool, ns->set->location);
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen storage->unexpanded_location =
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen p_strdup(_storage->pool, ns->unexpanded_set->location);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen storage->storage_class_name = p_strdup(_storage->pool, driver);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen storage_class = mail_user_get_storage_class(_storage->user, driver);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen if (storage_class != NULL)
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen _storage->class_flags = storage_class->class_flags;
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen else if (strcmp(driver, "auto") != 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen driver, NULL);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return -1;
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen }
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen wildcardp = strchr(ns->prefix, '%');
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen if (wildcardp == NULL) {
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen return -1;
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen }
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen have_username = FALSE;
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (*p != '%')
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen continue;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen key = p[1];
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (key == 'u' || key == 'n')
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen have_username = TRUE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen else if (key != '%' && key != 'd')
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen break;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainen if (*p != '\0') {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen *error_r = "Shared namespace prefix contains unknown variables";
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (!have_username) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return -1;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (p[-1] != mail_namespace_get_sep(ns) &&
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
c680a6b35b459045e92814778908da5a93922107Timo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) != 0) {
c680a6b35b459045e92814778908da5a93922107Timo Sirainen *error_r = "Shared namespace prefix doesn't end with hierarchy separator";
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return -1;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen }
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* truncate prefix after the above checks are done, so they can log
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen the full prefix in error conditions */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen *wildcardp = '\0';
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns->prefix_len = strlen(ns->prefix);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic void
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct mailbox_list_settings *set)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen set->layout = "shared";
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic void
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenget_nonexistent_user_location(struct shared_storage *storage,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const char *username, 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 nonexistent path as the mail root directory */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen str_append(location, storage->storage.user->set->base_dir);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen str_append(location, "/user-not-found/");
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen str_append(location, username);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainenstatic bool shared_namespace_exists(struct mail_namespace *ns)
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen{
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen const char *path;
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen struct stat st;
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen path = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen if (path == NULL) {
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen /* we can't know if this exists */
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen return TRUE;
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen }
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen return stat(path, &st) == 0;
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen}
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainenint shared_storage_get_namespace(struct mail_namespace **_ns,
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen const char **_name)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen{
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct mail_storage *_storage = (*_ns)->storage;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct mailbox_list *list = (*_ns)->list;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct mail_user *user = _storage->user;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct mail_namespace *new_ns, *ns = *_ns;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct mail_user *owner;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen const char *name, *p, *next, **dest, *error;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen string_t *prefix, *location;
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen char ns_sep = mail_namespace_get_sep(ns);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen int ret;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p = storage->ns_prefix_pattern;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen for (name = *_name; *p != '\0';) {
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen if (*p != '%') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*p != *name)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen break;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen p++; name++;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen continue;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen switch (*++p) {
5cdd348121e62a6244ba2f93db781731f7129a71Timo Sirainen case 'd':
5cdd348121e62a6244ba2f93db781731f7129a71Timo Sirainen dest = &domain;
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen break;
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen case 'n':
b43bb773ee6534c1013b01a62fbd5703e3b0d17dTimo Sirainen dest = &username;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen break;
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen case 'u':
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen dest = &userdomain;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen break;
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen default:
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen /* we checked this already above */
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen i_unreached();
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen p++;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen next = strchr(name, *p != '\0' ? *p : ns_sep);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (next == NULL) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen *dest = name;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen name = "";
b43bb773ee6534c1013b01a62fbd5703e3b0d17dTimo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen *dest = t_strdup_until(name, next);
f4ca89823693b9faa82a0c39c24510a7b0e606afTimo Sirainen name = next;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*p != '\0') {
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen if (*name == '\0' ||
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen (name[1] == '\0' && *name == ns_sep)) {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen /* trying to open <prefix>/<user> mailbox */
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen name = "INBOX";
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen } else {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen mailbox_list_set_critical(list,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen "Invalid namespace prefix %s vs %s",
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen storage->ns_prefix_pattern, *_name);
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen return -1;
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen }
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen }
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen /* successfully matched the name. */
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen if (userdomain != NULL) {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen /* user@domain given */
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen domain = strchr(userdomain, '@');
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (domain == NULL)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen username = userdomain;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen else {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen username = t_strdup_until(userdomain, domain);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen domain++;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen } else if (username == NULL) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* trying to open namespace "shared/domain"
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen namespace prefix. */
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(*_name));
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return -1;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen } else {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (domain == NULL) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* no domain given, use ours (if we have one) */
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen domain = i_strchr_to_next(user->username, '@');
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen }
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen userdomain = domain == NULL ? username :
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen t_strconcat(username, "@", domain, NULL);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen }
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen if (*userdomain == '\0') {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen "Empty username doesn't exist");
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen return -1;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen }
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen /* expand the namespace prefix and see if it already exists.
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen this should normally happen only when the mailbox is being opened */
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen struct var_expand_table tab[] = {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen { 'u', userdomain, "user" },
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen { 'n', username, "username" },
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen { 'd', domain, "domain" },
220195605754218b4d6e3a51f5a25be9d0e202e0Timo Sirainen { 'h', NULL, "home" },
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen { '\0', NULL, NULL }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen };
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen prefix = t_str_new(128);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen str_append(prefix, ns->prefix);
220195605754218b4d6e3a51f5a25be9d0e202e0Timo Sirainen if (var_expand(prefix, storage->ns_prefix_pattern, tab, &error) <= 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mailbox_list_set_critical(list,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen "Failed to expand namespace prefix '%s': %s",
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen storage->ns_prefix_pattern, error);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen return -1;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen }
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen if (*_ns != NULL) {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen *_name = mailbox_list_get_storage_name(ns->list,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen t_strconcat(ns->prefix, name, NULL));
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen return 0;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen }
fd3f33bdb57170d63aea66ecacc8bea0f0145d6aTimo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen owner = mail_user_alloc(userdomain, user->set_info,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen user->unexpanded_set);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen owner->_service_user = user->_service_user;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen owner->creator = user;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen owner->autocreated = TRUE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen owner->session_id = p_strdup(owner->pool, user->session_id);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (mail_user_init(owner, &error) < 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (!owner->nonexistent) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mailbox_list_set_critical(list,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "Couldn't create namespace '%s' for user %s: %s",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns->prefix, userdomain, error);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_user_unref(&owner);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ret = 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen } else if (!var_has_key(storage->location, 'h', "home")) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ret = 1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen } else {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* we'll need to look up the user's home directory */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if ((ret = mail_user_get_home(owner, &tab[3].value)) < 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mailbox_list_set_critical(list, "Namespace '%s': "
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "Could not lookup home for user %s",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns->prefix, userdomain);
ee248252648e99f5d701ecd6e33640ea77e11cb7Timo Sirainen mail_user_unref(&owner);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen location = t_str_new(256);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (ret > 0 &&
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen var_expand(location, storage->location, tab, &error) <= 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mailbox_list_set_critical(list,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "Failed to expand namespace location '%s': %s",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen storage->location, error);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* create the new namespace */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns = i_new(struct mail_namespace, 1);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns->refcount = 1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns->type = MAIL_NAMESPACE_TYPE_SHARED;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns->user = user;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns->prefix = i_strdup(str_c(prefix));
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns->owner = owner;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns->flags = (NAMESPACE_FLAG_SUBSCRIPTIONS & ns->flags) |
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX_ANY;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns->mail_set = _storage->set;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen i_array_init(&new_ns->all_storages, 2);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (ret <= 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen get_nonexistent_user_location(storage, userdomain, location);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (ns->user->mail_debug) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen i_debug("shared: Tried to access mails of "
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "nonexistent user %s", userdomain);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns_set->type = "shared";
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns_set->prefix = new_ns->prefix;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns_set->location = p_strdup(user->pool, str_c(location));
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns_set->hidden = TRUE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns_set->list = "yes";
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns->set = ns_set;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unexpanded_ns_set =
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen p_new(user->pool, struct mail_namespace_settings, 1);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen *unexpanded_ns_set = *ns_set;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unexpanded_ns_set->location =
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen p_strdup(user->pool, storage->unexpanded_location);
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen new_ns->unexpanded_set = unexpanded_ns_set;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen /* We need to create a prefix="" namespace for the owner */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (mail_namespaces_init_location(owner, str_c(location), &error) < 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* owner gets freed by namespace deinit */
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody mail_namespace_destroy(new_ns);
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody return -1;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (mail_storage_create(new_ns, NULL, _storage->flags |
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen MAIL_STORAGE_FLAG_NO_AUTOVERIFY, &error) < 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mailbox_list_set_critical(list, "Namespace '%s': %s",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns->prefix, error);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* owner gets freed by namespace deinit */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_namespace_destroy(new_ns);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return -1;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen !shared_namespace_exists(new_ns)) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* this user doesn't have a usable storage */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* mark the shared namespace root as usable, since it now has
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen child namespaces */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns->flags |= NAMESPACE_FLAG_USABLE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen *_name = mailbox_list_get_storage_name(new_ns->list,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen t_strconcat(new_ns->prefix, name, NULL));
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen *_ns = new_ns;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (_storage->class_flags == 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* flags are unset if we were using "auto" storage */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen _storage->class_flags =
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_namespace_get_default_storage(new_ns)->class_flags;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen }
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_user_add_namespace(user, &new_ns);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return 0;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen}
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstruct mail_storage shared_storage = {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen .name = MAIL_SHARED_STORAGE_NAME,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen .class_flags = 0, /* unknown at this point */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen .v = {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen NULL,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen shared_storage_alloc,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen shared_storage_create,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen index_storage_destroy,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen NULL,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen shared_storage_get_list_settings,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen NULL,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen fail_mailbox_alloc,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen NULL
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen }
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen};
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen