summaryrefslogtreecommitdiffstats
path: root/src/plugins/acl/acl-backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/acl/acl-backend.c')
-rw-r--r--src/plugins/acl/acl-backend.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/plugins/acl/acl-backend.c b/src/plugins/acl/acl-backend.c
new file mode 100644
index 0000000..0514dc7
--- /dev/null
+++ b/src/plugins/acl/acl-backend.c
@@ -0,0 +1,194 @@
+/* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "hash.h"
+#include "sort.h"
+#include "mail-storage-settings.h"
+#include "mailbox-list.h"
+#include "mail-namespace.h"
+#include "mail-user.h"
+#include "acl-cache.h"
+#include "acl-api-private.h"
+
+
+extern struct acl_backend_vfuncs acl_backend_vfile;
+
+const char *const all_mailbox_rights[] = {
+ MAIL_ACL_LOOKUP,
+ MAIL_ACL_READ,
+ MAIL_ACL_WRITE,
+ MAIL_ACL_WRITE_SEEN,
+ MAIL_ACL_WRITE_DELETED,
+ MAIL_ACL_INSERT,
+ MAIL_ACL_POST,
+ MAIL_ACL_EXPUNGE,
+ MAIL_ACL_CREATE,
+ MAIL_ACL_DELETE,
+ MAIL_ACL_ADMIN,
+ NULL
+};
+
+static const char *const *owner_mailbox_rights = all_mailbox_rights;
+static const char *const non_owner_mailbox_rights[] = { NULL };
+
+struct acl_backend *
+acl_backend_init(const char *data, struct mailbox_list *list,
+ const char *acl_username, const char *const *groups,
+ bool owner)
+{
+ struct mail_user *user = mailbox_list_get_user(list);
+ struct acl_backend *backend;
+ unsigned int i, group_count;
+
+ e_debug(user->event, "acl: initializing backend with data: %s", data);
+ e_debug(user->event, "acl: acl username = %s", acl_username);
+ e_debug(user->event, "acl: owner = %d", owner ? 1 : 0);
+
+ group_count = str_array_length(groups);
+
+ if (str_begins(data, "vfile:"))
+ data += 6;
+ else if (strcmp(data, "vfile") == 0)
+ data = "";
+ else
+ i_fatal("Unknown ACL backend: %s", t_strcut(data, ':'));
+
+ backend = acl_backend_vfile.alloc();
+ backend->debug = user->mail_debug;
+ backend->v = acl_backend_vfile;
+ backend->list = list;
+ backend->username = p_strdup(backend->pool, acl_username);
+ backend->owner = owner;
+ backend->globals_only =
+ mail_user_plugin_getenv_bool(user, "acl_globals_only");
+
+ if (group_count > 0) {
+ backend->group_count = group_count;
+ backend->groups =
+ p_new(backend->pool, const char *, group_count);
+ for (i = 0; i < group_count; i++) {
+ backend->groups[i] = p_strdup(backend->pool, groups[i]);
+ e_debug(user->event, "acl: group added: %s", groups[i]);
+ }
+ i_qsort(backend->groups, group_count, sizeof(const char *),
+ i_strcmp_p);
+ }
+
+ T_BEGIN {
+ if (acl_backend_vfile.init(backend, data) < 0)
+ i_fatal("acl: backend vfile init failed with data: %s",
+ data);
+ } T_END;
+
+ backend->default_rights = owner ? owner_mailbox_rights :
+ non_owner_mailbox_rights;
+ backend->default_aclmask =
+ acl_cache_mask_init(backend->cache, backend->pool,
+ backend->default_rights);
+ return backend;
+}
+
+void acl_backend_deinit(struct acl_backend **_backend)
+{
+ struct acl_backend *backend = *_backend;
+
+ *_backend = NULL;
+
+ if (backend->default_aclobj != NULL)
+ acl_object_deinit(&backend->default_aclobj);
+ acl_cache_deinit(&backend->cache);
+ backend->v.deinit(backend);
+}
+
+const char *acl_backend_get_acl_username(struct acl_backend *backend)
+{
+ return backend->username;
+}
+
+bool acl_backend_user_is_authenticated(struct acl_backend *backend)
+{
+ return backend->username != NULL;
+}
+
+bool acl_backend_user_is_owner(struct acl_backend *backend)
+{
+ return backend->owner;
+}
+
+bool acl_backend_user_name_equals(struct acl_backend *backend,
+ const char *username)
+{
+ if (backend->username == NULL) {
+ /* anonymous user never matches */
+ return FALSE;
+ }
+
+ return strcmp(backend->username, username) == 0;
+}
+
+bool acl_backend_user_is_in_group(struct acl_backend *backend,
+ const char *group_name)
+{
+ return i_bsearch(group_name, backend->groups, backend->group_count,
+ sizeof(const char *), bsearch_strcmp) != NULL;
+}
+
+bool acl_backend_rights_match_me(struct acl_backend *backend,
+ const struct acl_rights *rights)
+{
+ switch (rights->id_type) {
+ case ACL_ID_ANYONE:
+ return TRUE;
+ case ACL_ID_AUTHENTICATED:
+ return acl_backend_user_is_authenticated(backend);
+ case ACL_ID_GROUP:
+ case ACL_ID_GROUP_OVERRIDE:
+ return acl_backend_user_is_in_group(backend, rights->identifier);
+ case ACL_ID_USER:
+ return acl_backend_user_name_equals(backend, rights->identifier);
+ case ACL_ID_OWNER:
+ return acl_backend_user_is_owner(backend);
+ case ACL_ID_TYPE_COUNT:
+ break;
+ }
+ i_unreached();
+}
+
+unsigned int acl_backend_lookup_right(struct acl_backend *backend,
+ const char *right)
+{
+ return acl_cache_right_lookup(backend->cache, right);
+}
+
+struct acl_object *acl_backend_get_default_object(struct acl_backend *backend)
+{
+ struct mail_user *user = mailbox_list_get_user(backend->list);
+ struct mail_namespace *ns = mailbox_list_get_namespace(backend->list);
+ const char *default_name = "";
+
+ if (backend->default_aclobj != NULL)
+ return backend->default_aclobj;
+
+ if (mail_user_plugin_getenv_bool(user, "acl_defaults_from_inbox")) {
+ if (ns->type == MAIL_NAMESPACE_TYPE_PRIVATE ||
+ ns->type == MAIL_NAMESPACE_TYPE_SHARED)
+ default_name = "INBOX";
+ }
+ backend->default_aclobj =
+ acl_object_init_from_name(backend, default_name);
+ return backend->default_aclobj;
+}
+
+int acl_backend_get_default_rights(struct acl_backend *backend,
+ const struct acl_mask **mask_r)
+{
+ struct acl_object *aclobj = acl_backend_get_default_object(backend);
+
+ if (backend->v.object_refresh_cache(aclobj) < 0)
+ return -1;
+
+ *mask_r = acl_cache_get_my_rights(backend->cache, aclobj->name);
+ if (*mask_r == NULL)
+ *mask_r = backend->default_aclmask;
+ return 0;
+}