Mercurial > dovecot > core-2.2
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;