imap-acl-plugin.c revision 23fdad6c7e2581921f511e24cd9371c9eaebcef9
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "imap-common.h"
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen#include "str.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "imap-quote.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "imap-resp-code.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "imap-commands.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "mail-storage.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "mail-namespace.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "acl-api.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "acl-storage.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "acl-plugin.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "imap-acl-plugin.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen#include <stdlib.h>
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen#define ERROR_NOT_ADMIN "["IMAP_RESP_CODE_NOPERM"] " \
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "You lack administrator privileges on this mailbox."
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#define ACL_MAILBOX_FLAGS \
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#define IMAP_ACL_ANYONE "anyone"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#define IMAP_ACL_AUTHENTICATED "authenticated"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#define IMAP_ACL_OWNER "owner"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#define IMAP_ACL_GROUP_PREFIX "$"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#define IMAP_ACL_GROUP_OVERRIDE_PREFIX "!$"
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen#define IMAP_ACL_GLOBAL_PREFIX "#"
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainenstruct imap_acl_letter_map {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen char letter;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *name;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen};
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic const struct imap_acl_letter_map imap_acl_letter_map[] = {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'l', MAIL_ACL_LOOKUP },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'r', MAIL_ACL_READ },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'w', MAIL_ACL_WRITE },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 's', MAIL_ACL_WRITE_SEEN },
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen { 't', MAIL_ACL_WRITE_DELETED },
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen { 'i', MAIL_ACL_INSERT },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'p', MAIL_ACL_POST },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'e', MAIL_ACL_EXPUNGE },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'k', MAIL_ACL_CREATE },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'x', MAIL_ACL_DELETE },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { 'a', MAIL_ACL_ADMIN },
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen { '\0', NULL }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen};
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenconst char *imap_acl_plugin_version = PACKAGE_VERSION;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainenstatic void (*next_hook_client_created)(struct client **client);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic struct mailbox *
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenacl_mailbox_open_as_admin(struct client_command_context *cmd, const char *name)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_namespace *ns;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen struct mailbox *box;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen int ret;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen if (ACL_USER_CONTEXT(cmd->client->user) == NULL) {
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen client_send_command_error(cmd, "ACLs disabled.");
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen return NULL;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen }
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen ns = client_find_namespace(cmd, &name, CLIENT_VERIFY_MAILBOX_NONE);
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen if (ns == NULL)
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen return NULL;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* Force opening the mailbox so that we can give a nicer error message
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if mailbox isn't selectable but is listable. */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen box = mailbox_alloc(ns->list, name, NULL, ACL_MAILBOX_FLAGS |
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen MAILBOX_FLAG_IGNORE_ACLS);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_ADMIN);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (ret > 0)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen return box;
4376643cd2c7110e752c09f838f2c4eee6ed8ac6Timo Sirainen
4376643cd2c7110e752c09f838f2c4eee6ed8ac6Timo Sirainen /* not an administrator. */
4376643cd2c7110e752c09f838f2c4eee6ed8ac6Timo Sirainen if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_LOOKUP) <= 0) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen client_send_tagline(cmd, t_strdup_printf(
99aec80ae156689abd5a568c647884d0c72f143cTimo Sirainen "NO ["IMAP_RESP_CODE_NONEXISTENT"] "
99aec80ae156689abd5a568c647884d0c72f143cTimo Sirainen MAIL_ERRSTR_MAILBOX_NOT_FOUND, name));
99aec80ae156689abd5a568c647884d0c72f143cTimo Sirainen } else {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen client_send_tagline(cmd, "NO "ERROR_NOT_ADMIN);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen mailbox_close(&box);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen return NULL;
4376643cd2c7110e752c09f838f2c4eee6ed8ac6Timo Sirainen}
4376643cd2c7110e752c09f838f2c4eee6ed8ac6Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic const struct imap_acl_letter_map *
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenimap_acl_letter_map_find(const char *name)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen unsigned int i;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (i = 0; imap_acl_letter_map[i].name != NULL; i++) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (strcmp(imap_acl_letter_map[i].name, name) == 0)
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen return &imap_acl_letter_map[i];
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen }
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen return NULL;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen}
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenimap_acl_write_rights_list(string_t *dest, const char *const *rights)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen{
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen const struct imap_acl_letter_map *map;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen unsigned int i, orig_len = str_len(dest);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen bool append_c = FALSE, append_d = FALSE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen for (i = 0; rights[i] != NULL; i++) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* write only letters */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen map = imap_acl_letter_map_find(rights[i]);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (map != NULL) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str_append_c(dest, map->letter);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (map->letter == 'k' || map->letter == 'x')
ce89e2964b6bc4925d2dd690417200a110d041c5Timo Sirainen append_c = TRUE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (map->letter == 't' || map->letter == 'e')
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen append_d = TRUE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (append_c)
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen str_append_c(dest, 'c');
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (append_d)
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen str_append_c(dest, 'd');
5d4855d7b4dcffb6975ed8e3c9c376dac74e5c8aTimo Sirainen if (orig_len == str_len(dest))
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str_append(dest, "\"\"");
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainenstatic void
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenimap_acl_write_right(string_t *dest, string_t *tmp,
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen const struct acl_rights *right, bool neg)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *const *rights = neg ? right->neg_rights : right->rights;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_truncate(tmp, 0);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (neg) str_append_c(tmp,'-');
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (right->global)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_append(tmp, IMAP_ACL_GLOBAL_PREFIX);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen switch (right->id_type) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen case ACL_ID_ANYONE:
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen str_append(tmp, IMAP_ACL_ANYONE);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen break;
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen case ACL_ID_AUTHENTICATED:
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen str_append(tmp, IMAP_ACL_AUTHENTICATED);
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen break;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen case ACL_ID_OWNER:
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen str_append(tmp, IMAP_ACL_OWNER);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen break;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen case ACL_ID_USER:
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen str_append(tmp, right->identifier);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen case ACL_ID_GROUP:
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_append(tmp, IMAP_ACL_GROUP_PREFIX);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_append(tmp, right->identifier);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen case ACL_ID_GROUP_OVERRIDE:
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_append(tmp, IMAP_ACL_GROUP_OVERRIDE_PREFIX);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_append(tmp, right->identifier);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen case ACL_ID_TYPE_COUNT:
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen i_unreached();
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen imap_quote_append(dest, str_data(tmp), str_len(tmp), FALSE);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen str_append_c(dest, ' ');
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen imap_acl_write_rights_list(dest, rights);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen}
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainenstatic int
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainenimap_acl_write_aclobj(string_t *dest, struct acl_backend *backend,
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen struct acl_object *aclobj, bool convert_owner,
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen bool add_default)
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen{
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen struct acl_object_list_iter *iter;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen struct acl_rights rights;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen string_t *tmp;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen const char *username;
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen unsigned int orig_len = str_len(dest);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen bool owner, seen_owner = FALSE, seen_positive_owner = FALSE;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen int ret;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen username = acl_backend_get_acl_username(backend);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (username == NULL)
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen convert_owner = FALSE;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen tmp = t_str_new(128);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen iter = acl_object_list_init(aclobj);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen while ((ret = acl_object_list_next(iter, &rights)) > 0) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (rights.id_type == ACL_ID_USER &&
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen acl_backend_user_name_equals(backend, rights.identifier))
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen owner = TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen else if (rights.id_type == ACL_ID_OWNER) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen owner = TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (convert_owner) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen rights.id_type = ACL_ID_USER;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights.identifier = username;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen } else {
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen owner = FALSE;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (owner) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (seen_owner && convert_owner) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* oops, we have both owner and user=myself.
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen can't do the conversion, so try again. */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str_truncate(dest, orig_len);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen return imap_acl_write_aclobj(dest, backend,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen aclobj, FALSE,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen add_default);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen seen_owner = TRUE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (rights.rights != NULL)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen seen_positive_owner = TRUE;
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (rights.rights != NULL) {
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen str_append_c(dest, ' ');
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen imap_acl_write_right(dest, tmp, &rights, FALSE);
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (rights.neg_rights != NULL) {
4376643cd2c7110e752c09f838f2c4eee6ed8ac6Timo Sirainen str_append_c(dest, ' ');
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen imap_acl_write_right(dest, tmp, &rights, TRUE);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen acl_object_list_deinit(&iter);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (!seen_positive_owner && username != NULL && add_default) {
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen /* no positive owner rights returned, write default ACLs */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen memset(&rights, 0, sizeof(rights));
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen if (!convert_owner) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen rights.id_type = ACL_ID_OWNER;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen } else {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights.id_type = ACL_ID_USER;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights.identifier = username;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights.rights = acl_object_get_default_rights(aclobj);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (rights.rights != NULL) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_append_c(dest, ' ');
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen imap_acl_write_right(dest, tmp, &rights, FALSE);
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen }
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return ret;
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen}
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenstatic bool cmd_getacl(struct client_command_context *cmd)
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen{
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen struct acl_backend *backend;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen struct mail_namespace *ns;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen struct mailbox *box;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *mailbox;
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen string_t *str;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen int ret;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return FALSE;
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen box = acl_mailbox_open_as_admin(cmd, mailbox);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen if (box == NULL)
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen return TRUE;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen str = t_str_new(128);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen str_append(str, "* ACL ");
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen imap_quote_append_string(str, mailbox, FALSE);
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen ns = mailbox_get_namespace(box);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen backend = acl_mailbox_list_get_backend(ns->list);
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen ret = imap_acl_write_aclobj(str, backend,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen acl_mailbox_get_aclobj(box), TRUE,
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen ns->type == NAMESPACE_PRIVATE);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (ret == 0) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen client_send_line(cmd->client, str_c(str));
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen client_send_tagline(cmd, "OK Getacl completed.");
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen } else {
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen }
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen mailbox_close(&box);
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen return TRUE;
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen}
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainenstatic bool cmd_myrights(struct client_command_context *cmd)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_namespace *ns;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct mailbox *box;
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen const char *mailbox, *real_mailbox;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen const char *const *rights;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen string_t *str;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return FALSE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen if (ACL_USER_CONTEXT(cmd->client->user) == NULL) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_send_command_error(cmd, "ACLs disabled.");
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return TRUE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen real_mailbox = mailbox;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ns = client_find_namespace(cmd, &real_mailbox,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen CLIENT_VERIFY_MAILBOX_NONE);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (ns == NULL)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return TRUE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen box = mailbox_alloc(ns->list, real_mailbox, NULL,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ACL_MAILBOX_FLAGS | MAILBOX_FLAG_IGNORE_ACLS);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (acl_object_get_my_rights(acl_mailbox_get_aclobj(box),
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen pool_datastack_create(), &rights) < 0) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mailbox_close(&box);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return TRUE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* Post right alone doesn't give permissions to see if the mailbox
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen exists or not. Only mail deliveries care about that. */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (*rights == NULL ||
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen (strcmp(*rights, MAIL_ACL_POST) == 0 && rights[1] == NULL)) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_send_tagline(cmd, t_strdup_printf(
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen "NO ["IMAP_RESP_CODE_NONEXISTENT"] "
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen MAIL_ERRSTR_MAILBOX_NOT_FOUND, real_mailbox));
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mailbox_close(&box);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return TRUE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen str = t_str_new(128);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen str_append(str, "* MYRIGHTS ");
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen imap_quote_append_string(str, mailbox, FALSE);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen str_append_c(str,' ');
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen imap_acl_write_rights_list(str, rights);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_send_line(cmd->client, str_c(str));
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_send_tagline(cmd, "OK Myrights completed.");
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mailbox_close(&box);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return TRUE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenstatic bool cmd_listrights(struct client_command_context *cmd)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen{
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct mailbox *box;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen const char *mailbox, *identifier;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen string_t *str;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (!client_read_string_args(cmd, 2, &mailbox, &identifier))
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return FALSE;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen box = acl_mailbox_open_as_admin(cmd, mailbox);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (box == NULL)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return TRUE;
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str = t_str_new(128);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_append(str, "* LISTRIGHTS ");
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen imap_quote_append_string(str, mailbox, FALSE);
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen str_append_c(str, ' ');
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen imap_quote_append_string(str, identifier, FALSE);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen str_append_c(str, ' ');
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_append(str, "\"\" l r w s t p i e k x a c d");
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen client_send_line(cmd->client, str_c(str));
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen client_send_tagline(cmd, "OK Listrights completed.");
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen mailbox_close(&box);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen return TRUE;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen}
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainenstatic int
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainenimap_acl_letters_parse(const char *letters, const char *const **rights_r,
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen const char **error_r)
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen{
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen static const char *acl_k = MAIL_ACL_CREATE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen static const char *acl_x = MAIL_ACL_DELETE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen static const char *acl_e = MAIL_ACL_EXPUNGE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen static const char *acl_t = MAIL_ACL_WRITE_DELETED;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen ARRAY_TYPE(const_string) rights;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen unsigned int i;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen t_array_init(&rights, 64);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (; *letters != '\0'; letters++) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (i = 0; imap_acl_letter_map[i].name != NULL; i++) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (imap_acl_letter_map[i].letter == *letters) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen array_append(&rights,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen &imap_acl_letter_map[i].name, 1);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (imap_acl_letter_map[i].name == NULL) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen /* Handling of obsolete rights as virtual
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen rights according to RFC 4314 */
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen switch (*letters) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen case 'c':
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen array_append(&rights, &acl_k, 1);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen array_append(&rights, &acl_x, 1);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen break;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen case 'd':
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen array_append(&rights, &acl_e, 1);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen array_append(&rights, &acl_t, 1);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen break;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen default:
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen *error_r = t_strdup_printf(
bd354c19cb93c07ade79477674328a54146ea332Timo Sirainen "Invalid ACL right: %c", *letters);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return -1;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen (void)array_append_space(&rights);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen *rights_r = array_idx(&rights, 0);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return 0;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen}
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenstatic bool acl_anyone_allow(struct mail_user *user)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *env;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen env = mail_user_plugin_getenv(user, "acl_anyone");
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return env != NULL && strcmp(env, "allow") == 0;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic int
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenimap_acl_identifier_parse(struct client_command_context *cmd,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *id, struct acl_rights *rights,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen bool check_anyone, const char **error_r)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_user *user = cmd->client->user;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (strncmp(id, IMAP_ACL_GLOBAL_PREFIX,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen strlen(IMAP_ACL_GLOBAL_PREFIX)) == 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *error_r = t_strdup_printf("Global ACLs can't be modified: %s",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen id);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (strcmp(id, IMAP_ACL_ANYONE) == 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (check_anyone && !acl_anyone_allow(user)) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *error_r = "'anyone' identifier is disallowed";
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights->id_type = ACL_ID_ANYONE;
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen } else if (strcmp(id, IMAP_ACL_AUTHENTICATED) == 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (check_anyone && !acl_anyone_allow(user)) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *error_r = "'authenticated' identifier is disallowed";
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights->id_type = ACL_ID_AUTHENTICATED;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen } else if (strcmp(id, IMAP_ACL_OWNER) == 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights->id_type = ACL_ID_OWNER;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen else if (strncmp(id, IMAP_ACL_GROUP_PREFIX,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen strlen(IMAP_ACL_GROUP_PREFIX)) == 0) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen rights->id_type = ACL_ID_GROUP;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights->identifier = id + strlen(IMAP_ACL_GROUP_PREFIX);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen } else if (strncmp(id, IMAP_ACL_GROUP_OVERRIDE_PREFIX,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen strlen(IMAP_ACL_GROUP_OVERRIDE_PREFIX)) == 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights->id_type = ACL_ID_GROUP_OVERRIDE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights->identifier = id +
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen strlen(IMAP_ACL_GROUP_OVERRIDE_PREFIX);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen } else {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights->id_type = ACL_ID_USER;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights->identifier = id;
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen }
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen return 0;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainenstatic void imap_acl_update_ensure_keep_admins(struct acl_rights_update *update)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen static const char *acl_admin = MAIL_ACL_ADMIN;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *const *rights = update->rights.rights;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ARRAY_TYPE(const_string) new_rights;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen unsigned int i;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen t_array_init(&new_rights, 64);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (i = 0; rights[i] != NULL; i++) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (strcmp(rights[i], MAIL_ACL_ADMIN) == 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen array_append(&new_rights, &rights[i], 1);
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen switch (update->modify_mode) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen case ACL_MODIFY_MODE_REMOVE:
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (rights[i] == NULL)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* skip over the ADMIN removal and add the rest */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (i++; rights[i] != NULL; i++)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen array_append(&new_rights, &rights[i], 1);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen case ACL_MODIFY_MODE_REPLACE:
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (rights[i] != NULL)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* add the missing ADMIN right */
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen array_append(&new_rights, &acl_admin, 1);
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen break;
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen default:
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return;
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen }
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen (void)array_append_space(&new_rights);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen update->rights.rights = array_idx(&new_rights, 0);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic bool cmd_setacl(struct client_command_context *cmd)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_namespace *ns;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mailbox *box;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct acl_backend *backend;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct acl_rights_update update;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct acl_rights *r;
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen const char *mailbox, *identifier, *rights, *error;
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen bool negative = FALSE;
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (!client_read_string_args(cmd, 3, &mailbox, &identifier, &rights))
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return FALSE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen if (*identifier == '\0') {
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen client_send_command_error(cmd, "Invalid arguments.");
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen return TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen memset(&update, 0, sizeof(update));
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (*identifier == '-') {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen negative = TRUE;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen identifier++;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen switch (*rights) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen case '-':
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen update.modify_mode = ACL_MODIFY_MODE_REMOVE;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen rights++;
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen case '+':
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen update.modify_mode = ACL_MODIFY_MODE_ADD;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rights++;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen break;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen default:
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen update.modify_mode = ACL_MODIFY_MODE_REPLACE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (imap_acl_identifier_parse(cmd, identifier, &update.rights,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen TRUE, &error) < 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client_send_command_error(cmd, error);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (imap_acl_letters_parse(rights, &update.rights.rights, &error) < 0) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen client_send_command_error(cmd, error);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return TRUE;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen r = &update.rights;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen box = acl_mailbox_open_as_admin(cmd, mailbox);
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen if (box == NULL)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return TRUE;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen ns = mailbox_get_namespace(box);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen backend = acl_mailbox_list_get_backend(ns->list);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (ns->type == NAMESPACE_PUBLIC && r->id_type == ACL_ID_OWNER) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client_send_tagline(cmd, "NO Public namespaces have no owner");
mailbox_close(&box);
return TRUE;
}
if (negative) {
update.neg_modify_mode = update.modify_mode;
update.modify_mode = ACL_MODIFY_MODE_REMOVE;
update.rights.neg_rights = update.rights.rights;
update.rights.rights = NULL;
} else if (ns->type == NAMESPACE_PRIVATE && r->rights != NULL &&
((r->id_type == ACL_ID_USER &&
acl_backend_user_name_equals(backend, r->identifier)) ||
(r->id_type == ACL_ID_OWNER &&
strcmp(acl_backend_get_acl_username(backend),
ns->user->username) == 0))) {
/* make sure client doesn't (accidentally) remove admin
privileges from its own mailboxes */
imap_acl_update_ensure_keep_admins(&update);
}
if (acl_object_update(acl_mailbox_get_aclobj(box), &update) < 0)
client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
else
client_send_tagline(cmd, "OK Setacl complete.");
mailbox_close(&box);
return TRUE;
}
static bool cmd_deleteacl(struct client_command_context *cmd)
{
struct mailbox *box;
struct acl_rights_update update;
const char *mailbox, *identifier, *error;
if (!client_read_string_args(cmd, 2, &mailbox, &identifier))
return FALSE;
if (*identifier == '\0') {
client_send_command_error(cmd, "Invalid arguments.");
return TRUE;
}
memset(&update, 0, sizeof(update));
if (*identifier != '-')
update.modify_mode = ACL_MODIFY_MODE_CLEAR;
else {
update.neg_modify_mode = ACL_MODIFY_MODE_CLEAR;
identifier++;
}
if (imap_acl_identifier_parse(cmd, identifier, &update.rights,
FALSE, &error) < 0) {
client_send_command_error(cmd, error);
return TRUE;
}
box = acl_mailbox_open_as_admin(cmd, mailbox);
if (box == NULL)
return TRUE;
if (acl_object_update(acl_mailbox_get_aclobj(box), &update) < 0)
client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
else
client_send_tagline(cmd, "OK Deleteacl complete.");
mailbox_close(&box);
return TRUE;
}
static void imap_acl_client_created(struct client **client)
{
str_append((*client)->capability_string, " ACL RIGHTS=texk");
if (next_hook_client_created != NULL)
next_hook_client_created(client);
}
void imap_acl_plugin_init(void)
{
command_register("LISTRIGHTS", cmd_listrights, 0);
command_register("GETACL", cmd_getacl, 0);
command_register("MYRIGHTS", cmd_myrights, 0);
command_register("SETACL", cmd_setacl, 0);
command_register("DELETEACL", cmd_deleteacl, 0);
next_hook_client_created = hook_client_created;
hook_client_created = imap_acl_client_created;
}
void imap_acl_plugin_deinit(void)
{
command_unregister("GETACL");
command_unregister("MYRIGHTS");
command_unregister("SETACL");
command_unregister("DELETEACL");
command_unregister("LISTRIGHTS");
hook_client_created = next_hook_client_created;
}
const char *imap_acl_plugin_dependencies[] = { "acl", NULL };