changeset 1151:058f6c26f405 HEAD

Added mail_full_filesystem_access setting. Some of the setting variable types were declared wrong and caused Dovecot to crash if they were set in config file.
author Timo Sirainen <tss@iki.fi>
date Tue, 11 Feb 2003 21:37:16 +0200
parents 18a2074a4d3d
children 95d67b5c3fd4
files dovecot-example.conf src/lib-storage/index/maildir/maildir-list.c src/lib-storage/index/mbox/mbox-list.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/mail-storage.c src/lib-storage/mail-storage.h src/lib/Makefile.am src/lib/home-expand.c src/lib/home-expand.h src/master/master-settings.c src/master/master-settings.h
diffstat 11 files changed, 175 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/dovecot-example.conf	Tue Feb 11 20:01:38 2003 +0200
+++ b/dovecot-example.conf	Tue Feb 11 21:37:16 2003 +0200
@@ -223,6 +223,12 @@
 # NOTE: Evolution client breaks with this option when it's trying to APPEND.
 #mailbox_check_interval = 0
 
+# 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
+# maildir and mboxes, allowing you to prefix mailboxes names with eg. /path/
+# or ~user/.
+#mail_full_filesystem_access = no
+
 # Save mails with CR+LF instead of plain LF. This makes sending those mails
 # take less CPU, especially with sendfile() syscall with Linux and FreeBSD.
 # But it also creates a bit more disk I/O which may just make it slower.
--- a/src/lib-storage/index/maildir/maildir-list.c	Tue Feb 11 20:01:38 2003 +0200
+++ b/src/lib-storage/index/maildir/maildir-list.c	Tue Feb 11 21:37:16 2003 +0200
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "hostpid.h"
+#include "home-expand.h"
 #include "unlink-directory.h"
 #include "imap-match.h"
 #include "subscription-file/subscription-file.h"
@@ -79,15 +80,32 @@
 	struct dirent *d;
 	struct stat st;
         enum mailbox_flags flags;
+	const char *dir, *prefix, *p;
 	char path[PATH_MAX];
-	int failed, found_inbox;
+	int failed, found_inbox, ret;
 
 	mail_storage_clear_error(storage);
 
-	dirp = opendir(storage->dir);
+	if (!full_filesystem_access || (p = strrchr(mask, '/')) == NULL) {
+		dir = storage->dir;
+		prefix = "";
+	} else {
+		if (mask == p)
+			dir = prefix = "/";
+		else {
+			dir = t_strdup_until(mask, p);
+			prefix = t_strdup_until(mask, p+1);
+		}
+
+		if (*mask != '/' && *mask != '~')
+			dir = t_strconcat(storage->dir, "/", dir, NULL);
+		dir = home_expand(dir);
+	}
+
+	dirp = opendir(dir);
 	if (dirp == NULL) {
 		mail_storage_set_critical(storage, "opendir(%s) failed: %m",
-					  storage->dir);
+					  dir);
 		return FALSE;
 	}
 
@@ -106,10 +124,13 @@
 
 		/* make sure the mask matches - dirs beginning with ".."
 		   should be deleted and we always want to check those. */
-		if (fname[1] == '.' || imap_match(glob, fname+1) <= 0)
+		t_push();
+		ret = imap_match(glob, t_strconcat(prefix, fname+1, NULL));
+		t_pop();
+		if (fname[1] == '.' || ret <= 0)
 			continue;
 
-		if (str_path(path, sizeof(path), storage->dir, fname) < 0)
+		if (str_path(path, sizeof(path), dir, fname) < 0)
 			continue;
 
 		/* make sure it's a directory */
@@ -147,7 +168,8 @@
 
 		t_push();
 		flags = maildir_get_marked_flags(storage, path);
-		callback(storage, fname+1, flags, context);
+		callback(storage, t_strconcat(prefix, fname+1, NULL),
+			 flags, context);
 		t_pop();
 	}
 
--- a/src/lib-storage/index/mbox/mbox-list.c	Tue Feb 11 20:01:38 2003 +0200
+++ b/src/lib-storage/index/mbox/mbox-list.c	Tue Feb 11 21:37:16 2003 +0200
@@ -6,6 +6,7 @@
 #include "subscription-file/subscription-file.h"
 #include "mbox-index.h"
 #include "mbox-storage.h"
