changeset 13243:cc7cef1f6a21

lib-storage: mailbox_list_get_permissions() now returns struct mailbox_permissions. Also added new file_uid and file_gid fields to the mailbox_permissions.
author Timo Sirainen <tss@iki.fi>
date Mon, 15 Aug 2011 01:06:19 +0300
parents 584557ef2965
children 3439fc65838a
files src/lib-storage/list/mailbox-list-fs.c src/lib-storage/list/mailbox-list-maildir.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c src/lib-storage/mailbox-list.c src/lib-storage/mailbox-list.h src/plugins/acl/acl-backend-vfile.c
diffstat 7 files changed, 110 insertions(+), 96 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-fs.c	Mon Aug 15 00:44:01 2011 +0300
+++ b/src/lib-storage/list/mailbox-list-fs.c	Mon Aug 15 01:06:19 2011 +0300
@@ -265,9 +265,8 @@
 fs_list_create_mailbox_dir(struct mailbox_list *list, const char *name,
 			   enum mailbox_dir_create_type type)
 {
-	const char *path, *gid_origin, *p;
-	mode_t file_mode, dir_mode;
-	gid_t gid;
+	struct mailbox_permissions perm;
+	const char *path, *p;
 	bool directory, create_parent_dir;
 	int ret;
 
@@ -285,9 +284,10 @@
 		path = t_strdup_until(path, p);
 	}
 
-	mailbox_list_get_permissions(list, name, &file_mode, &dir_mode,
-				     &gid, &gid_origin);
-	if (mkdir_parents_chgrp(path, dir_mode, gid, gid_origin) == 0)
+	mailbox_list_get_permissions(list, name, &perm);
+	if (mkdir_parents_chgrp(path, perm.dir_create_mode,
+				perm.file_create_gid,
+				perm.file_create_gid_origin) == 0)
 		return 0;
 	else if (errno == EEXIST) {
 		if (create_parent_dir)
@@ -433,8 +433,8 @@
 		gid_t gid;
 		const char *origin;
 
-		mailbox_list_get_permissions(newlist, NULL, &file_mode,
-					     &dir_mode, &gid, &origin);
+		mailbox_list_get_root_permissions(newlist, &file_mode,
+						  &dir_mode, &gid, &origin);
 		if (mkdir_parents_chgrp(newparent, dir_mode, gid, origin) < 0 &&
 		    errno != EEXIST) {
 			if (mailbox_list_set_error_from_errno(oldlist))
@@ -471,12 +471,10 @@
 				  const char *newname, bool rename_children)
 {
 	struct mail_storage *oldstorage;
-	const char *oldvname, *oldpath, *newpath, *alt_newpath, *root_path;
-	const char *p, *origin, *old_origin;
+	const char *oldvname, *oldpath, *newpath, *alt_newpath, *root_path, *p;
 	enum mailbox_list_path_type path_type, alt_path_type;
 	struct stat st;
-	mode_t file_mode, dir_mode, old_file_mode, old_dir_mode;
-	gid_t gid, old_gid;
+	struct mailbox_permissions old_perm, new_perm;
 	bool rmdir_parent = FALSE;
 
 	oldvname = mailbox_list_get_vname(oldlist, oldname);
@@ -511,16 +509,15 @@
 		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);
+	mailbox_list_get_permissions(oldlist, oldname, &old_perm);
+	mailbox_list_get_permissions(newlist, newname, &new_perm);
 
 	/* 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)) {
+	    (new_perm.file_create_mode != old_perm.file_create_mode ||
+	     new_perm.dir_create_mode != old_perm.dir_create_mode ||
+	     new_perm.file_create_gid != old_perm.file_create_gid)) {
 		mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
 			"Renaming not supported across conflicting "
 			"directory permissions");
@@ -531,7 +528,9 @@
 	p = strrchr(newpath, '/');
 	if (p != NULL) {
 		p = t_strdup_until(newpath, p);
-		if (mkdir_parents_chgrp(p, dir_mode, gid, origin) < 0 &&
+		if (mkdir_parents_chgrp(p, new_perm.dir_create_mode,
+					new_perm.file_create_gid,
+					new_perm.file_create_gid_origin) < 0 &&
 		    errno != EEXIST) {
 			if (mailbox_list_set_error_from_errno(oldlist))
 				return -1;
--- a/src/lib-storage/list/mailbox-list-maildir.c	Mon Aug 15 00:44:01 2011 +0300
+++ b/src/lib-storage/list/mailbox-list-maildir.c	Mon Aug 15 01:06:19 2011 +0300
@@ -307,9 +307,8 @@
 maildir_list_create_mailbox_dir(struct mailbox_list *list, const char *name,
 				enum mailbox_dir_create_type type)
 {
-	const char *path, *root_dir, *gid_origin, *p;
-	mode_t file_mode, dir_mode;
-	gid_t gid;
+	struct mailbox_permissions perm;
+	const char *path, *root_dir, *p;
 	bool create_parent_dir;
 
 	if (type == MAILBOX_DIR_CREATE_TYPE_ONLY_NOSELECT) {
@@ -332,9 +331,10 @@
 
 	root_dir = mailbox_list_get_path(list, NULL,
 					 MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	mailbox_list_get_permissions(list, name, &file_mode, &dir_mode,
-				     &gid, &gid_origin);
-	if (mkdir_parents_chgrp(path, dir_mode, gid, gid_origin) == 0) {
+	mailbox_list_get_permissions(list, name, &perm);
+	if (mkdir_parents_chgrp(path, perm.dir_create_mode,
+				perm.file_create_gid,
+				perm.file_create_gid_origin) == 0) {
 		/* ok */
 	} else if (errno == EEXIST) {
 		if (create_parent_dir)
@@ -357,8 +357,10 @@
 		return -1;
 	}
 	return create_parent_dir || strcmp(path, root_dir) == 0 ? 0 :
