/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
+#include "eacces-error.h"
#include "restrict-access.h"
#include "nfs-workarounds.h"
#include "mail-index-private.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
+#include <grp.h>
#ifdef HAVE_FLOCK
# include <sys/file.h>
enum mbox_dotlock_op op)
{
const char *dir, *fname;
- int ret = -1, orig_dir_fd;
+ int ret = -1, orig_dir_fd, orig_errno;
orig_dir_fd = open(".", O_RDONLY);
if (orig_dir_fd == -1) {
ret = file_dotlock_create(set, fname, 0, &mbox->mbox_dotlock);
if (ret > 0)
mbox->mbox_used_privileges = TRUE;
+ else if (ret < 0 && errno == EACCES) {
+ const char *errmsg =
+ eacces_error_get_creating("file_dotlock_create",
+ fname);
+ mail_storage_set_critical(&mbox->storage->storage,
+ "%s", errmsg);
+ } else {
+ mbox_set_syscall_error(mbox, "file_dotlock_create()");
+ }
break;
case MBOX_DOTLOCK_OP_UNLOCK:
/* we're now privileged - avoid doing as much as possible */
ret = file_dotlock_delete(&mbox->mbox_dotlock);
+ if (ret < 0)
+ mbox_set_syscall_error(mbox, "file_dotlock_delete()");
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);
+ if (file_dotlock_delete(&mbox->mbox_dotlock) < 0) {
+ mbox_set_syscall_error(mbox,
+ "file_dotlock_delete()");
+ }
mbox->mbox_used_privileges = TRUE;
ret = -1;
} else {
ret = file_dotlock_touch(mbox->mbox_dotlock);
+ if (ret < 0) {
+ mbox_set_syscall_error(mbox,
+ "file_dotlock_touch()");
+ }
}
break;
}
+ orig_errno = errno;
restrict_access_drop_priv_gid();
if (fchdir(orig_dir_fd) < 0) {
"fchdir() failed: %m");
}
(void)close(orig_dir_fd);
+ errno = orig_errno;
return ret;
}
+static void
+mbox_dotlock_log_eacces_error(struct mbox_mailbox *mbox, const char *path)
+{
+ const char *dir, *errmsg;
+ struct stat st;
+ const struct group *group;
+ int orig_errno = errno;
+
+ errmsg = eacces_error_get_creating("file_dotlock_create", path);
+ dir = strrchr(path, '/');
+ dir = dir == NULL ? "." : t_strdup_until(path, dir);
+ if (stat(dir, &st) == 0 &&
+ (st.st_mode & 02) == 0 && /* not world-writable */
+ (st.st_mode & 020) != 0) { /* group-writable */
+ group = getgrgid(st.st_gid);
+ mail_storage_set_critical(&mbox->storage->storage,
+ "%s (set mail_privileged_group=%s)", errmsg,
+ group == NULL ? dec2str(st.st_gid) : group->gr_name);
+ } else {
+ mail_storage_set_critical(&mbox->storage->storage,
+ "%s (nonstandard permissions in %s)", errmsg, path);
+ }
+ errno = orig_errno;
+}
+
static int
mbox_lock_dotlock_int(struct mbox_lock_context *ctx, int lock_type, bool try)
{
if (!mbox->mbox_dotlocked)
return 1;
- if (!mbox->mbox_used_privileges)
- ret = file_dotlock_delete(&mbox->mbox_dotlock);
- else {
+ if (!mbox->mbox_used_privileges) {
+ if (file_dotlock_delete(&mbox->mbox_dotlock) <= 0) {
+ mbox_set_syscall_error(mbox,
+ "file_dotlock_delete()");
+ }
+ } else {
ctx->using_privileges = TRUE;
- ret = mbox_dotlock_privileged_op(mbox, NULL,
- MBOX_DOTLOCK_OP_UNLOCK);
+ (void)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;
- }
mbox->mbox_dotlocked = FALSE;
return 1;
}
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) {
+ if (ret >= 0) {
+ /* success / timeout */
+ } else if (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);
- }
+ } else if (errno == EACCES)
+ mbox_dotlock_log_eacces_error(mbox, mbox->path);
+ else
+ mbox_set_syscall_error(mbox, "file_dotlock_create()");
if (ret < 0) {
if ((ENOSPACE(errno) || errno == EACCES) && try)
return 1;
-
- mbox_set_syscall_error(mbox, "file_lock_dotlock()");
return -1;
}
if (ret == 0) {