doveadm-acl.c revision 6bd9ffc5d782e160c8542d53b26864ed973c8f66
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenconst char *doveadm_acl_plugin_version = DOVECOT_VERSION;
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenvoid doveadm_acl_plugin_init(struct module *module);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainencmd_acl_mailbox_open(struct mail_user *user, const char *mailbox,
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen struct acl_user *auser = ACL_USER_CONTEXT(user);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen i_error("ACL not enabled for %s", user->username);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen ns = mail_namespace_find(user->namespaces, mailbox);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen i_error("No namespace found for mailbox %s", mailbox);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT |
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenstatic void cmd_acl_get_right(const struct acl_rights *rights)
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen id = t_strconcat(ACL_ID_NAME_GROUP_OVERRIDE_PREFIX,
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen str_append(str, t_strarray_join(rights->rights, " "));
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen str_append(str, t_strarray_join(rights->neg_rights, " -"));
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenstatic void cmd_acl_get_mailbox(struct doveadm_acl_cmd_context *ctx,
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen struct acl_object *aclobj = acl_mailbox_get_aclobj(box);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen backend = acl_mailbox_list_get_backend(box->list);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen while ((ret = acl_object_list_next(iter, &rights)) > 0) T_BEGIN {
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen acl_backend_rights_match_me(backend, &rights))
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainencmd_acl_get_run(struct doveadm_mail_cmd_context *_ctx,
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen if (cmd_acl_mailbox_open(user, mailbox, &box) < 0)
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenstatic bool cmd_acl_get_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenstatic void cmd_acl_get_init(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen const char *const args[])
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_acl_cmd_context);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainencmd_acl_rights_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user)
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen const char *const *rights;
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen if (cmd_acl_mailbox_open(user, mailbox, &box) < 0)
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen if (acl_object_get_my_rights(aclobj, pool_datastack_create(),
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenstatic void cmd_acl_rights_init(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen const char *const args[])
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainencmd_acl_set_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user)
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen const char *mailbox = ctx->args[0], *id = ctx->args[1];
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen ARRAY_TYPE(const_string) dest_rights, dest_neg_rights, *dest;
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen unsigned int i, j;
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen if (cmd_acl_mailbox_open(user, mailbox, &box) < 0)
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen update.neg_modify_mode = ACL_MODIFY_MODE_REPLACE;
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen if (acl_identifier_parse(id, &update.rights) < 0)
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen for (j = 0; all_mailbox_rights[j] != NULL; j++)
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen array_append(dest, &all_mailbox_rights[j], 1);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen update.rights.rights = array_idx(&dest_rights, 0);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen update.rights.neg_rights = array_idx(&dest_neg_rights, 0);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenstatic void cmd_acl_set_init(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen const char *const args[])
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
3aa600b8467f5cec0fd2e0a76c4815973ca61e1fTimo Sirainencmd_acl_delete_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user)
3aa600b8467f5cec0fd2e0a76c4815973ca61e1fTimo Sirainen const char *mailbox = ctx->args[0], *id = ctx->args[1];
3aa600b8467f5cec0fd2e0a76c4815973ca61e1fTimo Sirainen if (cmd_acl_mailbox_open(user, mailbox, &box) < 0)
3aa600b8467f5cec0fd2e0a76c4815973ca61e1fTimo Sirainen update.neg_modify_mode = ACL_MODIFY_MODE_CLEAR;
3aa600b8467f5cec0fd2e0a76c4815973ca61e1fTimo Sirainen if (acl_identifier_parse(id, &update.rights) < 0)
3aa600b8467f5cec0fd2e0a76c4815973ca61e1fTimo Sirainenstatic void cmd_acl_delete_init(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
3aa600b8467f5cec0fd2e0a76c4815973ca61e1fTimo Sirainen const char *const args[])
3aa600b8467f5cec0fd2e0a76c4815973ca61e1fTimo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
6bd9ffc5d782e160c8542d53b26864ed973c8f66Timo Sirainenstatic bool cmd_acl_debug_mailbox(struct mailbox *box, bool *retry_r)
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen struct mail_namespace *ns = mailbox_get_namespace(box);
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen struct acl_user *auser = ACL_USER_CONTEXT(ns->user);
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen struct acl_object *aclobj = acl_mailbox_get_aclobj(box);
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen struct acl_backend *backend = acl_mailbox_list_get_backend(box->list);
7b39597853fc030086b5237169e677173f9aab62Timo Sirainen private_flags_mask = mailbox_get_private_flags_mask(box);
facd0971af3c905a3838ba14abc5682f285c9464Timo Sirainen i_info("All message flags are shared across users in mailbox");
7b39597853fc030086b5237169e677173f9aab62Timo Sirainen imap_write_flags(str, private_flags_mask, NULL);
facd0971af3c905a3838ba14abc5682f285c9464Timo Sirainen i_info("Per-user private flags in mailbox: %s", str_c(str));
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen /* check if user has lookup right */
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen if (acl_object_get_my_rights(aclobj, pool_datastack_create(),
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen i_info("User %s has no rights for mailbox", ns->user->username);
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen ns->user->username, t_strarray_join(rights, " "));
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen if (!str_array_find(rights, MAIL_ACL_LOOKUP)) {
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen /* check if mailbox is listable */
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen i_info("Mailbox in user's private namespace");
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen iter = acl_backend_nonowner_lookups_iter_init(backend);
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen while ((ret = acl_backend_nonowner_lookups_iter_next(iter, &name)) > 0) {
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen acl_backend_nonowner_lookups_iter_deinit(&iter);
6bd9ffc5d782e160c8542d53b26864ed973c8f66Timo Sirainen i_error("Mailbox not found from dovecot-acl-list, rebuilding");
6bd9ffc5d782e160c8542d53b26864ed973c8f66Timo Sirainen if (acl_backend_nonowner_lookups_rebuild(backend) < 0)
6bd9ffc5d782e160c8542d53b26864ed973c8f66Timo Sirainen i_fatal("dovecot-acl-list rebuilding failed");
6bd9ffc5d782e160c8542d53b26864ed973c8f66Timo Sirainen i_info("Mailbox found from dovecot-acl-list");
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen if (!acl_lookup_dict_is_enabled(auser->acl_lookup_dict)) {
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen /* shared namespace. see if it's in acl lookup dict */
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen diter = acl_lookup_dict_iterate_visible_init(auser->acl_lookup_dict);
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen while ((name = acl_lookup_dict_iterate_visible_next(diter)) != NULL) {
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen if (acl_lookup_dict_iterate_visible_deinit(&diter) < 0)
6bd9ffc5d782e160c8542d53b26864ed973c8f66Timo Sirainen i_error("User %s not found from ACL shared dict, rebuilding",
6bd9ffc5d782e160c8542d53b26864ed973c8f66Timo Sirainen if (acl_lookup_dict_rebuild(auser->acl_lookup_dict) < 0)
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainencmd_acl_debug_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user)
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen if (cmd_acl_mailbox_open(user, mailbox, &box) < 0)
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen i_info("Mailbox %s is visible in LIST", box->vname);
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen i_info("Mailbox %s is NOT visible in LIST", box->vname);
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainenstatic void cmd_acl_debug_init(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen const char *const args[])
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenstatic struct doveadm_mail_cmd acl_commands[] = {
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen { cmd_acl_get_alloc, "acl get", "[-m] <mailbox>" },
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen { cmd_acl_rights_alloc, "acl rights", "<mailbox>" },
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen { cmd_acl_set_alloc, "acl set", "<mailbox> <id> <rights>" },
3aa600b8467f5cec0fd2e0a76c4815973ca61e1fTimo Sirainen { cmd_acl_delete_alloc, "acl delete", "<mailbox> <id>" },
7c598f384223a1364e8040c1e2a4cad8d00edde6Timo Sirainen { cmd_acl_debug_alloc, "acl debug", "<mailbox>" }
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenvoid doveadm_acl_plugin_init(struct module *module ATTR_UNUSED)
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen unsigned int i;
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainen for (i = 0; i < N_ELEMENTS(acl_commands); i++)