imap-acl-plugin.c revision 411f318ed3a25fa66c1b932e10df43841e2725c9
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "imap-common.h"
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen#include "str.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "imap-quote.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "imap-resp-code.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "imap-commands.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mail-storage.h"
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen#include "mail-namespace.h"
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen#include "acl-api.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "acl-storage.h"
18565c69efcd7db003dbf27cf625ed822e889fb1Timo Sirainen#include "acl-plugin.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "imap-acl-plugin.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <stdlib.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#define ERROR_NOT_ADMIN "["IMAP_RESP_CODE_NOPERM"] " \
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen "You lack administrator privileges on this mailbox."
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#define ACL_MAILBOX_FLAGS \
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen (MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#define IMAP_ACL_ANYONE "anyone"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#define IMAP_ACL_AUTHENTICATED "authenticated"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#define IMAP_ACL_OWNER "owner"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#define IMAP_ACL_GROUP_PREFIX "$"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#define IMAP_ACL_GROUP_OVERRIDE_PREFIX "!$"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#define IMAP_ACL_GLOBAL_PREFIX "#"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstruct imap_acl_letter_map {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen char letter;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const char *name;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen};
af1f4b17a92ca7b2661737e65c7849df289d3070Timo Sirainen
af1f4b17a92ca7b2661737e65c7849df289d3070Timo Sirainenstatic const struct imap_acl_letter_map imap_acl_letter_map[] = {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen { 'l', MAIL_ACL_LOOKUP },
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen { 'r', MAIL_ACL_READ },
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen { 'w', MAIL_ACL_WRITE },
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen { 's', MAIL_ACL_WRITE_SEEN },
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen { 't', MAIL_ACL_WRITE_DELETED },
4b41116563110d00330896a568eff1078c382827Timo Sirainen { 'i', MAIL_ACL_INSERT },
4b41116563110d00330896a568eff1078c382827Timo Sirainen { 'p', MAIL_ACL_POST },
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen { 'e', MAIL_ACL_EXPUNGE },
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen { 'k', MAIL_ACL_CREATE },
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen { 'x', MAIL_ACL_DELETE },
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen { 'a', MAIL_ACL_ADMIN },
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen { '\0', NULL }
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen};
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenconst char *imap_acl_plugin_version = PACKAGE_VERSION;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainenstatic void (*next_hook_client_created)(struct client **client);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainenstatic struct mailbox *
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenacl_mailbox_open_as_admin(struct client_command_context *cmd, const char *name)
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen{
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen struct mail_namespace *ns;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen struct mailbox *box;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen int ret;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (ACL_USER_CONTEXT(cmd->client->user) == NULL) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen client_send_command_error(cmd, "ACLs disabled.");
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return NULL;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen ns = client_find_namespace(cmd, &name);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (ns == NULL)
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return NULL;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen /* Force opening the mailbox so that we can give a nicer error message
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen if mailbox isn't selectable but is listable. */
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen box = mailbox_alloc(ns->list, name, NULL, ACL_MAILBOX_FLAGS |
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen MAILBOX_FLAG_IGNORE_ACLS);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_ADMIN);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen if (ret > 0)
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen return box;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen /* not an administrator. */
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_LOOKUP) <= 0) {
597dce34068d603fb759b4dff404b34049213e51Timo Sirainen client_send_tagline(cmd, t_strdup_printf(
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen "NO ["IMAP_RESP_CODE_NONEXISTENT"] "
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen MAIL_ERRSTR_MAILBOX_NOT_FOUND, name));
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen } else {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen client_send_tagline(cmd, "NO "ERROR_NOT_ADMIN);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen mailbox_close(&box);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return NULL;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen}
4b41116563110d00330896a568eff1078c382827Timo Sirainen
910fa4e4204a73d3d24c03f3059dd24e727ca057Timo Sirainenstatic const struct imap_acl_letter_map *
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenimap_acl_letter_map_find(const char *name)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen unsigned int i;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
6060b7c8edf8fce73470d0df6a2479b69b01c537Timo Sirainen for (i = 0; imap_acl_letter_map[i].name != NULL; i++) {
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen if (strcmp(imap_acl_letter_map[i].name, name) == 0)
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return &imap_acl_letter_map[i];
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return NULL;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen}
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
4b41116563110d00330896a568eff1078c382827Timo Sirainenstatic void
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenimap_acl_write_rights_list(string_t *dest, const char *const *rights)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen const struct imap_acl_letter_map *map;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen unsigned int i, orig_len = str_len(dest);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen bool append_c = FALSE, append_d = FALSE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen for (i = 0; rights[i] != NULL; i++) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* write only letters */
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen map = imap_acl_letter_map_find(rights[i]);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (map != NULL) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append_c(dest, map->letter);
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (map->letter == 'k' || map->letter == 'x')
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen append_c = TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (map->letter == 't' || map->letter == 'e')
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen append_d = TRUE;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen }
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen }
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen if (append_c)
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen str_append_c(dest, 'c');
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (append_d)
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen str_append_c(dest, 'd');
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (orig_len == str_len(dest))
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen str_append(dest, "\"\"");
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic void
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainenimap_acl_write_right(string_t *dest, string_t *tmp,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen const struct acl_rights *right, bool neg)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen{
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen const char *const *rights = neg ? right->neg_rights : right->rights;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen str_truncate(tmp, 0);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen if (neg) str_append_c(tmp,'-');
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen if (right->global)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen str_append(tmp, IMAP_ACL_GLOBAL_PREFIX);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen switch (right->id_type) {
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen case ACL_ID_ANYONE:
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen str_append(tmp, IMAP_ACL_ANYONE);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen break;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen case ACL_ID_AUTHENTICATED:
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen str_append(tmp, IMAP_ACL_AUTHENTICATED);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen break;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen case ACL_ID_OWNER:
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen str_append(tmp, IMAP_ACL_OWNER);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen break;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen case ACL_ID_USER:
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append(tmp, right->identifier);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen break;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen case ACL_ID_GROUP:
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen str_append(tmp, IMAP_ACL_GROUP_PREFIX);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen str_append(tmp, right->identifier);
4b41116563110d00330896a568eff1078c382827Timo Sirainen break;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen case ACL_ID_GROUP_OVERRIDE:
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append(tmp, IMAP_ACL_GROUP_OVERRIDE_PREFIX);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen str_append(tmp, right->identifier);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen break;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen case ACL_ID_TYPE_COUNT:
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen i_unreached();
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen imap_quote_append(dest, str_data(tmp), str_len(tmp), FALSE);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen str_append_c(dest, ' ');
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen imap_acl_write_rights_list(dest, rights);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen}
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstatic int
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenimap_acl_write_aclobj(string_t *dest, struct acl_backend *backend,
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen struct acl_object *aclobj, bool convert_owner,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen bool add_default)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen{
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen struct acl_object_list_iter *iter;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen struct acl_rights rights;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen string_t *tmp;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const char *username;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen unsigned int orig_len = str_len(dest);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen bool owner, seen_owner = FALSE, seen_positive_owner = FALSE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen int ret;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen username = acl_backend_get_acl_username(backend);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (username == NULL)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen convert_owner = FALSE;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen tmp = t_str_new(128);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen iter = acl_object_list_init(aclobj);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen while ((ret = acl_object_list_next(iter, &rights)) > 0) {
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen if (rights.id_type == ACL_ID_USER &&
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen acl_backend_user_name_equals(backend, rights.identifier))
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen owner = TRUE;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen else if (rights.id_type == ACL_ID_OWNER) {
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen owner = TRUE;
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen if (convert_owner) {
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen rights.id_type = ACL_ID_USER;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen rights.identifier = username;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen } else {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen owner = FALSE;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (owner) {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (seen_owner && convert_owner) {
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen /* oops, we have both owner and user=myself.
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen can't do the conversion, so try again. */
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen str_truncate(dest, orig_len);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen return imap_acl_write_aclobj(dest, backend,
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen aclobj, FALSE,
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen add_default);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen }
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen seen_owner = TRUE;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (rights.rights != NULL)
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen seen_positive_owner = TRUE;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen }
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen if (rights.rights != NULL) {
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen str_append_c(dest, ' ');
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen imap_acl_write_right(dest, tmp, &rights, FALSE);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen }
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen if (rights.neg_rights != NULL) {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen str_append_c(dest, ' ');
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen imap_acl_write_right(dest, tmp, &rights, TRUE);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen }
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen acl_object_list_deinit(&iter);
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (!seen_positive_owner && username != NULL && add_default) {
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen /* no positive owner rights returned, write default ACLs */
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen memset(&rights, 0, sizeof(rights));
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen if (!convert_owner) {
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen rights.id_type = ACL_ID_OWNER;
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen } else {
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen rights.id_type = ACL_ID_USER;
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen rights.identifier = username;
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen }
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen rights.rights = acl_object_get_default_rights(aclobj);
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen if (rights.rights != NULL) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen str_append_c(dest, ' ');
a1808be0774cbcb28fec45341aabf803ec44bae5Timo Sirainen imap_acl_write_right(dest, tmp, &rights, FALSE);
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen }
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return ret;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen}
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic bool cmd_getacl(struct client_command_context *cmd)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen{
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen struct acl_backend *backend;
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen struct mail_namespace *ns;
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen struct mailbox *box;
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen const char *mailbox;
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen string_t *str;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen int ret;
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen return FALSE;
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen box = acl_mailbox_open_as_admin(cmd, mailbox);
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen if (box == NULL)
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen return TRUE;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen str = t_str_new(128);
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen str_append(str, "* ACL ");
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen imap_quote_append_string(str, mailbox, FALSE);
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen ns = mailbox_get_namespace(box);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen backend = acl_mailbox_list_get_backend(ns->list);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ret = imap_acl_write_aclobj(str, backend,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen acl_mailbox_get_aclobj(box), TRUE,
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ns->type == NAMESPACE_PRIVATE);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (ret == 0) {
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen client_send_line(cmd->client, str_c(str));
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen client_send_tagline(cmd, "OK Getacl completed.");
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen } else {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen mailbox_close(&box);
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen return TRUE;
4b41116563110d00330896a568eff1078c382827Timo Sirainen}
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainenstatic bool cmd_myrights(struct client_command_context *cmd)
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen{
f480b30abdddf6f1beb8a2c5b1ce4bf8999400dbTimo Sirainen struct mail_namespace *ns;
f480b30abdddf6f1beb8a2c5b1ce4bf8999400dbTimo Sirainen struct mailbox *box;
f480b30abdddf6f1beb8a2c5b1ce4bf8999400dbTimo Sirainen const char *mailbox, *real_mailbox;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen const char *const *rights;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen string_t *str;
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen return FALSE;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (ACL_USER_CONTEXT(cmd->client->user) == NULL) {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen client_send_command_error(cmd, "ACLs disabled.");
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return TRUE;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen }
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen real_mailbox = mailbox;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen ns = client_find_namespace(cmd, &real_mailbox);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (ns == NULL)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen return TRUE;
8f017a40470ef2f4b530000d947a8bce44350a5eTimo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen box = mailbox_alloc(ns->list, real_mailbox, NULL,
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen ACL_MAILBOX_FLAGS | MAILBOX_FLAG_IGNORE_ACLS);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (acl_object_get_my_rights(acl_mailbox_get_aclobj(box),
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen pool_datastack_create(), &rights) < 0) {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen mailbox_close(&box);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen return TRUE;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen }
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen /* Post right alone doesn't give permissions to see if the mailbox
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen exists or not. Only mail deliveries care about that. */
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (*rights == NULL ||
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen (strcmp(*rights, MAIL_ACL_POST) == 0 && rights[1] == NULL)) {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen client_send_tagline(cmd, t_strdup_printf(
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen "NO ["IMAP_RESP_CODE_NONEXISTENT"] "
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen MAIL_ERRSTR_MAILBOX_NOT_FOUND, real_mailbox));
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen mailbox_close(&box);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str = t_str_new(128);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append(str, "* MYRIGHTS ");
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen imap_quote_append_string(str, mailbox, FALSE);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen str_append_c(str,' ');
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen imap_acl_write_rights_list(str, rights);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen client_send_line(cmd->client, str_c(str));
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen client_send_tagline(cmd, "OK Myrights completed.");
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen mailbox_close(&box);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return TRUE;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen}
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainenstatic bool cmd_listrights(struct client_command_context *cmd)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen{
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct mailbox *box;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen const char *mailbox, *identifier;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen string_t *str;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (!client_read_string_args(cmd, 2, &mailbox, &identifier))
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return FALSE;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
0d86aa0d47f7393c669c084b34c0537b193688adTimo Sirainen box = acl_mailbox_open_as_admin(cmd, mailbox);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (box == NULL)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return TRUE;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str = t_str_new(128);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen str_append(str, "* LISTRIGHTS ");
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen imap_quote_append_string(str, mailbox, FALSE);
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen str_append_c(str, ' ');
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen imap_quote_append_string(str, identifier, FALSE);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append_c(str, ' ');
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append(str, "\"\" l r w s t p i e k x a c d");
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen client_send_line(cmd->client, str_c(str));
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen client_send_tagline(cmd, "OK Listrights completed.");
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen mailbox_close(&box);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen return TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic int
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenimap_acl_letters_parse(const char *letters, const char *const **rights_r,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const char **error_r)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
838e367716bbd5e44b4a1691db9cbf72af53e9f0Timo Sirainen static const char *acl_k = MAIL_ACL_CREATE;
01404d41657a104c5ea1c12bb87f9c321e9c1ac4Timo Sirainen static const char *acl_x = MAIL_ACL_DELETE;
01404d41657a104c5ea1c12bb87f9c321e9c1ac4Timo Sirainen static const char *acl_e = MAIL_ACL_EXPUNGE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen static const char *acl_t = MAIL_ACL_WRITE_DELETED;
ARRAY_TYPE(const_string) rights;
unsigned int i;
t_array_init(&rights, 64);
for (; *letters != '\0'; letters++) {
for (i = 0; imap_acl_letter_map[i].name != NULL; i++) {
if (imap_acl_letter_map[i].letter == *letters) {
array_append(&rights,
&imap_acl_letter_map[i].name, 1);
break;
}
}
if (imap_acl_letter_map[i].name == NULL) {
/* Handling of obsolete rights as virtual
rights according to RFC 4314 */
switch (*letters) {
case 'c':
array_append(&rights, &acl_k, 1);
array_append(&rights, &acl_x, 1);
break;
case 'd':
array_append(&rights, &acl_e, 1);
array_append(&rights, &acl_t, 1);
break;
default:
*error_r = t_strdup_printf(
"Invalid ACL right: %c", *letters);
return -1;
}
}
}
(void)array_append_space(&rights);
*rights_r = array_idx(&rights, 0);
return 0;
}
static bool acl_anyone_allow(struct mail_user *user)
{
const char *env;
env = mail_user_plugin_getenv(user, "acl_anyone");
return env != NULL && strcmp(env, "allow") == 0;
}
static int
imap_acl_identifier_parse(struct client_command_context *cmd,
const char *id, struct acl_rights *rights,
bool check_anyone, const char **error_r)
{
struct mail_user *user = cmd->client->user;
if (strncmp(id, IMAP_ACL_GLOBAL_PREFIX,
strlen(IMAP_ACL_GLOBAL_PREFIX)) == 0) {
*error_r = t_strdup_printf("Global ACLs can't be modified: %s",
id);
return -1;
}
if (strcmp(id, IMAP_ACL_ANYONE) == 0) {
if (check_anyone && !acl_anyone_allow(user)) {
*error_r = "'anyone' identifier is disallowed";
return -1;
}
rights->id_type = ACL_ID_ANYONE;
} else if (strcmp(id, IMAP_ACL_AUTHENTICATED) == 0) {
if (check_anyone && !acl_anyone_allow(user)) {
*error_r = "'authenticated' identifier is disallowed";
return -1;
}
rights->id_type = ACL_ID_AUTHENTICATED;
} else if (strcmp(id, IMAP_ACL_OWNER) == 0)
rights->id_type = ACL_ID_OWNER;
else if (strncmp(id, IMAP_ACL_GROUP_PREFIX,
strlen(IMAP_ACL_GROUP_PREFIX)) == 0) {
rights->id_type = ACL_ID_GROUP;
rights->identifier = id + strlen(IMAP_ACL_GROUP_PREFIX);
} else if (strncmp(id, IMAP_ACL_GROUP_OVERRIDE_PREFIX,
strlen(IMAP_ACL_GROUP_OVERRIDE_PREFIX)) == 0) {
rights->id_type = ACL_ID_GROUP_OVERRIDE;
rights->identifier = id +
strlen(IMAP_ACL_GROUP_OVERRIDE_PREFIX);
} else {
rights->id_type = ACL_ID_USER;
rights->identifier = id;
}
return 0;
}
static void imap_acl_update_ensure_keep_admins(struct acl_rights_update *update)
{
static const char *acl_admin = MAIL_ACL_ADMIN;
const char *const *rights = update->rights.rights;
ARRAY_TYPE(const_string) new_rights;
unsigned int i;
t_array_init(&new_rights, 64);
for (i = 0; rights[i] != NULL; i++) {
if (strcmp(rights[i], MAIL_ACL_ADMIN) == 0)
break;
array_append(&new_rights, &rights[i], 1);
}
switch (update->modify_mode) {
case ACL_MODIFY_MODE_REMOVE:
if (rights[i] == NULL)
return;
/* skip over the ADMIN removal and add the rest */
for (i++; rights[i] != NULL; i++)
array_append(&new_rights, &rights[i], 1);
break;
case ACL_MODIFY_MODE_REPLACE:
if (rights[i] != NULL)
return;
/* add the missing ADMIN right */
array_append(&new_rights, &acl_admin, 1);
break;
default:
return;
}
(void)array_append_space(&new_rights);
update->rights.rights = array_idx(&new_rights, 0);
}
static bool cmd_setacl(struct client_command_context *cmd)
{
struct mail_namespace *ns;
struct mailbox *box;
struct acl_backend *backend;
struct acl_rights_update update;
struct acl_rights *r;
const char *mailbox, *identifier, *rights, *error;
bool negative = FALSE;
if (!client_read_string_args(cmd, 3, &mailbox, &identifier, &rights))
return FALSE;
if (*identifier == '\0') {
client_send_command_error(cmd, "Invalid arguments.");
return TRUE;
}
memset(&update, 0, sizeof(update));
if (*identifier == '-') {
negative = TRUE;
identifier++;
}
switch (*rights) {
case '-':
update.modify_mode = ACL_MODIFY_MODE_REMOVE;
rights++;
break;
case '+':
update.modify_mode = ACL_MODIFY_MODE_ADD;
rights++;
break;
default:
update.modify_mode = ACL_MODIFY_MODE_REPLACE;
break;
}
if (imap_acl_identifier_parse(cmd, identifier, &update.rights,
TRUE, &error) < 0) {
client_send_command_error(cmd, error);
return TRUE;
}
if (imap_acl_letters_parse(rights, &update.rights.rights, &error) < 0) {
client_send_command_error(cmd, error);
return TRUE;
}
r = &update.rights;
box = acl_mailbox_open_as_admin(cmd, mailbox);
if (box == NULL)
return TRUE;
ns = mailbox_get_namespace(box);
backend = acl_mailbox_list_get_backend(ns->list);
if (ns->type == NAMESPACE_PUBLIC && r->id_type == ACL_ID_OWNER) {
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;
}