acl-lookup-dict.c revision c9dea5c23355dea35c6fa423de69f6507852efe4
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "lib.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "array.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "str.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "dict.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "mail-user.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "mail-namespace.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "acl-api-private.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "acl-storage.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "acl-plugin.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "acl-lookup-dict.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include <stdlib.h>
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#define DICT_SHARED_BOXES_PATH "shared-boxes/"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenstruct acl_lookup_dict {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct mail_user *user;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct dict *dict;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen};
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenstruct acl_lookup_dict_iter {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen pool_t pool;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_lookup_dict *dict;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ARRAY_TYPE(const_string) iter_ids;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct dict_iterate_context *dict_iter;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen unsigned int iter_idx;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char *prefix;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen unsigned int prefix_len;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen unsigned int failed:1;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen};
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenstruct acl_lookup_dict *acl_lookup_dict_init(struct mail_user *user)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen{
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_lookup_dict *dict;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen const char *uri;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen dict = i_new(struct acl_lookup_dict, 1);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen dict->user = user;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen uri = mail_user_plugin_getenv(user, "acl_shared_dict");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (uri != NULL) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen dict->dict = dict_init(uri, DICT_DATA_TYPE_STRING, "");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (dict->dict == NULL)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen i_error("acl: dict_init(%s) failed", uri);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen } else if (user->mail_debug) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen i_info("acl: No acl_shared_dict setting - "
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen "shared mailbox listing is disabled");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return dict;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen}
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenvoid acl_lookup_dict_deinit(struct acl_lookup_dict **_dict)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen{
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_lookup_dict *dict = *_dict;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen *_dict = NULL;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (dict->dict != NULL)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen dict_deinit(&dict->dict);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen i_free(dict);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen}
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenstatic void
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenacl_lookup_dict_write_rights_id(string_t *dest, const struct acl_rights *right)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen{
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen switch (right->id_type) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen case ACL_ID_ANYONE:
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen case ACL_ID_AUTHENTICATED:
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* don't bother separating these */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_append(dest, "anyone");
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen break;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen case ACL_ID_USER:
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_append(dest, "user/");
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_append(dest, right->identifier);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen break;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen case ACL_ID_GROUP:
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen case ACL_ID_GROUP_OVERRIDE:
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_append(dest, "group/");
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_append(dest, right->identifier);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen break;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen case ACL_ID_OWNER:
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen case ACL_ID_TYPE_COUNT:
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen i_unreached();
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen}
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenstatic int acl_lookup_dict_rebuild_add_backend(struct mail_namespace *ns,
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ARRAY_TYPE(const_string) *ids)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen{
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_backend *backend;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_mailbox_list_context *ctx;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_object *aclobj;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_object_list_iter *iter;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_rights rights;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char *name, *id_dup;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen string_t *id;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen int ret, ret2 = 0;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
16db188cfddce117500a161302f17ae691b4500eTimo Sirainen if ((ns->flags & NAMESPACE_FLAG_NOACL) != 0 || ns->owner == NULL)
671ecc41b231616d7193a5319e5ba95c6a299aabTimo Sirainen return 0;
671ecc41b231616d7193a5319e5ba95c6a299aabTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen id = t_str_new(128);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen backend = acl_mailbox_list_get_backend(ns->list);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ctx = acl_backend_nonowner_lookups_iter_init(backend);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen while ((ret = acl_backend_nonowner_lookups_iter_next(ctx, &name)) > 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen aclobj = acl_object_init_from_name(backend, name);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen iter = acl_object_list_init(aclobj);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen while ((ret = acl_object_list_next(iter, &rights)) > 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (acl_rights_has_nonowner_lookup_changes(&rights)) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_truncate(id, 0);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen acl_lookup_dict_write_rights_id(id, &rights);
1fa4e468e2784b14bb461830a20c947340688a57Timo Sirainen str_append_c(id, '/');
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen str_append(id, ns->owner->username);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen id_dup = t_strdup(str_c(id));
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen array_append(ids, &id_dup, 1);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen acl_object_list_deinit(&iter);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (ret < 0)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ret2 = -1;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen acl_object_deinit(&aclobj);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen acl_backend_nonowner_lookups_iter_deinit(&ctx);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return ret < 0 || ret2 < 0 ? -1 : 0;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen}
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenstatic int
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenacl_lookup_dict_rebuild_update(struct acl_lookup_dict *dict,
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const ARRAY_TYPE(const_string) *new_ids_arr,
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen bool no_removes)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen{
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char *username = dict->user->username;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct dict_iterate_context *iter;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct dict_transaction_context *dt;
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen const char *prefix, *key, *value, *const *old_ids, *const *new_ids, *p;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ARRAY_TYPE(const_string) old_ids_arr;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen unsigned int newi, oldi, old_count, new_count;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen string_t *path;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen unsigned int prefix_len;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen int ret;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
1fa4e468e2784b14bb461830a20c947340688a57Timo Sirainen /* get all existing identifiers for the user. we might be able to
1fa4e468e2784b14bb461830a20c947340688a57Timo Sirainen sync identifiers also for other users whose shared namespaces we
1fa4e468e2784b14bb461830a20c947340688a57Timo Sirainen have, but it's possible that the other users have other namespaces
1fa4e468e2784b14bb461830a20c947340688a57Timo Sirainen that aren't visible to us, so we don't want to remove anything
1fa4e468e2784b14bb461830a20c947340688a57Timo Sirainen that could break them. */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen t_array_init(&old_ids_arr, 128);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen prefix = DICT_PATH_SHARED DICT_SHARED_BOXES_PATH;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen prefix_len = strlen(prefix);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen iter = dict_iterate_init(dict->dict, prefix, DICT_ITERATE_FLAG_RECURSE);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen while ((ret = dict_iterate(iter, &key, &value)) > 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* prefix/$dest/$source */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen key += prefix_len;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen p = strchr(key, '/');
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (p != NULL && strcmp(p + 1, username) == 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen key = t_strdup_until(key, p);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen array_append(&old_ids_arr, &key, 1);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen dict_iterate_deinit(&iter);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (ret < 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen i_error("acl: dict iteration failed, can't update dict");
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return -1;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* sort the existing identifiers */
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen array_sort(&old_ids_arr, i_strcmp_p);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* sync the identifiers */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen path = t_str_new(256);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_append(path, prefix);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen dt = dict_transaction_begin(dict->dict);
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen old_ids = array_get(&old_ids_arr, &old_count);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen new_ids = array_get(new_ids_arr, &new_count);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen for (newi = oldi = 0; newi < new_count || oldi < old_count; ) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ret = newi == new_count ? 1 :
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen oldi == old_count ? -1 :
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen strcmp(new_ids[newi], old_ids[oldi]);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (ret == 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen newi++; oldi++;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen } else if (ret < 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* new identifier, add it */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_truncate(path, prefix_len);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_append(path, new_ids[newi]);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen dict_set(dt, str_c(path), "1");
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen newi++;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen } else if (!no_removes) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* old identifier removed */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_truncate(path, prefix_len);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_append(path, old_ids[oldi]);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_append_c(path, '/');
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen str_append(path, username);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen dict_unset(dt, str_c(path));
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen oldi++;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (dict_transaction_commit(&dt) < 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen i_error("acl: dict commit failed");
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return -1;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return 0;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen}
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenint acl_lookup_dict_rebuild(struct acl_lookup_dict *dict)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen{
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct mail_namespace *ns;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ARRAY_TYPE(const_string) ids_arr;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char **ids;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen unsigned int i, dest, count;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen int ret = 0;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (dict->dict == NULL)
372d3167088e17ccece2b922961c05cb8a7e4e03Timo Sirainen return 0;
372d3167088e17ccece2b922961c05cb8a7e4e03Timo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* get all ACL identifiers with a positive lookup right */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen t_array_init(&ids_arr, 128);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen for (ns = dict->user->namespaces; ns != NULL; ns = ns->next) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (acl_lookup_dict_rebuild_add_backend(ns, &ids_arr) < 0)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ret = -1;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* sort identifiers and remove duplicates */
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen array_sort(&ids_arr, i_strcmp_p);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen ids = array_get_modifiable(&ids_arr, &count);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen for (i = 1, dest = 0; i < count; i++) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (strcmp(ids[dest], ids[i]) != 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (++dest != i)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ids[dest] = ids[i];
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (++dest < count)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen array_delete(&ids_arr, dest, count-dest);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* if lookup failed at some point we can still add new ids,
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen but we can't remove any existing ones */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (acl_lookup_dict_rebuild_update(dict, &ids_arr, ret < 0) < 0)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ret = -1;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return ret;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen}
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenstatic void acl_lookup_dict_iterate_start(struct acl_lookup_dict_iter *iter)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen{
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char *const *idp;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen idp = array_idx(&iter->iter_ids, iter->iter_idx);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen iter->iter_idx++;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen iter->prefix = p_strconcat(iter->pool, DICT_PATH_SHARED
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen DICT_SHARED_BOXES_PATH, *idp, "/", NULL);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen iter->prefix_len = strlen(iter->prefix);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen iter->dict_iter = dict_iterate_init(iter->dict->dict, iter->prefix,
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen DICT_ITERATE_FLAG_RECURSE);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen}
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenstruct acl_lookup_dict_iter *
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenacl_lookup_dict_iterate_visible_init(struct acl_lookup_dict *dict)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen{
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_user *auser = ACL_USER_CONTEXT(dict->user);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_lookup_dict_iter *iter;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char *id;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen unsigned int i;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen pool_t pool;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen pool = pool_alloconly_create("acl lookup dict iter", 512);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen iter = p_new(pool, struct acl_lookup_dict_iter, 1);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen iter->pool = pool;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen iter->dict = dict;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen p_array_init(&iter->iter_ids, pool, 16);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen id = "anyone";
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen array_append(&iter->iter_ids, &id, 1);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen id = p_strconcat(pool, "user/", dict->user->username, NULL);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen array_append(&iter->iter_ids, &id, 1);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* get all groups we belong to */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (auser->groups != NULL) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen for (i = 0; auser->groups[i] != NULL; i++) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen id = p_strconcat(pool, "group/", auser->groups[i],
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen NULL);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen array_append(&iter->iter_ids, &id, 1);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* iterate through all identifiers that match us, start with the
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen first one */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (dict->dict != NULL)
372d3167088e17ccece2b922961c05cb8a7e4e03Timo Sirainen acl_lookup_dict_iterate_start(iter);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return iter;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen}
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenconst char *
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenacl_lookup_dict_iterate_visible_next(struct acl_lookup_dict_iter *iter)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen{
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char *key, *value;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen int ret;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
372d3167088e17ccece2b922961c05cb8a7e4e03Timo Sirainen if (iter->dict_iter == NULL)
372d3167088e17ccece2b922961c05cb8a7e4e03Timo Sirainen return 0;
372d3167088e17ccece2b922961c05cb8a7e4e03Timo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ret = dict_iterate(iter->dict_iter, &key, &value);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (ret > 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen i_assert(iter->prefix_len < strlen(key));
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return key + iter->prefix_len;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (ret < 0)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen iter->failed = TRUE;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen dict_iterate_deinit(&iter->dict_iter);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (iter->iter_idx < array_count(&iter->iter_ids)) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* get to the next iterator */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen acl_lookup_dict_iterate_start(iter);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return acl_lookup_dict_iterate_visible_next(iter);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return NULL;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen}
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenint acl_lookup_dict_iterate_visible_deinit(struct acl_lookup_dict_iter **_iter)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen{
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_lookup_dict_iter *iter = *_iter;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen int ret = iter->failed ? -1 : 0;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen *_iter = NULL;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (iter->dict_iter != NULL)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen dict_iterate_deinit(&iter->dict_iter);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen pool_unref(&iter->pool);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return ret;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen}