2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina#include "lib.h"
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina#include "array.h"
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina#include "ioloop.h"
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina#include "str.h"
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina#include "var-expand.h"
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina#include "acl-plugin.h"
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina#include "acl-lookup-dict.h"
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina#include "acl-shared-storage.h"
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina#include "index/shared/shared-storage.h"
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina#define SHARED_NS_RETRY_SECS (60*60)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březinastatic bool acl_ns_prefix_exists(struct mail_namespace *ns)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina{
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina struct mailbox *box;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina const char *vname;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina enum mailbox_existence existence;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina bool ret;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (ns->list->mail_set->mail_shared_explicit_inbox)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina return FALSE;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
d38ffc9c92daeb62de7d28c409bdaeff98f82775Pavel Březina vname = t_strndup(ns->prefix, ns->prefix_len-1);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina box = mailbox_alloc(ns->list, vname, 0);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina ret = mailbox_exists(box, FALSE, &existence) == 0 &&
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina existence == MAILBOX_EXISTENCE_SELECT;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina mailbox_free(&box);
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina return ret;
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina}
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březinastatic void
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březinaacl_shared_namespace_add(struct mail_namespace *ns,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina struct mail_storage *storage, const char *userdomain)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina{
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina struct shared_storage *sstorage = (struct shared_storage *)storage;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina struct mail_namespace *new_ns = ns;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina struct mailbox_list_iterate_context *iter;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina const struct mailbox_info *info;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina const char *mailbox, *error;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov string_t *str;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (strcmp(ns->user->username, userdomain) == 0) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* skip ourself */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina return;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina }
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina const struct var_expand_table tab[] = {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina { 'u', userdomain, "user" },
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina { 'n', t_strcut(userdomain, '@'), "username" },
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina { 'd', i_strchr_to_next(userdomain, '@'), "domain" },
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina { '\0', NULL, NULL }
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina };
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina str = t_str_new(128);
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina if (var_expand(str, sstorage->ns_prefix_pattern, tab, &error) <= 0) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina i_error("Failed to expand namespace prefix %s: %s",
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina sstorage->ns_prefix_pattern, error);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina return;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina }
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina mailbox = str_c(str);
1b3144586978c47506eaa39db505e6231e3b0c0aJakub Hrozek if (shared_storage_get_namespace(&new_ns, &mailbox) < 0)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina return;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* check if there are any mailboxes really visible to us */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina iter = mailbox_list_iter_init(new_ns->list, "*",
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina while ((info = mailbox_list_iter_next(iter)) != NULL)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina break;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina (void)mailbox_list_iter_deinit(&iter);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (info == NULL && !acl_ns_prefix_exists(new_ns)) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* no visible mailboxes, remove the namespace */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina mail_namespace_destroy(new_ns);
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina }
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina}
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březinaint acl_shared_namespaces_add(struct mail_namespace *ns)
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina{
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina struct acl_user *auser = ACL_USER_CONTEXT(ns->user);
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ns->list);
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina struct mail_storage *storage = mail_namespace_get_default_storage(ns);
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina struct acl_lookup_dict_iter *iter;
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina const char *name;
573e86dc3156e481ce53d39ac901da2e99cfa0caJakub Hrozek
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina i_assert(auser != NULL && alist != NULL);
573e86dc3156e481ce53d39ac901da2e99cfa0caJakub Hrozek i_assert(ns->type == MAIL_NAMESPACE_TYPE_SHARED);
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina i_assert(strcmp(storage->name, MAIL_SHARED_STORAGE_NAME) == 0);
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina if (ioloop_time < alist->last_shared_add_check + SHARED_NS_RETRY_SECS) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov /* already added, don't bother rechecking */
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina return 0;
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina }
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina alist->last_shared_add_check = ioloop_time;
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina iter = acl_lookup_dict_iterate_visible_init(auser->acl_lookup_dict);
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina while ((name = acl_lookup_dict_iterate_visible_next(iter)) != NULL) {
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina T_BEGIN {
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina acl_shared_namespace_add(ns, storage, name);
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina } T_END;
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina }
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina return acl_lookup_dict_iterate_visible_deinit(&iter);
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina}
710472d946f6c337a095699dfd79134fa8b9eab9Pavel Březina