# HG changeset patch # User Timo Sirainen # Date 1226792056 -7200 # Node ID d00c446a95dfd57ab3d8e5c20bbbe87944776b70 # Parent d486dfe02c1eeb0fab7edec74bd58a59a96c8f1e ACL: Crashfix to previous change. Also fixes "-id" to work correctly with missing "id". 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } -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 @@ 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 @@ 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 @@ /* 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. */