dovecot-1.2: ACL: Crashfix to previous change. Also fixes "-id" ...

dovecot at dovecot.org dovecot at dovecot.org
Sun Nov 16 01:34:34 EET 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/d00c446a95df
changeset: 8415:d00c446a95df
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Nov 16 01:34:16 2008 +0200
description:
ACL: Crashfix to previous change. Also fixes "-id" to work correctly with missing "id".

diffstat:

4 files changed, 68 insertions(+), 32 deletions(-)
src/plugins/acl/acl-api.h           |    3 +
src/plugins/acl/acl-backend-vfile.c |   28 +++++++++++---
src/plugins/acl/acl-cache.c         |   67 ++++++++++++++++++++++-------------
src/plugins/acl/acl-cache.h         |    2 -

diffs (197 lines):

diff -r d486dfe02c1e -r d00c446a95df src/plugins/acl/acl-api.h
--- a/src/plugins/acl/acl-api.h	Sun Nov 16 00:15:15 2008 +0200
+++ b/src/plugins/acl/acl-api.h	Sun Nov 16 01:34:16 2008 +0200
@@ -62,7 +62,8 @@ struct acl_rights {
 	/* Identifier, eg. username / group name */
 	const char *identifier;
 
-	/* Rights assigned */
+	/* Rights assigned. NULL entry can be ignored, but { NULL } means user
+	   has no rights. */
 	const char *const *rights;
 	/* Negative rights assigned */
 	const char *const *neg_rights;
diff -r d486dfe02c1e -r d00c446a95df src/plugins/acl/acl-backend-vfile.c
--- a/src/plugins/acl/acl-backend-vfile.c	Sun Nov 16 00:15:15 2008 +0200
+++ b/src/plugins/acl/acl-backend-vfile.c	Sun Nov 16 01:34:16 2008 +0200
@@ -632,10 +632,14 @@ acl_rights_merge(pool_t pool, const char
 	unsigned int i;
 
 	t_array_init(&rights, 64);
-	for (i = 0; dest[i] != NULL; i++)
-		array_append(&rights, &dest[i], 1);
-	for (i = 0; src[i] != NULL; i++)
-		array_append(&rights, &src[i], 1);
+	if (dest != NULL) {
+		for (i = 0; dest[i] != NULL; i++)
+			array_append(&rights, &dest[i], 1);
+	}
+	if (src != NULL) {
+		for (i = 0; src[i] != NULL; i++)
+			array_append(&rights, &src[i], 1);
+	}
 
 	*destp = acl_rights_alloc(pool, &rights);
 }
@@ -679,6 +683,7 @@ static void acl_backend_vfile_cache_rebu
 	struct acl_rights_update ru;
 	const struct acl_rights *rights;
 	unsigned int i, count;
+	bool first_global = TRUE;
 
 	acl_cache_flush(_aclobj->backend->cache, _aclobj->name);
 
@@ -688,9 +693,20 @@ static void acl_backend_vfile_cache_rebu
 	memset(&ru, 0, sizeof(ru));
 	rights = array_get(&aclobj->rights, &count);
 	for (i = 0; i < count; i++) {
-		ru.modify_mode = ACL_MODIFY_MODE_REPLACE;
-		ru.neg_modify_mode = ACL_MODIFY_MODE_REPLACE;
+		/* If [neg_]rights is NULL it needs to be ignored.
+		   The easiest way to do that is to just mark it with
+		   REMOVE mode */
+		ru.modify_mode = rights[i].rights == NULL ?
+			ACL_MODIFY_MODE_REMOVE : ACL_MODIFY_MODE_REPLACE;
+		ru.neg_modify_mode = rights[i].neg_rights == NULL ?
+			ACL_MODIFY_MODE_REMOVE : ACL_MODIFY_MODE_REPLACE;
 		ru.rights = rights[i];
+		if (rights[i].global && first_global) {
+			/* first global: reset negative ACLs so local ACLs
+			   can't mess things up via them */
+			first_global = FALSE;
+			ru.neg_modify_mode = ACL_MODIFY_MODE_REPLACE;
+		}
 		acl_cache_update(_aclobj->backend->cache, _aclobj->name, &ru);
 	}
 }
diff -r d486dfe02c1e -r d00c446a95df src/plugins/acl/acl-cache.c
--- a/src/plugins/acl/acl-cache.c	Sun Nov 16 00:15:15 2008 +0200
+++ b/src/plugins/acl/acl-cache.c	Sun Nov 16 01:34:16 2008 +0200
@@ -4,7 +4,7 @@
 #include "array.h"
 #include "hash.h"
 #include "acl-cache.h"
-#include "acl-api.h"
+#include "acl-api-private.h"
 
 /* Give more than enough so that the arrays should never have to be grown.
    IMAP ACLs define only 10 standard rights and 10 user-defined rights. */
@@ -116,6 +116,18 @@ struct acl_mask *acl_cache_mask_init(str
 	return mask;
 }
 
