shared-storage.c revision d09be27cc4d98d23ba6ae78f13248945a28f9090
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2008-2017 Dovecot authors, see the included COPYING file */
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainenstatic struct mail_storage *shared_storage_alloc(void)
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen pool = pool_alloconly_create("shared storage", 1024);
12d38e76ba7f70d6219c89ec7416fea0d5de7e02Timo Sirainen storage = p_new(pool, struct shared_storage, 1);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char **error_r)
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen const char *driver, *p;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* location must begin with the actual mailbox driver */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen driver = t_strdup_until(ns->set->location, p);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen storage->location = p_strdup(_storage->pool, ns->set->location);
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen p_strdup(_storage->pool, ns->unexpanded_set->location);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen storage->storage_class_name = p_strdup(_storage->pool, driver);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen storage_class = mail_user_get_storage_class(_storage->user, driver);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen _storage->class_flags = storage_class->class_flags;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (*p != '%')
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (*p != '\0') {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *error_r = "Shared namespace prefix contains unknown variables";
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *error_r = "Shared namespace prefix doesn't end with hierarchy separator";
83d2e37f065eabe38dc92db485c5ca39ee43ce05Timo Sirainen /* truncate prefix after the above checks are done, so they can log
83d2e37f065eabe38dc92db485c5ca39ee43ce05Timo Sirainen the full prefix in error conditions */
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainenshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
798cfe56c9871262770384da1239162b3800cce1Timo Sirainenget_nonexistent_user_location(struct shared_storage *storage,
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen /* user wasn't found. we'll still need to create the storage
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainen to avoid exposing which users exist and which don't. */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen str_append(location, storage->storage_class_name);
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen /* use a reachable but nonexistent path as the mail root directory */
4b1781e4c64be52e25b5994e5242dbe696cc7d29Timo Sirainen str_append(location, storage->storage.user->set->base_dir);
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainenstatic bool shared_namespace_exists(struct mail_namespace *ns)
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen path = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen /* we can't know if this exists */
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainenint shared_storage_get_namespace(struct mail_namespace **_ns,
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen const char **_name)
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen struct mail_storage *_storage = (*_ns)->storage;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (*p != '%') {
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen switch (*++p) {
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen /* we checked this already above */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen next = strchr(name, *p != '\0' ? *p : ns_sep);
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen if (*p != '\0') {
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen /* trying to open <prefix>/<user> mailbox */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen "Invalid namespace prefix %s vs %s",
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen /* successfully matched the name. */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* user@domain given */
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen username = t_strdup_until(userdomain, domain);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen /* trying to open namespace "shared/domain"
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen namespace prefix. */
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* no domain given, use ours (if we have one) */
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen domain = i_strchr_to_next(user->username, '@');
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen "Empty username doesn't exist");
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen /* expand the namespace prefix and see if it already exists.
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen this should normally happen only when the mailbox is being opened */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (var_expand(prefix, storage->ns_prefix_pattern, tab, &error) <= 0) {
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen "Failed to expand namespace prefix '%s': %s",
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
3db05c8c00faca6ab9ac8391e1d6977365f4d1b3Timo Sirainen *_name = mailbox_list_get_storage_name(ns->list,
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen owner = mail_user_alloc(userdomain, user->set_info,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mail_storage_service_user_ref(owner->_service_user);
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen owner->session_id = p_strdup(owner->pool, user->session_id);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "Couldn't create namespace '%s' for user %s: %s",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen } else if (!var_has_key(storage->location, 'h', "home")) {
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen /* we'll need to look up the user's home directory */
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if ((ret = mail_user_get_home(owner, &tab[3].value)) < 0) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen mailbox_list_set_critical(list, "Namespace '%s': "
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen "Could not lookup home for user %s",
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen var_expand(location, storage->location, tab, &error) <= 0) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen "Failed to expand namespace location '%s': %s",
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen /* create the new namespace */
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen new_ns->flags = (NAMESPACE_FLAG_SUBSCRIPTIONS & ns->flags) |
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX_ANY;
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen get_nonexistent_user_location(storage, userdomain, location);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ns_set->location = p_strdup(user->pool, str_c(location));
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen p_new(user->pool, struct mail_namespace_settings, 1);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen p_strdup(user->pool, storage->unexpanded_location);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* We need to create a prefix="" namespace for the owner */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (mail_namespaces_init_location(owner, str_c(location), &error) < 0) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* owner gets freed by namespace deinit */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (mail_storage_create(new_ns, NULL, _storage->flags |
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen MAIL_STORAGE_FLAG_NO_AUTOVERIFY, &error) < 0) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mailbox_list_set_critical(list, "Namespace '%s': %s",
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* owner gets freed by namespace deinit */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* this user doesn't have a usable storage */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* mark the shared namespace root as usable, since it now has
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen child namespaces */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen *_name = mailbox_list_get_storage_name(new_ns->list,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* flags are unset if we were using "auto" storage */