]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added mail_full_filesystem_access setting. Some of the setting variable
authorTimo Sirainen <tss@iki.fi>
Tue, 11 Feb 2003 19:37:16 +0000 (21:37 +0200)
committerTimo Sirainen <tss@iki.fi>
Tue, 11 Feb 2003 19:37:16 +0000 (21:37 +0200)
types were declared wrong and caused Dovecot to crash if they were set in
config file.

--HG--
branch : HEAD

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 [new file with mode: 0644]
src/lib/home-expand.h [new file with mode: 0644]
src/master/master-settings.c
src/master/master-settings.h

index dc91243cb3b7f8c883893bcf7d193ed06060a2da..1bbe75d403b8b7bf3b7d45db5844f6a6bb405a68 100644 (file)
@@ -223,6 +223,12 @@ login = pop3
 # 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.
index 987aeaeefa3b33b62cd865c4c4f58b9b25172227..b0202200c3c28d54d2a9802f91bee8a7aa339aa5 100644 (file)
@@ -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 @@ int maildir_find_mailboxes(struct mail_storage *storage, const char *mask,
        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 @@ int maildir_find_mailboxes(struct mail_storage *storage, const char *mask,
 
                /* 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 @@ int maildir_find_mailboxes(struct mail_storage *storage, const char *mask,
 
                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();
        }
 
index a67d9cd7b27f004bec240c3dfc3f79e0163518a6..df4f8f7e4a4cf6303867dde4e93c37472c2a5a13 100644 (file)
@@ -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 @@ struct find_subscribed_context {
        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 @@ static int mbox_find_path(struct mail_storage *storage,
        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 @@ static int mbox_find_path(struct mail_storage *storage,
                dir = fulldir;
        }
 
+       dir = home_expand(dir);
        dirp = opendir(dir);
        if (dirp == NULL) {
                t_pop();
@@ -54,7 +65,16 @@ static int mbox_find_path(struct mail_storage *storage,
                        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 @@ static int mbox_find_path(struct mail_storage *storage,
                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 @@ static int mbox_find_path(struct mail_storage *storage,
                        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 @@ static int mbox_find_path(struct mail_storage *storage,
                        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 @@ static int mbox_find_path(struct mail_storage *storage,
                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 @@ static const char *mask_get_dir(const char *mask)
                        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 @@ int mbox_find_mailboxes(struct mail_storage *storage, const char *mask,
                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;
index 68576dc177968ca1037ffc68899712311aacebca..7366d069fe8b214879614a9e5242232baae5b9a2 100644 (file)
@@ -220,6 +220,13 @@ int mbox_is_valid_mask(const char *mask)
        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++) {
index 32169879f18d2a2311b01dc4d515bab89f89a34c..f1ad843331f3f3afac36e8b9edb7397dba47ae21 100644 (file)
@@ -28,6 +28,7 @@ struct client_workaround_list client_workaround_list[] = {
 
 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 @@ void mail_storage_init(void)
        const char *env;
        const char *const *str;
 
+        full_filesystem_access = getenv("FULL_FILESYSTEM_ACCESS") != NULL;
+
        env = getenv("CLIENT_WORKAROUNDS");
        if (env == NULL)
                return;
index bc4c383fa9fab7f092931ff13fc39b8883d42b95..e286fa79ce6a258787c13762ff5e46ed5ffc8082 100644 (file)
@@ -394,6 +394,7 @@ struct mail_storage_callbacks {
 };
 
 extern enum client_workarounds client_workarounds;
+extern int full_filesystem_access;
 
 /* Initialize mail storage. */
 void mail_storage_init(void);
index d3187b91920c9f36383523f989be2ac7675da158..57439bdcf84032cc152f78664c169f22948383c8 100644 (file)
@@ -14,6 +14,7 @@ liblib_a_SOURCES = \
        file-set-size.c \
        hash.c \
        hex-binary.c \
+       home-expand.c \
        hostpid.c \
        imem.c \
        iostream.c \
@@ -68,6 +69,7 @@ noinst_HEADERS = \
        file-set-size.h \
        hash.h \
        hex-binary.h \
+       home-expand.h \
        hostpid.h \
        imem.h \
        iostream-internal.h \
diff --git a/src/lib/home-expand.c b/src/lib/home-expand.c
new file mode 100644 (file)
index 0000000..a95055e
--- /dev/null
@@ -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);
+}
diff --git a/src/lib/home-expand.h b/src/lib/home-expand.h
new file mode 100644 (file)
index 0000000..810c07b
--- /dev/null
@@ -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
index 5a8561d61fef0798a19008672b17780f354e0089..ccc176c9ab3d234d197258b474bd580232c12b44 100644 (file)
@@ -54,17 +54,18 @@ static struct setting_def setting_defs[] = {
        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 @@ struct settings default_settings = {
        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,
index da27078ecf5d8db9cd9da42db397e37397f0f088..bda815bd8afb4c99fc251f6d440d0fd3f7d433ec 100644 (file)
@@ -39,6 +39,7 @@ struct settings {
        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;