]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
ACL: Crashfix to previous change. Also fixes "-id" to work correctly with missing...
authorTimo Sirainen <tss@iki.fi>
Sat, 15 Nov 2008 23:34:16 +0000 (01:34 +0200)
committerTimo Sirainen <tss@iki.fi>
Sat, 15 Nov 2008 23:34:16 +0000 (01:34 +0200)
--HG--
branch : HEAD

src/plugins/acl/acl-api.h
src/plugins/acl/acl-backend-vfile.c
src/plugins/acl/acl-cache.c
src/plugins/acl/acl-cache.h

index a3129677c71bd561f43bd0a6515b4dc08e627a06..f254cb3e9a5bd68fd37e26d1fcd6b66f31aa40ae 100644 (file)
@@ -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;
index aaebdf9eda2d6a456c09141f47ed9960ac926704..0f5dfb0d17e92b8f0b6a4828ff44325337fa9542 100644 (file)
@@ -632,10 +632,14 @@ acl_rights_merge(pool_t pool, const char *const **destp, const char *const *src)
        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_rebuild(struct acl_object_vfile *aclobj)
        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_rebuild(struct acl_object_vfile *aclobj)
        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);
        }
 }
index 2ef875d6551aa2fb7d2e151028251199875ab57e..9a8cd434e30155844b4f9b942887c2cab6b1e7bf 100644 (file)
@@ -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(struct acl_cache *cache, pool_t pool,
        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_cache *cache,
        }
 }
 
-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 *cache, const char *objname,
        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 *cache, const char *objname,
        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();
index 940056d228484876cd391826b5843ee5a17dda64..396e9ddc8a92454d0a9d2d3c57424eff555d2729 100644 (file)
@@ -34,7 +34,7 @@ void acl_cache_flush_all(struct acl_cache *cache);
 /* 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. */