shared-storage.c revision 0116003edce8cad684715b1b37cf57e3674cf2cb
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2008-2018 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"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "index-storage.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-storage-service.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mailbox-list-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "fail-mail-storage.h"
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen#include "shared-storage.h"
56561d472db25ebda35ae6afdc7f7deb75c323fcTimo Sirainen
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen#include <ctype.h>
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainenextern struct mail_storage shared_storage;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct mail_storage *shared_storage_alloc(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct shared_storage *storage;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_t pool;
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen pool = pool_alloconly_create("shared storage", 1024);
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen storage = p_new(pool, struct shared_storage, 1);
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen storage->storage = shared_storage;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage->storage.pool = pool;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return &storage->storage;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainenstatic int
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainenshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen const char **error_r)
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen{
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen struct shared_storage *storage = SHARED_STORAGE(_storage);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen const char *driver, *p;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen char *wildcardp, key;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen bool have_username;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* location must begin with the actual mailbox driver */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen p = strchr(ns->set->location, ':');
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (p == NULL) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen driver = t_strdup_until(ns->set->location, p);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen storage->location = p_strdup(_storage->pool, ns->set->location);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen storage->unexpanded_location =
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen p_strdup(_storage->pool, ns->unexpanded_set->location);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen storage->storage_class_name = p_strdup(_storage->pool, driver);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (mail_user_get_storage_class(_storage->user, driver) == NULL &&
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen strcmp(driver, "auto") != 0) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen driver, NULL);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return -1;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen wildcardp = strchr(ns->prefix, '%');
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (wildcardp == NULL) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen return -1;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen have_username = FALSE;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (*p != '%')
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen continue;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen key = p[1];
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen if (key == 'u' || key == 'n')
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen have_username = TRUE;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen else if (key != '%' && key != 'd')
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen break;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (*p != '\0') {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo 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";
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return -1;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (p[-1] != mail_namespace_get_sep(ns) &&
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) != 0) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen *error_r = "Shared namespace prefix doesn't end with hierarchy separator";
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return -1;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* truncate prefix after the above checks are done, so they can log
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen the full prefix in error conditions */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen *wildcardp = '\0';
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainen ns->prefix_len = strlen(ns->prefix);
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen return 0;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen}
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenstatic void
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen struct mailbox_list_settings *set)
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen{
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen set->layout = "shared";
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen}
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainenstatic void
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainenget_nonexistent_user_location(struct shared_storage *storage,
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen const char *username, string_t *location)
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen{
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);
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen str_append_c(location, ':');
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* use a reachable but nonexistent path as the mail root directory */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen str_append(location, storage->storage.user->set->base_dir);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen str_append(location, "/user-not-found/");
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen str_append(location, username);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen}
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainenstatic bool shared_namespace_exists(struct mail_namespace *ns)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen{
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen const char *path;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct stat st;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen path = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (path == NULL) {
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen /* we can't know if this exists */
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen return TRUE;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen }
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen return stat(path, &st) == 0;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen}
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenint shared_storage_get_namespace(struct mail_namespace **_ns,
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainen const char **_name)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen{
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct mail_storage *_storage = (*_ns)->storage;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct mailbox_list *list = (*_ns)->list;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct shared_storage *storage = SHARED_STORAGE(_storage);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct mail_user *user = _storage->user;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct mail_namespace *new_ns, *ns = *_ns;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct mail_user *owner;
c680a6b35b459045e92814778908da5a93922107Timo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
c680a6b35b459045e92814778908da5a93922107Timo Sirainen const char *name, *p, *next, **dest, *error;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen string_t *prefix, *location;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen char ns_sep = mail_namespace_get_sep(ns);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen int ret;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen p = storage->ns_prefix_pattern;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen for (name = *_name; *p != '\0';) {
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen if (*p != '%') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*p != *name)
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen break;
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen p++; name++;
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen continue;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen switch (*++p) {
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen case 'd':
659fe5d24825b160cae512538088020d97a60239Timo Sirainen dest = &domain;
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen break;
a0d1b7178be151f49204ca2b33d5fa0ba314571aTimo Sirainen case 'n':
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainen dest = &username;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen break;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen case 'u':
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen dest = &userdomain;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen default:
5cdd348121e62a6244ba2f93db781731f7129a71Timo Sirainen /* we checked this already above */
5cdd348121e62a6244ba2f93db781731f7129a71Timo Sirainen i_unreached();
5cdd348121e62a6244ba2f93db781731f7129a71Timo Sirainen }
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen p++;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen next = strchr(name, *p != '\0' ? *p : ns_sep);
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen if (next == NULL) {
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen *dest = name;
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen name = "";
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen break;
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen }
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen *dest = t_strdup_until(name, next);
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen name = next;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (*p != '\0') {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (*name == '\0' ||
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen (name[1] == '\0' && *name == ns_sep)) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* trying to open <prefix>/<user> mailbox */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen name = "INBOX";
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen } else {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen mailbox_list_set_critical(list,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Invalid namespace prefix %s vs %s",
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen storage->ns_prefix_pattern, *_name);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return -1;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen /* successfully matched the name. */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (userdomain != NULL) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* user@domain given */
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen domain = strchr(userdomain, '@');
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen if (domain == NULL)
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen username = userdomain;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen else {
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen username = t_strdup_until(userdomain, domain);
a0d1b7178be151f49204ca2b33d5fa0ba314571aTimo Sirainen domain++;
a0d1b7178be151f49204ca2b33d5fa0ba314571aTimo Sirainen }
a0d1b7178be151f49204ca2b33d5fa0ba314571aTimo Sirainen } else if (username == NULL) {
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen /* trying to open namespace "shared/domain"
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen namespace prefix. */
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(*_name));
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return -1;
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen } else {
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen if (domain == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* no domain given, use ours (if we have one) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen domain = i_strchr_to_next(user->username, '@');
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen }
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen userdomain = domain == NULL ? username :
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen t_strconcat(username, "@", domain, NULL);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen }
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen if (*userdomain == '\0') {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen "Empty username doesn't exist");
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen return -1;
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen }
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen
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 struct var_expand_table tab[] = {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen { 'u', userdomain, "user" },
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen { 'n', username, "username" },
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen { 'd', domain, "domain" },
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen { 'h', NULL, "home" },
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen { '\0', NULL, NULL }
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen };
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen prefix = t_str_new(128);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen str_append(prefix, ns->prefix);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen if (var_expand(prefix, storage->ns_prefix_pattern, tab, &error) <= 0) {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen mailbox_list_set_critical(list,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen "Failed to expand namespace prefix '%s': %s",
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen storage->ns_prefix_pattern, error);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen return -1;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen }
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo 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));
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen return 0;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen }
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen owner = mail_user_alloc(event_get_parent(user->event), userdomain,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen user->set_info, user->unexpanded_set);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen owner->_service_user = user->_service_user;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen mail_storage_service_user_ref(owner->_service_user);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen owner->creator = user;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen owner->autocreated = TRUE;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen owner->session_id = p_strdup(owner->pool, user->session_id);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen if (mail_user_init(owner, &error) < 0) {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen if (!owner->nonexistent) {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen mailbox_list_set_critical(list,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen "Couldn't create namespace '%s' for user %s: %s",
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen ns->prefix, userdomain, error);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen mail_user_unref(&owner);
fd3f33bdb57170d63aea66ecacc8bea0f0145d6aTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
7761758f43d6150be4b07f4c54457ce662f78c4cTimo Sirainen ret = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (!var_has_key(storage->location, 'h', "home")) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else {
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",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ns->prefix, userdomain);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_user_unref(&owner);
d39c0e195c67be5f2b0a15f25a8d6039bef02711Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen }
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen location = t_str_new(256);
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen if (ret > 0 &&
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen var_expand(location, storage->location, tab, &error) <= 0) {
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen mailbox_list_set_critical(list,
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen "Failed to expand namespace location '%s': %s",
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen storage->location, error);
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen return -1;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen }
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* create the new namespace */
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen new_ns = i_new(struct mail_namespace, 1);
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen new_ns->refcount = 1;
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen new_ns->type = MAIL_NAMESPACE_TYPE_SHARED;
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen new_ns->user = user;
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen new_ns->prefix = i_strdup(str_c(prefix));
1d06a935b555024420d1c22249f0c847e51a9b7aTimo Sirainen new_ns->owner = owner;
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;
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen new_ns->user_set = user->set;
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen new_ns->mail_set = _storage->set;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen i_array_init(&new_ns->all_storages, 2);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret <= 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen get_nonexistent_user_location(storage, userdomain, location);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ns->user->mail_debug) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_debug("shared: Tried to access mails of "
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen "nonexistent user %s", userdomain);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen }
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen ns_set->type = "shared";
56561d472db25ebda35ae6afdc7f7deb75c323fcTimo Sirainen ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen ns_set->prefix = new_ns->prefix;
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen ns_set->location = p_strdup(user->pool, str_c(location));
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen ns_set->hidden = TRUE;
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen ns_set->list = "yes";
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen new_ns->set = ns_set;
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen unexpanded_ns_set =
530c3ece3717ad8193046ea7774227f91971a0dcTimo Sirainen p_new(user->pool, struct mail_namespace_settings, 1);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen *unexpanded_ns_set = *ns_set;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen unexpanded_ns_set->location =
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen p_strdup(user->pool, storage->unexpanded_location);
8082f8848607490ba7118a9b11ee3d184632344cTimo Sirainen new_ns->unexpanded_set = unexpanded_ns_set;
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainen
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 */
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen mail_namespace_destroy(new_ns);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return -1;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
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",
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen new_ns->prefix, error);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen /* owner gets freed by namespace deinit */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen mail_namespace_destroy(new_ns);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return -1;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
0c09e57c5d5a649c248d0073438d79acbb80c72bTimo Sirainen !shared_namespace_exists(new_ns)) {
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen /* this user doesn't have a usable storage */
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen }
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen /* mark the shared namespace root as usable, since it now has
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen child namespaces */
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen ns->flags |= NAMESPACE_FLAG_USABLE;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen *_name = mailbox_list_get_storage_name(new_ns->list,
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen t_strconcat(new_ns->prefix, name, NULL));
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen *_ns = new_ns;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen if (_storage->class_flags == 0) {
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen /* flags are unset if we were using "auto" storage */
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen _storage->class_flags =
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen mail_namespace_get_default_storage(new_ns)->class_flags;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen mail_user_add_namespace(user, &new_ns);
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_storage shared_storage = {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen .name = MAIL_SHARED_STORAGE_NAME,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen .class_flags = 0, /* unknown at this point */
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen
24c6aaf3c540d078021bb4a326982ae4e3d7eaf8Timo Sirainen .v = {
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen NULL,
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen shared_storage_alloc,
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen shared_storage_create,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_storage_destroy,
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen NULL,
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen shared_storage_get_list_settings,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen NULL,
8ef80b0b9c73fb0a0188788b14b3e15084b7a452Timo Sirainen fail_mailbox_alloc,
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen NULL,
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen NULL,
87ca2e468841829b44c09d618ac02f61a30b7a49Timo Sirainen }
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen};
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen