shared-storage.c revision 0f5dc4da3982053036be65190e44bf28a67b1ca2
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2008-2016 Dovecot authors, see the included COPYING file */
f1765f773591385d513fb68e1799fd1cb4206852Timo Sirainenstatic struct mail_storage *shared_storage_alloc(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool = pool_alloconly_create("shared storage", 1024);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage = p_new(pool, struct shared_storage, 1);
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainenshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const char **error_r)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen const char *driver, *p;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen /* location must begin with the actual mailbox driver */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen driver = t_strdup_until(ns->set->location, p);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen storage->location = p_strdup(_storage->pool, ns->set->location);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen p_strdup(_storage->pool, ns->unexpanded_set->location);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen storage->storage_class_name = p_strdup(_storage->pool, driver);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen storage_class = mail_user_get_storage_class(_storage->user, driver);
9a25d843320a418799494ebaef91112ade0c5fdcTimo Sirainen _storage->class_flags = storage_class->class_flags;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (*p != '%')
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainen if (*p != '\0') {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen *error_r = "Shared namespace prefix contains unknown variables";
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
c680a6b35b459045e92814778908da5a93922107Timo Sirainen *error_r = "Shared namespace prefix doesn't end with hierarchy separator";
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* truncate prefix after the above checks are done, so they can log
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen the full prefix in error conditions */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenget_nonexistent_user_location(struct shared_storage *storage,
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 /* use a reachable but nonexistent path as the mail root directory */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen str_append(location, storage->storage.user->set->base_dir);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainenstatic bool shared_namespace_exists(struct mail_namespace *ns)
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen path = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen /* we can't know if this exists */
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainenint shared_storage_get_namespace(struct mail_namespace **_ns,
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen const char **_name)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct mail_storage *_storage = (*_ns)->storage;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen if (*p != '%') {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen switch (*++p) {
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen /* we checked this already above */
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen next = strchr(name, *p != '\0' ? *p : ns_sep);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*p != '\0') {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen /* trying to open <prefix>/<user> mailbox */
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen "Invalid namespace prefix %s vs %s",
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen /* successfully matched the name. */
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen /* user@domain given */
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen username = t_strdup_until(userdomain, domain);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* trying to open namespace "shared/domain"
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen namespace prefix. */
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* no domain given, use ours (if we have one) */
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen domain = i_strchr_to_next(user->username, '@');
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen "Empty username doesn't exist");
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 */
220195605754218b4d6e3a51f5a25be9d0e202e0Timo Sirainen if (var_expand(prefix, storage->ns_prefix_pattern, tab, &error) <= 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen "Failed to expand namespace prefix '%s': %s",
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen *_name = mailbox_list_get_storage_name(ns->list,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen owner = mail_user_alloc(userdomain, user->set_info,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen owner->session_id = p_strdup(owner->pool, user->session_id);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "Couldn't create namespace '%s' for user %s: %s",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen } else if (!var_has_key(storage->location, 'h', "home")) {
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 var_expand(location, storage->location, tab, &error) <= 0) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "Failed to expand namespace location '%s': %s",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* create the new namespace */
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 get_nonexistent_user_location(storage, userdomain, location);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ns_set->location = p_strdup(user->pool, str_c(location));
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen p_new(user->pool, struct mail_namespace_settings, 1);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen p_strdup(user->pool, storage->unexpanded_location);
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 */
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 /* owner gets freed by namespace deinit */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* this user doesn't have a usable storage */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* mark the shared namespace root as usable, since it now has
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen child namespaces */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen *_name = mailbox_list_get_storage_name(new_ns->list,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* flags are unset if we were using "auto" storage */