dovecot-1.2: acl: Fixed handling 'k' right. Although box/child c...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Sep 7 17:59:28 EEST 2008
details: http://hg.dovecot.org/dovecot-1.2/rev/459c4c496983
changeset: 8165:459c4c496983
user: Timo Sirainen <tss at iki.fi>
date: Sun Sep 07 15:18:29 2008 +0300
description:
acl: Fixed handling 'k' right. Although box/child creation was prevented, box/child/child wasn't.
diffstat:
7 files changed, 170 insertions(+), 51 deletions(-)
src/plugins/acl/acl-api-private.h | 3
src/plugins/acl/acl-api.c | 7 +
src/plugins/acl/acl-api.h | 3
src/plugins/acl/acl-backend-vfile.c | 129 ++++++++++++++++++++++++++++++++---
src/plugins/acl/acl-mailbox-list.c | 59 +++++++---------
src/plugins/acl/acl-plugin.h | 4 -
src/plugins/acl/acl-storage.c | 16 ++--
diffs (truncated from 438 to 300 lines):
diff -r 314fab62b3d1 -r 459c4c496983 src/plugins/acl/acl-api-private.h
--- a/src/plugins/acl/acl-api-private.h Sun Sep 07 10:54:46 2008 +0300
+++ b/src/plugins/acl/acl-api-private.h Sun Sep 07 15:18:29 2008 +0300
@@ -18,6 +18,9 @@ struct acl_backend_vfuncs {
struct acl_object *(*object_init)(struct acl_backend *backend,
struct mail_storage *storage,
const char *name);
+ struct acl_object *(*object_init_parent)(struct acl_backend *backend,
+ struct mail_storage *storage,
+ const char *child_name);
void (*object_deinit)(struct acl_object *aclobj);
int (*object_refresh_cache)(struct acl_object *aclobj);
diff -r 314fab62b3d1 -r 459c4c496983 src/plugins/acl/acl-api.c
--- a/src/plugins/acl/acl-api.c Sun Sep 07 10:54:46 2008 +0300
+++ b/src/plugins/acl/acl-api.c Sun Sep 07 15:18:29 2008 +0300
@@ -10,6 +10,13 @@ struct acl_object *acl_object_init_from_
const char *name)
{
return backend->v.object_init(backend, storage, name);
+}
+
+struct acl_object *acl_object_init_from_parent(struct acl_backend *backend,
+ struct mail_storage *storage,
+ const char *child_name)
+{
+ return backend->v.object_init_parent(backend, storage, child_name);
}
void acl_object_deinit(struct acl_object **_aclobj)
diff -r 314fab62b3d1 -r 459c4c496983 src/plugins/acl/acl-api.h
--- a/src/plugins/acl/acl-api.h Sun Sep 07 10:54:46 2008 +0300
+++ b/src/plugins/acl/acl-api.h Sun Sep 07 15:18:29 2008 +0300
@@ -108,6 +108,9 @@ struct acl_object *acl_object_init_from_
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_parent(struct acl_backend *backend,
+ struct mail_storage *storage,
+ const char *child_name);
void acl_object_deinit(struct acl_object **aclobj);
/* Returns 1 if we have the requested rights, 0 if not, or -1 if internal
diff -r 314fab62b3d1 -r 459c4c496983 src/plugins/acl/acl-backend-vfile.c
--- a/src/plugins/acl/acl-backend-vfile.c Sun Sep 07 10:54:46 2008 +0300
+++ b/src/plugins/acl/acl-backend-vfile.c Sun Sep 07 15:18:29 2008 +0300
@@ -30,6 +30,7 @@ struct acl_vfile_validity {
struct acl_backend_vfile_validity {
struct acl_vfile_validity global_validity, local_validity;
+ struct acl_vfile_validity mailbox_validity;
};
struct acl_letter_map {
@@ -106,6 +107,20 @@ static void acl_backend_vfile_deinit(str
pool_unref(&backend->backend.pool);
}
+static const char *
+acl_backend_vfile_get_local_dir(struct mail_storage *storage, const char *name)
+{
+ const char *dir;
+ bool is_file;
+
+ dir = mail_storage_get_mailbox_path(storage, name, &is_file);
+ if (is_file) {
+ dir = mailbox_list_get_path(storage->list, name,
+ MAILBOX_LIST_PATH_TYPE_CONTROL);
+ }
+ return dir;
+}
+
static struct acl_object *
acl_backend_vfile_object_init(struct acl_backend *_backend,
struct mail_storage *storage, const char *name)
@@ -114,7 +129,6 @@ acl_backend_vfile_object_init(struct acl
(struct acl_backend_vfile *)_backend;
struct acl_object_vfile *aclobj;
const char *dir;
- bool is_file;
aclobj = i_new(struct acl_object_vfile, 1);
aclobj->aclobj.backend = _backend;
@@ -127,14 +141,111 @@ acl_backend_vfile_object_init(struct acl
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);
- }
+ dir = acl_backend_vfile_get_local_dir(storage, name);
}
aclobj->local_path = i_strconcat(dir, "/"ACL_FILENAME, NULL);
return &aclobj->aclobj;
+}
+
+static const char *
+get_parent_mailbox(struct mail_storage *storage, const char *name)
+{
+ const char *p;
+ char sep;
+
+ sep = mailbox_list_get_hierarchy_sep(storage->list);
+ p = strrchr(name, sep);
+ return p == NULL ? NULL : t_strdup_until(name, p);
+}
+
+static int
+acl_backend_vfile_exists(struct acl_backend_vfile *backend, const char *path,
+ struct acl_vfile_validity *validity)
+{
+ struct stat st;
+
+ if (validity->last_check + (time_t)backend->cache_secs > ioloop_time) {
+ /* use the cached value */
+ return validity->last_mtime != VALIDITY_MTIME_NOTFOUND;
+ }
+
+ validity->last_check = ioloop_time;
+ if (stat(path, &st) < 0) {
+ if (errno == ENOENT) {
+ validity->last_mtime = VALIDITY_MTIME_NOTFOUND;
+ return 0;
+ }
+ if (errno == EACCES) {
+ validity->last_mtime = VALIDITY_MTIME_NOACCESS;
+ return 1;
+ }
+ i_error("stat(%s) failed: %m", path);
+ return -1;
+ }
+ validity->last_mtime = st.st_mtime;
+ validity->last_size = st.st_size;
+ return 1;
+}
+
+static bool
+acl_backend_vfile_has_acl(struct acl_backend *_backend,
+ struct mail_storage *storage, const char *name)
+{
+ struct acl_backend_vfile *backend =
+ (struct acl_backend_vfile *)_backend;
+ struct acl_backend_vfile_validity *old_validity, new_validity;
+ const char *path, *local_path, *global_path, *dir;
+ int ret;
+
+ old_validity = acl_cache_get_validity(_backend->cache, name);
+ if (old_validity != NULL)
+ new_validity = *old_validity;
+ else
+ memset(&new_validity, 0, sizeof(new_validity));
+
+ /* See if the mailbox exists. If we wanted recursive lookups we could
+ skip this, but at least for now we assume that if an existing
+ mailbox has no ACL it's equivalent to default ACLs. */
+ path = mailbox_list_get_path(storage->list, name,
+ MAILBOX_LIST_PATH_TYPE_MAILBOX);
+ ret = acl_backend_vfile_exists(backend, path,
+ &new_validity.mailbox_validity);
+ if (ret == 0) {
+ dir = acl_backend_vfile_get_local_dir(storage, name);
+ local_path = t_strconcat(dir, "/", name, NULL);
+ ret = acl_backend_vfile_exists(backend, local_path,
+ &new_validity.local_validity);
+ }
+ if (ret == 0 && backend->global_dir != NULL) {
+ global_path = t_strconcat(backend->global_dir, "/", name, NULL);
+ ret = acl_backend_vfile_exists(backend, global_path,
+ &new_validity.global_validity);
+ }
+ acl_cache_set_validity(_backend->cache, name, &new_validity);
+ return ret > 0;
+}
+
+static struct acl_object *
+acl_backend_vfile_object_init_parent(struct acl_backend *backend,
+ struct mail_storage *storage,
+ const char *child_name)
+{
+ const char *parent;
+
+ /* stop at the first parent that
+ a) has global ACL file
+ b) has local ACL file
+ c) exists */
+ while ((parent = get_parent_mailbox(storage, child_name)) != NULL) {
+ if (acl_backend_vfile_has_acl(backend, storage, parent))
+ break;
+ child_name = parent;
+ }
+ if (parent == NULL) {
+ /* use the root */
+ parent = "";
+ }
+ return acl_backend_vfile_object_init(backend, storage, parent);
}
static void acl_backend_vfile_object_deinit(struct acl_object *_aclobj)
@@ -470,8 +581,9 @@ acl_backend_vfile_refresh(struct acl_obj
seconds) */
time_t cache_secs = backend->cache_secs;
- if (st.st_mtime < validity->last_read_time - cache_secs ||
- ioloop_time - validity->last_read_time <= cache_secs)
+ if (validity->last_read_time != 0 &&
+ (st.st_mtime < validity->last_read_time - cache_secs ||
+ ioloop_time - validity->last_read_time <= cache_secs))
return 0;
}
@@ -591,6 +703,7 @@ struct acl_backend_vfuncs acl_backend_vf
acl_backend_vfile_nonowner_iter_next,
acl_backend_vfile_nonowner_iter_deinit,
acl_backend_vfile_object_init,
+ acl_backend_vfile_object_init_parent,
acl_backend_vfile_object_deinit,
acl_backend_vfile_object_refresh_cache,
acl_backend_vfile_object_update,
diff -r 314fab62b3d1 -r 459c4c496983 src/plugins/acl/acl-mailbox-list.c
--- a/src/plugins/acl/acl-mailbox-list.c Sun Sep 07 10:54:46 2008 +0300
+++ b/src/plugins/acl/acl-mailbox-list.c Sun Sep 07 15:18:29 2008 +0300
@@ -42,24 +42,19 @@ struct acl_backend *acl_mailbox_list_get
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,
+static int
+acl_mailbox_list_have_right(struct mailbox_list *list, 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);
+ struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
+ int ret;
+
+ ret = acl_storage_rights_ctx_have_right(&alist->rights, name, FALSE,
+ acl_storage_right_idx,
+ can_see_r);
+ if (ret < 0)
+ mailbox_list_set_internal_error(list);
+ return ret;
}
static void
@@ -185,7 +180,6 @@ acl_mailbox_list_info_is_visible(struct
acl_mailbox_list_info_is_visible(struct acl_mailbox_list_iterate_context *ctx,
const struct mailbox_info *info)
{
- struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ctx->ctx.list);
const char *acl_name;
int ret;
@@ -195,7 +189,7 @@ acl_mailbox_list_info_is_visible(struct
}
acl_name = acl_mailbox_list_iter_get_name(&ctx->ctx, info->name);
- ret = acl_mailbox_list_have_right(alist, acl_name,
+ ret = acl_mailbox_list_have_right(ctx->ctx.list, acl_name,
ACL_STORAGE_RIGHT_LOOKUP,
NULL);
if (ret != 0)
@@ -255,7 +249,7 @@ acl_mailbox_list_iter_is_mailbox(struct
return ret;
mailbox_name = acl_mailbox_list_iter_get_name(ctx, mailbox_name);
- return acl_mailbox_list_have_right(alist, mailbox_name,
+ return acl_mailbox_list_have_right(ctx->list, mailbox_name,
ACL_STORAGE_RIGHT_LOOKUP, NULL);
}
@@ -283,14 +277,14 @@ static int acl_get_mailbox_name_status(s
struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
int ret;
- ret = acl_mailbox_list_have_right(alist, name, ACL_STORAGE_RIGHT_LOOKUP,
+ ret = acl_mailbox_list_have_right(list, name, ACL_STORAGE_RIGHT_LOOKUP,
NULL);
if (ret < 0)
return -1;
if (ret == 0) {
/* If we have INSERT right for the mailbox, we'll need to
reveal its existence so that APPEND and COPY works. */
- ret = acl_mailbox_list_have_right(alist, name,
+ ret = acl_mailbox_list_have_right(list, name,
ACL_STORAGE_RIGHT_INSERT,
More information about the dovecot-cvs
mailing list