diff --git a/src/lib-sieve-tool/mail-raw.c b/src/lib-sieve-tool/mail-raw.c index d3c773f48094ed213f4abb58389e43563df11bb9..5417dc49e642c0021aeb4eb1713d7302256d28d3 100644 --- a/src/lib-sieve-tool/mail-raw.c +++ b/src/lib-sieve-tool/mail-raw.c @@ -9,7 +9,7 @@ #include "str-sanitize.h" #include "strescape.h" #include "safe-mkstemp.h" -#include "abspath.h" +#include "path-util.h" #include "message-address.h" #include "mbox-from.h" #include "raw-storage.h" @@ -153,11 +153,13 @@ static struct mail_raw *mail_raw_create { struct mail_raw *mailr; struct mailbox_header_lookup_ctx *headers_ctx; - const char *envelope_sender; + const char *envelope_sender, *error; int ret; if ( mailfile != NULL && *mailfile != '/' ) - mailfile = t_abspath(mailfile); + if (t_abspath(mailfile, &mailfile, &error) < 0) + i_fatal("t_abspath(%s) failed: %s", + mailfile, error); mailr = i_new(struct mail_raw, 1); diff --git a/src/lib-sieve/storage/file/sieve-file-script.c b/src/lib-sieve/storage/file/sieve-file-script.c index 4c3e722d919179c924a311c07ceddddc3454f890..ec0b97d65353dfa75d7c15273b45fc7a8f8399ed 100644 --- a/src/lib-sieve/storage/file/sieve-file-script.c +++ b/src/lib-sieve/storage/file/sieve-file-script.c @@ -3,7 +3,7 @@ #include "lib.h" #include "mempool.h" -#include "abspath.h" +#include "path-util.h" #include "istream.h" #include "time-util.h" #include "eacces-error.h" @@ -55,10 +55,20 @@ static void sieve_file_script_handle_error const char *name, enum sieve_error *error_r) { struct sieve_script *script = &fscript->script; + const char *abspath, *error; switch ( errno ) { case ENOENT: - sieve_script_sys_debug(script, "File `%s' not found", t_abspath(path)); + if (t_abspath(path, &abspath, &error) < 0) { + sieve_script_set_error(script, + SIEVE_ERROR_TEMP_FAILURE, + "t_abspath(%s) failed: %s", + path, error); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + break; + } + sieve_script_sys_debug(script, "File `%s' not found", + abspath); sieve_script_set_error(script, SIEVE_ERROR_NOT_FOUND, "Sieve script `%s' not found", name); diff --git a/src/lib-sieve/storage/file/sieve-file-storage-active.c b/src/lib-sieve/storage/file/sieve-file-storage-active.c index cef80560ceb6ebca5f0b97b1d7b05cd3bfcfc622..5cbdd759d7962fc3462b2bb39767cb7accabde82 100644 --- a/src/lib-sieve/storage/file/sieve-file-storage-active.c +++ b/src/lib-sieve/storage/file/sieve-file-storage-active.c @@ -2,13 +2,11 @@ */ #include "lib.h" -#include "abspath.h" +#include "path-util.h" #include "ioloop.h" #include "hostpid.h" #include "file-copy.h" -#include "realpath.h" - #include "sieve-file-storage.h" #include <unistd.h> @@ -21,9 +19,10 @@ static int sieve_file_storage_active_read_link (struct sieve_file_storage *fstorage, const char **link_r) { struct sieve_storage *storage = &fstorage->storage; + const char *error = NULL; int ret; - ret = t_readlink(fstorage->active_path, link_r); + ret = t_readlink(fstorage->active_path, link_r, &error); if ( ret < 0 ) { *link_r = NULL; @@ -49,8 +48,8 @@ static int sieve_file_storage_active_read_link /* We do need to panic otherwise */ sieve_storage_set_critical(storage, - "Performing readlink() on active sieve symlink '%s' failed: %m", - fstorage->active_path); + "Performing t_readlink() on active sieve symlink '%s' failed: %s", + fstorage->active_path, error); return -1; } @@ -95,11 +94,12 @@ static const char *sieve_file_storage_active_parse_link } /* Check whether the path is any good */ - if ( t_normpath_to(scriptpath, link_dir, &scriptpath) < 0 ) { + const char *error = NULL; + if ( t_normpath_to(scriptpath, link_dir, &scriptpath, &error) < 0 ) { sieve_storage_sys_warning(storage, "Failed to check active Sieve script symlink %s: " - "Failed to normalize path (points to %s).", - fstorage->active_path, scriptpath); + "Failed to normalize path (points to %s): %s", + fstorage->active_path, scriptpath, error); return NULL; } if ( strcmp(scriptpath, fstorage->path) != 0 ) { diff --git a/src/lib-sieve/storage/file/sieve-file-storage.c b/src/lib-sieve/storage/file/sieve-file-storage.c index eacff8c15a0a365441b9d2cd90cb71f8988412fe..e5468bf11491d2c26330447c0888e474d6d974b5 100644 --- a/src/lib-sieve/storage/file/sieve-file-storage.c +++ b/src/lib-sieve/storage/file/sieve-file-storage.c @@ -2,7 +2,7 @@ */ #include "lib.h" -#include "abspath.h" +#include "path-util.h" #include "home-expand.h" #include "ioloop.h" #include "mkdir-parents.h" @@ -10,8 +10,6 @@ #include "unlink-old-files.h" #include "mail-storage-private.h" -#include "realpath.h" - #include "sieve.h" #include "sieve-common.h" #include "sieve-settings.h" @@ -54,6 +52,7 @@ static int sieve_file_storage_stat { struct sieve_storage *storage = &fstorage->storage; struct stat st; + const char *abspath, *error; if ( lstat(path, &st) == 0 ) { fstorage->lnk_st = st; @@ -66,8 +65,14 @@ static int sieve_file_storage_stat switch ( errno ) { case ENOENT: + if (t_abspath(path, &abspath, &error) < 0) { + sieve_storage_set_critical(storage, + "t_abspath(%s) failed: %s", path, error); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + break; + } sieve_storage_sys_debug(storage, - "Storage path `%s' not found", t_abspath(path)); + "Storage path `%s' not found", abspath); sieve_storage_set_internal_error(storage); // should be overriden *error_r = SIEVE_ERROR_NOT_FOUND; break; @@ -294,7 +299,7 @@ static int sieve_file_storage_init_common ATTR_NULL(2, 3) { struct sieve_storage *storage = &fstorage->storage; - const char *tmp_dir, *link_path, *active_fname, *storage_dir; + const char *tmp_dir, *link_path, *active_fname, *storage_dir, *error; bool have_link = FALSE; int ret; @@ -333,11 +338,11 @@ static int sieve_file_storage_init_common return -1; } - if (t_realpath(active_dir, &active_dir) < 0) { + if (t_realpath(active_dir, &active_dir, &error) < 0) { if (errno != ENOENT) { sieve_storage_sys_error(storage, - "Failed to normalize active script directory (path=%s): %m", - active_dir); + "Failed to normalize active script directory (path=%s): %s", + active_dir, error); *error_r = SIEVE_ERROR_TEMP_FAILURE; return -1; } @@ -455,10 +460,10 @@ static int sieve_file_storage_init_common return -1; if ( have_link ) { - if ( t_realpath(storage_path, &storage_path) < 0 ) { + if ( t_realpath(storage_path, &storage_path, &error) < 0 ) { sieve_storage_sys_error(storage, - "Failed to normalize storage path (path=%s): %m", - storage_path); + "Failed to normalize storage path (path=%s): %s", + storage_path, error); *error_r = SIEVE_ERROR_TEMP_FAILURE; return -1; } diff --git a/src/lib-sieve/util/Makefile.am b/src/lib-sieve/util/Makefile.am index b57fa041de1d163bf8313abc23a24542d9dc9cb3..8f2d8c5e8627bc2d0a7a81a76e9e32c657ba3810 100644 --- a/src/lib-sieve/util/Makefile.am +++ b/src/lib-sieve/util/Makefile.am @@ -9,13 +9,11 @@ libsieve_util_la_DEPENDENCIES = $(LIBDOVECOT_STORAGE_DEPS) $(LIBDOVECOT_DEPS) libsieve_util_la_SOURCES = \ edit-mail.c \ - rfc2822.c \ - realpath.c + rfc2822.c headers = \ edit-mail.h \ - rfc2822.h \ - realpath.h + rfc2822.h pkginc_libdir=$(dovecot_pkgincludedir)/sieve pkginc_lib_HEADERS = $(headers) diff --git a/src/lib-sieve/util/realpath.c b/src/lib-sieve/util/realpath.c deleted file mode 100644 index a8cfdc2b943eef653c24d8a1855ca057263b0102..0000000000000000000000000000000000000000 --- a/src/lib-sieve/util/realpath.c +++ /dev/null @@ -1,239 +0,0 @@ -/* Copyright (c) 2009-2016 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "str.h" - -#include "realpath.h" - -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> - -// FIXME: move/merge to Dovecot - -#define REALPATH_MAX_PATH 8*1024 -#define REALPATH_MAX_SYMLINKS 80 - -static int t_getcwd_alloc(char **dir_r, size_t *asize_r) -{ - /* @UNSAFE */ - char *dir; - size_t asize = 128; - - dir = t_buffer_get(asize); - while (getcwd(dir, asize) == NULL) { - if (errno != ERANGE) - return -1; - asize = nearest_power(asize+1); - dir = t_buffer_get(asize); - } - *asize_r = asize; - *dir_r = dir; - return 0; -} - -static int path_normalize(const char *path, bool resolve_links, - const char **npath_r) -{ - /* @UNSAFE */ - unsigned int link_count = 0; - char *npath, *npath_pos; - const char *p; - size_t asize; - - if (path[0] != '/') { - /* relative; initialize npath with current directory */ - if (t_getcwd_alloc(&npath, &asize) < 0) - return -1; - npath_pos = npath + strlen(npath); - i_assert(npath[0] == '/'); - } else { - /* absolute; initialize npath with root */ - asize = 128; - npath = t_buffer_get(asize); - npath[0] = '/'; - npath_pos = npath + 1; - } - - p = path; - while (*p != '\0') { - struct stat st; - ptrdiff_t seglen; - const char *segend; - - /* skip duplicate shashes */ - while (*p == '/') - p++; - - /* find end of path segment */ - for (segend = p; *segend != '\0' && *segend != '/'; segend++); - - if (segend == p) - break; /* '\0' */ - seglen = segend - p; - if (seglen == 1 && p[0] == '.') { - /* a reference to this segment; nothing to do */ - } else if (seglen == 2 && p[0] == '.' && p[1] == '.') { - /* a reference to parent segment; back up to previous slash */ - if (npath_pos > npath + 1) { - if (*(npath_pos-1) == '/') - npath_pos--; - for (; *(npath_pos-1) != '/'; npath_pos--); - } - } else { - /* make sure npath now ends in slash */ - if (*(npath_pos-1) != '/') - *(npath_pos++) = '/'; - - /* allocate space if necessary */ - if ((npath_pos + seglen + 1) >= (npath + asize)) { - ptrdiff_t npath_offset = npath_pos - npath; - asize = nearest_power(npath_offset + seglen + 2); - npath = t_buffer_reget(npath, asize); - npath_pos = npath + npath_offset; - } - - /* copy segment to normalized path */ - (void)memmove(npath_pos, p, seglen); - npath_pos += seglen; - } - - if (resolve_links) { - /* stat path up to here (segend points to tail) */ - *npath_pos = '\0'; - if (lstat(npath, &st) < 0) - return -1; - - if (S_ISLNK (st.st_mode)) { - /* symlink */ - char *npath_link; - size_t lsize = 128, tlen = strlen(segend), espace; - size_t ltlen = (link_count == 0 ? 0 : tlen); - ssize_t ret; - - /* limit link dereferences */ - if (++link_count > REALPATH_MAX_SYMLINKS) { - errno = ELOOP; - return -1; - } - - /* allocate space for preserving tail of previous symlink and - first attempt at reading symlink with room for the tail - - buffer will look like this: - [npath][0][preserved tail][link buffer][room for tail][0] - */ - espace = ltlen + tlen + 2; - if ((npath_pos + espace + lsize) >= (npath + asize)) { - ptrdiff_t npath_offset = npath_pos - npath; - asize = nearest_power((npath_offset + espace + lsize) + 1); - lsize = asize - (npath_offset + espace); - npath = t_buffer_reget(npath, asize); - npath_pos = npath + npath_offset; - } - - if (ltlen > 0) { - /* preserve tail just after end of npath */ - (void)memmove(npath_pos + 1, segend, ltlen); - } - - /* read the symlink after the preserved tail */ - for (;;) { - npath_link = (npath_pos + 1) + ltlen; - - /* attempt to read the link */ - if ((ret=readlink(npath, npath_link, lsize)) < 0) - return -1; - if ((size_t)ret < lsize) { - /* make static analyzers happy */ - npath_link[ret] = '\0'; - break; - } - - /* sum of new symlink content length and path tail length may not - exeed maximum */ - if ((size_t)(ret + tlen) >= REALPATH_MAX_PATH) { - errno = ENAMETOOLONG; - return -1; - } - - /* try again with bigger buffer */ - espace = ltlen + tlen + 2; - if ((npath_pos + espace + lsize) >= (npath + asize)) { - ptrdiff_t npath_offset = npath_pos - npath; - asize = nearest_power((npath_offset + espace + lsize) + 1); - lsize = asize - (npath_offset + espace); - npath = t_buffer_reget(npath, asize); - npath_pos = npath + npath_offset; - } - } - - /* add tail of previous path at end of symlink */ - if (ltlen > 0) - (void)memcpy(npath_link + ret, npath_pos + 1, tlen); - else - (void)memcpy(npath_link + ret, segend, tlen); - *(npath_link+ret+tlen) = '\0'; - - /* use as new source path */ - path = segend = npath_link; - - if (path[0] == '/') { - /* absolute symlink; start over at root */ - npath_pos = npath + 1; - } else { - /* relative symlink; back up to previous segment */ - if (npath_pos > npath + 1) { - if (*(npath_pos-1) == '/') - npath_pos--; - for (; *(npath_pos-1) != '/'; npath_pos--); - } - } - - } else if (*segend != '\0' && !S_ISDIR (st.st_mode)) { - /* not last segment, but not a directory either */ - errno = ENOTDIR; - return -1; - } - } - - p = segend; - } - - /* remove any trailing slash */ - if (npath_pos > npath + 1 && *(npath_pos-1) == '/') - npath_pos--; - *npath_pos = '\0'; - - t_buffer_alloc(npath_pos - npath + 1); - *npath_r = npath; - return 0; -} - -int t_normpath(const char *path, const char **npath_r) -{ - return path_normalize(path, FALSE, npath_r); -} - -int t_normpath_to(const char *path, const char *root, - const char **npath_r) -{ - if (*path == '/') - return t_normpath(path, npath_r); - - return t_normpath(t_strconcat(root, "/", path, NULL), npath_r); -} - -int t_realpath(const char *path, const char **npath_r) -{ - return path_normalize(path, TRUE, npath_r); -} - -int t_realpath_to(const char *path, const char *root, - const char **npath_r) -{ - if (*path == '/') - return t_realpath(path, npath_r); - - return t_realpath(t_strconcat(root, "/", path, NULL), npath_r); -} diff --git a/src/lib-sieve/util/realpath.h b/src/lib-sieve/util/realpath.h deleted file mode 100644 index 4a5d34288fcc23f93cb449ddbc4d1f7f36265bdd..0000000000000000000000000000000000000000 --- a/src/lib-sieve/util/realpath.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef REALPATH_H -#define REALPATH_H - -/* Returns path as the normalized absolute path, which means that './' - and '../' components are resolved, and that duplicate and trailing - slashes are removed. If it's not already the absolute path, it's - assumed to be relative to the current working directory. - - NOTE: Be careful with this function. The resolution of '../' components - with the parent component as if it were a normal directory is not valid - if the path contains symbolic links. - */ -int t_normpath(const char *path, const char **npath_r); -/* Like t_normpath(), but path is relative to given root. */ -int t_normpath_to(const char *path, const char *root, - const char **npath_r); - -/* Returns path as the real normalized absolute path, which means that all - symbolic links in the path are resolved, that './' and '../' components - are resolved, and that duplicate and trailing slashes are removed. If it's - not already the absolute path, it's assumed to be relative to the current - working directory. - - NOTE: This function calls stat() for each path component and more when - there are symbolic links (just like POSIX realpath()). - */ -int t_realpath(const char *path, const char **npath_r); -/* Like t_realpath(), but path is relative to given root. */ -int t_realpath_to(const char *path, const char *root, - const char **npath_r); - -#endif - diff --git a/src/managesieve/main.c b/src/managesieve/main.c index 43bd0268696952cbdbc6e47073a5767170b4f40c..93eb9e24ea0cc87d5b619344c60605dee131473b 100644 --- a/src/managesieve/main.c +++ b/src/managesieve/main.c @@ -6,7 +6,7 @@ #include "ioloop.h" #include "istream.h" #include "ostream.h" -#include "abspath.h" +#include "path-util.h" #include "str.h" #include "base64.h" #include "process-title.h" @@ -248,7 +248,7 @@ int main(int argc, char *argv[]) struct master_login_settings login_set; enum master_service_flags service_flags = 0; enum mail_storage_service_flags storage_service_flags = 0; - const char *username = NULL; + const char *username = NULL, *error = NULL; int c; i_zero(&login_set); @@ -314,9 +314,18 @@ int main(int argc, char *argv[]) main_stdio_run(username); } T_END; } else { - login_set.auth_socket_path = t_abspath("auth-master"); - if (argv[optind] != NULL) - login_set.postlogin_socket_path = t_abspath(argv[optind]); + if (t_abspath("auth-master", + &login_set.auth_socket_path, &error) < 0) { + i_fatal("t_abspath(%s) failed: %s", + "auth-master", error); + } + + if (argv[optind] != NULL && t_abspath(argv[optind], + &login_set.postlogin_socket_path, &error) < 0) { + i_fatal("t_abspath(%s) failed: %s", + argv[optind], error); + } + login_set.callback = login_client_connected; login_set.failure_callback = login_client_failed; diff --git a/src/testsuite/testsuite-mailstore.c b/src/testsuite/testsuite-mailstore.c index 10b7eaa267b1fa4e51de5b49ad1ae981b61e38f3..f7dcaa816845df81c5546426a77ef0841e0bd3a5 100644 --- a/src/testsuite/testsuite-mailstore.c +++ b/src/testsuite/testsuite-mailstore.c @@ -7,7 +7,7 @@ #include "array.h" #include "strfuncs.h" #include "str-sanitize.h" -#include "abspath.h" +#include "path-util.h" #include "unlink-directory.h" #include "env-util.h" #include "mail-namespace.h" @@ -57,7 +57,7 @@ void testsuite_mailstore_init(void) struct mail_namespace *ns; struct mail_namespace_settings *ns_set; struct mail_storage_settings *mail_set; - const char *tmpdir, *error; + const char *tmpdir, *error, *cwd; tmpdir = testsuite_tmp_dir_get(); testsuite_mailstore_location = @@ -74,7 +74,9 @@ void testsuite_mailstore_init(void) mail_user = mail_user_alloc("testsuite mail user", mail_user_dovecot->set_info, mail_user_dovecot->unexpanded_set); mail_user->autocreated = TRUE; - mail_user_set_home(mail_user, t_abspath("")); + if (t_get_working_dir(&cwd, &error) < 0) + i_fatal("Failed to get working directory: %s", error); + mail_user_set_home(mail_user, cwd); if (mail_user_init(mail_user, &error) < 0) i_fatal("Testsuite user initialization failed: %s", error); diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c index 6d4b4e9c8342e0667e4aaf7ae49c5f91e4169ca8..bf0068fcdc4699278b90dbf1e39e7bd3a3166d37 100644 --- a/src/testsuite/testsuite.c +++ b/src/testsuite/testsuite.c @@ -7,7 +7,7 @@ #include "env-util.h" #include "ostream.h" #include "hostpid.h" -#include "abspath.h" +#include "path-util.h" #include "sieve.h" #include "sieve-extensions.h" @@ -86,7 +86,7 @@ int main(int argc, char **argv) const char *scriptfile, *dumpfile, *tracefile; struct sieve_trace_config trace_config; struct sieve_binary *sbin; - const char *sieve_dir; + const char *sieve_dir, *cwd, *error; bool log_stdout = FALSE; int ret, c; @@ -133,8 +133,10 @@ int main(int argc, char **argv) i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]); } + if (t_get_working_dir(&cwd, &error) < 0) + i_fatal("Failed to get working directory: %s", error); /* Initialize mail user */ - sieve_tool_set_homedir(sieve_tool, t_abspath("")); + sieve_tool_set_homedir(sieve_tool, cwd); /* Initialize settings environment */ testsuite_settings_init();