imap-acl-plugin.c revision 411f318ed3a25fa66c1b932e10df43841e2725c9
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#define ERROR_NOT_ADMIN "["IMAP_RESP_CODE_NOPERM"] " \
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen "You lack administrator privileges on this mailbox."
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen (MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT)
af1f4b17a92ca7b2661737e65c7849df289d3070Timo Sirainenstatic const struct imap_acl_letter_map imap_acl_letter_map[] = {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenconst char *imap_acl_plugin_version = PACKAGE_VERSION;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainenstatic void (*next_hook_client_created)(struct client **client);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainenstatic struct mailbox *
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenacl_mailbox_open_as_admin(struct client_command_context *cmd, const char *name)
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (ACL_USER_CONTEXT(cmd->client->user) == NULL) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen client_send_command_error(cmd, "ACLs disabled.");
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 ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_ADMIN);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen /* not an administrator. */
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_LOOKUP) <= 0) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen client_send_tagline(cmd, "NO "ERROR_NOT_ADMIN);
910fa4e4204a73d3d24c03f3059dd24e727ca057Timo Sirainenstatic const struct imap_acl_letter_map *
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen unsigned int i;
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)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenimap_acl_write_rights_list(string_t *dest, const char *const *rights)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* write only letters */
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainenimap_acl_write_right(string_t *dest, string_t *tmp,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen const char *const *rights = neg ? right->neg_rights : right->rights;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append(tmp, IMAP_ACL_GROUP_OVERRIDE_PREFIX);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen imap_quote_append(dest, str_data(tmp), str_len(tmp), FALSE);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenimap_acl_write_aclobj(string_t *dest, struct acl_backend *backend,
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen struct acl_object *aclobj, bool convert_owner,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen bool owner, seen_owner = FALSE, seen_positive_owner = FALSE;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen username = acl_backend_get_acl_username(backend);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen while ((ret = acl_object_list_next(iter, &rights)) > 0) {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen acl_backend_user_name_equals(backend, rights.identifier))
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen /* oops, we have both owner and user=myself.
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen can't do the conversion, so try again. */
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen imap_acl_write_right(dest, tmp, &rights, FALSE);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen imap_acl_write_right(dest, tmp, &rights, TRUE);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (!seen_positive_owner && username != NULL && add_default) {
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen /* no positive owner rights returned, write default ACLs */
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen rights.rights = acl_object_get_default_rights(aclobj);
a1808be0774cbcb28fec45341aabf803ec44bae5Timo Sirainen imap_acl_write_right(dest, tmp, &rights, FALSE);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic bool cmd_getacl(struct client_command_context *cmd)
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen box = acl_mailbox_open_as_admin(cmd, mailbox);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen imap_quote_append_string(str, mailbox, FALSE);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen backend = acl_mailbox_list_get_backend(ns->list);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen client_send_tagline(cmd, "OK Getacl completed.");
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainenstatic bool cmd_myrights(struct client_command_context *cmd)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen const char *const *rights;
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (ACL_USER_CONTEXT(cmd->client->user) == NULL) {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen client_send_command_error(cmd, "ACLs disabled.");
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen ns = client_find_namespace(cmd, &real_mailbox);
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 client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
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 (strcmp(*rights, MAIL_ACL_POST) == 0 && rights[1] == NULL)) {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen MAIL_ERRSTR_MAILBOX_NOT_FOUND, real_mailbox));
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen imap_quote_append_string(str, mailbox, FALSE);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen client_send_tagline(cmd, "OK Myrights completed.");
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainenstatic bool cmd_listrights(struct client_command_context *cmd)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (!client_read_string_args(cmd, 2, &mailbox, &identifier))
0d86aa0d47f7393c669c084b34c0537b193688adTimo Sirainen box = acl_mailbox_open_as_admin(cmd, mailbox);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen imap_quote_append_string(str, mailbox, FALSE);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen imap_quote_append_string(str, identifier, FALSE);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append(str, "\"\" l r w s t p i e k x a c d");
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen client_send_tagline(cmd, "OK Listrights completed.");
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenimap_acl_letters_parse(const char *letters, const char *const **rights_r,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const char **error_r)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen static const char *acl_t = MAIL_ACL_WRITE_DELETED;
switch (*letters) {
const char *env;
id);
case ACL_MODIFY_MODE_REMOVE:
case ACL_MODIFY_MODE_REPLACE:
struct acl_rights *r;
return FALSE;
return TRUE;
identifier++;
switch (*rights) {
rights++;
rights++;
return TRUE;
return TRUE;
return TRUE;
return TRUE;
if (negative) {
return TRUE;
return FALSE;
return TRUE;
identifier++;
return TRUE;
return TRUE;
return TRUE;
void imap_acl_plugin_init(void)
void imap_acl_plugin_deinit(void)