shared-storage.c revision 0116003edce8cad684715b1b37cf57e3674cf2cb
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct mail_storage *shared_storage_alloc(void)
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen pool = pool_alloconly_create("shared storage", 1024);
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen storage = p_new(pool, struct shared_storage, 1);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainenshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen const char **error_r)
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen struct shared_storage *storage = SHARED_STORAGE(_storage);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen const char *driver, *p;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* location must begin with the actual mailbox driver */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen driver = t_strdup_until(ns->set->location, p);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen storage->location = p_strdup(_storage->pool, ns->set->location);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen p_strdup(_storage->pool, ns->unexpanded_set->location);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen storage->storage_class_name = p_strdup(_storage->pool, driver);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (mail_user_get_storage_class(_storage->user, driver) == NULL &&
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (*p != '%')
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (*p != '\0') {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen *error_r = "Shared namespace prefix contains unknown variables";
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen *error_r = "Shared namespace prefix doesn't end with hierarchy separator";
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* truncate prefix after the above checks are done, so they can log
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen the full prefix in error conditions */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainenget_nonexistent_user_location(struct shared_storage *storage,
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen /* user wasn't found. we'll still need to create the storage
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen to avoid exposing which users exist and which don't. */
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen str_append(location, storage->storage_class_name);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* use a reachable but nonexistent path as the mail root directory */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen str_append(location, storage->storage.user->set->base_dir);
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainenstatic bool shared_namespace_exists(struct mail_namespace *ns)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen path = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen /* we can't know if this exists */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenint shared_storage_get_namespace(struct mail_namespace **_ns,
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainen const char **_name)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct mail_storage *_storage = (*_ns)->storage;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct shared_storage *storage = SHARED_STORAGE(_storage);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
c680a6b35b459045e92814778908da5a93922107Timo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen if (*p != '%') {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen switch (*++p) {
5cdd348121e62a6244ba2f93db781731f7129a71Timo Sirainen /* we checked this already above */
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen next = strchr(name, *p != '\0' ? *p : ns_sep);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (*p != '\0') {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* trying to open <prefix>/<user> mailbox */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Invalid namespace prefix %s vs %s",
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen /* successfully matched the name. */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* user@domain given */
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen username = t_strdup_until(userdomain, domain);
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen /* trying to open namespace "shared/domain"
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen namespace prefix. */
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* no domain given, use ours (if we have one) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen domain = i_strchr_to_next(user->username, '@');
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen "Empty username doesn't exist");
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen /* expand the namespace prefix and see if it already exists.
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen this should normally happen only when the mailbox is being opened */
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen if (var_expand(prefix, storage->ns_prefix_pattern, tab, &error) <= 0) {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen "Failed to expand namespace prefix '%s': %s",
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen *_name = mailbox_list_get_storage_name(ns->list,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen owner = mail_user_alloc(event_get_parent(user->event), userdomain,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen mail_storage_service_user_ref(owner->_service_user);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen owner->session_id = p_strdup(owner->pool, user->session_id);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen "Couldn't create namespace '%s' for user %s: %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (!var_has_key(storage->location, 'h', "home")) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* we'll need to look up the user's home directory */
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen if ((ret = mail_user_get_home(owner, &tab[3].value)) < 0) {
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen mailbox_list_set_critical(list, "Namespace '%s': "
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen "Could not lookup home for user %s",
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen var_expand(location, storage->location, tab, &error) <= 0) {
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen "Failed to expand namespace location '%s': %s",
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* create the new namespace */
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen new_ns->flags = (NAMESPACE_FLAG_SUBSCRIPTIONS & ns->flags) |
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX_ANY;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen get_nonexistent_user_location(storage, userdomain, location);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
56561d472db25ebda35ae6afdc7f7deb75c323fcTimo Sirainen ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen ns_set->location = p_strdup(user->pool, str_c(location));
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen p_new(user->pool, struct mail_namespace_settings, 1);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen p_strdup(user->pool, storage->unexpanded_location);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* We need to create a prefix="" namespace for the owner */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (mail_namespaces_init_location(owner, str_c(location), &error) < 0) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* owner gets freed by namespace deinit */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (mail_storage_create(new_ns, NULL, _storage->flags |
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen MAIL_STORAGE_FLAG_NO_AUTOVERIFY, &error) < 0) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen mailbox_list_set_critical(list, "Namespace '%s': %s",
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen /* owner gets freed by namespace deinit */
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen /* this user doesn't have a usable storage */
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen /* mark the shared namespace root as usable, since it now has
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen child namespaces */
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen *_name = mailbox_list_get_storage_name(new_ns->list,
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen /* flags are unset if we were using "auto" storage */