-		maildir_list_create_maildirfolder_file(list, path, file_mode,
-						       gid, gid_origin);
+		maildir_list_create_maildirfolder_file(list, path,
+						       perm.file_create_mode,
+						       perm.file_create_gid,
+						       perm.file_create_gid_origin);
 }
 
 static const char *
@@ -576,17 +578,14 @@
 	/* 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;
+		struct mailbox_permissions old_perm, new_perm;
 
-		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);
+		mailbox_list_get_permissions(oldlist, oldname, &old_perm);
+		mailbox_list_get_permissions(newlist, newname, &new_perm);
 
-		if ((file_mode != old_file_mode ||
-		     dir_mode != old_dir_mode || gid != old_gid)) {
+		if ((new_perm.file_create_mode != old_perm.file_create_mode ||
+		     new_perm.dir_create_mode != old_perm.dir_create_mode ||
+		     new_perm.file_create_gid != old_perm.file_create_gid)) {
 			mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
 				"Renaming not supported across conflicting "
 				"directory permissions");
--- a/src/lib-storage/mail-storage-private.h	Mon Aug 15 00:44:01 2011 +0300
+++ b/src/lib-storage/mail-storage-private.h	Mon Aug 15 01:06:19 2011 +0300
@@ -201,16 +201,6 @@
 	struct mail_storage_module_register *reg;
 };
 
-struct mailbox_permissions {
-	/* mode and GID to use for newly created files/dirs */
-	mode_t file_create_mode, dir_create_mode;
-	gid_t file_create_gid;
-	/* origin (e.g. path) where the file_create_gid was got from */
-	const char *file_create_gid_origin;
-
-	bool mail_index_permissions_set;
-};
-
 struct mailbox {
 	const char *name;
 	/* mailbox's virtual name (from mail_namespace_get_vname()) */
--- a/src/lib-storage/mail-storage.c	Mon Aug 15 00:44:01 2011 +0300
+++ b/src/lib-storage/mail-storage.c	Mon Aug 15 01:06:19 2011 +0300
@@ -1601,6 +1601,7 @@
 		return;
 
 	if (box->input != NULL) {
+		box->_perm.file_uid = geteuid();
 		box->_perm.file_create_mode = 0600;
 		box->_perm.dir_create_mode = 0700;
 		box->_perm.file_create_gid = (gid_t)-1;
@@ -1608,11 +1609,9 @@
 		return;
 	}
 
-	mailbox_list_get_permissions(box->list, box->name,
-				     &box->_perm.file_create_mode,
-				     &box->_perm.dir_create_mode,
-				     &box->_perm.file_create_gid, &origin);
-	box->_perm.file_create_gid_origin = p_strdup(box->pool, origin);
+	mailbox_list_get_permissions(box->list, box->name, &box->_perm);
+	box->_perm.file_create_gid_origin =
+		p_strdup(box->pool, box->_perm.file_create_gid_origin);
 }
 
 const struct mailbox_permissions *mailbox_get_permissions(struct mailbox *box)
--- a/src/lib-storage/mailbox-list.c	Mon Aug 15 00:44:01 2011 +0300
+++ b/src/lib-storage/mailbox-list.c	Mon Aug 15 01:06:19 2011 +0300
@@ -609,19 +609,21 @@
 	return list->v.get_hierarchy_sep(list);
 }
 
