acl-lookup-dict.c revision c9dea5c23355dea35c6fa423de69f6507852efe4
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenstruct acl_lookup_dict *acl_lookup_dict_init(struct mail_user *user)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen const char *uri;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen uri = mail_user_plugin_getenv(user, "acl_shared_dict");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen dict->dict = dict_init(uri, DICT_DATA_TYPE_STRING, "");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen "shared mailbox listing is disabled");
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenvoid acl_lookup_dict_deinit(struct acl_lookup_dict **_dict)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenacl_lookup_dict_write_rights_id(string_t *dest, const struct acl_rights *right)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* don't bother separating these */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenstatic int acl_lookup_dict_rebuild_add_backend(struct mail_namespace *ns,
16db188cfddce117500a161302f17ae691b4500eTimo Sirainen if ((ns->flags & NAMESPACE_FLAG_NOACL) != 0 || ns->owner == NULL)
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 while ((ret = acl_object_list_next(iter, &rights)) > 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (acl_rights_has_nonowner_lookup_changes(&rights)) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen acl_backend_nonowner_lookups_iter_deinit(&ctx);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenacl_lookup_dict_rebuild_update(struct acl_lookup_dict *dict,
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen const char *prefix, *key, *value, *const *old_ids, *const *new_ids, *p;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen unsigned int newi, oldi, old_count, new_count;
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 prefix = DICT_PATH_SHARED DICT_SHARED_BOXES_PATH;
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 if (p != NULL && strcmp(p + 1, username) == 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen i_error("acl: dict iteration failed, can't update dict");
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* sort the existing identifiers */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* sync the identifiers */
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen old_ids = array_get(&old_ids_arr, &old_count);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen for (newi = oldi = 0; newi < new_count || oldi < old_count; ) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen } else if (ret < 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* new identifier, add it */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen } else if (!no_removes) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* old identifier removed */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenint acl_lookup_dict_rebuild(struct acl_lookup_dict *dict)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char **ids;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* get all ACL identifiers with a positive lookup right */
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 /* sort identifiers and remove duplicates */
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 Sirainenstatic void acl_lookup_dict_iterate_start(struct acl_lookup_dict_iter *iter)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char *const *idp;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen idp = array_idx(&iter->iter_ids, iter->iter_idx);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen iter->prefix = p_strconcat(iter->pool, DICT_PATH_SHARED
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen iter->dict_iter = dict_iterate_init(iter->dict->dict, iter->prefix,
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenacl_lookup_dict_iterate_visible_init(struct acl_lookup_dict *dict)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_user *auser = ACL_USER_CONTEXT(dict->user);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char *id;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen unsigned int i;
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 id = p_strconcat(pool, "user/", dict->user->username, NULL);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* get all groups we belong to */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen id = p_strconcat(pool, "group/", auser->groups[i],
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* iterate through all identifiers that match us, start with the
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainenacl_lookup_dict_iterate_visible_next(struct acl_lookup_dict_iter *iter)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ret = dict_iterate(iter->dict_iter, &key, &value);
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (iter->iter_idx < array_count(&iter->iter_ids)) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* get to the next iterator */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen return acl_lookup_dict_iterate_visible_next(iter);