acl-mailbox.c revision ef3f582fdf2d007838bba693f8c2629d079668de
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen/* FIXME: If we don't have permission to change flags/keywords, the changes
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen should still be stored temporarily for this session. However most clients
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen don't care and it's a huge job, so I currently this isn't done. The same
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen problem actually exists when opening read-only mailboxes. */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen union mailbox_transaction_module_context module_ctx;
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(acl_mail_module, &mail_module_register);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic struct acl_transaction_context acl_transaction_failure;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstatic int mailbox_acl_right_lookup(struct mailbox *box, unsigned int right_idx)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mail_storage *astorage = ACL_CONTEXT(box->storage);
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen astorage->rights.acl_storage_right_idx[right_idx]);
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen mail_storage_set_internal_error(box->storage);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainenstatic bool acl_is_readonly(struct mailbox *box)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if (mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_INSERT) > 0)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if (mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_EXPUNGE) > 0)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen /* Next up is the "shared flag rights" */
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if (mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE) > 0)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if ((box->private_flags_mask & MAIL_DELETED) == 0 &&
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_DELETED) > 0)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if ((box->private_flags_mask & MAIL_SEEN) == 0 &&
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_SEEN) > 0)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainenstatic bool acl_allow_new_keywords(struct mailbox *box)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if (!abox->module_ctx.super.allow_new_keywords(box))
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen return mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE) > 0;
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainenstatic int acl_mailbox_close(struct mailbox *box)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen bool *flags_r, bool *flag_seen_r, bool *flag_del_r)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ret = mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ret = mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_SEEN);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ret = mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_DELETED);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void acl_transaction_set_failure(struct mailbox_transaction_context *t)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_mail_update_flags(struct mail *_mail, enum modify_type modify_type,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mail_module_context *amail = ACL_MAIL_CONTEXT(mail);
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen if (acl_get_write_rights(_mail->box, &acl_flags, &acl_flag_seen,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen acl_transaction_set_failure(_mail->transaction);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen /* adding/removing flags. just remove the disallowed
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen flags from the mask. */
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen } else if (!acl_flags || !acl_flag_seen || !acl_flag_del) {
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen /* we don't have permission to replace all the flags. */
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (!acl_flags && !acl_flag_seen && !acl_flag_del) {
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen /* no flag changes allowed. ignore silently. */
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen /* handle this by first removing the allowed flags and
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen then adding the allowed flags */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen acl_mail_update_flags(_mail, MODIFY_REMOVE, ~flags);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen acl_mail_update_flags(_mail, MODIFY_ADD, flags);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen amail->super.update_flags(_mail, modify_type, flags);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_mail_update_keywords(struct mail *_mail, enum modify_type modify_type,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mail_module_context *amail = ACL_MAIL_CONTEXT(mail);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ret = mailbox_acl_right_lookup(_mail->box, ACL_STORAGE_RIGHT_WRITE);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen /* if we don't have permission, just silently return success. */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen acl_transaction_set_failure(_mail->transaction);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen amail->super.update_keywords(_mail, modify_type, keywords);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void acl_mail_expunge(struct mail *_mail)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mail_module_context *amail = ACL_MAIL_CONTEXT(mail);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ret = mailbox_acl_right_lookup(_mail->box, ACL_STORAGE_RIGHT_EXPUNGE);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen /* if we don't have permission, silently return success so
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen users won't see annoying error messages in case their
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen clients try automatic expunging. */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen acl_transaction_set_failure(_mail->transaction);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstatic struct mail *
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_mail_alloc(struct mailbox_transaction_context *t,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(t->box);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen amail = p_new(mail->pool, union mail_module_context, 1);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen mail->v.update_keywords = acl_mail_update_keywords;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET_SELF(mail, acl_mail_module, amail);
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainenstatic int acl_save_get_flags(struct mailbox *box, enum mail_flags *flags,
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen if (acl_get_write_rights(box, &acl_flags, &acl_flag_seen,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_save_init(struct mailbox_transaction_context *t,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen enum mail_flags flags, struct mail_keywords *keywords,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen const char *from_envelope, struct istream *input,
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen struct mail *dest_mail, struct mail_save_context **ctx_r)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(t->box);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (mailbox_acl_right_lookup(t->box, ACL_STORAGE_RIGHT_INSERT) <= 0)
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen if (acl_save_get_flags(t->box, &flags, &keywords) < 0)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_copy(struct mailbox_transaction_context *t, struct mail *mail,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen enum mail_flags flags, struct mail_keywords *keywords,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(t->box);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (mailbox_acl_right_lookup(t->box, ACL_STORAGE_RIGHT_INSERT) <= 0)
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen if (acl_save_get_flags(t->box, &flags, &keywords) < 0)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return abox->module_ctx.super.copy(t, mail, flags, keywords, dest_mail);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenacl_transaction_commit(struct mailbox_transaction_context *ctx,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen uint32_t *first_saved_uid_r, uint32_t *last_saved_uid_r)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(ctx->box);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen abox->module_ctx.super.transaction_rollback(ctx);
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainenacl_keywords_create(struct mailbox *box, const char *const keywords[],
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen struct mail_keywords **keywords_r, bool skip_invalid)
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen ret = mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE);
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen /* we can't return failure. assume we don't have permissions. */
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen /* no permission to update any flags. just return empty
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen keywords list. */
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen return abox->module_ctx.super.keywords_create(box, &null,
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen return abox->module_ctx.super.keywords_create(box, keywords,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstruct mailbox *acl_mailbox_open_box(struct mailbox *box)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mail_storage *astorage = ACL_CONTEXT(box->storage);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen abox = p_new(box->pool, struct acl_mailbox, 1);
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen abox->aclobj = acl_object_init_from_name(astorage->rights.backend,
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen box->v.allow_new_keywords = acl_allow_new_keywords;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen box->v.transaction_commit = acl_transaction_commit;