imap-acl-plugin.c revision eacce2276278ce6a8176a9a100807dba50bbfb36
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2008-2011 Dovecot authors, see the included COPYING file */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "imap-common.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "str.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "imap-quote.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "imap-resp-code.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "imap-commands.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "mail-storage.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "mail-namespace.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "acl-api.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "acl-storage.h"
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen#include "acl-plugin.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "imap-acl-plugin.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include <stdlib.h>
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#define ERROR_NOT_ADMIN "["IMAP_RESP_CODE_NOPERM"] " \
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "You lack administrator privileges on this mailbox."
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#define IMAP_ACL_ANYONE "anyone"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#define IMAP_ACL_AUTHENTICATED "authenticated"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#define IMAP_ACL_OWNER "owner"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#define IMAP_ACL_GROUP_PREFIX "$"
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen#define IMAP_ACL_GROUP_OVERRIDE_PREFIX "!$"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#define IMAP_ACL_GLOBAL_PREFIX "#"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainenstruct imap_acl_letter_map {
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainen char letter;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const char *name;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen};
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic const struct imap_acl_letter_map imap_acl_letter_map[] = {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen { 'l', MAIL_ACL_LOOKUP },
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainen { 'r', MAIL_ACL_READ },
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen { 'w', MAIL_ACL_WRITE },
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen { 's', MAIL_ACL_WRITE_SEEN },
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen { 't', MAIL_ACL_WRITE_DELETED },
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen { 'i', MAIL_ACL_INSERT },
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen { 'p', MAIL_ACL_POST },
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen { 'e', MAIL_ACL_EXPUNGE },
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen { 'k', MAIL_ACL_CREATE },
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen { 'x', MAIL_ACL_DELETE },
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen { 'a', MAIL_ACL_ADMIN },
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen { '\0', NULL }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen};
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenconst char *imap_acl_plugin_version = DOVECOT_VERSION;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic struct module *imap_acl_module;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic void (*next_hook_client_created)(struct client **client);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic struct mailbox *
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenacl_mailbox_open_as_admin(struct client_command_context *cmd, const char *name)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_namespace *ns;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mailbox *box;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen enum mailbox_existence existence = MAILBOX_EXISTENCE_NONE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen int ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ACL_USER_CONTEXT(cmd->client->user) == NULL) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client_send_command_error(cmd, "ACLs disabled.");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return NULL;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ns = client_find_namespace(cmd, &name);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ns == NULL)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return NULL;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* Force opening the mailbox so that we can give a nicer error message
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if mailbox isn't selectable but is listable. */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen box = mailbox_alloc(ns->list, name, MAILBOX_FLAG_READONLY |
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen MAILBOX_FLAG_IGNORE_ACLS);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (mailbox_exists(box, TRUE, &existence) == 0 &&
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen existence == MAILBOX_EXISTENCE_SELECT) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_ADMIN);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ret > 0)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return box;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* mailbox doesn't exist / not an administrator. */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (existence != MAILBOX_EXISTENCE_SELECT ||
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_LOOKUP) <= 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_tagline(cmd, t_strdup_printf(
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "NO ["IMAP_RESP_CODE_NONEXISTENT"] "
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen MAIL_ERRSTR_MAILBOX_NOT_FOUND, name));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen } else {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_tagline(cmd, "NO "ERROR_NOT_ADMIN);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mailbox_free(&box);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return NULL;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic const struct imap_acl_letter_map *
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenimap_acl_letter_map_find(const char *name)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen unsigned int i;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen for (i = 0; imap_acl_letter_map[i].name != NULL; i++) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (strcmp(imap_acl_letter_map[i].name, name) == 0)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return &imap_acl_letter_map[i];
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return NULL;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic void
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenimap_acl_write_rights_list(string_t *dest, const char *const *rights)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const struct imap_acl_letter_map *map;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen unsigned int i, orig_len = str_len(dest);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen bool append_c = FALSE, append_d = FALSE;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen for (i = 0; rights[i] != NULL; i++) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* write only letters */
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen map = imap_acl_letter_map_find(rights[i]);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (map != NULL) {
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen str_append_c(dest, map->letter);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (map->letter == 'k' || map->letter == 'x')
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen append_c = TRUE;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (map->letter == 't' || map->letter == 'e')
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen append_d = TRUE;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen }
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen }
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (append_c)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen str_append_c(dest, 'c');
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (append_d)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen str_append_c(dest, 'd');
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (orig_len == str_len(dest))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append(dest, "\"\"");
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen}
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainenstatic void
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainenimap_acl_write_right(string_t *dest, string_t *tmp,
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen const struct acl_rights *right, bool neg)
0bf3eac1110a902e7ec7e695c64e8e46c114e623Timo Sirainen{
0bf3eac1110a902e7ec7e695c64e8e46c114e623Timo Sirainen const char *const *rights = neg ? right->neg_rights : right->rights;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen str_truncate(tmp, 0);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (neg) str_append_c(tmp,'-');
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (right->global)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen str_append(tmp, IMAP_ACL_GLOBAL_PREFIX);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen switch (right->id_type) {
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen case ACL_ID_ANYONE:
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen str_append(tmp, IMAP_ACL_ANYONE);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen break;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen case ACL_ID_AUTHENTICATED:
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen str_append(tmp, IMAP_ACL_AUTHENTICATED);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen break;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen case ACL_ID_OWNER:
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append(tmp, IMAP_ACL_OWNER);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen break;
88b8aea03a24ef7a9efc30399080487b7eb03537Timo Sirainen case ACL_ID_USER:
dffa503fd4ce31334346e539496084c80a2d8d37Timo Sirainen str_append(tmp, right->identifier);
dffa503fd4ce31334346e539496084c80a2d8d37Timo Sirainen break;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen case ACL_ID_GROUP:
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen str_append(tmp, IMAP_ACL_GROUP_PREFIX);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen str_append(tmp, right->identifier);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen break;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen case ACL_ID_GROUP_OVERRIDE:
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen str_append(tmp, IMAP_ACL_GROUP_OVERRIDE_PREFIX);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen str_append(tmp, right->identifier);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen break;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen case ACL_ID_TYPE_COUNT:
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen i_unreached();
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen imap_quote_append(dest, str_data(tmp), str_len(tmp), FALSE);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append_c(dest, ' ');
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen imap_acl_write_rights_list(dest, rights);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic bool
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenacl_rights_is_owner(struct acl_backend *backend,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const struct acl_rights *rights)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen switch (rights->id_type) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen case ACL_ID_OWNER:
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen case ACL_ID_USER:
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return acl_backend_user_name_equals(backend,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights->identifier);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen default:
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return FALSE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic bool have_positive_owner_rights(struct acl_backend *backend,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct acl_object *aclobj)
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen{
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen struct acl_object_list_iter *iter;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen struct acl_rights rights;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen bool ret = FALSE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen iter = acl_object_list_init(aclobj);
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen while ((ret = acl_object_list_next(iter, &rights)) > 0) {
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen if (acl_rights_is_owner(backend, &rights)) {
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen if (rights.rights != NULL) {
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen ret = TRUE;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen break;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen }
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen }
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen }
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen acl_object_list_deinit(&iter);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return ret;
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen}
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainenstatic int
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainenimap_acl_write_aclobj(string_t *dest, struct acl_backend *backend,
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen struct acl_object *aclobj, bool convert_owner,
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen bool add_default)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct acl_object_list_iter *iter;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct acl_rights rights;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen string_t *tmp;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen const char *username;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen unsigned int orig_len = str_len(dest);
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen bool seen_owner = FALSE, seen_positive_owner = FALSE;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen int ret;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen username = acl_backend_get_acl_username(backend);
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen if (username == NULL)
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen convert_owner = FALSE;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen tmp = t_str_new(128);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen iter = acl_object_list_init(aclobj);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen while ((ret = acl_object_list_next(iter, &rights)) > 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (acl_rights_is_owner(backend, &rights)) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (rights.id_type == ACL_ID_OWNER && convert_owner) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights.id_type = ACL_ID_USER;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights.identifier = username;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (seen_owner && convert_owner) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* oops, we have both owner and user=myself.
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen can't do the conversion, so try again. */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_truncate(dest, orig_len);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return imap_acl_write_aclobj(dest, backend,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen aclobj, FALSE,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen add_default);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen seen_owner = TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (rights.rights != NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen seen_positive_owner = TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (rights.rights != NULL) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append_c(dest, ' ');
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen imap_acl_write_right(dest, tmp, &rights, FALSE);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (rights.neg_rights != NULL) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append_c(dest, ' ');
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen imap_acl_write_right(dest, tmp, &rights, TRUE);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen acl_object_list_deinit(&iter);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (!seen_positive_owner && username != NULL && add_default) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* no positive owner rights returned, write default ACLs */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen memset(&rights, 0, sizeof(rights));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (!convert_owner) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights.id_type = ACL_ID_OWNER;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen } else {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights.id_type = ACL_ID_USER;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights.identifier = username;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights.rights = acl_object_get_default_rights(aclobj);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (rights.rights != NULL) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append_c(dest, ' ');
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen imap_acl_write_right(dest, tmp, &rights, FALSE);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
5707510e5d1c8aa79a0acf737ee1429caf3d59c2Timo Sirainen return ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic bool cmd_getacl(struct client_command_context *cmd)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct acl_backend *backend;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_namespace *ns;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mailbox *box;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const char *mailbox;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen string_t *str;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen int ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return FALSE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen box = acl_mailbox_open_as_admin(cmd, mailbox);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (box == NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str = t_str_new(128);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append(str, "* ACL ");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen imap_quote_append_string(str, mailbox, FALSE);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ns = mailbox_get_namespace(box);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen backend = acl_mailbox_list_get_backend(ns->list);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ret = imap_acl_write_aclobj(str, backend,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen acl_mailbox_get_aclobj(box), TRUE,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ns->type == NAMESPACE_PRIVATE);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ret == 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_line(cmd->client, str_c(str));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_tagline(cmd, "OK Getacl completed.");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen } else {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mailbox_free(&box);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic bool cmd_myrights(struct client_command_context *cmd)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_namespace *ns;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mailbox *box;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const char *mailbox;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const char *const *rights;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen string_t *str;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return FALSE;
cc833a7a4e2258afdc834ace4bfe6579820a1df3Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ACL_USER_CONTEXT(cmd->client->user) == NULL) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_command_error(cmd, "ACLs disabled.");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ns = client_find_namespace(cmd, &mailbox);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ns == NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen box = mailbox_alloc(ns->list, mailbox,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen MAILBOX_FLAG_READONLY | MAILBOX_FLAG_IGNORE_ACLS);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (acl_object_get_my_rights(acl_mailbox_get_aclobj(box),
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen pool_datastack_create(), &rights) < 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mailbox_free(&box);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* Post right alone doesn't give permissions to see if the mailbox
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen exists or not. Only mail deliveries care about that. */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (*rights == NULL ||
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen (strcmp(*rights, MAIL_ACL_POST) == 0 && rights[1] == NULL)) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_tagline(cmd, t_strdup_printf(
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "NO ["IMAP_RESP_CODE_NONEXISTENT"] "
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen MAIL_ERRSTR_MAILBOX_NOT_FOUND, mailbox));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mailbox_free(&box);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str = t_str_new(128);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append(str, "* MYRIGHTS ");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen imap_quote_append_string(str, mailbox, FALSE);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append_c(str,' ');
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen imap_acl_write_rights_list(str, rights);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_line(cmd->client, str_c(str));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_tagline(cmd, "OK Myrights completed.");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mailbox_free(&box);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen return TRUE;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen}
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainenstatic bool cmd_listrights(struct client_command_context *cmd)
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen{
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen struct mailbox *box;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen const char *mailbox, *identifier;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen string_t *str;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen if (!client_read_string_args(cmd, 2, &mailbox, &identifier))
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen return FALSE;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen box = acl_mailbox_open_as_admin(cmd, mailbox);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen if (box == NULL)
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen return TRUE;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen str = t_str_new(128);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen str_append(str, "* LISTRIGHTS ");
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen imap_quote_append_string(str, mailbox, FALSE);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen str_append_c(str, ' ');
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen imap_quote_append_string(str, identifier, FALSE);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append_c(str, ' ');
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append(str, "\"\" l r w s t p i e k x a c d");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_line(cmd->client, str_c(str));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_tagline(cmd, "OK Listrights completed.");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mailbox_free(&box);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainenstatic int
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainenimap_acl_letters_parse(const char *letters, const char *const **rights_r,
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen const char **error_r)
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen static const char *acl_k = MAIL_ACL_CREATE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen static const char *acl_x = MAIL_ACL_DELETE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen static const char *acl_e = MAIL_ACL_EXPUNGE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen static const char *acl_t = MAIL_ACL_WRITE_DELETED;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen ARRAY_TYPE(const_string) rights;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen unsigned int i;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen t_array_init(&rights, 64);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen for (; *letters != '\0'; letters++) {
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen for (i = 0; imap_acl_letter_map[i].name != NULL; i++) {
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen if (imap_acl_letter_map[i].letter == *letters) {
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen array_append(&rights,
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen &imap_acl_letter_map[i].name, 1);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen break;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (imap_acl_letter_map[i].name == NULL) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* Handling of obsolete rights as virtual
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen rights according to RFC 4314 */
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen switch (*letters) {
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen case 'c':
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen array_append(&rights, &acl_k, 1);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen array_append(&rights, &acl_x, 1);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen break;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen case 'd':
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen array_append(&rights, &acl_e, 1);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen array_append(&rights, &acl_t, 1);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen break;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen default:
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen *error_r = t_strdup_printf(
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen "Invalid ACL right: %c", *letters);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen return -1;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen (void)array_append_space(&rights);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *rights_r = array_idx(&rights, 0);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return 0;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic bool acl_anyone_allow(struct mail_user *user)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const char *env;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen env = mail_user_plugin_getenv(user, "acl_anyone");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return env != NULL && strcmp(env, "allow") == 0;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainenstatic int
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenimap_acl_identifier_parse(struct client_command_context *cmd,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const char *id, struct acl_rights *rights,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen bool check_anyone, const char **error_r)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_user *user = cmd->client->user;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainen if (strncmp(id, IMAP_ACL_GLOBAL_PREFIX,
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainen strlen(IMAP_ACL_GLOBAL_PREFIX)) == 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *error_r = t_strdup_printf("Global ACLs can't be modified: %s",
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen id);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen }
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (strcmp(id, IMAP_ACL_ANYONE) == 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (check_anyone && !acl_anyone_allow(user)) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *error_r = "'anyone' identifier is disallowed";
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights->id_type = ACL_ID_ANYONE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen } else if (strcmp(id, IMAP_ACL_AUTHENTICATED) == 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (check_anyone && !acl_anyone_allow(user)) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *error_r = "'authenticated' identifier is disallowed";
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen rights->id_type = ACL_ID_AUTHENTICATED;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen } else if (strcmp(id, IMAP_ACL_OWNER) == 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen rights->id_type = ACL_ID_OWNER;
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainen else if (strncmp(id, IMAP_ACL_GROUP_PREFIX,
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainen strlen(IMAP_ACL_GROUP_PREFIX)) == 0) {
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainen rights->id_type = ACL_ID_GROUP;
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainen rights->identifier = id + strlen(IMAP_ACL_GROUP_PREFIX);
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainen } else if (strncmp(id, IMAP_ACL_GROUP_OVERRIDE_PREFIX,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen strlen(IMAP_ACL_GROUP_OVERRIDE_PREFIX)) == 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights->id_type = ACL_ID_GROUP_OVERRIDE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights->identifier = id +
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen strlen(IMAP_ACL_GROUP_OVERRIDE_PREFIX);
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen } else {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights->id_type = ACL_ID_USER;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen rights->identifier = id;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic void imap_acl_update_ensure_keep_admins(struct acl_backend *backend,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct acl_object *aclobj,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct acl_rights_update *update)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen static const char *acl_admin = MAIL_ACL_ADMIN;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *const *rights = update->rights.rights;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *const *default_rights;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ARRAY_TYPE(const_string) new_rights;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen unsigned int i;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen t_array_init(&new_rights, 64);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen for (i = 0; rights[i] != NULL; i++) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (strcmp(rights[i], MAIL_ACL_ADMIN) == 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen break;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen array_append(&new_rights, &rights[i], 1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen switch (update->modify_mode) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen case ACL_MODIFY_MODE_ADD:
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (have_positive_owner_rights(backend, aclobj))
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* adding initial rights for a user. we need to add
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen the defaults also. don't worry about duplicates. */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen for (; rights[i] != NULL; i++)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen array_append(&new_rights, &rights[i], 1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen default_rights = acl_object_get_default_rights(aclobj);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen for (i = 0; default_rights[i] != NULL; i++)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen array_append(&new_rights, &default_rights[i], 1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen break;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen case ACL_MODIFY_MODE_REMOVE:
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (rights[i] == NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* skip over the ADMIN removal and add the rest */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen for (i++; rights[i] != NULL; i++)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen array_append(&new_rights, &rights[i], 1);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen break;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen case ACL_MODIFY_MODE_REPLACE:
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (rights[i] != NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen /* add the missing ADMIN right */
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen array_append(&new_rights, &acl_admin, 1);
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen break;
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen default:
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen return;
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen }
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen (void)array_append_space(&new_rights);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen update->rights.rights = array_idx(&new_rights, 0);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic bool cmd_setacl(struct client_command_context *cmd)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct mail_namespace *ns;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct mailbox *box;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct acl_backend *backend;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen struct acl_object *aclobj;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct acl_rights_update update;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct acl_rights *r;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *mailbox, *identifier, *rights, *error;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen bool negative = FALSE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!client_read_string_args(cmd, 3, &mailbox, &identifier, &rights))
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return FALSE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (*identifier == '\0') {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client_send_command_error(cmd, "Invalid arguments.");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return TRUE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen memset(&update, 0, sizeof(update));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (*identifier == '-') {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen negative = TRUE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen identifier++;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen switch (*rights) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen case '-':
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen update.modify_mode = ACL_MODIFY_MODE_REMOVE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen rights++;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen break;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen case '+':
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen update.modify_mode = ACL_MODIFY_MODE_ADD;
347acd14d8da653ce3757b3e29981326502bed6bTimo Sirainen rights++;
347acd14d8da653ce3757b3e29981326502bed6bTimo Sirainen break;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen default:
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen update.modify_mode = ACL_MODIFY_MODE_REPLACE;
8cd0a1a2200e65cd134d03fe3f93ec02f1746359Timo Sirainen break;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (imap_acl_identifier_parse(cmd, identifier, &update.rights,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen TRUE, &error) < 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client_send_command_error(cmd, error);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return TRUE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (imap_acl_letters_parse(rights, &update.rights.rights, &error) < 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_command_error(cmd, error);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen r = &update.rights;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen box = acl_mailbox_open_as_admin(cmd, mailbox);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (box == NULL)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return TRUE;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen ns = mailbox_get_namespace(box);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen backend = acl_mailbox_list_get_backend(ns->list);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (ns->type == NAMESPACE_PUBLIC && r->id_type == ACL_ID_OWNER) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client_send_tagline(cmd, "NO Public namespaces have no owner");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mailbox_free(&box);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen aclobj = acl_mailbox_get_aclobj(box);
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen if (negative) {
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen update.neg_modify_mode = update.modify_mode;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen update.modify_mode = ACL_MODIFY_MODE_REMOVE;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen update.rights.neg_rights = update.rights.rights;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen update.rights.rights = NULL;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen } else if (ns->type == NAMESPACE_PRIVATE && r->rights != NULL &&
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen ((r->id_type == ACL_ID_USER &&
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen acl_backend_user_name_equals(backend, r->identifier)) ||
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen (r->id_type == ACL_ID_OWNER &&
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen strcmp(acl_backend_get_acl_username(backend),
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ns->user->username) == 0))) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* make sure client doesn't (accidentally) remove admin
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen privileges from its own mailboxes */
629600d9a85e8025c15a5eaeb80329e116e022c9Timo Sirainen imap_acl_update_ensure_keep_admins(backend, aclobj, &update);
629600d9a85e8025c15a5eaeb80329e116e022c9Timo Sirainen }
629600d9a85e8025c15a5eaeb80329e116e022c9Timo Sirainen
629600d9a85e8025c15a5eaeb80329e116e022c9Timo Sirainen if (acl_object_update(aclobj, &update) < 0)
629600d9a85e8025c15a5eaeb80329e116e022c9Timo Sirainen client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
629600d9a85e8025c15a5eaeb80329e116e022c9Timo Sirainen else
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client_send_tagline(cmd, "OK Setacl complete.");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mailbox_free(&box);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return TRUE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic bool cmd_deleteacl(struct client_command_context *cmd)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mailbox *box;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct acl_rights_update update;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const char *mailbox, *identifier, *error;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (!client_read_string_args(cmd, 2, &mailbox, &identifier))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return FALSE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (*identifier == '\0') {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_command_error(cmd, "Invalid arguments.");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
9716b2665ee3938d3dfe64bda44d7c3ae3b55d30Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen memset(&update, 0, sizeof(update));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (*identifier != '-')
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen update.modify_mode = ACL_MODIFY_MODE_CLEAR;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen else {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen update.neg_modify_mode = ACL_MODIFY_MODE_CLEAR;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen identifier++;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (imap_acl_identifier_parse(cmd, identifier, &update.rights,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen FALSE, &error) < 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_command_error(cmd, error);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen box = acl_mailbox_open_as_admin(cmd, mailbox);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (box == NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (acl_object_update(acl_mailbox_get_aclobj(box), &update) < 0)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen else
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen client_send_tagline(cmd, "OK Deleteacl complete.");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mailbox_free(&box);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic void imap_acl_client_created(struct client **client)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (mail_user_is_plugin_loaded((*client)->user, imap_acl_module))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen str_append((*client)->capability_string, " ACL RIGHTS=texk");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (next_hook_client_created != NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen next_hook_client_created(client);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid imap_acl_plugin_init(struct module *module)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen command_register("LISTRIGHTS", cmd_listrights, 0);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen command_register("GETACL", cmd_getacl, 0);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen command_register("MYRIGHTS", cmd_myrights, 0);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen command_register("SETACL", cmd_setacl, 0);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen command_register("DELETEACL", cmd_deleteacl, 0);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen imap_acl_module = module;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen next_hook_client_created =
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen imap_client_created_hook_set(imap_acl_client_created);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid imap_acl_plugin_deinit(void)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen command_unregister("GETACL");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen command_unregister("MYRIGHTS");
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen command_unregister("SETACL");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen command_unregister("DELETEACL");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen command_unregister("LISTRIGHTS");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen imap_client_created_hook_set(next_hook_client_created);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenconst char *imap_acl_plugin_dependencies[] = { "acl", NULL };
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenconst char imap_acl_plugin_binary_dependency[] = "imap";
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen