Mercurial > dovecot > original-hg > dovecot-1.2
view src/plugins/acl/acl-storage.c @ 9283:0de21e725d4e HEAD
ssl_username_from_cert=yes: Don't truncate username, don't allow NULs in it.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 04 Aug 2009 14:54:56 -0400 |
parents | 8faf1cc19bd7 |
children | 6df681067e0a |
line wrap: on
line source
/* Copyright (c) 2006-2009 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "array.h" #include "istream.h" #include "mail-namespace.h" #include "mailbox-list-private.h" #include "acl-api-private.h" #include "acl-lookup-dict.h" #include "acl-plugin.h" #include <stdlib.h> struct acl_storage_module acl_storage_module = MODULE_CONTEXT_INIT(&mail_storage_module_register); struct acl_user_module acl_user_module = MODULE_CONTEXT_INIT(&mail_user_module_register); static const char *acl_storage_right_names[ACL_STORAGE_RIGHT_COUNT] = { MAIL_ACL_LOOKUP, MAIL_ACL_READ, MAIL_ACL_WRITE, MAIL_ACL_WRITE_SEEN, MAIL_ACL_WRITE_DELETED, MAIL_ACL_INSERT, MAIL_ACL_POST, MAIL_ACL_EXPUNGE, MAIL_ACL_CREATE, MAIL_ACL_DELETE, MAIL_ACL_ADMIN }; void acl_storage_rights_ctx_init(struct acl_storage_rights_context *ctx, struct acl_backend *backend) { unsigned int i; ctx->backend = backend; for (i = 0; i < ACL_STORAGE_RIGHT_COUNT; i++) { ctx->acl_storage_right_idx[i] = acl_backend_lookup_right(backend, acl_storage_right_names[i]); } } int acl_storage_rights_ctx_have_right(struct acl_storage_rights_context *ctx, const char *name, bool parent, unsigned int acl_storage_right_idx, bool *can_see_r) { const unsigned int *idx_arr = ctx->acl_storage_right_idx; struct mail_namespace *ns; struct acl_object *aclobj; int ret, ret2; ns = mailbox_list_get_namespace(ctx->backend->list); aclobj = !parent ? acl_object_init_from_name(ctx->backend, ns->storage, name) : acl_object_init_from_parent(ctx->backend, ns->storage, name); ret = acl_object_have_right(aclobj, idx_arr[acl_storage_right_idx]); if (can_see_r != NULL) { ret2 = acl_object_have_right(aclobj, idx_arr[ACL_STORAGE_RIGHT_LOOKUP]); if (ret2 < 0) ret = -1; *can_see_r = ret2 > 0; } acl_object_deinit(&aclobj); return ret; } static int acl_storage_have_right(struct mail_storage *storage, const char *name, unsigned int acl_storage_right_idx, bool *can_see_r) { struct acl_mail_storage *astorage = ACL_CONTEXT(storage); int ret; ret = acl_storage_rights_ctx_have_right(&astorage->rights, name, FALSE, acl_storage_right_idx, can_see_r); if (ret < 0) mail_storage_set_internal_error(storage); return ret; } static void acl_storage_destroy(struct mail_storage *storage) { struct acl_mail_storage *astorage = ACL_CONTEXT(storage); acl_backend_deinit(&astorage->rights.backend); if (astorage->module_ctx.super.destroy != NULL) astorage->module_ctx.super.destroy(storage); } static struct mailbox * acl_mailbox_open(struct mail_storage *storage, const char *name, struct istream *input, enum mailbox_open_flags flags) { struct acl_mail_storage *astorage = ACL_CONTEXT(storage); struct mailbox *box; enum acl_storage_rights save_right; bool can_see; int ret; /* mailbox can be opened either for reading or appending new messages */ if ((flags & MAILBOX_OPEN_IGNORE_ACLS) != 0) { ret = 1; } else if ((flags & MAILBOX_OPEN_SAVEONLY) == 0) { ret = acl_storage_have_right(storage, name, ACL_STORAGE_RIGHT_READ, &can_see); } else { save_right = (flags & MAILBOX_OPEN_POST_SESSION) != 0 ? ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT; ret = acl_storage_have_right(storage, name, save_right, &can_see); } if (ret <= 0) { if (ret < 0) return NULL; if (can_see) { mail_storage_set_error(storage, MAIL_ERROR_PERM, MAIL_ERRSTR_NO_PERMISSION); } else { mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND, T_MAIL_ERR_MAILBOX_NOT_FOUND(name)); } return NULL; } box = astorage->module_ctx.super. mailbox_open(storage, name, input, flags); if (box == NULL) return NULL; return acl_mailbox_open_box(box); } static void acl_mailbox_copy_acls_from_parent(struct mail_storage *storage, const char *name) { struct acl_mail_storage *astorage = ACL_CONTEXT(storage); struct acl_object *parent_aclobj, *child_aclobj; struct acl_object_list_iter *iter; struct acl_rights_update update; memset(&update, 0, sizeof(update)); update.modify_mode = ACL_MODIFY_MODE_REPLACE; update.neg_modify_mode = ACL_MODIFY_MODE_REPLACE; child_aclobj = acl_object_init_from_name(astorage->rights.backend, storage, name); parent_aclobj = acl_object_init_from_parent(astorage->rights.backend, storage, name); iter = acl_object_list_init(parent_aclobj); while (acl_object_list_next(iter, &update.rights) > 0) (void)acl_object_update(child_aclobj, &update); acl_object_list_deinit(&iter); acl_object_deinit(&parent_aclobj); acl_object_deinit(&child_aclobj); } static int acl_mailbox_create(struct mail_storage *storage, const char *name, bool directory) { struct acl_mail_storage *astorage = ACL_CONTEXT(storage); int ret; T_BEGIN { ret = acl_storage_rights_ctx_have_right(&astorage->rights, 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 not reveals to user the mailbox's existence. Can't help it. */ mail_storage_set_error(storage, MAIL_ERROR_PERM, MAIL_ERRSTR_NO_PERMISSION); } else { mail_storage_set_internal_error(storage); } return -1; } if (astorage->module_ctx.super. mailbox_create(storage, name, directory) < 0) return -1; if (!directory) acl_mailbox_copy_acls_from_parent(storage, name); return 0; } void acl_mail_storage_created(struct mail_storage *storage) { struct acl_mail_storage *astorage; struct acl_backend *backend; if ((storage->ns->flags & NAMESPACE_FLAG_NOACL) != 0) { /* no ACL checks for internal namespaces (deliver) */ } else { astorage = p_new(storage->pool, struct acl_mail_storage, 1); astorage->module_ctx.super = storage->v; storage->v.destroy = acl_storage_destroy; storage->v.mailbox_open = acl_mailbox_open; storage->v.mailbox_create = acl_mailbox_create; backend = acl_mailbox_list_get_backend(mail_storage_get_list(storage)); acl_storage_rights_ctx_init(&astorage->rights, backend); MODULE_CONTEXT_SET(storage, acl_storage_module, astorage); } if (acl_next_hook_mail_storage_created != NULL) acl_next_hook_mail_storage_created(storage); } static void acl_user_deinit(struct mail_user *user) { struct acl_user *auser = ACL_USER_CONTEXT(user); acl_lookup_dict_deinit(&auser->acl_lookup_dict); auser->module_ctx.super.deinit(user); } void acl_mail_user_created(struct mail_user *user) { struct acl_user *auser; const char *env; auser = p_new(user->pool, struct acl_user, 1); auser->module_ctx.super = user->v; user->v.deinit = acl_user_deinit; auser->acl_lookup_dict = acl_lookup_dict_init(user); auser->acl_env = getenv("ACL"); i_assert(auser->acl_env != NULL); auser->master_user = getenv("MASTER_USER"); env = getenv("ACL_GROUPS"); if (env != NULL) { auser->groups = (const char *const *)p_strsplit(user->pool, env, ","); } MODULE_CONTEXT_SET(user, acl_user_module, auser); if (acl_next_hook_mail_user_created != NULL) acl_next_hook_mail_user_created(user); }