Hi,

here is the patch against the master.

Best regards,

On Friday 21 January 2011 03:14:57 Jeroen van Meeuwen (Kolab Systems) wrote:
> Bron Gondwana wrote:
> > I like the idea - and it would be great if you did a patch again git
> > master at http://git.cyrusimap.org/ - follow the links.  Or if you use
> > git you can just fork it and ask us to pull your branch!  That way you
> > get full credit :)
> 
> Send us a patch via email and you get full credit ;-)
> 
> Send us a patch via snail mail and forget to mention your name and email
> address... then there's not so much we can do for you ;-)
> 
> Kind regards,
> 
> Jeroen van Meeuwen

-- 
Guilherme Maciel Ferreira
Intra2net AG | Mömpelgarder Weg 8 | 72072 Tübingen | DE

Telefon   +49-7071-56510-0
Telefax   +49-7071-56510-50
Internet  www.intra2net.com

Vorstand | Steffen Jarosch
Aufsichtsrat | Ulrich Emmert | Vorsitzender
Handelsregister | HRB 382770 | Amtsgericht Stuttgart
Identnummern | USt-Id DE216036710 | WEEE DE72185423
diff --git a/imap/mboxlist.c b/imap/mboxlist.c
index b59057b..c39c405 100644
--- a/imap/mboxlist.c
+++ b/imap/mboxlist.c
@@ -1279,6 +1279,33 @@ int mboxlist_renamemailbox(const char *oldname, const char *newname,
 }
 
 /*
+ * Verify if the 'user' is the mailbox 'name' owner.
+ */
+static int mboxlist_is_owner(const char *name, int domainlen,
+			     const char *user, int userlen)
+{
+    char *cp = NULL;
+
+    int enough_length = !strncmp(name+domainlen, "user.", 5);
+    int user_complete = (!(cp = strchr(user, '.')) || (cp - user) > userlen);
+    int match_strings = !strncmp(name+domainlen+5, user, userlen);
+    int match_length = (name[domainlen+5+userlen] == '\0' ||
+			name[domainlen+5+userlen] == '.');
+
+    return (enough_length && user_complete && match_strings && match_length);
+}
+
+/*
+ * Check if the admin rights are present in the 'rights'
+ */
+static int mboxlist_have_admin_rights(const char* rights) {
+    int access = cyrus_acl_strtomask(rights);
+    int have_admin_access = access & ACL_ADMIN;
+
+    return have_admin_access;
+}
+
+/*
  * Change the ACL for mailbox 'name' so that 'identifier' has the
  * rights enumerated in the string 'rights'.  If 'rights' is the null
  * pointer, removes the ACL entry for 'identifier'.   'isadmin' is
@@ -1298,13 +1325,19 @@ int mboxlist_setacl(const char *name, const char *identifier,
 		    struct auth_state *auth_state)
 {
     struct mboxlist_entry *mbentry = NULL;
-    int useridlen = strlen(userid), domainlen = 0;
+    int useridlen = strlen(userid);
+    int domainlen = 0;
+    int identifierlen = strlen(identifier);
     char *cp, ident[256];
     const char *domain = NULL;
     int r;
     int myrights;
     int mode = ACL_MODE_SET;
-    int isusermbox = 0, anyoneuseracl = 1;
+    int isusermbox = 0;
+    int isidentifiermbox = 0;
+    int anyoneuseracl = 1;
+    int ensure_owner_rights = 0;
+    const char *mailbox_owner = NULL;
     struct mailbox *mailbox = NULL;
     char *newacl = NULL;
     char *mboxent = NULL;
@@ -1351,15 +1384,30 @@ int mboxlist_setacl(const char *name, const char *identifier,
 	identifier = ident;
     }
 
-    if (!strncmp(name+domainlen, "user.", 5) &&
-	(!(cp = strchr(userid, '.')) || (cp - userid) > useridlen) &&
-	!strncmp(name+domainlen+5, userid, useridlen) &&
-	(name[domainlen+5+useridlen] == '\0' ||
-	 name[domainlen+5+useridlen] == '.')) {
+    /* checks if the mailbox belongs to the user who is trying to change the
+       access rights */
+    if (mboxlist_is_owner(name, domainlen, userid, useridlen)) {
 	isusermbox = 1;
     }
     anyoneuseracl = config_getswitch(IMAPOPT_ANYONEUSERACL);
 
+    /* checks if the identifier is the mailbox owner */
+    if (mboxlist_is_owner(name, domainlen, identifier, identifierlen)) {
+	isidentifiermbox = 1;
+    }
+
+    /* who is the mailbox owner? */
+    if (isusermbox) {
+	mailbox_owner = userid;
+    }
+    else if (isidentifiermbox) {
+	mailbox_owner = identifier;
+    }
+
+    /* ensure the access rights if the folder owner is the current user or
+       the identifier */
+    ensure_owner_rights = isusermbox || isidentifiermbox;
+
     /* 1. Start Transaction */
     /* lookup the mailbox to make sure it exists and get its acl */
     do {
@@ -1423,17 +1471,35 @@ int mboxlist_setacl(const char *name, const char *identifier,
 		rights++;
 		mode = ACL_MODE_REMOVE;
 	    }
-	    
+	    /* do not allow to remove the admin rights from mailbox owner */
+	    if (isidentifiermbox && (mode != ACL_MODE_ADD) &&
+		!mboxlist_have_admin_rights(rights)) {
+		syslog(LOG_ERR,"Denied to change admin access rights for "
+		       "folder \"%s\" (owner: %s) by user \"%s\"", name,
+		       mailbox_owner, userid);
+		r = IMAP_PERMISSION_DENIED;
+		goto done;
+	    }
+
 	    if (cyrus_acl_set(&newacl, identifier, mode,
 			      cyrus_acl_strtomask(rights),
-			      isusermbox ? mboxlist_ensureOwnerRights : 0,
-			      (void *)userid)) {
+			      ensure_owner_rights ? mboxlist_ensureOwnerRights : 0,
+			      (void *)mailbox_owner)) {
 		r = IMAP_INVALID_IDENTIFIER;
 	    }
 	} else {
+	    /* do not allow to remove the admin rights from mailbox owner */
+	    if (isidentifiermbox) {
+		syslog(LOG_ERR,"Denied to delete admin access rights for "
+		       "folder \"%s\" (owner: %s) by user \"%s\"", name,
+		       mailbox_owner, userid);
+		r = IMAP_PERMISSION_DENIED;
+		goto done;
+	    }
+
 	    if (cyrus_acl_remove(&newacl, identifier,
-				 isusermbox ? mboxlist_ensureOwnerRights : 0,
-				 (void *)userid)) {
+				 ensure_owner_rights ? mboxlist_ensureOwnerRights : 0,
+				 (void *)mailbox_owner)) {
 		r = IMAP_INVALID_IDENTIFIER;
 	    }
 	}

Reply via email to