acl-mailbox.c revision ef3f582fdf2d007838bba693f8c2629d079668de
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
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. */
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "lib.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "array.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "istream.h"
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include "mailbox-list-private.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "acl-api-private.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "acl-plugin.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include <sys/stat.h>
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#define ACL_MAIL_CONTEXT(obj) \
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT(obj, acl_mail_module)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstruct acl_mailbox {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mailbox_module_context module_ctx;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_object *aclobj;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen unsigned int save_hack:1;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen};
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstruct acl_transaction_context {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen union mailbox_transaction_module_context module_ctx;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen};
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(acl_mail_module, &mail_module_register);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic struct acl_transaction_context acl_transaction_failure;
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstatic int mailbox_acl_right_lookup(struct mailbox *box, unsigned int right_idx)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(box);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mail_storage *astorage = ACL_CONTEXT(box->storage);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen int ret;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ret = acl_object_have_right(abox->aclobj,
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen astorage->rights.acl_storage_right_idx[right_idx]);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (ret > 0)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return 1;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen if (ret < 0) {
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen mail_storage_set_internal_error(box->storage);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return -1;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen }
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen MAIL_ERRSTR_NO_PERMISSION);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return 0;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainenstatic bool acl_is_readonly(struct mailbox *box)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen{
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(box);
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if (abox->module_ctx.super.is_readonly(box))
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen return TRUE;
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if (mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_INSERT) > 0)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen return FALSE;
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if (mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_EXPUNGE) > 0)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen return FALSE;
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen /* Next up is the "shared flag rights" */
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if (mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE) > 0)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen return FALSE;
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 return FALSE;
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if ((box->private_flags_mask & MAIL_SEEN) == 0 &&
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_SEEN) > 0)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen return FALSE;
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen return TRUE;
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen}
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainenstatic bool acl_allow_new_keywords(struct mailbox *box)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen{
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(box);
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen if (!abox->module_ctx.super.allow_new_keywords(box))
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen return FALSE;
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen return mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE) > 0;
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen}
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainenstatic int acl_mailbox_close(struct mailbox *box)
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen{
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(box);
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen acl_object_deinit(&abox->aclobj);
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen return abox->module_ctx.super.close(box);
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen}
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstatic int
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_get_write_rights(struct mailbox *box,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen bool *flags_r, bool *flag_seen_r, bool *flag_del_r)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen int ret;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ret = mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (ret < 0)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return -1;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen *flags_r = ret > 0;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ret = mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_SEEN);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (ret < 0)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return -1;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen *flag_seen_r = ret > 0;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ret = mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_DELETED);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (ret < 0)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return -1;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen *flag_del_r = ret > 0;
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen return 0;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void acl_transaction_set_failure(struct mailbox_transaction_context *t)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen MODULE_CONTEXT_SET(t, acl_storage_module,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen &acl_transaction_failure);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen}
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_mail_update_flags(struct mail *_mail, enum modify_type modify_type,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen enum mail_flags flags)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mail_module_context *amail = ACL_MAIL_CONTEXT(mail);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen bool acl_flags, acl_flag_seen, acl_flag_del;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen if (acl_get_write_rights(_mail->box, &acl_flags, &acl_flag_seen,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen &acl_flag_del) < 0) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen acl_transaction_set_failure(_mail->transaction);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (modify_type != MODIFY_REPLACE) {
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen /* adding/removing flags. just remove the disallowed
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen flags from the mask. */
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (!acl_flags)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen flags &= MAIL_SEEN | MAIL_DELETED;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (!acl_flag_seen)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen flags &= ~MAIL_SEEN;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (!acl_flag_del)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen flags &= ~MAIL_DELETED;
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. */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen }
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
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);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen }
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen amail->super.update_flags(_mail, modify_type, flags);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_mail_update_keywords(struct mail *_mail, enum modify_type modify_type,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mail_keywords *keywords)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mail_module_context *amail = ACL_MAIL_CONTEXT(mail);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen int ret;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ret = mailbox_acl_right_lookup(_mail->box, ACL_STORAGE_RIGHT_WRITE);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (ret <= 0) {
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen /* if we don't have permission, just silently return success. */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (ret < 0)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen acl_transaction_set_failure(_mail->transaction);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen }
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen amail->super.update_keywords(_mail, modify_type, keywords);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void acl_mail_expunge(struct mail *_mail)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mail_module_context *amail = ACL_MAIL_CONTEXT(mail);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen int ret;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ret = mailbox_acl_right_lookup(_mail->box, ACL_STORAGE_RIGHT_EXPUNGE);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (ret <= 0) {
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 if (ret < 0)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen acl_transaction_set_failure(_mail->transaction);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen }
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen amail->super.expunge(_mail);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstatic struct mail *
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_mail_alloc(struct mailbox_transaction_context *t,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen enum mail_fetch_field wanted_fields,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(t->box);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mail_module_context *amail;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mail *_mail;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mail_private *mail;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen _mail = abox->module_ctx.super.
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail_alloc(t, wanted_fields, wanted_headers);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen mail = (struct mail_private *)_mail;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen amail = p_new(mail->pool, union mail_module_context, 1);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen amail->super = mail->v;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen mail->v.update_flags = acl_mail_update_flags;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen mail->v.update_keywords = acl_mail_update_keywords;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen mail->v.expunge = acl_mail_expunge;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET_SELF(mail, acl_mail_module, amail);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return _mail;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainenstatic int acl_save_get_flags(struct mailbox *box, enum mail_flags *flags,
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen struct mail_keywords **keywords)
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen{
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen bool acl_flags, acl_flag_seen, acl_flag_del;
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen if (acl_get_write_rights(box, &acl_flags, &acl_flag_seen,
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen &acl_flag_del) < 0)
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen return -1;
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen if (!acl_flag_seen)
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen *flags &= ~MAIL_SEEN;
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen if (!acl_flag_del)
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen *flags &= ~MAIL_DELETED;
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen if (!acl_flags) {
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen *flags &= MAIL_SEEN | MAIL_DELETED;
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen *keywords = NULL;
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen }
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen return 0;
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen}
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstatic int
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_save_init(struct mailbox_transaction_context *t,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen enum mail_flags flags, struct mail_keywords *keywords,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen time_t received_date, int timezone_offset,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen const char *from_envelope, struct istream *input,
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen struct mail *dest_mail, struct mail_save_context **ctx_r)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(t->box);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (mailbox_acl_right_lookup(t->box, ACL_STORAGE_RIGHT_INSERT) <= 0)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return -1;
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen if (acl_save_get_flags(t->box, &flags, &keywords) < 0)
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen return -1;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return abox->module_ctx.super.
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen save_init(t, flags, keywords, received_date,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen timezone_offset, from_envelope,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen input, dest_mail, ctx_r);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstatic int
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_copy(struct mailbox_transaction_context *t, struct mail *mail,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen enum mail_flags flags, struct mail_keywords *keywords,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct mail *dest_mail)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(t->box);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (mailbox_acl_right_lookup(t->box, ACL_STORAGE_RIGHT_INSERT) <= 0)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return -1;
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen if (acl_save_get_flags(t->box, &flags, &keywords) < 0)
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen return -1;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return abox->module_ctx.super.copy(t, mail, flags, keywords, dest_mail);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic int
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenacl_transaction_commit(struct mailbox_transaction_context *ctx,
63f36c2b47217fc2dc4ed49cfc1907311d5ed366Timo Sirainen uint32_t *uid_validity_r,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen uint32_t *first_saved_uid_r, uint32_t *last_saved_uid_r)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(ctx->box);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen void *at = ACL_CONTEXT(ctx);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (at != NULL) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen abox->module_ctx.super.transaction_rollback(ctx);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return -1;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return abox->module_ctx.super.
63f36c2b47217fc2dc4ed49cfc1907311d5ed366Timo Sirainen transaction_commit(ctx, uid_validity_r,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen first_saved_uid_r, last_saved_uid_r);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen}
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainenstatic int
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainenacl_keywords_create(struct mailbox *box, const char *const keywords[],
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen struct mail_keywords **keywords_r, bool skip_invalid)
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen{
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen struct acl_mailbox *abox = ACL_CONTEXT(box);
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen int ret;
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen ret = mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_WRITE);
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen if (ret < 0) {
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen if (!skip_invalid)
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen return -1;
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen /* we can't return failure. assume we don't have permissions. */
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen ret = 0;
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen }
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen if (ret == 0) {
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen /* no permission to update any flags. just return empty
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen keywords list. */
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen const char *null = NULL;
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen return abox->module_ctx.super.keywords_create(box, &null,
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen keywords_r,
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen skip_invalid);
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen }
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen return abox->module_ctx.super.keywords_create(box, keywords,
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen keywords_r, skip_invalid);
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen}
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstruct mailbox *acl_mailbox_open_box(struct mailbox *box)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mail_storage *astorage = ACL_CONTEXT(box->storage);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_mailbox *abox;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen abox = p_new(box->pool, struct acl_mailbox, 1);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen abox->module_ctx.super = box->v;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen abox->aclobj = acl_object_init_from_name(astorage->rights.backend,
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen box->storage,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen mailbox_get_name(box));
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen box->v.is_readonly = acl_is_readonly;
11fec79522fc0cebe7321d1a9206568d22ddc1c0Timo Sirainen box->v.allow_new_keywords = acl_allow_new_keywords;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen box->v.close = acl_mailbox_close;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen box->v.mail_alloc = acl_mail_alloc;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen box->v.save_init = acl_save_init;
ef3f582fdf2d007838bba693f8c2629d079668deTimo Sirainen box->v.keywords_create = acl_keywords_create;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen box->v.copy = acl_copy;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen box->v.transaction_commit = acl_transaction_commit;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(box, acl_storage_module, abox);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return box;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}