dovecot: Replaced mail_extra_groups setting with mail_privileged...
dovecot at dovecot.org
dovecot at dovecot.org
Tue Mar 4 08:51:53 EET 2008
details: http://hg.dovecot.org/dovecot/rev/12adb981226e
changeset: 7329:12adb981226e
user: Timo Sirainen <tss at iki.fi>
date: Tue Mar 04 07:54:53 2008 +0200
description:
Replaced mail_extra_groups setting with mail_privileged_group and
mail_access_groups settings. mail_privileged_group allows temporary access
to the group when creating mbox INBOX dotlocks.
diffstat:
13 files changed, 354 insertions(+), 37 deletions(-)
dovecot-example.conf | 17 ++-
src/lib-storage/index/mbox/mbox-lock.c | 124 +++++++++++++++++++++++++
src/lib-storage/index/mbox/mbox-lock.h | 2
src/lib-storage/index/mbox/mbox-storage.c | 41 ++++++++
src/lib-storage/index/mbox/mbox-storage.h | 2
src/lib/restrict-access.c | 141 +++++++++++++++++++++++++----
src/lib/restrict-access.h | 13 ++
src/master/auth-process.c | 4
src/master/login-process.c | 2
src/master/mail-process.c | 12 +-
src/master/master-settings-defs.c | 2
src/master/master-settings.c | 26 +++++
src/master/master-settings.h | 5 -
diffs (truncated from 702 to 300 lines):
diff -r 2e8ff3074f5b -r 12adb981226e dovecot-example.conf
--- a/dovecot-example.conf Tue Mar 04 07:44:19 2008 +0200
+++ b/dovecot-example.conf Tue Mar 04 07:54:53 2008 +0200
@@ -269,12 +269,17 @@
#mail_uid =
#mail_gid =
-# Grant access to these extra groups for mail processes. Typical use would be
-# to give "mail" group write access to /var/mail to be able to create dotlocks.
-# WARNING: If your users can create symlinks, this will allow the users to
-# read any files that are group-readable by one of these groups! Make sure at
-# least all the common mailboxes have 0600 permissions (or a different group).
-#mail_extra_groups =
+# Group to enable temporarily for privileged operations. Currently this is
+# used only for creating mbox dotlock files when creation fails for INBOX.
+# Typically this is set to "mail" to give access to /var/mail.
+#mail_privileged_group =
+
+# Grant access to these supplementary groups for mail processes. Typically
+# these are used to set up access to shared mailboxes. Note that it may be
+# dangerous to set these if users can create symlinks (e.g. if "mail" group is
+# set here, ln -s /var/mail ~/mail/var could allow a user to delete others'
+# mailboxes, or ln -s /secret/shared/box ~/mail/mybox would allow reading it).
+#mail_access_groups =
# Allow full filesystem access to clients. There's no access checks other than
# what the operating system does for the active UID/GID. It works with both
diff -r 2e8ff3074f5b -r 12adb981226e src/lib-storage/index/mbox/mbox-lock.c
--- a/src/lib-storage/index/mbox/mbox-lock.c Tue Mar 04 07:44:19 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-lock.c Tue Mar 04 07:54:53 2008 +0200
@@ -1,6 +1,7 @@
/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
#include "lib.h"
+#include "restrict-access.h"
#include "nfs-workarounds.h"
#include "mail-index-private.h"
#include "mbox-storage.h"
@@ -38,6 +39,12 @@ enum mbox_lock_type {
MBOX_LOCK_COUNT
};
+enum mbox_dotlock_op {
+ MBOX_DOTLOCK_OP_LOCK,
+ MBOX_DOTLOCK_OP_UNLOCK,
+ MBOX_DOTLOCK_OP_TOUCH
+};
+
struct mbox_lock_context {
struct mbox_mailbox *mbox;
int lock_status[MBOX_LOCK_COUNT];
@@ -46,6 +53,7 @@ struct mbox_lock_context {
int lock_type;
bool dotlock_last_stale;
bool fcntl_locked;
+ bool using_privileges;
};
struct mbox_lock_data {
@@ -200,6 +208,9 @@ static bool dotlock_callback(unsigned in
enum mbox_lock_type *lock_types;
int i;
+ if (ctx->using_privileges)
+ restrict_access_drop_priv_gid();
+
if (stale && !ctx->dotlock_last_stale) {
/* get next index we wish to try locking. it's the one after
dotlocking. */
@@ -231,7 +242,90 @@ static bool dotlock_callback(unsigned in
MAILBOX_LOCK_NOTIFY_MAILBOX_OVERRIDE :
MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT,
secs_left);
+ if (ctx->using_privileges) {
+ if (restrict_access_use_priv_gid() < 0) {
+ /* shouldn't get here */
+ return FALSE;
+ }
+ }
return TRUE;
+}
+
+static int mbox_dotlock_privileged_op(struct mbox_mailbox *mbox,
+ struct dotlock_settings *set,
+ enum mbox_dotlock_op op)
+{
+ const char *dir, *fname;
+ int ret = -1, orig_dir_fd;
+
+ orig_dir_fd = open(".", O_RDONLY);
+ if (orig_dir_fd == -1) {
+ i_error("open(.) failed: %m");
+ return -1;
+ }
+
+ /* allow dotlocks to be created only for files we can read while we're
+ unprivileged. to make sure there are no race conditions we first
+ have to chdir to the mbox file's directory and then use relative
+ paths. unless this is done, users could:
+ - create *.lock files to any directory writable by the
+ privileged group
+ - DoS other users by dotlocking their mailboxes infinitely
+ */
+ fname = strrchr(mbox->path, '/');
+ if (fname == NULL) {
+ /* already relative */
+ fname = mbox->path;
+ } else {
+ dir = t_strdup_until(mbox->path, fname);
+ if (chdir(dir) < 0) {
+ i_error("chdir(%s) failed: %m", dir);
+ (void)close(orig_dir_fd);
+ return -1;
+ }
+ fname++;
+ }
+ if (op == MBOX_DOTLOCK_OP_LOCK) {
+ if (access(fname, R_OK) < 0) {
+ i_error("access(%s) failed: %m", mbox->path);
+ return -1;
+ }
+ }
+
+ if (restrict_access_use_priv_gid() < 0) {
+ (void)close(orig_dir_fd);
+ return -1;
+ }
+
+ switch (op) {
+ case MBOX_DOTLOCK_OP_LOCK:
+ /* we're now privileged - avoid doing as much as possible */
+ ret = file_dotlock_create(set, fname, 0, &mbox->mbox_dotlock);
+ if (ret > 0)
+ mbox->mbox_used_privileges = TRUE;
+ break;
+ case MBOX_DOTLOCK_OP_UNLOCK:
+ /* we're now privileged - avoid doing as much as possible */
+ ret = file_dotlock_delete(&mbox->mbox_dotlock);
+ mbox->mbox_used_privileges = FALSE;
+ break;
+ case MBOX_DOTLOCK_OP_TOUCH:
+ if (!file_dotlock_is_locked(mbox->mbox_dotlock)) {
+ file_dotlock_delete(&mbox->mbox_dotlock);
+ mbox->mbox_used_privileges = TRUE;
+ ret = -1;
+ } else {
+ ret = file_dotlock_touch(mbox->mbox_dotlock);
+ }
+ break;
+ }
+
+ restrict_access_drop_priv_gid();
+
+ if (fchdir(orig_dir_fd) < 0)
+ i_error("fchdir() failed: %m");
+ (void)close(orig_dir_fd);
+ return ret;
}
static int
@@ -245,7 +339,15 @@ mbox_lock_dotlock_int(struct mbox_lock_c
if (!mbox->mbox_dotlocked)
return 1;
- if (file_dotlock_delete(&mbox->mbox_dotlock) <= 0) {
+ if (!mbox->mbox_used_privileges)
+ ret = file_dotlock_delete(&mbox->mbox_dotlock);
+ else {
+ ctx->using_privileges = TRUE;
+ ret = mbox_dotlock_privileged_op(mbox, NULL,
+ MBOX_DOTLOCK_OP_UNLOCK);
+ ctx->using_privileges = FALSE;
+ }
+ if (ret <= 0) {
mbox_set_syscall_error(mbox, "file_dotlock_delete()");
ret = -1;
}
@@ -269,6 +371,13 @@ mbox_lock_dotlock_int(struct mbox_lock_c
set.context = ctx;
ret = file_dotlock_create(&set, mbox->path, 0, &mbox->mbox_dotlock);
+ if (ret < 0 && errno == EACCES && restrict_access_have_priv_gid() &&
+ mbox->mbox_privileged_locking) {
+ /* try again, this time with extra privileges */
+ ret = mbox_dotlock_privileged_op(mbox, &set,
+ MBOX_DOTLOCK_OP_LOCK);
+ }
+
if (ret < 0) {
if ((ENOSPACE(errno) || errno == EACCES) && try)
return 1;
@@ -643,3 +752,16 @@ int mbox_unlock(struct mbox_mailbox *mbo
return mbox_unlock_files(&ctx);
}
+
+void mbox_dotlock_touch(struct mbox_mailbox *mbox)
+{
+ if (mbox->mbox_dotlock == NULL)
+ return;
+
+ if (!mbox->mbox_used_privileges)
+ (void)file_dotlock_touch(mbox->mbox_dotlock);
+ else {
+ (void)mbox_dotlock_privileged_op(mbox, NULL,
+ MBOX_DOTLOCK_OP_TOUCH);
+ }
+}
diff -r 2e8ff3074f5b -r 12adb981226e src/lib-storage/index/mbox/mbox-lock.h
--- a/src/lib-storage/index/mbox/mbox-lock.h Tue Mar 04 07:44:19 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-lock.h Tue Mar 04 07:54:53 2008 +0200
@@ -7,4 +7,6 @@ int mbox_lock(struct mbox_mailbox *mbox,
unsigned int *lock_id_r);
int mbox_unlock(struct mbox_mailbox *mbox, unsigned int lock_id);
+void mbox_dotlock_touch(struct mbox_mailbox *mbox);
+
#endif
diff -r 2e8ff3074f5b -r 12adb981226e src/lib-storage/index/mbox/mbox-storage.c
--- a/src/lib-storage/index/mbox/mbox-storage.c Tue Mar 04 07:44:19 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.c Tue Mar 04 07:54:53 2008 +0200
@@ -396,6 +396,33 @@ static struct mail_storage *mbox_alloc(v
return &storage->storage;
}
+static bool mbox_name_is_dotlock(const char *name)
+{
+ unsigned int len = strlen(name);
+
+ return len >= 5 && strcmp(name + len - 5, ".lock") == 0;
+}
+
+static bool
+mbox_is_valid_existing_name(struct mailbox_list *list, const char *name)
+{
+ struct mbox_storage *storage = MBOX_LIST_CONTEXT(list);
+
+ return storage->list_module_ctx.super.
+ is_valid_existing_name(list, name) &&
+ !mbox_name_is_dotlock(name);
+}
+
+static bool
+mbox_is_valid_create_name(struct mailbox_list *list, const char *name)
+{
+ struct mbox_storage *storage = MBOX_LIST_CONTEXT(list);
+
+ return storage->list_module_ctx.super.
+ is_valid_create_name(list, name) &&
+ !mbox_name_is_dotlock(name);
+}
+
static int mbox_create(struct mail_storage *_storage, const char *data,
const char **error_r)
{
@@ -419,6 +446,8 @@ static int mbox_create(struct mail_stora
}
_storage->list->v.iter_is_mailbox = mbox_list_iter_is_mailbox;
_storage->list->v.delete_mailbox = mbox_list_delete_mailbox;
+ _storage->list->v.is_valid_existing_name = mbox_is_valid_existing_name;
+ _storage->list->v.is_valid_create_name = mbox_is_valid_create_name;
MODULE_CONTEXT_SET_FULL(_storage->list, mbox_mailbox_list_module,
storage, &storage->list_module_ctx);
@@ -492,7 +521,7 @@ static bool want_memory_indexes(struct m
static void mbox_lock_touch_timeout(struct mbox_mailbox *mbox)
{
- (void)file_dotlock_touch(mbox->mbox_dotlock);
+ mbox_dotlock_touch(mbox);
}
static struct mbox_mailbox *
@@ -553,7 +582,7 @@ mbox_open(struct mbox_storage *storage,
struct mail_storage *_storage = &storage->storage;
struct mbox_mailbox *mbox;
struct mail_index *index;
- const char *path;
+ const char *path, *rootdir;
path = mailbox_list_get_path(_storage->list, name,
MAILBOX_LIST_PATH_TYPE_MAILBOX);
@@ -570,6 +599,14 @@ mbox_open(struct mbox_storage *storage,
}
}
+ if (strcmp(name, "INBOX") == 0) {
+ /* if INBOX isn't under the root directory, it's probably in
+ /var/mail and we want to allow privileged dotlocking */
+ rootdir = mailbox_list_get_path(_storage->list, NULL,
+ MAILBOX_LIST_PATH_TYPE_DIR);
+ if (strncmp(path, rootdir, strlen(rootdir)) != 0)
+ mbox->mbox_privileged_locking = TRUE;
+ }
return &mbox->ibox.box;
}
diff -r 2e8ff3074f5b -r 12adb981226e src/lib-storage/index/mbox/mbox-storage.h
--- a/src/lib-storage/index/mbox/mbox-storage.h Tue Mar 04 07:44:19 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.h Tue Mar 04 07:54:53 2008 +0200
More information about the dovecot-cvs
mailing list