-void mailbox_list_get_permissions(struct mailbox_list *list,
-				  const char *name,
-				  mode_t *file_mode_r, mode_t *dir_mode_r,
-				  gid_t *gid_r, const char **gid_origin_r)
+void mailbox_list_get_permissions(struct mailbox_list *list, const char *name,
+				  struct mailbox_permissions *permissions_r)
 {
 	const char *path, *parent_name, *p;
 	struct stat st;
 
+	memset(permissions_r, 0, sizeof(permissions_r));
+
 	/* use safe defaults */
-	*file_mode_r = 0600;
-	*dir_mode_r = 0700;
-	*gid_r = (gid_t)-1;
-	*gid_origin_r = "defaults";
+	permissions_r->file_uid = (uid_t)-1;
+	permissions_r->file_gid = (gid_t)-1;
+	permissions_r->file_create_mode = 0600;
+	permissions_r->dir_create_mode = 0700;
+	permissions_r->file_create_gid = (gid_t)-1;
+	permissions_r->file_create_gid_origin = "defaults";
 
 	path = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR);
 	if (path == NULL) {
@@ -644,43 +646,50 @@
 				parent_name = t_strdup_until(name, p);
 			}
 			mailbox_list_get_permissions(list, parent_name,
-						     file_mode_r, dir_mode_r,
-						     gid_r, gid_origin_r);
+						     permissions_r);
 			return;
 		}
+		/* assume current defaults for mailboxes that don't exist or
+		   can't be looked up for some other reason */
+		permissions_r->file_uid = geteuid();
+		permissions_r->file_gid = getegid();
 	} else {
-		*file_mode_r = (st.st_mode & 0666) | 0600;
-		*dir_mode_r = (st.st_mode & 0777) | 0700;
-		*gid_origin_r = path;
+		permissions_r->file_uid = st.st_uid;
+		permissions_r->file_gid = st.st_gid;
+		permissions_r->file_create_mode = (st.st_mode & 0666) | 0600;
+		permissions_r->dir_create_mode = (st.st_mode & 0777) | 0700;
+		permissions_r->file_create_gid_origin = path;
 
 		if (!S_ISDIR(st.st_mode)) {
 			/* we're getting permissions from a file.
 			   apply +x modes as necessary. */
-			*dir_mode_r = get_dir_mode(*dir_mode_r);
+			permissions_r->dir_create_mode =
+				get_dir_mode(permissions_r->dir_create_mode);
 		}
 
 		if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) {
 			/* directory's GID is used automatically for new
 			   files */
-			*gid_r = (gid_t)-1;
+			permissions_r->file_create_gid = (gid_t)-1;
 		} else if ((st.st_mode & 0070) >> 3 == (st.st_mode & 0007)) {
 			/* group has same permissions as world, so don't bother
 			   changing it */
-			*gid_r = (gid_t)-1;
+			permissions_r->file_create_gid = (gid_t)-1;
 		} else if (getegid() == st.st_gid) {
 			/* using our own gid, no need to change it */
-			*gid_r = (gid_t)-1;
+			permissions_r->file_create_gid = (gid_t)-1;
 		} else {
-			*gid_r = st.st_gid;
+			permissions_r->file_create_gid = st.st_gid;
 		}
 	}
 
 	if (name == NULL) {
-		list->file_create_mode = *file_mode_r;
-		list->dir_create_mode = *dir_mode_r;
-		list->file_create_gid = *gid_r;
+		list->file_create_mode = permissions_r->file_create_mode;
+		list->dir_create_mode = permissions_r->dir_create_mode;
+		list->file_create_gid = permissions_r->file_create_gid;
 		list->file_create_gid_origin =
-			p_strdup(list->pool, *gid_origin_r);
+			p_strdup(list->pool,
+				 permissions_r->file_create_gid_origin);
 	}
 
 	if (list->mail_set->mail_debug && name == NULL) {
@@ -697,15 +706,20 @@
 				       mode_t *file_mode_r, mode_t *dir_mode_r,
 				       gid_t *gid_r, const char **gid_origin_r)
 {
+	struct mailbox_permissions perm;
+
 	if (list->file_create_mode != (mode_t)-1) {
 		*file_mode_r = list->file_create_mode;
 		*dir_mode_r = list->dir_create_mode;
 		*gid_r = list->file_create_gid;
 		*gid_origin_r = list->file_create_gid_origin;
 	} else {
-		mailbox_list_get_permissions(list, NULL,
-					     file_mode_r, dir_mode_r,
-					     gid_r, gid_origin_r);
+		mailbox_list_get_permissions(list, NULL, &perm);
+
+		*file_mode_r = perm.file_create_mode;
+		*dir_mode_r = perm.dir_create_mode;
+		*gid_r = perm.file_create_gid;
+		*gid_origin_r = perm.file_create_gid_origin;
 	}
 }
 