+#include "home-expand.h"
 
 #include <dirent.h>
 #include <sys/stat.h>
@@ -15,10 +16,16 @@
 	void *context;
 };
 
-static int mbox_find_path(struct mail_storage *storage,
-			  struct imap_match_glob *glob,
-			  mailbox_list_callback_t callback, void *context,
-			  const char *relative_dir)
+struct list_context {
+	struct mail_storage *storage;
+	struct imap_match_glob *glob;
+	mailbox_list_callback_t *callback;
+	void *context;
+
+	const char *rootdir;
+};
+
+static int mbox_find_path(struct list_context *ctx, const char *relative_dir)
 {
 	DIR *dirp;
 	struct dirent *d;
@@ -31,11 +38,14 @@
 	t_push();
 
 	if (relative_dir == NULL)
-		dir = storage->dir;
+		dir = ctx->rootdir;
+	else if (*ctx->rootdir == '\0' && *relative_dir != '\0')
+		dir = relative_dir;
 	else {
 		if (str_path(fulldir, sizeof(fulldir),
-			     storage->dir, relative_dir) < 0) {
-			mail_storage_set_critical(storage, "Path too long: %s",
+			     ctx->rootdir, relative_dir) < 0) {
+			mail_storage_set_critical(ctx->storage,
+						  "Path too long: %s",
 						  relative_dir);
 			return FALSE;
 		}
@@ -43,6 +53,7 @@
 		dir = fulldir;
 	}
 
+	dir = home_expand(dir);
 	dirp = opendir(dir);
 	if (dirp == NULL) {
 		t_pop();
@@ -54,7 +65,16 @@
 			return TRUE;
 		}
 
-		mail_storage_set_critical(storage,
+		if (errno == EACCES) {
+			if (relative_dir != NULL) {
+				/* subfolder, ignore */
+				return TRUE;
+			}
+			mail_storage_set_error(ctx->storage, "Access denied");
+			return FALSE;
+		}
+
+		mail_storage_set_critical(ctx->storage,
 					  "opendir(%s) failed: %m", dir);
 		return FALSE;
 	}
@@ -78,7 +98,7 @@
 		else {
 			if (str_path(path, sizeof(path),
 				     relative_dir, fname) < 0) {
-				mail_storage_set_critical(storage,
+				mail_storage_set_critical(ctx->storage,
 					"Path too long: %s/%s",
 					relative_dir, fname);
 				failed = TRUE;
@@ -87,12 +107,12 @@
 			listpath = path;
 		}
 
-		if ((match = imap_match(glob, listpath)) < 0)
+		if ((match = imap_match(ctx->glob, listpath)) < 0)
 			continue;
 
 		/* see if it's a directory */
 		if (str_path(fullpath, sizeof(fullpath), dir, fname) < 0) {
-			mail_storage_set_critical(storage,
+			mail_storage_set_critical(ctx->storage,
 						  "Path too long: %s/%s",
 						  dir, fname);
 			failed = TRUE;
@@ -103,8 +123,9 @@
 			if (errno == ENOENT)
 				continue; /* just deleted, ignore */
 
-			mail_storage_set_critical(storage, "stat(%s) failed: "
-						  "%m", fullpath);
+			mail_storage_set_critical(ctx->storage,
+						  "stat(%s) failed: %m",
+						  fullpath);
 			failed = TRUE;
 			break;
 		}
@@ -112,22 +133,23 @@
 		if (S_ISDIR(st.st_mode)) {
 			/* subdirectory, scan it too */
 			t_push();
-			callback(storage, listpath, MAILBOX_NOSELECT, context);
+			ctx->callback(ctx->storage, listpath, MAILBOX_NOSELECT,
+				      ctx->context);
 			t_pop();
 
-			if (!mbox_find_path(storage, glob, callback,
-					    context, listpath)) {
+			if (!mbox_find_path(ctx, listpath)) {
 				failed = TRUE;
 				break;
 			}
 		} else if (match > 0 &&
-			   strcmp(fullpath, storage->inbox_file) != 0 &&
+			   strcmp(fullpath, ctx->storage->inbox_file) != 0 &&
 			   strcasecmp(listpath, "INBOX") != 0) {
 			/* don't match any INBOX here, it's added later.
 			   we might also have ~/mail/inbox, ~/mail/Inbox etc.
 			   Just ignore them for now. */
 			t_push();
-			callback(storage, listpath, MAILBOX_NOINFERIORS, context);
+			ctx->callback(ctx->storage, listpath,
+				      MAILBOX_NOINFERIORS, ctx->context);
 			t_pop();
 		}
 	}
@@ -148,12 +170,13 @@
 			last_dir = p;
 	}
 
-	return last_dir != NULL ? t_strdup_until(mask, last_dir) : NULL;
+	return last_dir == NULL ? NULL : t_strdup_until(mask, last_dir);
 }
 
 int mbox_find_mailboxes(struct mail_storage *storage, const char *mask,
 			mailbox_list_callback_t callback, void *context)
 {
+        struct list_context ctx;
 	struct imap_match_glob *glob;
 	const char *relative_dir;
 
@@ -175,7 +198,31 @@
 		callback(storage, "INBOX", MAILBOX_NOINFERIORS, context);
 	}
 
-	if (!mbox_find_path(storage, glob, callback, context, relative_dir))
+	memset(&ctx, 0, sizeof(ctx));
+	ctx.storage = storage;
+	ctx.glob = glob;
+	ctx.callback = callback;
+	ctx.context = context;
+
+	if (!full_filesystem_access || relative_dir == NULL ||
+	    (*relative_dir != '/' && *relative_dir != '~' &&
+	     *relative_dir != '\0'))
+		ctx.rootdir = storage->dir;
+	else
+		ctx.rootdir = "";
+
+	if (relative_dir != NULL) {
+		const char *matchdir = t_strconcat(relative_dir, "/", NULL);
+
+		if (imap_match(ctx.glob, matchdir) > 0) {
+			t_push();
+			ctx.callback(ctx.storage, matchdir, MAILBOX_NOSELECT,
+				     ctx.context);
+			t_pop();
+		}
+	}
+
+	if (!mbox_find_path(&ctx, relative_dir))
 		return FALSE;
 
 	return TRUE;
--- a/src/lib-storage/index/mbox/mbox-storage.c	Tue Feb 11 20:01:38 2003 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Tue Feb 11 21:37:16 2003 +0200
@@ -220,6 +220,13 @@
 	const char *p;
 	int newdir;
 
+	if (full_filesystem_access)
+		return TRUE;
+
+	/* make sure it's not absolute path */
+	if (*mask == '/' || *mask == '\\' || *mask == '~')
+		return FALSE;
+
 	/* make sure there's no "../" or "..\" stuff */
 	newdir = TRUE;
 	for (p = mask; *p != '\0'; p++) {
--- a/src/lib-storage/mail-storage.c	Tue Feb 11 20:01:38 2003 +0200
+++ b/src/lib-storage/mail-storage.c	Tue Feb 11 21:37:16 2003 +0200
@@ -28,6 +28,7 @@
 
 static struct mail_storage_list *storages = NULL;
 enum client_workarounds client_workarounds = 0;
+int full_filesystem_access = FALSE;
 
 void mail_storage_init(void)
 {
@@ -35,6 +36,8 @@
 	const char *env;
 	const char *const *str;
 
+        full_filesystem_access = getenv("FULL_FILESYSTEM_ACCESS") != NULL;
+
 	env = getenv("CLIENT_WORKAROUNDS");
 	if (env == NULL)
 		return;
--- a/src/lib-storage/mail-storage.h	Tue Feb 11 20:01:38 2003 +0200
+++ b/src/lib-storage/mail-storage.h	Tue Feb 11 21:37:16 2003 +0200
@@ -394,6 +394,7 @@
 };
 
 extern enum client_workarounds client_workarounds;
+extern int full_filesystem_access;
 
 /* Initialize mail storage. */
 void mail_storage_init(void);
--- a/src/lib/Makefile.am	Tue Feb 11 20:01:38 2003 +0200
+++ b/src/lib/Makefile.am	Tue Feb 11 21:37:16 2003 +0200
@@ -14,6 +14,7 @@
 	file-set-size.c \
 	hash.c \
 	hex-binary.c \
+	home-expand.c \
 	hostpid.c \
 	imem.c \
 	iostream.c \
@@ -68,6 +69,7 @@
 	file-set-size.h \
 	hash.h \
 	hex-binary.h \
+	home-expand.h \
 	hostpid.h \
 	imem.h \
 	iostream-internal.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/home-expand.c	Tue Feb 11 21:37:16 2003 +0200
@@ -0,0 +1,41 @@
+/* Copyright (C) 2003 Timo Sirainen */
+
+#include "lib.h"
+#include "home-expand.h"
+
+#include <stdlib.h>
+#include <pwd.h>
+
+/* expand ~/ or ~user/ in beginning of path */
+const char *home_expand(const char *path)
+{
+	const char *home, *p, *orig_path;
+	struct passwd *pw;
+
+	if (*path != '~')
+		return path;
+
+	orig_path = path++;
+	if (*path == '/' || *path == '\0') {
+		home = getenv("HOME");
+		if (*path != '\0') path++;
+	} else {
+		p = strchr(path, '/');
+		if (p == NULL) {
+			pw = getpwnam(path);
+			path = "";
+		} else {
+			pw = getpwnam(t_strdup_until(path, p));
+			path = p+1;
+		}
+
+		home = pw == NULL ? NULL : pw->pw_dir;
+	}
+
+	if (home == NULL)
+		return orig_path;
+	else if (*path == '\0')
+		return t_strdup(home);
+	else
+		return t_strconcat(home, "/", path, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/home-expand.h	Tue Feb 11 21:37:16 2003 +0200
@@ -0,0 +1,7 @@
+#ifndef __HOME_EXPAND_H
+#define __HOME_EXPAND_H
+
+/* expand ~/ or ~user/ in beginning of path */
+const char *home_expand(const char *path);
+
+#endif
--- a/src/master/master-settings.c	Tue Feb 11 20:01:38 2003 +0200
+++ b/src/master/master-settings.c	Tue Feb 11 21:37:16 2003 +0200
@@ -54,17 +54,18 @@
 	DEF(SET_STR, mail_cache_fields),
 	DEF(SET_STR, mail_never_cache_fields),
 	DEF(SET_STR, client_workarounds),
-	DEF(SET_STR, mailbox_check_interval),
-	DEF(SET_STR, mail_save_crlf),
-	DEF(SET_STR, mail_read_mmaped),
-	DEF(SET_STR, maildir_copy_with_hardlinks),
-	DEF(SET_STR, maildir_check_content_changes),
+	DEF(SET_INT, mailbox_check_interval),
+	DEF(SET_BOOL, mail_full_filesystem_access),
+	DEF(SET_BOOL, mail_save_crlf),
+	DEF(SET_BOOL, mail_read_mmaped),
+	DEF(SET_BOOL, maildir_copy_with_hardlinks),
+	DEF(SET_BOOL, maildir_check_content_changes),
 	DEF(SET_STR, mbox_locks),
-	DEF(SET_STR, mbox_read_dotlock),
-	DEF(SET_STR, mbox_lock_timeout),
-	DEF(SET_STR, mbox_dotlock_change_timeout),
-	DEF(SET_STR, overwrite_incompatible_index),
-	DEF(SET_STR, umask),
+	DEF(SET_BOOL, mbox_read_dotlock),
+	DEF(SET_INT, mbox_lock_timeout),
+	DEF(SET_INT, mbox_dotlock_change_timeout),
+	DEF(SET_BOOL, overwrite_incompatible_index),
+	DEF(SET_INT, umask),
 
 	/* imap */
 	DEF(SET_STR, imap_executable),
@@ -157,6 +158,7 @@
 	MEMBER(mail_never_cache_fields) NULL,
 	MEMBER(client_workarounds) NULL,
 	MEMBER(mailbox_check_interval) 0,
+	MEMBER(mail_full_filesystem_access) FALSE,
 	MEMBER(mail_save_crlf) FALSE,
 	MEMBER(mail_read_mmaped) FALSE,
 	MEMBER(maildir_copy_with_hardlinks) FALSE,
--- a/src/master/master-settings.h	Tue Feb 11 20:01:38 2003 +0200
+++ b/src/master/master-settings.h	Tue Feb 11 21:37:16 2003 +0200
@@ -39,6 +39,7 @@
 	const char *mail_never_cache_fields;
 	const char *client_workarounds;
 	unsigned int mailbox_check_interval;
+	int mail_full_filesystem_access;
 	int mail_save_crlf;
 	int mail_read_mmaped;
 	int maildir_copy_with_hardlinks;