changeset 12653:e2605d2d6b33

lib-storage: Don't allow renaming mailbox under another one with different permissions. This is mainly to avoid any weird situations arising with shared mailboxes.
author Timo Sirainen <tss@iki.fi>
date Sat, 12 Feb 2011 00:16:06 +0200
parents 31b633336ab5
children 87a75628c8f5
files src/lib-storage/list/mailbox-list-fs.c src/lib-storage/list/mailbox-list-maildir.c
diffstat 2 files changed, 41 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-fs.c	Sat Feb 12 00:15:04 2011 +0200
+++ b/src/lib-storage/list/mailbox-list-fs.c	Sat Feb 12 00:16:06 2011 +0200
@@ -447,11 +447,11 @@
 {
 	struct mail_storage *oldstorage;
 	const char *oldvname, *oldpath, *newpath, *alt_newpath, *root_path;
-	const char *p, *origin;
+	const char *p, *origin, *old_origin;
 	enum mailbox_list_path_type path_type, alt_path_type;
 	struct stat st;
-	mode_t file_mode, dir_mode;
-	gid_t gid;
+	mode_t file_mode, dir_mode, old_file_mode, old_dir_mode;
+	gid_t gid, old_gid;
 	bool rmdir_parent = FALSE;
 
 	oldvname = mailbox_list_get_vname(oldlist, oldname);
@@ -486,11 +486,25 @@
 		return -1;
 	}
 
+	mailbox_list_get_permissions(oldlist, oldname, &old_file_mode,
+				     &old_dir_mode, &old_gid, &old_origin);
+	mailbox_list_get_permissions(newlist, newname, &file_mode,
+				     &dir_mode, &gid, &origin);
+
+	/* if we're renaming under another mailbox, require its permissions
+	   to be same as ours. */
+	if (strchr(newname, mailbox_list_get_hierarchy_sep(newlist)) != NULL &&
+	    (file_mode != old_file_mode ||
+	     dir_mode != old_dir_mode || gid != old_gid)) {
+		mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
+			"Renaming not supported across conflicting "
+			"directory permissions");
+		return -1;
+	}
+
 	/* create the hierarchy */
 	p = strrchr(newpath, '/');
 	if (p != NULL) {
-		mailbox_list_get_root_permissions(newlist, &file_mode,
-						  &dir_mode, &gid, &origin);
 		p = t_strdup_until(newpath, p);
 		if (mkdir_parents_chgrp(p, dir_mode, gid, origin) < 0 &&
 		    errno != EEXIST) {
--- a/src/lib-storage/list/mailbox-list-maildir.c	Sat Feb 12 00:15:04 2011 +0200
+++ b/src/lib-storage/list/mailbox-list-maildir.c	Sat Feb 12 00:16:06 2011 +0200
@@ -574,6 +574,28 @@
 		return -1;
 	}
 
+	/* if we're renaming under another mailbox, require its permissions
+	   to be same as ours. */
+	if (strchr(newname, mailbox_list_get_hierarchy_sep(newlist)) != NULL) {
+		const char *origin, *old_origin;
+		mode_t file_mode, dir_mode, old_file_mode, old_dir_mode;
+		gid_t gid, old_gid;
+
+		mailbox_list_get_permissions(oldlist, oldname, &old_file_mode,
+					     &old_dir_mode, &old_gid, &old_origin);
+		mailbox_list_get_permissions(newlist, newname, &file_mode,
+					     &dir_mode, &gid, &origin);
+
+		if ((file_mode != old_file_mode ||
+		     dir_mode != old_dir_mode || gid != old_gid)) {
+			mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
+				"Renaming not supported across conflicting "
+				"directory permissions");
+			return -1;
+		}
+	}
+
+
 	ret = rename(oldpath, newpath);
 	if (ret == 0 || errno == ENOENT) {
 		(void)rename_dir(oldlist, oldname, newlist, newname,