Mercurial > dovecot > original-hg > dovecot-1.2
changeset 8037:ab1c170b1559 HEAD
Use permissions based on mail root directory when creating new files/dirs under it.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 20 Jul 2008 23:20:19 +0300 |
parents | b3303b65c3f2 |
children | dc280df713f4 |
files | src/lib-storage/index/cydir/cydir-storage.c src/lib-storage/index/dbox/dbox-storage.c src/lib-storage/index/index-storage.c src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/maildir/maildir-util.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/list/mailbox-list-fs.c src/lib-storage/list/subscription-file.c src/lib-storage/mailbox-list.c src/lib-storage/mailbox-list.h src/plugins/quota/quota-maildir.c |
diffstat | 11 files changed, 130 insertions(+), 47 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/cydir/cydir-storage.c Sun Jul 20 23:19:34 2008 +0300 +++ b/src/lib-storage/index/cydir/cydir-storage.c Sun Jul 20 23:20:19 2008 +0300 @@ -130,7 +130,12 @@ static int create_cydir(struct mail_storage *storage, const char *path) { - if (mkdir_parents(path, CREATE_MODE) < 0 && errno != EEXIST) { + mode_t mode; + gid_t gid; + + mailbox_list_get_dir_permissions(storage->list, &mode, &gid); + if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) < 0 && + errno != EEXIST) { if (!mail_storage_set_error_from_errno(storage)) { mail_storage_set_critical(storage, "mkdir(%s) failed: %m", path);
--- a/src/lib-storage/index/dbox/dbox-storage.c Sun Jul 20 23:19:34 2008 +0300 +++ b/src/lib-storage/index/dbox/dbox-storage.c Sun Jul 20 23:20:19 2008 +0300 @@ -146,7 +146,12 @@ static int create_dbox(struct mail_storage *storage, const char *path) { - if (mkdir_parents(path, CREATE_MODE) < 0 && errno != EEXIST) { + mode_t mode; + gid_t gid; + + mailbox_list_get_dir_permissions(storage->list, &mode, &gid); + if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) < 0 && + errno != EEXIST) { if (!mail_storage_set_error_from_errno(storage)) { mail_storage_set_critical(storage, "mkdir(%s) failed: %m", path);
--- a/src/lib-storage/index/index-storage.c Sun Jul 20 23:19:34 2008 +0300 +++ b/src/lib-storage/index/index-storage.c Sun Jul 20 23:20:19 2008 +0300 @@ -17,8 +17,6 @@ #include <unistd.h> #include <sys/stat.h> -#define CREATE_MODE 0770 /* umask() should limit it more */ - #define DEFAULT_CACHE_FIELDS "" #define DEFAULT_NEVER_CACHE_FIELDS "imap.envelope" @@ -69,9 +67,38 @@ i_free(list); } +static int stat_parent(struct mail_storage *storage, const char *path, + mode_t *mode_r, gid_t *gid_r) +{ + struct stat st; + const char *p; + + while ((p = strrchr(path, '/')) != NULL) { + path = t_strdup_until(path, p); + if (stat(path, &st) == 0) { + *mode_r = st.st_mode; + *gid_r = (st.st_mode & S_ISGID) != 0 || + st.st_gid == getegid() ? + (gid_t)-1 : st.st_gid; + return 0; + } + if (errno != ENOENT) { + mail_storage_set_critical(storage, + "stat(%s) failed: %m", path); + return -1; + } + } + /* use default permissions */ + *mode_r = 0700; + *gid_r = (gid_t)-1; + return 0; +} + static int create_index_dir(struct mail_storage *storage, const char *name) { const char *root_dir, *index_dir; + mode_t mode; + gid_t gid; root_dir = mailbox_list_get_path(storage->list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX); @@ -80,7 +107,12 @@ if (strcmp(index_dir, root_dir) == 0 || *index_dir == '\0') return 0; - if (mkdir_parents(index_dir, CREATE_MODE) < 0 && errno != EEXIST) { + /* get permissions from the parent directory */ + if (stat_parent(storage, index_dir, &mode, &gid) < 0) + return -1; + + if (mkdir_parents_chown(index_dir, mode, (uid_t)-1, gid) < 0 && + errno != EEXIST) { mail_storage_set_critical(storage, "mkdir(%s) failed: %m", index_dir); return -1;
--- a/src/lib-storage/index/maildir/maildir-storage.c Sun Jul 20 23:19:34 2008 +0300 +++ b/src/lib-storage/index/maildir/maildir-storage.c Sun Jul 20 23:20:19 2008 +0300 @@ -21,8 +21,6 @@ #include <unistd.h> #include <sys/stat.h> -#define CREATE_MODE 0777 /* umask() should limit it more */ - #define MAILDIR_PLUSPLUS_DRIVER_NAME "maildir++" #define MAILDIR_SUBFOLDER_FILENAME "maildirfolder" @@ -290,7 +288,7 @@ } static int mkdir_verify(struct mail_storage *storage, - const char *dir, bool verify) + const char *dir, mode_t mode, gid_t gid, bool verify) { struct stat st; @@ -305,7 +303,7 @@ } } - if (mkdir_parents(dir, CREATE_MODE) == 0) + if (mkdir_parents_chown(dir, mode, (uid_t)-1, gid) == 0) return 0; if (errno == EEXIST) { @@ -355,8 +353,10 @@ /* create or fix maildir, ignore if it already exists */ static int create_maildir(struct mail_storage *storage, - const char *dir, bool verify) + const char *dir, mode_t mode, gid_t gid, bool verify) { + const char *path; + unsigned int i; int ret; ret = maildir_check_tmp(storage, dir); @@ -372,12 +372,11 @@ return -1; /* doesn't exist, create */ - if (mkdir_verify(storage, t_strconcat(dir, "/cur", NULL), verify) < 0) - return -1; - if (mkdir_verify(storage, t_strconcat(dir, "/new", NULL), verify) < 0) - return -1; - if (mkdir_verify(storage, t_strconcat(dir, "/tmp", NULL), verify) < 0) - return -1; + for (i = 0; i < N_ELEMENTS(maildir_subdirs); i++) { + path = t_strconcat(dir, "/", maildir_subdirs[i], NULL); + if (mkdir_verify(storage, path, mode, gid, verify) < 0) + return -1; + } return 0; } @@ -474,6 +473,8 @@ struct maildir_storage *storage = (struct maildir_storage *)_storage; const char *path; struct stat st; + mode_t mode; + gid_t gid; int ret; if (input != NULL) { @@ -488,7 +489,8 @@ if (strcmp(name, "INBOX") == 0 && (_storage->ns->flags & NAMESPACE_FLAG_INBOX) != 0) { /* INBOX always exists */ - if (create_maildir(_storage, path, TRUE) < 0) + mailbox_list_get_dir_permissions(_storage->list, &mode, &gid); + if (create_maildir(_storage, path, mode, gid, TRUE) < 0) return NULL; return maildir_open(storage, "INBOX", flags); } @@ -506,7 +508,8 @@ /* tmp/ directory doesn't exist. does the maildir? */ if (stat(path, &st) == 0) { /* yes, we'll need to create the missing dirs */ - if (create_maildir(_storage, path, TRUE) < 0) + mailbox_list_get_dir_permissions(_storage->list, &mode, &gid); + if (create_maildir(_storage, path, mode, gid, TRUE) < 0) return NULL; return maildir_open(storage, name, flags); @@ -526,7 +529,6 @@ { const char *path; mode_t old_mask; - unsigned int i; int fd; /* add the execute bit if either read or write bit is set */ @@ -534,23 +536,10 @@ if ((mode & 0060) != 0) mode |= 0010; if ((mode & 0006) != 0) mode |= 0001; - old_mask = umask(0777 ^ mode); - if (create_maildir(storage, dir, FALSE) < 0) { - umask(old_mask); + if (create_maildir(storage, dir, mode, gid, FALSE) < 0) return -1; - } - if (chown(dir, (uid_t)-1, gid) < 0) { - mail_storage_set_critical(storage, - "chown(%s) failed: %m", dir); - } - for (i = 0; i < N_ELEMENTS(maildir_subdirs); i++) { - path = t_strconcat(dir, "/", maildir_subdirs[i], NULL); - if (chown(path, (uid_t)-1, gid) < 0) { - mail_storage_set_critical(storage, - "chown(%s) failed: %m", path); - } - } + old_mask = umask(0777 ^ mode); path = t_strconcat(dir, "/dovecot-shared", NULL); fd = open(path, O_WRONLY | O_CREAT, mode & 0666); umask(old_mask); @@ -590,9 +579,10 @@ st.st_mode & 0666, st.st_gid) < 0) return -1; } else { - st.st_mode = CREATE_MODE; - st.st_gid = (gid_t)-1; - if (create_maildir(_storage, path, FALSE) < 0) + mailbox_list_get_dir_permissions(_storage->list, + &st.st_mode, &st.st_gid); + if (create_maildir(_storage, path, st.st_mode, st.st_gid, + FALSE) < 0) return -1; }
--- a/src/lib-storage/index/maildir/maildir-util.c Sun Jul 20 23:19:34 2008 +0300 +++ b/src/lib-storage/index/maildir/maildir-util.c Sun Jul 20 23:20:19 2008 +0300 @@ -115,7 +115,8 @@ "stat(%s) failed: %m", path); break; } - if (mkdir_parents(path, box->dir_create_mode) < 0 && + if (mkdir_parents_chown(path, box->dir_create_mode, + (uid_t)-1, box->file_create_gid) < 0 && errno != EEXIST) { if (errno == ENOENT) { /* mailbox was being deleted just now */
--- a/src/lib-storage/index/mbox/mbox-storage.c Sun Jul 20 23:19:34 2008 +0300 +++ b/src/lib-storage/index/mbox/mbox-storage.c Sun Jul 20 23:20:19 2008 +0300 @@ -692,9 +692,10 @@ { const char *path, *p; struct stat st; + mode_t mode; + gid_t gid; int fd; - /* make sure it doesn't exist already */ path = mailbox_list_get_path(_storage->list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX); @@ -719,7 +720,9 @@ p = directory ? path + strlen(path) : strrchr(path, '/'); if (p != NULL) { p = t_strdup_until(path, p); - if (mkdir_parents(p, CREATE_MODE) < 0 && errno != EEXIST) { + mailbox_list_get_dir_permissions(_storage->list, &mode, &gid); + if (mkdir_parents_chown(p, mode, (uid_t)-1, gid) < 0 && + errno != EEXIST) { if (!mail_storage_set_error_from_errno(_storage)) { mail_storage_set_critical(_storage, "mkdir_parents(%s) failed: %m", p);
--- a/src/lib-storage/list/mailbox-list-fs.c Sun Jul 20 23:19:34 2008 +0300 +++ b/src/lib-storage/list/mailbox-list-fs.c Sun Jul 20 23:20:19 2008 +0300 @@ -11,7 +11,6 @@ #include <unistd.h> #include <sys/stat.h> -#define CREATE_MODE 0770 /* umask() should limit it more */ #define GLOBAL_TEMP_PREFIX ".temp." extern struct mailbox_list fs_mailbox_list; @@ -283,6 +282,8 @@ { const char *oldpath, *newpath, *old_indexdir, *new_indexdir, *p; struct stat st; + mode_t mode; + gid_t gid; oldpath = mailbox_list_get_path(list, oldname, MAILBOX_LIST_PATH_TYPE_DIR); @@ -292,8 +293,10 @@ /* create the hierarchy */ p = strrchr(newpath, '/'); if (p != NULL) { + mailbox_list_get_dir_permissions(list, &mode, &gid); p = t_strdup_until(newpath, p); - if (mkdir_parents(p, CREATE_MODE) < 0 && errno != EEXIST) { + if (mkdir_parents_chown(p, mode, (uid_t)-1, gid) < 0 && + errno != EEXIST) { if (mailbox_list_set_error_from_errno(list)) return -1;
--- a/src/lib-storage/list/subscription-file.c Sun Jul 20 23:19:34 2008 +0300 +++ b/src/lib-storage/list/subscription-file.c Sun Jul 20 23:20:19 2008 +0300 @@ -82,6 +82,8 @@ struct istream *input; struct ostream *output; int fd_in, fd_out; + mode_t mode, dir_mode; + gid_t gid; bool found, failed = FALSE; if (strcasecmp(name, "INBOX") == 0) @@ -96,17 +98,22 @@ dotlock_set.timeout = SUBSCRIPTION_FILE_LOCK_TIMEOUT; dotlock_set.stale_timeout = SUBSCRIPTION_FILE_CHANGE_TIMEOUT; - fd_out = file_dotlock_open(&dotlock_set, path, 0, &dotlock); + mailbox_list_get_permissions(list, &mode, &gid); + mailbox_list_get_dir_permissions(list, &dir_mode, &gid); + fd_out = file_dotlock_open_mode(&dotlock_set, path, 0, + mode, (uid_t)-1, gid, &dotlock); if (fd_out == -1 && errno == ENOENT) { /* directory hasn't been created yet. */ p = strrchr(path, '/'); dir = p == NULL ? NULL : t_strdup_until(path, p); - if (dir != NULL && mkdir_parents(dir, 0700) < 0 && + if (dir != NULL && + mkdir_parents_chown(dir, dir_mode, (uid_t)-1, gid) < 0 && errno != EEXIST) { subsfile_set_syscall_error(list, "mkdir()", dir); return -1; } - fd_out = file_dotlock_open(&dotlock_set, path, 0, &dotlock); + fd_out = file_dotlock_open_mode(&dotlock_set, path, 0, + mode, (uid_t)-1, gid, &dotlock); } if (fd_out == -1) { if (errno == EAGAIN) {
--- a/src/lib-storage/mailbox-list.c Sun Jul 20 23:19:34 2008 +0300 +++ b/src/lib-storage/mailbox-list.c Sun Jul 20 23:20:19 2008 +0300 @@ -291,6 +291,21 @@ *gid_r = list->file_create_gid; } +void mailbox_list_get_dir_permissions(struct mailbox_list *list, + mode_t *mode_r, gid_t *gid_r) +{ + mode_t mode; + + mailbox_list_get_permissions(list, &mode, gid_r); + + /* add the execute bit if either read or write bit is set */ + if ((mode & 0600) != 0) mode |= 0100; + if ((mode & 0060) != 0) mode |= 0010; + if ((mode & 0006) != 0) mode |= 0001; + + *mode_r = mode; +} + bool mailbox_list_is_valid_pattern(struct mailbox_list *list, const char *pattern) {
--- a/src/lib-storage/mailbox-list.h Sun Jul 20 23:19:34 2008 +0300 +++ b/src/lib-storage/mailbox-list.h Sun Jul 20 23:20:19 2008 +0300 @@ -141,6 +141,10 @@ necessary to change the default */ void mailbox_list_get_permissions(struct mailbox_list *list, mode_t *mode_r, gid_t *gid_r); +/* Like mailbox_list_get_permissions(), but add execute-bits for mode + if either read or write bit is set (e.g. 0640 -> 0750). */ +void mailbox_list_get_dir_permissions(struct mailbox_list *list, + mode_t *mode_r, gid_t *gid_r); /* Returns TRUE if the name doesn't contain any invalid characters. The create name check can be more strict. */
--- a/src/plugins/quota/quota-maildir.c Sun Jul 20 23:19:34 2008 +0300 +++ b/src/plugins/quota/quota-maildir.c Sun Jul 20 23:20:19 2008 +0300 @@ -218,16 +218,34 @@ static int maildirsize_write(struct maildir_quota_root *root, const char *path) { const struct quota_rule *rule = &root->root.default_rule; + struct mail_storage *const *storages; + unsigned int i, count; struct dotlock *dotlock; string_t *str; + mode_t mode; + gid_t gid; int fd; i_assert(root->fd == -1); + /* figure out what permissions we should use for maildirsize. + use the inbox namespace's permissions if possible. */ + mode = 0600; + gid = (gid_t)-1; + storages = array_get(&root->root.quota->storages, &count); + for (i = 0; i < count; i++) { + if ((storages[i]->ns->flags & NAMESPACE_FLAG_INBOX) != 0) { + mailbox_list_get_permissions(storages[i]->ns->list, + &mode, &gid); + break; + } + } + dotlock_settings.use_excl_lock = getenv("DOTLOCK_USE_EXCL") != NULL; dotlock_settings.nfs_flush = getenv("MAIL_NFS_STORAGE") != NULL; - fd = file_dotlock_open(&dotlock_settings, path, - DOTLOCK_CREATE_FLAG_NONBLOCK, &dotlock); + fd = file_dotlock_open_mode(&dotlock_settings, path, + DOTLOCK_CREATE_FLAG_NONBLOCK, + mode, (uid_t)-1, gid, &dotlock); if (fd == -1) { if (errno == EAGAIN) { /* someone's just in the middle of updating it */