static int acl_mailbox_rename(struct mailbox *src, struct mailbox *dest) { struct acl_mailbox *abox = ACL_CONTEXT(src); int ret; /* renaming requires rights to delete the old mailbox */ ret = acl_mailbox_right_lookup(src, ACL_STORAGE_RIGHT_DELETE); if (ret <= 0) { if (ret == 0) acl_mailbox_fail_not_found(src); return -1; } /* and create the new one under the parent mailbox */ T_BEGIN { ret = acl_mailbox_list_have_right(dest->list, dest->name, TRUE, ACL_STORAGE_RIGHT_CREATE, NULL); } T_END; if (ret <= 0) { if (ret == 0) { /* Note that if the mailbox didn't have LOOKUP permission, this now reveals to user the mailbox's existence. Can't help it. */ mail_storage_set_error(src->storage, MAIL_ERROR_PERM, MAIL_ERRSTR_NO_PERMISSION); } else { mail_storage_set_internal_error(src->storage); } return -1; } return abox->module_ctx.super.rename_box(src, dest); }
static int acl_mailbox_update(struct mailbox *box, const struct mailbox_update *update) { struct acl_mailbox *abox = ACL_CONTEXT(box); int ret; ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_ADMIN); if (ret <= 0) return -1; return abox->module_ctx.super.update_box(box, update); }
static bool acl_copy_has_rights(struct mail_save_context *ctx, struct mail *mail) { struct mailbox *destbox = ctx->transaction->box; enum acl_storage_rights save_right; if (ctx->moving) { if (acl_mailbox_right_lookup(mail->box, ACL_STORAGE_RIGHT_EXPUNGE) <= 0) return FALSE; } save_right = (destbox->flags & MAILBOX_FLAG_POST_SESSION) != 0 ? ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT; if (acl_mailbox_right_lookup(destbox, save_right) <= 0) return FALSE; if (acl_save_get_flags(destbox, &ctx->data.flags, &ctx->data.pvt_flags, &ctx->data.keywords) < 0) return FALSE; return TRUE; }
static int acl_have_attribute_rights(struct mailbox *box) { int ret; /* RFC 5464: When the ACL extension [RFC4314] is present, users can only set and retrieve private or shared mailbox annotations on a mailbox on which they have the "l" right and any one of the "r", "s", "w", "i", or "p" rights. */ ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_LOOKUP); if (ret <= 0) { if (ret < 0) return -1; mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND, T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname)); return -1; } if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_READ) > 0) return 0; if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_SEEN) > 0) return 0; if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE) > 0) return 0; if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_INSERT) > 0) return 0; if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_POST) > 0) return 0; return -1; }
static int acl_mailbox_get_status(struct mailbox *box, enum mailbox_status_items items, struct mailbox_status *status_r) { struct acl_mailbox *abox = ACL_CONTEXT(box); if (abox->module_ctx.super.get_status(box, items, status_r) < 0) return -1; if ((items & STATUS_PERMANENT_FLAGS) != 0) { if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE) <= 0) { status_r->permanent_flags &= MAIL_DELETED|MAIL_SEEN; status_r->permanent_keywords = FALSE; status_r->allow_new_keywords = FALSE; } if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_DELETED) <= 0) status_r->permanent_flags &= ~MAIL_DELETED; if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_SEEN) <= 0) status_r->permanent_flags &= ~MAIL_SEEN; } return 0; }
static int acl_get_write_rights(struct mailbox *box, bool *flags_r, bool *flag_seen_r, bool *flag_del_r) { int ret; ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE); if (ret < 0) return -1; *flags_r = ret > 0; ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_SEEN); if (ret < 0) return -1; *flag_seen_r = ret > 0; ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_DELETED); if (ret < 0) return -1; *flag_del_r = ret > 0; return 0; }
static void acl_mailbox_fail_not_found(struct mailbox *box) { int ret; ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_LOOKUP); if (ret > 0) { mail_storage_set_error(box->storage, MAIL_ERROR_PERM, MAIL_ERRSTR_NO_PERMISSION); } else if (ret == 0) { mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND, T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname)); } }
static bool acl_is_readonly(struct mailbox *box) { struct acl_mailbox *abox = ACL_CONTEXT(box); enum acl_storage_rights save_right; if (abox->module_ctx.super.is_readonly(box)) return TRUE; save_right = (box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ? ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT; if (acl_mailbox_right_lookup(box, save_right) > 0) return FALSE; if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_EXPUNGE) > 0) return FALSE; if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE) > 0) return FALSE; if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_DELETED) > 0) return FALSE; if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE_SEEN) > 0) return FALSE; return TRUE; }
static int acl_mailbox_delete(struct mailbox *box) { struct acl_mailbox *abox = ACL_CONTEXT(box); int ret; ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_DELETE); if (ret <= 0) { if (ret == 0) acl_mailbox_fail_not_found(box); return -1; } return abox->module_ctx.super.delete_box(box); }
static int acl_save_begin(struct mail_save_context *ctx, struct istream *input) { struct mailbox *box = ctx->transaction->box; struct acl_mailbox *abox = ACL_CONTEXT(box); enum acl_storage_rights save_right; save_right = (box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ? ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT; if (acl_mailbox_right_lookup(box, save_right) <= 0) return -1; if (acl_save_get_flags(box, &ctx->data.flags, &ctx->data.pvt_flags, &ctx->data.keywords) < 0) return -1; return abox->module_ctx.super.save_begin(ctx, input); }
static void acl_mail_expunge(struct mail *_mail) { struct mail_private *mail = (struct mail_private *)_mail; union mail_module_context *amail = ACL_MAIL_CONTEXT(mail); int ret; ret = acl_mailbox_right_lookup(_mail->box, ACL_STORAGE_RIGHT_EXPUNGE); if (ret <= 0) { /* if we don't have permission, silently return success so users won't see annoying error messages in case their clients try automatic expunging. */ acl_transaction_set_failure(_mail->transaction); return; } amail->super.expunge(_mail); }
static void acl_mail_update_keywords(struct mail *_mail, enum modify_type modify_type, struct mail_keywords *keywords) { struct mail_private *mail = (struct mail_private *)_mail; union mail_module_context *amail = ACL_MAIL_CONTEXT(mail); int ret; ret = acl_mailbox_right_lookup(_mail->box, ACL_STORAGE_RIGHT_WRITE); if (ret <= 0) { /* if we don't have permission, just silently return success. */ if (ret < 0) acl_transaction_set_failure(_mail->transaction); return; } amail->super.update_keywords(_mail, modify_type, keywords); }
static int acl_mailbox_delete(struct mailbox *box) { struct acl_mailbox *abox = ACL_CONTEXT(box); int ret; ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_DELETE); if (ret <= 0) { if (ret == 0) acl_mailbox_fail_not_found(box); return -1; } /* deletion might internally open the mailbox. let it succeed even if we don't have READ permission. */ abox->skip_acl_checks = TRUE; ret = abox->module_ctx.super.delete_box(box); abox->skip_acl_checks = FALSE; return ret; }