bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "lib.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "hash.h"
6e2856a5beeeb0edf5d852dde63d99fb9af11151Martti Rannanjärvi#include "sort.h"
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#include "mail-storage-settings.h"
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#include "mailbox-list.h"
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen#include "mail-namespace.h"
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#include "mail-user.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "acl-cache.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#include "acl-api-private.h"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenextern struct acl_backend_vfuncs acl_backend_vfile;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenconst char *const all_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,
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainen MAIL_ACL_POST,
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
7d8afd1e15bdf23b5fd13aa9ac9606aca2797125Timo Sirainenstatic const char *const *owner_mailbox_rights = all_mailbox_rights;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstatic const char *const non_owner_mailbox_rights[] = { NULL };
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenstruct acl_backend *
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainenacl_backend_init(const char *data, struct mailbox_list *list,
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen const char *acl_username, const char *const *groups,
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen bool owner)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct mail_user *user = mailbox_list_get_user(list);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen struct acl_backend *backend;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen unsigned int i, group_count;
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (user->mail_debug) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk i_debug("acl: initializing backend with data: %s", data);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk i_debug("acl: acl username = %s", acl_username);
f0339f522dc9c8e2e8a29ef9a3f937c431c6bd1bTimo Sirainen i_debug("acl: owner = %d", owner ? 1 : 0);
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen }
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
d3837c0362588792db3e3148d217f31ff3172922Timo Sirainen group_count = str_array_length(groups);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen if (strncmp(data, "vfile:", 6) == 0)
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen data += 6;
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen else if (strcmp(data, "vfile") == 0)
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen data = "";
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen else
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen i_fatal("Unknown ACL backend: %s", t_strcut(data, ':'));
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen backend = acl_backend_vfile.alloc();
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen backend->debug = user->mail_debug;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->v = acl_backend_vfile;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen backend->list = list;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->username = p_strdup(backend->pool, acl_username);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen backend->owner = owner;
95c8d28ebfc13f3252b71c71f3d5c0d809110a08Timo Sirainen backend->globals_only =
95c8d28ebfc13f3252b71c71f3d5c0d809110a08Timo Sirainen mail_user_plugin_getenv_bool(user, "acl_globals_only");
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if (group_count > 0) {
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen backend->group_count = group_count;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->groups =
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen p_new(backend->pool, const char *, group_count);
0e731a17eb66e67b2280b7788295bf469b1bcccdTimo Sirainen for (i = 0; i < group_count; i++) {
c7d655351dc85d917a27392c0d6ac89867786424Timo Sirainen backend->groups[i] = p_strdup(backend->pool, groups[i]);
0e731a17eb66e67b2280b7788295bf469b1bcccdTimo Sirainen if (user->mail_debug)
0e731a17eb66e67b2280b7788295bf469b1bcccdTimo Sirainen i_debug("acl: group added: %s", groups[i]);
0e731a17eb66e67b2280b7788295bf469b1bcccdTimo Sirainen }
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen i_qsort(backend->groups, group_count, sizeof(const char *),
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen i_strcmp_p);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen }
8ab69d02c689fbdad2a1c83a5cd27e6adf21ca6cTimo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (acl_backend_vfile.init(backend, data) < 0)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen i_fatal("acl: backend vfile init failed with data: %s",
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen data);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen
7705148680904051b573a9125ecee765032a5809Timo Sirainen backend->default_rights = owner ? owner_mailbox_rights :
7705148680904051b573a9125ecee765032a5809Timo Sirainen non_owner_mailbox_rights;
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen backend->default_aclmask =
3809b9691c46926aa54968ac8e418d04361e1efaTimo Sirainen acl_cache_mask_init(backend->cache, backend->pool,
7705148680904051b573a9125ecee765032a5809Timo Sirainen backend->default_rights);
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
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen *_backend = NULL;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
16d8e47d20a0061cb16ccaa2453ea8f1653013ffTimo Sirainen if (backend->default_aclobj != NULL)
16d8e47d20a0061cb16ccaa2453ea8f1653013ffTimo Sirainen acl_object_deinit(&backend->default_aclobj);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen acl_cache_deinit(&backend->cache);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen backend->v.deinit(backend);
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainenconst char *acl_backend_get_acl_username(struct acl_backend *backend)
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen{
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen return backend->username;
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen}
0b2f7be9fadfd4026a9174e51170890cde3edf48Timo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenbool acl_backend_user_is_authenticated(struct acl_backend *backend)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen{
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return backend->username != NULL;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainenbool acl_backend_user_is_owner(struct acl_backend *backend)
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen{
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen return backend->owner;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen}
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo 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{
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen return i_bsearch(group_name, backend->groups, backend->group_count,
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen sizeof(const char *), bsearch_strcmp) != NULL;
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen}
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainenbool acl_backend_rights_match_me(struct acl_backend *backend,
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen const struct acl_rights *rights)
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen{
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen switch (rights->id_type) {
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen case ACL_ID_ANYONE:
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen return TRUE;
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen case ACL_ID_AUTHENTICATED:
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen return acl_backend_user_is_authenticated(backend);
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen case ACL_ID_GROUP:
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen case ACL_ID_GROUP_OVERRIDE:
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen return acl_backend_user_is_in_group(backend, rights->identifier);
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen case ACL_ID_USER:
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen return acl_backend_user_name_equals(backend, rights->identifier);
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen case ACL_ID_OWNER:
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen return acl_backend_user_is_owner(backend);
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen case ACL_ID_TYPE_COUNT:
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen break;
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen }
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen i_unreached();
27a7dee37444438522e04273ce17e6c48775b35cTimo Sirainen}
27a7dee37444438522e04273ce17e6c48775b35cTimo 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}
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainenstruct acl_object *acl_backend_get_default_object(struct acl_backend *backend)
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen{
02c28668f01219ae17e112cd4d3cdd3a0af539a1Timo Sirainen struct mail_user *user = mailbox_list_get_user(backend->list);
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen struct mail_namespace *ns = mailbox_list_get_namespace(backend->list);
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen const char *default_name = "";
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen if (backend->default_aclobj != NULL)
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen return backend->default_aclobj;
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen
b1e097e04ceff5800101ec3615f815f2d0f2fd12Timo Sirainen if (mail_user_plugin_getenv_bool(user, "acl_defaults_from_inbox")) {
02c28668f01219ae17e112cd4d3cdd3a0af539a1Timo Sirainen if (ns->type == MAIL_NAMESPACE_TYPE_PRIVATE ||
02c28668f01219ae17e112cd4d3cdd3a0af539a1Timo Sirainen ns->type == MAIL_NAMESPACE_TYPE_SHARED)
02c28668f01219ae17e112cd4d3cdd3a0af539a1Timo Sirainen default_name = "INBOX";
02c28668f01219ae17e112cd4d3cdd3a0af539a1Timo Sirainen }
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen backend->default_aclobj =
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen acl_object_init_from_name(backend, default_name);
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen return backend->default_aclobj;
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen}
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainenint acl_backend_get_default_rights(struct acl_backend *backend,
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen const struct acl_mask **mask_r)
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen{
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen struct acl_object *aclobj = acl_backend_get_default_object(backend);
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen if (backend->v.object_refresh_cache(aclobj) < 0)
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen return -1;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
515d649c1802beb48433b90125518c00d0a1fbb4Timo Sirainen *mask_r = acl_cache_get_my_rights(backend->cache, aclobj->name);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen if (*mask_r == NULL)
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen *mask_r = backend->default_aclmask;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen return 0;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen}