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);
}
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);
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);
}
}
#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. */
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;
}
}
-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)
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;
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();