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