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;
}
}