+static struct acl_mask *
+acl_cache_mask_dup(pool_t pool, const struct acl_mask *src)
+{
+	struct acl_mask *mask;
+
+	mask = p_malloc(pool, SIZEOF_ACL_MASK(src->size));
+	memcpy(mask->mask, src->mask, src->size);
+	mask->pool = pool;
+	mask->size = src->size;
+	return mask;
+}
+
 void acl_cache_mask_deinit(struct acl_mask **_mask)
 {
 	struct acl_mask *mask = *_mask;
@@ -251,19 +263,6 @@ acl_cache_update_rights_mask(struct acl_
 	}
 }
 
-static void
-acl_cache_update_rights(struct acl_cache *cache,
-			struct acl_object_cache *obj_cache,
-			const struct acl_rights_update *rights)
-{
-	acl_cache_update_rights_mask(cache, obj_cache, rights->modify_mode,
-				     rights->rights.rights,
-				     &obj_cache->my_rights);
-	acl_cache_update_rights_mask(cache, obj_cache, rights->neg_modify_mode,
-				     rights->rights.neg_rights,
-				     &obj_cache->my_neg_rights);
-}
-
 static struct acl_object_cache *
 acl_cache_object_get(struct acl_cache *cache, const char *objname,
 		     bool *created_r)
@@ -283,8 +282,9 @@ acl_cache_object_get(struct acl_cache *c
 	return obj_cache;
 }
 
-void acl_cache_update(struct acl_cache *cache, const char *objname,
-		      const struct acl_rights_update *rights)
+static void
+acl_cache_update_rights(struct acl_cache *cache, const char *objname,
+			const struct acl_rights_update *update)
 {
 	struct acl_object_cache *obj_cache;
 	bool created;
@@ -292,28 +292,47 @@ void acl_cache_update(struct acl_cache *
 	obj_cache = acl_cache_object_get(cache, objname, &created);
 	i_assert(obj_cache->my_current_rights != &negative_cache_entry);
 
-	switch (rights->rights.id_type) {
+	if (created && update->modify_mode != ACL_MODIFY_MODE_REPLACE) {
+		/* since the rights aren't being replaced, start with our
+		   default rights */
+		obj_cache->my_rights =
+			acl_cache_mask_dup(default_pool,
+					   cache->backend->default_aclmask);
+	}
+
+	acl_cache_update_rights_mask(cache, obj_cache, update->modify_mode,
+				     update->rights.rights,
+				     &obj_cache->my_rights);
+	acl_cache_update_rights_mask(cache, obj_cache, update->neg_modify_mode,
+				     update->rights.neg_rights,
+				     &obj_cache->my_neg_rights);
+}
+
+void acl_cache_update(struct acl_cache *cache, const char *objname,
+		      const struct acl_rights_update *update)
+{
+	switch (update->rights.id_type) {
 	case ACL_ID_ANYONE:
-		acl_cache_update_rights(cache, obj_cache, rights);
+		acl_cache_update_rights(cache, objname, update);
 		break;
 	case ACL_ID_AUTHENTICATED:
 		if (acl_backend_user_is_authenticated(cache->backend))
-			acl_cache_update_rights(cache, obj_cache, rights);
+			acl_cache_update_rights(cache, objname, update);
 		break;
 	case ACL_ID_GROUP:
 	case ACL_ID_GROUP_OVERRIDE:
 		if (acl_backend_user_is_in_group(cache->backend,
-						 rights->rights.identifier))
-			acl_cache_update_rights(cache, obj_cache, rights);
+						 update->rights.identifier))
+			acl_cache_update_rights(cache, objname, update);
 		break;
 	case ACL_ID_USER:
 		if (acl_backend_user_name_equals(cache->backend,
-						 rights->rights.identifier))
-			acl_cache_update_rights(cache, obj_cache, rights);
+						 update->rights.identifier))
+			acl_cache_update_rights(cache, objname, update);
 		break;
 	case ACL_ID_OWNER:
 		if (acl_backend_user_is_owner(cache->backend))
-			acl_cache_update_rights(cache, obj_cache, rights);
+			acl_cache_update_rights(cache, objname, update);
 		break;
 	case ACL_ID_TYPE_COUNT:
 		i_unreached();
diff -r d486dfe02c1e -r d00c446a95df src/plugins/acl/acl-cache.h
--- a/src/plugins/acl/acl-cache.h	Sun Nov 16 00:15:15 2008 +0200
+++ b/src/plugins/acl/acl-cache.h	Sun Nov 16 01:34:16 2008 +0200
@@ -34,7 +34,7 @@ void acl_cache_flush_all(struct acl_cach
 /* Update object ACLs. The new rights are always applied on top of the
    existing rights. The ordering by acl_id_type must be done by the caller. */
 void acl_cache_update(struct acl_cache *cache, const char *objname,
-		      const struct acl_rights_update *rights);
+		      const struct acl_rights_update *update);
 /* Return ACL object validity, or NULL if object doesn't exit. */
 void *acl_cache_get_validity(struct acl_cache *cache, const char *objname);
 /* Update ACL object validity, creating the object if needed. */


More information about the dovecot-cvs mailing list