dovecot-2.0: imap-acl: Initial SETACL box owner +rights should a...

dovecot at dovecot.org dovecot at dovecot.org
Mon Aug 9 18:08:02 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/bbfe3a00bc74
changeset: 11964:bbfe3a00bc74
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Aug 09 16:07:54 2010 +0100
description:
imap-acl: Initial SETACL box owner +rights should apply on top of default rights, not empty rights.
So typically this should be a no-op when mailbox doesn't yet have explicit
rights for owner.

diffstat:

 src/plugins/imap-acl/imap-acl-plugin.c |  73 +++++++++++++++++++++++++++++-------
 1 files changed, 58 insertions(+), 15 deletions(-)

diffs (140 lines):

diff -r 8814ced6d012 -r bbfe3a00bc74 src/plugins/imap-acl/imap-acl-plugin.c
--- a/src/plugins/imap-acl/imap-acl-plugin.c	Mon Aug 09 15:33:20 2010 +0100
+++ b/src/plugins/imap-acl/imap-acl-plugin.c	Mon Aug 09 16:07:54 2010 +0100
@@ -177,6 +177,41 @@
 	imap_acl_write_rights_list(dest, rights);
 }
 
+static bool
+acl_rights_is_owner(struct acl_backend *backend,
+		    const struct acl_rights *rights)
+{
+	switch (rights->id_type) {
+	case ACL_ID_OWNER:
+		return TRUE;
+	case ACL_ID_USER:
+		return acl_backend_user_name_equals(backend,
+						    rights->identifier);
+	default:
+		return FALSE;
+	}
+}
+
+static bool have_positive_owner_rights(struct acl_backend *backend,
+				       struct acl_object *aclobj)
+{
+	struct acl_object_list_iter *iter;
+	struct acl_rights rights;
+	bool ret = FALSE;
+
+	iter = acl_object_list_init(aclobj);
+	while ((ret = acl_object_list_next(iter, &rights)) > 0) {
+		if (acl_rights_is_owner(backend, &rights)) {
+			if (rights.rights != NULL) {
+				ret = TRUE;
+				break;
+			}
+		}
+	}
+	acl_object_list_deinit(&iter);
+	return ret;
+}
+
 static int
 imap_acl_write_aclobj(string_t *dest, struct acl_backend *backend,
 		      struct acl_object *aclobj, bool convert_owner,
@@ -187,7 +222,7 @@
 	string_t *tmp;
 	const char *username;
 	unsigned int orig_len = str_len(dest);
-	bool owner, seen_owner = FALSE, seen_positive_owner = FALSE;
+	bool seen_owner = FALSE, seen_positive_owner = FALSE;
 	int ret;
 
 	username = acl_backend_get_acl_username(backend);
@@ -197,20 +232,11 @@
 	tmp = t_str_new(128);
 	iter = acl_object_list_init(aclobj);
 	while ((ret = acl_object_list_next(iter, &rights)) > 0) {
-		if (rights.id_type == ACL_ID_USER &&
-		    acl_backend_user_name_equals(backend, rights.identifier))
-			owner = TRUE;
-		else if (rights.id_type == ACL_ID_OWNER) {
-			owner = TRUE;
-			if (convert_owner) {
+		if (acl_rights_is_owner(backend, &rights)) {
+			if (rights.id_type == ACL_ID_OWNER && convert_owner) {
 				rights.id_type = ACL_ID_USER;
 				rights.identifier = username;
 			}
-		} else {
-			owner = FALSE;
-		}
-
-		if (owner) {
 			if (seen_owner && convert_owner) {
 				/* oops, we have both owner and user=myself.
 				   can't do the conversion, so try again. */
@@ -462,10 +488,13 @@
 	return 0;
 }
 
-static void imap_acl_update_ensure_keep_admins(struct acl_rights_update *update)
+static void imap_acl_update_ensure_keep_admins(struct acl_backend *backend,
+					       struct acl_object *aclobj,
+					       struct acl_rights_update *update)
 {
 	static const char *acl_admin = MAIL_ACL_ADMIN;
 	const char *const *rights = update->rights.rights;
+	const char *const *default_rights;
 	ARRAY_TYPE(const_string) new_rights;
 	unsigned int i;
 
@@ -477,6 +506,18 @@
 	}
 
 	switch (update->modify_mode) {
+	case ACL_MODIFY_MODE_ADD:
+		if (have_positive_owner_rights(backend, aclobj))
+			return;
+
+		/* adding initial rights for a user. we need to add
+		   the defaults also. don't worry about duplicates. */
+		for (; rights[i] != NULL; i++)
+			array_append(&new_rights, &rights[i], 1);
+		default_rights = acl_object_get_default_rights(aclobj);
+		for (i = 0; default_rights[i] != NULL; i++)
+			array_append(&new_rights, &default_rights[i], 1);
+		break;
 	case ACL_MODIFY_MODE_REMOVE:
 		if (rights[i] == NULL)
 			return;
@@ -504,6 +545,7 @@
 	struct mail_namespace *ns;
 	struct mailbox *box;
 	struct acl_backend *backend;
+	struct acl_object *aclobj;
 	struct acl_rights_update update;
 	struct acl_rights *r;
 	const char *mailbox, *identifier, *rights, *error;
@@ -560,6 +602,7 @@
 		return TRUE;
 	}
 
+	aclobj = acl_mailbox_get_aclobj(box);
 	if (negative) {
 		update.neg_modify_mode = update.modify_mode;
 		update.modify_mode = ACL_MODIFY_MODE_REMOVE;
@@ -573,10 +616,10 @@
 			    ns->user->username) == 0))) {
 		/* make sure client doesn't (accidentally) remove admin
 		   privileges from its own mailboxes */
-		imap_acl_update_ensure_keep_admins(&update);
+		imap_acl_update_ensure_keep_admins(backend, aclobj, &update);
 	}
 
-	if (acl_object_update(acl_mailbox_get_aclobj(box), &update) < 0)
+	if (acl_object_update(aclobj, &update) < 0)
 		client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
 	else
 		client_send_tagline(cmd, "OK Setacl complete.");


More information about the dovecot-cvs mailing list