Mercurial > dovecot > original-hg > dovecot-1.2
changeset 5540:1216c0ebe492 HEAD
acl_backend is now tied to mailbox_list instead of mail_storage.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 11 Apr 2007 14:02:31 +0300 |
parents | 7d828d1b39ab |
children | 7082bef9081e |
files | src/plugins/acl/acl-api-private.h src/plugins/acl/acl-api.c src/plugins/acl/acl-api.h src/plugins/acl/acl-backend-vfile.c src/plugins/acl/acl-backend.c src/plugins/acl/acl-mailbox-list.c src/plugins/acl/acl-mailbox.c src/plugins/acl/acl-plugin.h src/plugins/acl/acl-storage.c |
diffstat | 9 files changed, 182 insertions(+), 152 deletions(-) [+] |
line wrap: on
line diff
--- a/src/plugins/acl/acl-api-private.h Wed Apr 11 13:55:34 2007 +0300 +++ b/src/plugins/acl/acl-api-private.h Wed Apr 11 14:02:31 2007 +0300 @@ -9,6 +9,7 @@ void (*deinit)(struct acl_backend *backend); struct acl_object *(*object_init)(struct acl_backend *backend, + struct mail_storage *storage, const char *name); void (*object_deinit)(struct acl_object *aclobj); @@ -29,7 +30,7 @@ const char **groups; unsigned int group_count; - struct mail_storage *storage; + struct mailbox_list *list; struct acl_cache *cache; struct acl_object *default_aclobj;
--- a/src/plugins/acl/acl-api.c Wed Apr 11 13:55:34 2007 +0300 +++ b/src/plugins/acl/acl-api.c Wed Apr 11 14:02:31 2007 +0300 @@ -2,22 +2,14 @@ #include "lib.h" #include "hash.h" -#include "mail-storage.h" #include "acl-cache.h" #include "acl-api-private.h" struct acl_object *acl_object_init_from_name(struct acl_backend *backend, + struct mail_storage *storage, const char *name) { - return backend->v.object_init(backend, name); -} - -struct acl_object *acl_object_init_from_mailbox(struct acl_backend *backend, - struct mailbox *box) -{ - i_assert(mailbox_get_storage(box) == backend->storage); - - return acl_object_init_from_name(backend, mailbox_get_name(box)); + return backend->v.object_init(backend, storage, name); } void acl_object_deinit(struct acl_object **_aclobj)
--- a/src/plugins/acl/acl-api.h Wed Apr 11 13:55:34 2007 +0300 +++ b/src/plugins/acl/acl-api.h Wed Apr 11 14:02:31 2007 +0300 @@ -1,8 +1,8 @@ #ifndef __ACL_API_H #define __ACL_API_H +struct mailbox_list; struct mail_storage; -struct mailbox; struct acl_object; /* Show mailbox in mailbox list. Allow subscribing to it. */ @@ -73,7 +73,7 @@ is NULL, it means the user is anonymous. Username and groups are matched case-sensitively. */ struct acl_backend * -acl_backend_init(const char *data, struct mail_storage *storage, +acl_backend_init(const char *data, struct mailbox_list *list, const char *acl_username, const char *const *groups, const char *owner_username); void acl_backend_deinit(struct acl_backend **user); @@ -90,9 +90,8 @@ const char *right); struct acl_object *acl_object_init_from_name(struct acl_backend *backend, + struct mail_storage *storage, const char *name); -struct acl_object *acl_object_init_from_mailbox(struct acl_backend *backend, - struct mailbox *box); void acl_object_deinit(struct acl_object **aclobj); /* Returns 1 if we have the requested rights, 0 if not, or -1 if internal
--- a/src/plugins/acl/acl-backend-vfile.c Wed Apr 11 13:55:34 2007 +0300 +++ b/src/plugins/acl/acl-backend-vfile.c Wed Apr 11 14:02:31 2007 +0300 @@ -84,7 +84,7 @@ t_push(); tmp = t_strsplit(data, ":"); - backend->global_dir = p_strdup(_backend->pool, *tmp); + backend->global_dir = p_strdup_empty(_backend->pool, *tmp); while (*++tmp != NULL) { if (strncmp(*tmp, "cache_secs=", 11) == 0) @@ -113,37 +113,30 @@ } static struct acl_object * -acl_backend_vfile_object_init(struct acl_backend *_backend, const char *name) +acl_backend_vfile_object_init(struct acl_backend *_backend, + struct mail_storage *storage, const char *name) { struct acl_backend_vfile *backend = (struct acl_backend_vfile *)_backend; struct acl_object_vfile *aclobj; - const char *control_dir, *dir; + const char *dir; bool is_file; aclobj = i_new(struct acl_object_vfile, 1); aclobj->aclobj.backend = _backend; aclobj->aclobj.name = i_strdup(name); - aclobj->global_path = *backend->global_dir == '\0' ? NULL : + aclobj->global_path = backend->global_dir == NULL ? NULL : i_strconcat(backend->global_dir, "/", name, NULL); - control_dir = - mail_storage_get_mailbox_control_dir(_backend->storage, name); - dir = mail_storage_get_mailbox_path(_backend->storage, name, &is_file); - if (is_file) { - /* use control directory with mboxes */ - dir = control_dir; - } else if (strcmp(control_dir, dir) != 0) { - /* FIXME: this is only for making sure people won't upgrade - improperly. remove this check some day. */ - const char *path; - struct stat st; - - path = t_strconcat(control_dir, "/"ACL_FILENAME, NULL); - if (stat(path, &st) == 0) { - i_fatal("%s is no longer kept in control directory, " - "move it to the actual maildir (%s)", - path, dir); + if (storage == NULL) { + /* the default ACL for mailbox list */ + dir = mailbox_list_get_path(_backend->list, NULL, + MAILBOX_LIST_PATH_TYPE_DIR); + } else { + dir = mail_storage_get_mailbox_path(storage, name, &is_file); + if (is_file) { + dir = mailbox_list_get_path(_backend->list, name, + MAILBOX_LIST_PATH_TYPE_CONTROL); } } aclobj->local_path = i_strconcat(dir, "/"ACL_FILENAME, NULL); @@ -258,9 +251,7 @@ } if (error != NULL) { - mail_storage_set_critical(aclobj->backend->storage, - "ACL file %s line %u: %s", - path, linenum, error); + i_error("ACL file %s line %u: %s", path, linenum, error); t_pop(); return -1; } @@ -276,7 +267,6 @@ struct acl_vfile_validity *validity, bool try_retry, bool *is_dir_r) { - struct mail_storage *storage = aclobj->backend->storage; struct istream *input; struct stat st; const char *line; @@ -296,7 +286,7 @@ validity->last_read_time = ioloop_time; return 1; } - mail_storage_set_critical(storage, "open(%s) failed: %m", path); + i_error("open(%s) failed: %m", path); return -1; } @@ -306,8 +296,7 @@ return 0; } - mail_storage_set_critical(storage, - "fstat(%s) failed: %m", path); + i_error("fstat(%s) failed: %m", path); (void)close(fd); return -1; } @@ -337,8 +326,7 @@ ret = 0; else { ret = -1; - mail_storage_set_critical(storage, - "read(%s) failed: %m", path); + i_error("read(%s) failed: %m", path); } } @@ -348,8 +336,7 @@ ret = 0; else { ret = -1; - mail_storage_set_critical(storage, - "read(%s) failed: %m", path); + i_error("read(%s) failed: %m", path); } } else { validity->last_read_time = ioloop_time; @@ -363,8 +350,7 @@ if (errno == ESTALE && try_retry) return 0; - mail_storage_set_critical(storage, "close(%s) failed: %m", - path); + i_error("close(%s) failed: %m", path); return -1; } return ret; @@ -419,8 +405,7 @@ /* if the file used to exist, we have to re-read it */ return validity->last_mtime != 0; } - mail_storage_set_critical(aclobj->backend->storage, - "stat(%s) failed: %m", path); + i_error("stat(%s) failed: %m", path); return -1; }
--- a/src/plugins/acl/acl-backend.c Wed Apr 11 13:55:34 2007 +0300 +++ b/src/plugins/acl/acl-backend.c Wed Apr 11 14:02:31 2007 +0300 @@ -26,7 +26,7 @@ static const char *const non_owner_mailbox_rights[] = { NULL }; struct acl_backend * -acl_backend_init(const char *data, struct mail_storage *storage, +acl_backend_init(const char *data, struct mailbox_list *list, const char *acl_username, const char *const *groups, const char *owner_username) { @@ -54,7 +54,7 @@ backend = acl_backend_vfile.alloc(); backend->debug = debug; backend->v = acl_backend_vfile; - backend->storage = storage; + backend->list = list; backend->username = p_strdup(backend->pool, acl_username); backend->owner_username = owner_username == NULL ? "" : p_strdup(backend->pool, owner_username); @@ -79,7 +79,7 @@ storage_owner ? owner_mailbox_rights : non_owner_mailbox_rights); - backend->default_aclobj = acl_object_init_from_name(backend, ""); + backend->default_aclobj = acl_object_init_from_name(backend, NULL, ""); return backend; }
--- a/src/plugins/acl/acl-mailbox-list.c Wed Apr 11 13:55:34 2007 +0300 +++ b/src/plugins/acl/acl-mailbox-list.c Wed Apr 11 14:02:31 2007 +0300 @@ -2,25 +2,51 @@ #include "lib.h" #include "array.h" +#include "mail-namespace.h" #include "mailbox-list-private.h" #include "acl-api-private.h" #include "acl-plugin.h" +#include <stdlib.h> + #define ACL_LIST_CONTEXT(obj) \ MODULE_CONTEXT(obj, acl_mailbox_list_module) struct acl_mailbox_list { union mailbox_list_module_context module_ctx; - /* FIXME: this is wrong. multiple storages can use the same - mailbox_list, so the whole ACL plugin probably needs redesigning. - for now this is just kludged to work this way. */ - struct mail_storage *storage; + struct acl_storage_rights_context rights; }; static MODULE_CONTEXT_DEFINE_INIT(acl_mailbox_list_module, &mailbox_list_module_register); +struct acl_backend *acl_mailbox_list_get_backend(struct mailbox_list *list) +{ + struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list); + + return alist->rights.backend; +} + +const char *acl_mailbox_list_get_parent_mailbox_name(struct mailbox_list *list, + const char *name) +{ + const char *p; + char sep; + + sep = mailbox_list_get_hierarchy_sep(list); + p = strrchr(name, sep); + return p == NULL ? "" : t_strdup_until(name, p); +} + +static int +acl_mailbox_list_have_right(struct acl_mailbox_list *alist, const char *name, + unsigned int acl_storage_right_idx, bool *can_see_r) +{ + return acl_storage_rights_ctx_have_right(&alist->rights, name, + acl_storage_right_idx, + can_see_r); +} static struct mailbox_info * acl_mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx) @@ -34,8 +60,9 @@ if (info == NULL) return NULL; - ret = acl_storage_have_right(alist->storage, info->name, - ACL_STORAGE_RIGHT_LOOKUP, NULL); + ret = acl_mailbox_list_have_right(alist, info->name, + ACL_STORAGE_RIGHT_LOOKUP, + NULL); if (ret > 0) return info; if (ret < 0) { @@ -63,8 +90,8 @@ const char *parent; int ret; - ret = acl_storage_have_right(alist->storage, name, - ACL_STORAGE_RIGHT_LOOKUP, NULL); + ret = acl_mailbox_list_have_right(alist, name, ACL_STORAGE_RIGHT_LOOKUP, + NULL); if (ret < 0) return -1; @@ -85,10 +112,10 @@ case MAILBOX_NAME_NOINFERIORS: /* have to check if we are allowed to see the parent */ t_push(); - parent = acl_storage_get_parent_mailbox_name(alist->storage, - name); - ret = acl_storage_have_right(alist->storage, parent, - ACL_STORAGE_RIGHT_LOOKUP, NULL); + parent = acl_mailbox_list_get_parent_mailbox_name(list, name); + ret = acl_mailbox_list_have_right(alist, parent, + ACL_STORAGE_RIGHT_LOOKUP, + NULL); t_pop(); if (ret < 0) @@ -109,17 +136,17 @@ bool can_see; int ret; - ret = acl_storage_have_right(alist->storage, name, - ACL_STORAGE_RIGHT_DELETE, &can_see); + ret = acl_mailbox_list_have_right(alist, name, ACL_STORAGE_RIGHT_DELETE, + &can_see); if (ret <= 0) { if (ret < 0) return -1; if (can_see) { - mail_storage_set_error(alist->storage, + mailbox_list_set_error(list, MAILBOX_LIST_ERR_NO_PERMISSION); } else { - mail_storage_set_error(alist->storage, - MAILBOX_LIST_ERR_MAILBOX_NOT_FOUND, name); + mailbox_list_set_error(list, t_strdup_printf( + MAILBOX_LIST_ERR_MAILBOX_NOT_FOUND, name)); } return -1; } @@ -136,25 +163,25 @@ int ret; /* renaming requires rights to delete the old mailbox */ - ret = acl_storage_have_right(alist->storage, oldname, - ACL_STORAGE_RIGHT_DELETE, &can_see); + ret = acl_mailbox_list_have_right(alist, oldname, + ACL_STORAGE_RIGHT_DELETE, &can_see); if (ret <= 0) { if (ret < 0) return -1; if (can_see) { - mail_storage_set_error(alist->storage, + mailbox_list_set_error(list, MAILBOX_LIST_ERR_NO_PERMISSION); } else { - mail_storage_set_error(alist->storage, - MAILBOX_LIST_ERR_MAILBOX_NOT_FOUND, oldname); + mailbox_list_set_error(list, t_strdup_printf( + MAILBOX_LIST_ERR_MAILBOX_NOT_FOUND, oldname)); } return 0; } /* and create the new one under the parent mailbox */ t_push(); - ret = acl_storage_have_right(alist->storage, - acl_storage_get_parent_mailbox_name(alist->storage, newname), + ret = acl_mailbox_list_have_right(alist, + acl_mailbox_list_get_parent_mailbox_name(list, newname), ACL_STORAGE_RIGHT_CREATE, NULL); t_pop(); @@ -163,7 +190,7 @@ /* 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(alist->storage, + mailbox_list_set_error(list, MAILBOX_LIST_ERR_NO_PERMISSION); } return -1; @@ -175,10 +202,45 @@ void acl_mailbox_list_created(struct mailbox_list *list) { struct acl_mailbox_list *alist; + struct acl_backend *backend; + struct mail_namespace *ns; + enum mailbox_list_flags flags; + const char *acl_env, *current_username, *owner_username; if (acl_next_hook_mailbox_list_created != NULL) acl_next_hook_mailbox_list_created(list); + acl_env = getenv("ACL"); + i_assert(acl_env != NULL); + + owner_username = getenv("USER"); + if (owner_username == NULL) + i_fatal("ACL: USER environment not set"); + + current_username = getenv("MASTER_USER"); + if (current_username == NULL) + current_username = owner_username; + + /* We don't care about the username for non-private mailboxes. + It's used only when checking if we're the mailbox owner. We never + are for shared/public mailboxes. */ + ns = mailbox_list_get_namespace(list); + if (ns->type != NAMESPACE_PRIVATE) + owner_username = NULL; + + /* FIXME: set groups */ + backend = acl_backend_init(acl_env, list, current_username, NULL, + owner_username); + if (backend == NULL) + i_fatal("ACL backend initialization failed"); + + flags = mailbox_list_get_flags(list); + if ((flags & MAILBOX_LIST_FLAG_FULL_FS_ACCESS) != 0) { + /* not necessarily, but safer to do this for now.. */ + i_fatal("mail_full_filesystem_access=yes is " + "incompatible with ACLs"); + } + alist = p_new(list->pool, struct acl_mailbox_list, 1); alist->module_ctx.super = list->v; list->v.iter_next = acl_mailbox_list_iter_next; @@ -186,14 +248,7 @@ list->v.delete_mailbox = acl_mailbox_list_delete; list->v.rename_mailbox = acl_mailbox_list_rename; + acl_storage_rights_ctx_init(&alist->rights, backend); + MODULE_CONTEXT_SET(list, acl_mailbox_list_module, alist); } - -void acl_mailbox_list_set_storage(struct mail_storage *storage) -{ - struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(storage->list); - - i_assert(alist->storage == NULL); - - alist->storage = storage; -}
--- a/src/plugins/acl/acl-mailbox.c Wed Apr 11 13:55:34 2007 +0300 +++ b/src/plugins/acl/acl-mailbox.c Wed Apr 11 14:02:31 2007 +0300 @@ -40,11 +40,13 @@ int ret; ret = acl_object_have_right(abox->aclobj, - astorage->acl_storage_right_idx[right_idx]); + astorage->rights.acl_storage_right_idx[right_idx]); if (ret > 0) return 1; - if (ret < 0) + if (ret < 0) { + mail_storage_set_internal_error(box->storage); return -1; + } mail_storage_set_error(box->storage, MAILBOX_LIST_ERR_NO_PERMISSION); return 0; @@ -210,7 +212,8 @@ abox = p_new(box->pool, struct acl_mailbox, 1); abox->module_ctx.super = box->v; - abox->aclobj = acl_object_init_from_name(astorage->backend, + abox->aclobj = acl_object_init_from_name(astorage->rights.backend, + box->storage, mailbox_get_name(box)); box->v.close = acl_mailbox_close;
--- a/src/plugins/acl/acl-plugin.h Wed Apr 11 13:55:34 2007 +0300 +++ b/src/plugins/acl/acl-plugin.h Wed Apr 11 14:02:31 2007 +0300 @@ -21,11 +21,14 @@ ACL_STORAGE_RIGHT_COUNT }; +struct acl_storage_rights_context { + struct acl_backend *backend; + unsigned int acl_storage_right_idx[ACL_STORAGE_RIGHT_COUNT]; +}; + struct acl_mail_storage { union mail_storage_module_context module_ctx; - - struct acl_backend *backend; - unsigned int acl_storage_right_idx[ACL_STORAGE_RIGHT_COUNT]; + struct acl_storage_rights_context rights; }; extern void (*acl_next_hook_mail_storage_created) @@ -38,12 +41,16 @@ struct mailbox *acl_mailbox_open_box(struct mailbox *box); -const char * -acl_storage_get_parent_mailbox_name(struct mail_storage *storage, - const char *name); -int acl_storage_have_right(struct mail_storage *storage, const char *name, - unsigned int acl_storage_right_idx, bool *can_see_r); -void acl_mailbox_list_set_storage(struct mail_storage *storage); +void acl_storage_rights_ctx_init(struct acl_storage_rights_context *ctx, + struct acl_backend *backend); +int acl_storage_rights_ctx_have_right(struct acl_storage_rights_context *ctx, + const char *name, + unsigned int acl_storage_right_idx, + bool *can_see_r); + +struct acl_backend *acl_mailbox_list_get_backend(struct mailbox_list *list); +const char *acl_mailbox_list_get_parent_mailbox_name(struct mailbox_list *list, + const char *name); void acl_plugin_init(void); void acl_plugin_deinit(void);
--- a/src/plugins/acl/acl-storage.c Wed Apr 11 13:55:34 2007 +0300 +++ b/src/plugins/acl/acl-storage.c Wed Apr 11 14:02:31 2007 +0300 @@ -4,11 +4,10 @@ #include "array.h" #include "istream.h" #include "acl-api-private.h" +#include "mail-namespace.h" #include "mailbox-list-private.h" #include "acl-plugin.h" -#include <stdlib.h> - struct acl_storage_module acl_storage_module = MODULE_CONTEXT_INIT(&mail_storage_module_register); @@ -25,15 +24,31 @@ MAIL_ACL_ADMIN }; -int acl_storage_have_right(struct mail_storage *storage, const char *name, - unsigned int acl_storage_right_idx, bool *can_see_r) +void acl_storage_rights_ctx_init(struct acl_storage_rights_context *ctx, + struct acl_backend *backend) { - struct acl_mail_storage *astorage = ACL_CONTEXT(storage); - const unsigned int *idx_arr = astorage->acl_storage_right_idx; + 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, + 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; - aclobj = acl_object_init_from_name(astorage->backend, name); + ns = mailbox_list_get_namespace(ctx->backend->list); + aclobj = acl_object_init_from_name(ctx->backend, ns->storage, name); ret = acl_object_have_right(aclobj, idx_arr[acl_storage_right_idx]); if (can_see_r != NULL) { @@ -48,24 +63,28 @@ return ret; } -const char * -acl_storage_get_parent_mailbox_name(struct mail_storage *storage, - const char *name) +static int +acl_storage_have_right(struct mail_storage *storage, const char *name, + unsigned int acl_storage_right_idx, bool *can_see_r) { - const char *p; - char sep; + struct acl_mail_storage *astorage = ACL_CONTEXT(storage); + int ret; - sep = mail_storage_get_hierarchy_sep(storage); - p = strrchr(name, sep); - return p == NULL ? "" : t_strdup_until(name, p); + ret = acl_storage_rights_ctx_have_right(&astorage->rights, name, + 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->backend); - astorage->module_ctx.super.destroy(storage); + acl_backend_deinit(&astorage->rights.backend); + if (astorage->module_ctx.super.destroy != NULL) + astorage->module_ctx.super.destroy(storage); } static struct mailbox * @@ -112,11 +131,12 @@ bool directory) { struct acl_mail_storage *astorage = ACL_CONTEXT(storage); + struct mailbox_list *list = mail_storage_get_list(storage); int ret; t_push(); ret = acl_storage_have_right(storage, - acl_storage_get_parent_mailbox_name(storage, name), + acl_mailbox_list_get_parent_mailbox_name(list, name), ACL_STORAGE_RIGHT_CREATE, NULL); t_pop(); @@ -139,50 +159,18 @@ { struct acl_mail_storage *astorage; struct acl_backend *backend; - const char *acl_env, *user_env, *owner_username; - unsigned int i; if (acl_next_hook_mail_storage_created != NULL) acl_next_hook_mail_storage_created(storage); - acl_env = getenv("ACL"); - user_env = getenv("MASTER_USER"); - if (user_env == NULL) - user_env = getenv("USER"); - i_assert(acl_env != NULL && user_env != NULL); - - /* FIXME: set groups. owner_username isn't also correct here it's a - per-mailbox thing. but we don't currently support shared mailboxes, - so this will do for now.. */ - owner_username = - (storage->flags & MAIL_STORAGE_FLAG_SHARED_NAMESPACE) == 0 ? - getenv("USER") : NULL; - backend = acl_backend_init(acl_env, storage, user_env, NULL, - owner_username); - if (backend == NULL) - i_fatal("ACL backend initialization failed"); - - if ((storage->flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0) { - /* FIXME: not necessarily, but safer to do this for now.. */ - i_fatal("mail_full_filesystem_access=yes is " - "incompatible with ACLs"); - } - astorage = p_new(storage->pool, struct acl_mail_storage, 1); astorage->module_ctx.super = storage->v; - astorage->backend = backend; storage->v.destroy = acl_storage_destroy; storage->v.mailbox_open = acl_mailbox_open; storage->v.mailbox_create = acl_mailbox_create; - acl_mailbox_list_set_storage(storage); - - /* build ACL right lookup table */ - for (i = 0; i < ACL_STORAGE_RIGHT_COUNT; i++) { - astorage->acl_storage_right_idx[i] = - acl_backend_lookup_right(backend, - acl_storage_right_names[i]); - } + 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); }