@@ -1653,13 +1667,12 @@
 int mailbox_list_mkdir(struct mailbox_list *list,
 		       const char *mailbox, const char *path)
 {
-	mode_t file_mode, dir_mode;
-	gid_t gid;
-	const char *origin;
+	struct mailbox_permissions perm;
 
-	mailbox_list_get_permissions(list, mailbox, &file_mode, &dir_mode,
-				     &gid, &origin);
-	if (mkdir_parents_chgrp(path, dir_mode, gid, origin) < 0 &&
+	mailbox_list_get_permissions(list, mailbox, &perm);
+	if (mkdir_parents_chgrp(path, perm.dir_create_mode,
+				perm.file_create_gid,
+				perm.file_create_gid_origin) < 0 &&
 	    errno != EEXIST) {
 		mailbox_list_set_critical(list, "mkdir_parents(%s) failed: %m",
 					  path);
@@ -1683,9 +1696,8 @@
 int mailbox_list_create_missing_index_dir(struct mailbox_list *list,
 					  const char *name)
 {
-	const char *root_dir, *index_dir, *parent_dir, *p, *origin;
-	mode_t file_mode, dir_mode;
-	gid_t gid;
+	const char *root_dir, *index_dir, *parent_dir, *p;
+	struct mailbox_permissions perm;
 	unsigned int n = 0;
 
 	list->index_root_dir_created = TRUE;
@@ -1701,9 +1713,10 @@
 					       MAILBOX_LIST_PATH_TYPE_INDEX);
 	}
 
-	mailbox_list_get_permissions(list, name, &file_mode, &dir_mode,
-				     &gid, &origin);
-	while (mkdir_chgrp(index_dir, dir_mode, gid, origin) < 0) {
+	mailbox_list_get_permissions(list, name, &perm);
+	while (mkdir_chgrp(index_dir, perm.dir_create_mode,
+			   perm.file_create_gid,
+			   perm.file_create_gid_origin) < 0) {
 		if (errno == EEXIST)
 			break;
 
--- a/src/lib-storage/mailbox-list.h	Mon Aug 15 00:44:01 2011 +0300
+++ b/src/lib-storage/mailbox-list.h	Mon Aug 15 01:06:19 2011 +0300
@@ -143,6 +143,21 @@
 	struct mail_namespace *ns;
 };
 
+struct mailbox_permissions {
+	/* The actual uid/gid of the mailbox */
+	uid_t file_uid;
+	gid_t file_gid;
+
+	/* mode and GID to use for newly created files/dirs.
+	   (gid_t)-1 is used if the default GID can be used. */
+	mode_t file_create_mode, dir_create_mode;
+	gid_t file_create_gid;
+	/* origin (e.g. path) where the file_create_gid was got from */
+	const char *file_create_gid_origin;
+
+	bool mail_index_permissions_set;
+};
+
 /* register all drivers */
 void mailbox_list_register_all(void);
 
@@ -177,8 +192,7 @@
    directories to the specified mailbox. (gid_t)-1 is returned if it's not
    necessary to change the default gid. */
 void mailbox_list_get_permissions(struct mailbox_list *list, const char *name,
-				  mode_t *file_mode_r, mode_t *dir_mode_r,
-				  gid_t *gid_r, const char **gid_origin_r);
+				  struct mailbox_permissions *permissions_r);
 /* Like mailbox_list_get_permissions(), but for creating files/dirs to the
    mail root directory (or even the root dir itself). */
 void mailbox_list_get_root_permissions(struct mailbox_list *list,
--- a/src/plugins/acl/acl-backend-vfile.c	Mon Aug 15 00:44:01 2011 +0300
+++ b/src/plugins/acl/acl-backend-vfile.c	Mon Aug 15 01:06:19 2011 +0300
@@ -863,9 +863,7 @@
 					  struct dotlock **dotlock_r)
 {
 	struct acl_object *_aclobj = &aclobj->aclobj;
-	const char *gid_origin;
-	mode_t file_mode, dir_mode;
-	gid_t gid;
+	struct mailbox_permissions perm;
 	int fd;
 
 	if (aclobj->local_path == NULL) {
@@ -875,10 +873,12 @@
 	}
 
 	/* first lock the ACL file */
-	mailbox_list_get_permissions(_aclobj->backend->list, _aclobj->name,
-				     &file_mode, &dir_mode, &gid, &gid_origin);
+	mailbox_list_get_permissions(_aclobj->backend->list,
+				     _aclobj->name, &perm);
 	fd = file_dotlock_open_group(&dotlock_set, aclobj->local_path, 0,
-				     file_mode, gid, gid_origin, dotlock_r);
+				     perm.file_create_mode,
+				     perm.file_create_gid,
+				     perm.file_create_gid_origin, dotlock_r);
 	if (fd == -1) {
 		i_error("file_dotlock_open(%s) failed: %m", aclobj->local_path);
 		return -1;