125
118
struct acl_mailbox *abox = ACL_CONTEXT(box);
128
/* we already checked permissions in list.mailbox_create_dir().
129
ignore ACLs in this mailbox until creation is complete, because
121
/* we're looking up CREATE permission from our parent's rights */
122
ret = acl_mailbox_list_have_right(box->list, box->name, TRUE,
123
ACL_STORAGE_RIGHT_CREATE, NULL);
126
mail_storage_set_internal_error(box->storage);
129
/* Note that if user didn't have LOOKUP permission to parent
130
mailbox, this may reveal the mailbox's existence to user.
132
mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
133
MAIL_ERRSTR_NO_PERMISSION);
137
/* ignore ACLs in this mailbox until creation is complete, because
130
138
super.create() may call e.g. mailbox_open() which will fail since
131
139
we haven't yet copied ACLs to this mailbox. */
132
140
abox->skip_acl_checks = TRUE;
133
ret = abox->module_ctx.super.create(box, update, directory);
141
ret = abox->module_ctx.super.create_box(box, update, directory);
134
142
abox->skip_acl_checks = FALSE;
136
144
acl_mailbox_copy_acls_from_parent(box);
179
187
/* deletion might internally open the mailbox. let it succeed even if
180
188
we don't have READ permission. */
181
189
abox->skip_acl_checks = TRUE;
182
ret = abox->module_ctx.super.delete(box);
190
ret = abox->module_ctx.super.delete_box(box);
183
191
abox->skip_acl_checks = FALSE;
188
acl_mailbox_rename(struct mailbox *src, struct mailbox *dest,
189
bool rename_children)
196
acl_mailbox_rename(struct mailbox *src, struct mailbox *dest)
191
198
struct acl_mailbox *abox = ACL_CONTEXT(src);
349
355
MODULE_CONTEXT_SET_SELF(mail, acl_mail_module, amail);
352
static int acl_save_get_flags(struct mailbox *box, enum mail_flags *flags,
353
struct mail_keywords **keywords)
359
acl_save_get_flags(struct mailbox *box, enum mail_flags *flags,
360
enum mail_flags *pvt_flags, struct mail_keywords **keywords)
355
362
bool acl_flags, acl_flag_seen, acl_flag_del;
380
392
ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
381
393
if (acl_mailbox_right_lookup(box, save_right) <= 0)
383
if (acl_save_get_flags(box, &ctx->flags, &ctx->keywords) < 0)
395
if (acl_save_get_flags(box, &ctx->data.flags,
396
&ctx->data.pvt_flags, &ctx->data.keywords) < 0)
386
399
return abox->module_ctx.super.save_begin(ctx, input);
403
acl_copy_has_rights(struct mail_save_context *ctx, struct mail *mail)
405
struct mailbox *destbox = ctx->transaction->box;
406
enum acl_storage_rights save_right;
409
if (acl_mailbox_right_lookup(mail->box,
410
ACL_STORAGE_RIGHT_EXPUNGE) <= 0)
414
save_right = (destbox->flags & MAILBOX_FLAG_POST_SESSION) != 0 ?
415
ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
416
if (acl_mailbox_right_lookup(destbox, save_right) <= 0)
418
if (acl_save_get_flags(destbox, &ctx->data.flags,
419
&ctx->data.pvt_flags, &ctx->data.keywords) < 0)
390
425
acl_copy(struct mail_save_context *ctx, struct mail *mail)
392
427
struct mailbox_transaction_context *t = ctx->transaction;
393
428
struct acl_mailbox *abox = ACL_CONTEXT(t->box);
394
enum acl_storage_rights save_right;
396
save_right = (t->box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ?
397
ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
398
if (acl_mailbox_right_lookup(t->box, save_right) <= 0)
400
if (acl_save_get_flags(t->box, &ctx->flags, &ctx->keywords) < 0)
430
if (!acl_copy_has_rights(ctx, mail)) {
431
mailbox_save_cancel(&ctx);
403
435
return abox->module_ctx.super.copy(ctx, mail);
570
if (box->list->ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
571
(box->list->ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
572
/* this is the root shared namespace, which itself doesn't
573
have any existing mailboxes. */
538
577
abox = p_new(box->pool, struct acl_mailbox, 1);
539
578
abox->module_ctx.super = *v;
540
579
box->vlast = &abox->module_ctx.super;
550
589
v->exists = acl_mailbox_exists;
551
590
v->open = acl_mailbox_open;
552
591
v->get_status = acl_mailbox_get_status;
553
v->create = acl_mailbox_create;
554
v->update = acl_mailbox_update;
555
v->delete = acl_mailbox_delete;
556
v->rename = acl_mailbox_rename;
592
v->create_box = acl_mailbox_create;
593
v->update_box = acl_mailbox_update;
594
v->delete_box = acl_mailbox_delete;
595
v->rename_box = acl_mailbox_rename;
557
596
v->save_begin = acl_save_begin;
558
597
v->copy = acl_copy;
559
598
v->transaction_commit = acl_transaction_commit;
599
v->attribute_set = acl_attribute_set;
600
v->attribute_get = acl_attribute_get;
601
v->attribute_iter_init = acl_attribute_iter_init;
602
v->attribute_iter_next = acl_attribute_iter_next;
603
v->attribute_iter_deinit = acl_attribute_iter_deinit;
561
605
MODULE_CONTEXT_SET(box, acl_storage_module, abox);
609
acl_mailbox_update_removed_id(struct acl_object *aclobj,
610
const struct acl_rights_update *update)
612
struct acl_object_list_iter *iter;
613
struct acl_rights rights;
616
if (update->modify_mode != ACL_MODIFY_MODE_CLEAR &&
617
update->neg_modify_mode != ACL_MODIFY_MODE_CLEAR)
619
if (update->modify_mode == ACL_MODIFY_MODE_CLEAR &&
620
update->neg_modify_mode == ACL_MODIFY_MODE_CLEAR)
623
/* mixed clear/non-clear. see if the identifier exists anymore */
624
iter = acl_object_list_init(aclobj);
625
while ((ret = acl_object_list_next(iter, &rights)) > 0) {
626
if (rights.id_type == update->rights.id_type &&
627
null_strcmp(rights.identifier, update->rights.identifier) == 0)
630
acl_object_list_deinit(&iter);
634
int acl_mailbox_update_acl(struct mailbox_transaction_context *t,
635
const struct acl_rights_update *update)
637
struct acl_object *aclobj;
639
time_t ts = update->last_change != 0 ?
640
update->last_change : ioloop_time;
642
key = t_strdup_printf(MAILBOX_ATTRIBUTE_PREFIX_ACL"%s",
643
acl_rights_get_id(&update->rights));
644
aclobj = acl_mailbox_get_aclobj(t->box);
645
if (acl_object_update(aclobj, update) < 0) {
646
mail_storage_set_critical(t->box->storage, "Failed to set ACL");
650
/* FIXME: figure out some value lengths, so maybe some day
651
quota could apply to ACLs as well. */
652
if (acl_mailbox_update_removed_id(aclobj, update))
653
mail_index_attribute_unset(t->itrans, FALSE, key, ts);
655
mail_index_attribute_set(t->itrans, FALSE, key, ts, 0);