acl-backend.c revision 7fb70daba4e571eab5b64f496d20b9e37e31141b
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen/* Copyright (C) 2006 Timo Sirainen */
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "lib.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "hash.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "acl-cache.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "acl-api-private.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include <stdlib.h>
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenextern struct acl_backend_vfuncs acl_backend_vfile;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstatic const char *const owner_mailbox_rights[] = {
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen MAIL_ACL_LOOKUP,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen MAIL_ACL_READ,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen MAIL_ACL_WRITE,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen MAIL_ACL_WRITE_SEEN,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen MAIL_ACL_WRITE_DELETED,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen MAIL_ACL_INSERT,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen MAIL_ACL_EXPUNGE,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen MAIL_ACL_CREATE,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen MAIL_ACL_DELETE,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen MAIL_ACL_ADMIN,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen NULL
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen};
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstatic const char *const non_owner_mailbox_rights[] = { NULL };
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstruct acl_backend *
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenacl_backend_init(const char *data, struct mail_storage *storage,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen const char *acl_username, const char *const *groups,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen const char *owner_username)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_backend *backend;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen unsigned int i, group_count;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen bool storage_owner;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen group_count = strarray_length(groups);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (strncmp(data, "vfile:", 6) != 0)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen i_fatal("Unknown ACL backend: %s", t_strcut(data, ':'));
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen data += 6;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend = acl_backend_vfile.init(data);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->v = acl_backend_vfile;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->storage = storage;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->username = p_strdup(backend->pool, acl_username);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->owner_username = p_strdup(backend->pool, owner_username);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->group_count = group_count;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->cache = acl_cache_init(backend);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->aclobjs = hash_create(default_pool, backend->pool, 0,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen str_hash, (hash_cmp_callback_t *)strcmp);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen storage_owner = owner_username != NULL &&
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen strcmp(acl_username, owner_username) == 0;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->default_rights =
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen acl_cache_mask_init(backend->cache, backend->pool,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen storage_owner ? owner_mailbox_rights :
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen non_owner_mailbox_rights);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (group_count > 0) {
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->groups =
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen p_new(backend->pool, const char *, group_count);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen for (i = 0; i < group_count; i++)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->groups[i] = groups[i];
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen qsort(backend->groups, group_count, sizeof(const char *),
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen strcmp_p);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen }
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return backend;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenvoid acl_backend_deinit(struct acl_backend **_backend)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_backend *backend = *_backend;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct hash_iterate_context *iter;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen void *key, *value;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen *_backend = NULL;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen iter = hash_iterate_init(backend->aclobjs);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen while (hash_iterate(iter, &key, &value)) {
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_object *aclobj = value;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen aclobj->backend->v.object_deinit(aclobj);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen }
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen hash_iterate_deinit(iter);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen acl_cache_deinit(&backend->cache);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen hash_destroy(backend->aclobjs);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->v.deinit(backend);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenbool acl_backend_user_is_authenticated(struct acl_backend *backend)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return backend->username != NULL;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenbool acl_backend_user_name_equals(struct acl_backend *backend,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen const char *username)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (backend->username == NULL) {
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen /* anonymous user never matches */
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return FALSE;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen }
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return strcmp(backend->username, username) == 0;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenbool acl_backend_user_is_in_group(struct acl_backend *backend,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen const char *group_name)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return bsearch(group_name, backend->groups, backend->group_count,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen sizeof(const char *), bsearch_strcmp) != NULL;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenunsigned int acl_backend_lookup_right(struct acl_backend *backend,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen const char *right)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return acl_cache_right_lookup(backend->cache, right);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}