dovecot-1.2: imap-acl: Don't let client remove admin ACL from it...

dovecot at dovecot.org dovecot at dovecot.org
Sat Feb 21 00:11:30 EET 2009


details:   http://hg.dovecot.org/dovecot-1.2/rev/f810b81c8e05
changeset: 8758:f810b81c8e05
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Feb 20 17:11:25 2009 -0500
description:
imap-acl: Don't let client remove admin ACL from its own mailboxes.

diffstat:

1 file changed, 61 insertions(+), 1 deletion(-)
src/plugins/imap-acl/imap-acl-plugin.c |   62 +++++++++++++++++++++++++++++++-

diffs (95 lines):

diff -r 0ac80bed5d3e -r f810b81c8e05 src/plugins/imap-acl/imap-acl-plugin.c
--- a/src/plugins/imap-acl/imap-acl-plugin.c	Fri Feb 20 16:31:37 2009 -0500
+++ b/src/plugins/imap-acl/imap-acl-plugin.c	Fri Feb 20 17:11:25 2009 -0500
@@ -447,10 +447,51 @@ imap_acl_identifier_parse(const char *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 mail_storage *storage;
 	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;
 
@@ -489,12 +530,22 @@ static bool cmd_setacl(struct client_com
 		client_send_command_error(cmd, error);
 		return TRUE;
 	}
+	r = &update.rights;
 
 	box = acl_mailbox_open_as_admin(cmd, mailbox);
 	if (box == NULL)
 		return TRUE;
 
-	if (update.rights.rights[0] == NULL) {
+	storage = mailbox_get_storage(box);
+	backend = acl_storage_get_backend(storage);
+	ns = mail_storage_get_namespace(storage);
+	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 (r->rights[0] == NULL) {
 		if (negative) {
 			update.modify_mode = 0;
 			update.rights.rights = NULL;
@@ -511,6 +562,15 @@ static bool cmd_setacl(struct client_com
 		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)


More information about the dovecot-cvs mailing list