shared-storage.c revision d09be27cc4d98d23ba6ae78f13248945a28f9090
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2008-2017 Dovecot authors, see the included COPYING file */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "lib.h"
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen#include "array.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "str.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "ioloop.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "var-expand.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "index-storage.h"
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen#include "mail-storage-service.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "mailbox-list-private.h"
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen#include "fail-mail-storage.h"
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen#include "shared-storage.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include <ctype.h>
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenextern struct mail_storage shared_storage;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainenstatic struct mail_storage *shared_storage_alloc(void)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct shared_storage *storage;
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen pool_t pool;
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen pool = pool_alloconly_create("shared storage", 1024);
12d38e76ba7f70d6219c89ec7416fea0d5de7e02Timo Sirainen storage = p_new(pool, struct shared_storage, 1);
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen storage->storage = shared_storage;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen storage->storage.pool = pool;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return &storage->storage;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic int
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char **error_r)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen struct mail_storage *storage_class;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen const char *driver, *p;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen char *wildcardp, key;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool have_username;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* location must begin with the actual mailbox driver */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen p = strchr(ns->set->location, ':');
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (p == NULL) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen return -1;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen driver = t_strdup_until(ns->set->location, p);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen storage->location = p_strdup(_storage->pool, ns->set->location);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen storage->unexpanded_location =
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen p_strdup(_storage->pool, ns->unexpanded_set->location);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen storage->storage_class_name = p_strdup(_storage->pool, driver);
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen storage_class = mail_user_get_storage_class(_storage->user, driver);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (storage_class != NULL)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen _storage->class_flags = storage_class->class_flags;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen else if (strcmp(driver, "auto") != 0) {
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen driver, NULL);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen return -1;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen }
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen wildcardp = strchr(ns->prefix, '%');
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen if (wildcardp == NULL) {
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen return -1;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen }
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen have_username = FALSE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (*p != '%')
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen continue;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen key = p[1];
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (key == 'u' || key == 'n')
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen have_username = TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen else if (key != '%' && key != 'd')
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (*p != '\0') {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *error_r = "Shared namespace prefix contains unknown variables";
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen return -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (!have_username) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (p[-1] != mail_namespace_get_sep(ns) &&
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) != 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *error_r = "Shared namespace prefix doesn't end with hierarchy separator";
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
83d2e37f065eabe38dc92db485c5ca39ee43ce05Timo Sirainen /* truncate prefix after the above checks are done, so they can log
83d2e37f065eabe38dc92db485c5ca39ee43ce05Timo Sirainen the full prefix in error conditions */
83d2e37f065eabe38dc92db485c5ca39ee43ce05Timo Sirainen *wildcardp = '\0';
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ns->prefix_len = strlen(ns->prefix);
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen return 0;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainenshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mailbox_list_settings *set)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen set->layout = "shared";
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen}
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen
798cfe56c9871262770384da1239162b3800cce1Timo Sirainenstatic void
798cfe56c9871262770384da1239162b3800cce1Timo Sirainenget_nonexistent_user_location(struct shared_storage *storage,
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen const char *username, string_t *location)
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen{
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);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen str_append_c(location, ':');
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen /* use a reachable but nonexistent path as the mail root directory */
4b1781e4c64be52e25b5994e5242dbe696cc7d29Timo Sirainen str_append(location, storage->storage.user->set->base_dir);
4b1781e4c64be52e25b5994e5242dbe696cc7d29Timo Sirainen str_append(location, "/user-not-found/");
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen str_append(location, username);
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen}
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainenstatic bool shared_namespace_exists(struct mail_namespace *ns)
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen{
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen const char *path;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen struct stat st;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen path = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen if (path == NULL) {
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen /* we can't know if this exists */
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen return TRUE;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen }
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen return stat(path, &st) == 0;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen}
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainenint shared_storage_get_namespace(struct mail_namespace **_ns,
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen const char **_name)
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen{
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen struct mail_storage *_storage = (*_ns)->storage;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen struct mailbox_list *list = (*_ns)->list;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen struct shared_storage *storage = (struct shared_storage *)_storage;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_user *user = _storage->user;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_namespace *new_ns, *ns = *_ns;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_user *owner;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *name, *p, *next, **dest, *error;
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen string_t *prefix, *location;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen char ns_sep = mail_namespace_get_sep(ns);
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen int ret;
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen p = storage->ns_prefix_pattern;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (name = *_name; *p != '\0';) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (*p != '%') {
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi if (*p != *name)
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi break;
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi p++; name++;
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi continue;
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen }
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen switch (*++p) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen case 'd':
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen dest = &domain;
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen break;
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen case 'n':
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen dest = &username;
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen break;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen case 'u':
5d4855d7b4dcffb6975ed8e3c9c376dac74e5c8aTimo Sirainen dest = &userdomain;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen break;
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen default:
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen /* we checked this already above */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen i_unreached();
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen p++;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen next = strchr(name, *p != '\0' ? *p : ns_sep);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen if (next == NULL) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *dest = name;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen name = "";
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *dest = t_strdup_until(name, next);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen name = next;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen if (*p != '\0') {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (*name == '\0' ||
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen (name[1] == '\0' && *name == ns_sep)) {
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen /* trying to open <prefix>/<user> mailbox */
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen name = "INBOX";
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen } else {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen mailbox_list_set_critical(list,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen "Invalid namespace prefix %s vs %s",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen storage->ns_prefix_pattern, *_name);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen return -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen /* successfully matched the name. */
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen if (userdomain != NULL) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* user@domain given */
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen domain = strchr(userdomain, '@');
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen if (domain == NULL)
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen username = userdomain;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen else {
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen username = t_strdup_until(userdomain, domain);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen domain++;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen }
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen } else if (username == NULL) {
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen /* trying to open namespace "shared/domain"
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen namespace prefix. */
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(*_name));
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen return -1;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen } else {
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen if (domain == NULL) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* no domain given, use ours (if we have one) */
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen domain = i_strchr_to_next(user->username, '@');
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen userdomain = domain == NULL ? username :
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen t_strconcat(username, "@", domain, NULL);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen }
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen if (*userdomain == '\0') {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen "Empty username doesn't exist");
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
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 */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct var_expand_table tab[] = {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'u', userdomain, "user" },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'n', username, "username" },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'd', domain, "domain" },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'h', NULL, "home" },
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen { '\0', NULL, NULL }
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen };
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen prefix = t_str_new(128);
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str_append(prefix, ns->prefix);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (var_expand(prefix, storage->ns_prefix_pattern, tab, &error) <= 0) {
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi mailbox_list_set_critical(list,
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen "Failed to expand namespace prefix '%s': %s",
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen storage->ns_prefix_pattern, error);
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi return -1;
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi }
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen if (*_ns != NULL) {
3db05c8c00faca6ab9ac8391e1d6977365f4d1b3Timo Sirainen *_name = mailbox_list_get_storage_name(ns->list,
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen t_strconcat(ns->prefix, name, NULL));
3db05c8c00faca6ab9ac8391e1d6977365f4d1b3Timo Sirainen return 0;
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen }
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen owner = mail_user_alloc(userdomain, user->set_info,
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen user->unexpanded_set);
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen owner->_service_user = user->_service_user;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mail_storage_service_user_ref(owner->_service_user);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen owner->creator = user;
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen owner->autocreated = TRUE;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen owner->session_id = p_strdup(owner->pool, user->session_id);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (mail_user_init(owner, &error) < 0) {
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen if (!owner->nonexistent) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mailbox_list_set_critical(list,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "Couldn't create namespace '%s' for user %s: %s",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ns->prefix, userdomain, error);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen mail_user_unref(&owner);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ret = 0;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen } else if (!var_has_key(storage->location, 'h', "home")) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ret = 1;
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen } else {
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",
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen ns->prefix, userdomain);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen mail_user_unref(&owner);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return -1;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen location = t_str_new(256);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (ret > 0 &&
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen var_expand(location, storage->location, tab, &error) <= 0) {
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen mailbox_list_set_critical(list,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen "Failed to expand namespace location '%s': %s",
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen storage->location, error);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen return -1;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen }
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen /* create the new namespace */
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen new_ns = i_new(struct mail_namespace, 1);
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen new_ns->refcount = 1;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen new_ns->type = MAIL_NAMESPACE_TYPE_SHARED;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen new_ns->user = user;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen new_ns->prefix = i_strdup(str_c(prefix));
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen new_ns->owner = owner;
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;
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen new_ns->user_set = user->set;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen new_ns->mail_set = _storage->set;
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen i_array_init(&new_ns->all_storages, 2);
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen
430c0b0c370bebeeceba2e206be76bc134742f41Timo Sirainen if (ret <= 0) {
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen get_nonexistent_user_location(storage, userdomain, location);
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen if (ns->user->mail_debug) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_debug("shared: Tried to access mails of "
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "nonexistent user %s", userdomain);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ns_set->type = "shared";
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ns_set->prefix = new_ns->prefix;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ns_set->location = p_strdup(user->pool, str_c(location));
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen ns_set->hidden = TRUE;
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen ns_set->list = "yes";
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen new_ns->set = ns_set;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen unexpanded_ns_set =
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen p_new(user->pool, struct mail_namespace_settings, 1);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen *unexpanded_ns_set = *ns_set;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen unexpanded_ns_set->location =
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen p_strdup(user->pool, storage->unexpanded_location);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen new_ns->unexpanded_set = unexpanded_ns_set;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
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 */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen mail_namespace_destroy(new_ns);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return -1;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen
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",
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen new_ns->prefix, error);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* owner gets freed by namespace deinit */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen mail_namespace_destroy(new_ns);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return -1;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen !shared_namespace_exists(new_ns)) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* this user doesn't have a usable storage */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* mark the shared namespace root as usable, since it now has
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen child namespaces */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ns->flags |= NAMESPACE_FLAG_USABLE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen *_name = mailbox_list_get_storage_name(new_ns->list,
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen t_strconcat(new_ns->prefix, name, NULL));
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen *_ns = new_ns;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (_storage->class_flags == 0) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* flags are unset if we were using "auto" storage */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen _storage->class_flags =
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen mail_namespace_get_default_storage(new_ns)->class_flags;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mail_user_add_namespace(user, &new_ns);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return 0;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen}
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstruct mail_storage shared_storage = {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen .name = MAIL_SHARED_STORAGE_NAME,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen .class_flags = 0, /* unknown at this point */
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen .v = {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen NULL,
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen shared_storage_alloc,
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen shared_storage_create,
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen index_storage_destroy,
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen NULL,
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen shared_storage_get_list_settings,
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen NULL,
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen fail_mailbox_alloc,
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen NULL,
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen NULL,
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen }
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen};
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen