From 9245e6319ebbfa32db7301b04c5cf3220a1f3bea Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 12 Mar 2015 21:34:10 +0100
Subject: [PATCH] lib-sieve: Implemented normalization for script storage
 locations for all storage drivers. This is particularly important when the
 location is recorded in the binary for checking whether it is up-to-date.

---
 src/lib-sieve/sieve-script.c                  |  1 -
 .../storage/dict/sieve-dict-script.c          | 21 +++++++--------
 .../storage/dict/sieve-dict-storage.c         | 14 +++++++---
 .../storage/dict/sieve-dict-storage.h         |  1 +
 src/lib-sieve/storage/file/Makefile.am        |  3 ++-
 .../storage/file/sieve-file-script.c          |  7 +----
 .../storage/file/sieve-file-storage.c         | 26 +++++++++++++++++--
 .../storage/ldap/sieve-ldap-script.c          | 22 +++++++---------
 .../storage/ldap/sieve-ldap-storage.c         |  5 +++-
 9 files changed, 60 insertions(+), 40 deletions(-)

diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c
index f78fb4328..6009642a3 100644
--- a/src/lib-sieve/sieve-script.c
+++ b/src/lib-sieve/sieve-script.c
@@ -170,7 +170,6 @@ int sieve_script_open
 	if ( script->open )
 		return 0;
 
-	script->location = NULL;
 	if ( script->v.open(script, error_r) < 0 )
 		return -1;
 
diff --git a/src/lib-sieve/storage/dict/sieve-dict-script.c b/src/lib-sieve/storage/dict/sieve-dict-script.c
index 52e2d9170..40ee831e5 100644
--- a/src/lib-sieve/storage/dict/sieve-dict-script.c
+++ b/src/lib-sieve/storage/dict/sieve-dict-script.c
@@ -35,13 +35,19 @@ struct sieve_dict_script *sieve_dict_script_init
 {
 	struct sieve_storage *storage = &dstorage->storage;
 	struct sieve_dict_script *dscript = NULL;
+	const char *location;
 
-	if ( name == NULL )
+	if ( name == NULL ) {
 		name = SIEVE_DICT_SCRIPT_DEFAULT;
+		location = storage->location;
+    } else {
+		location = t_strconcat
+			(storage->location, ";name=", name, NULL);
+    }
 
 	dscript = sieve_dict_script_alloc();
 	sieve_script_init(&dscript->script,
-		storage, &sieve_dict_script, storage->location, name);
+		storage, &sieve_dict_script, location, name);
 
 	return dscript;
 }
@@ -70,7 +76,7 @@ static int sieve_dict_script_open
 	if ( sieve_dict_storage_get_dict
 		(dstorage, &dscript->dict, error_r) < 0 )
 		return -1;
-		
+
 	path = t_strconcat
 		(DICT_SIEVE_NAME_PATH, dict_escape_string(name), NULL);
 
@@ -92,15 +98,6 @@ static int sieve_dict_script_open
 		return -1;
 	}
 
-	if ( strcmp(name, SIEVE_DICT_SCRIPT_DEFAULT) == 0 ) {
-		script->location = p_strconcat(script->pool,
-			SIEVE_DICT_STORAGE_DRIVER_NAME, ":", storage->location, NULL);
-	} else {
-		script->location = p_strconcat(script->pool,
-			SIEVE_DICT_STORAGE_DRIVER_NAME, ":", storage->location,
-				";name=", name, NULL);
-	}
-
 	return 0;
 }
 
diff --git a/src/lib-sieve/storage/dict/sieve-dict-storage.c b/src/lib-sieve/storage/dict/sieve-dict-storage.c
index 976eb3dfe..395016337 100644
--- a/src/lib-sieve/storage/dict/sieve-dict-storage.c
+++ b/src/lib-sieve/storage/dict/sieve-dict-storage.c
@@ -33,7 +33,7 @@ static int sieve_dict_storage_init
 	struct sieve_dict_storage *dstorage =
 		(struct sieve_dict_storage *)storage;
 	struct sieve_instance *svinst = storage->svinst;
-	const char *username = NULL;
+	const char *uri = storage->location, *username = NULL;
 
 	if ( options != NULL ) {
 		while ( *options != NULL ) {
@@ -70,9 +70,15 @@ static int sieve_dict_storage_init
 	}
 
 	sieve_storage_sys_debug(storage,
-		"user=%s, uri=%s", username, storage->location);
+		"user=%s, uri=%s", username, uri);
 
+	dstorage->uri = p_strdup(storage->pool, uri);
 	dstorage->username = p_strdup(storage->pool, username);
+
+	storage->location = p_strconcat(storage->pool,
+		SIEVE_DICT_STORAGE_DRIVER_NAME, ":", storage->location,
+		";user=", username, NULL);
+
 	return 0;
 }
 
@@ -86,12 +92,12 @@ int sieve_dict_storage_get_dict
 	int ret;
 
 	if ( dstorage->dict == NULL ) {
-		ret = dict_init(storage->location, DICT_DATA_TYPE_STRING,
+		ret = dict_init(dstorage->uri, DICT_DATA_TYPE_STRING,
 			dstorage->username, svinst->base_dir, &dstorage->dict, &error);
 		if ( ret < 0 ) {
 			sieve_storage_set_critical(storage,
 				"Failed to initialize dict with data `%s' for user `%s': %s",
-				storage->location, dstorage->username, error);
+				dstorage->uri, dstorage->username, error);
 			*error_r = SIEVE_ERROR_TEMP_FAILURE;
 			return -1;
 		}
diff --git a/src/lib-sieve/storage/dict/sieve-dict-storage.h b/src/lib-sieve/storage/dict/sieve-dict-storage.h
index 35979e29b..a9198bc4b 100644
--- a/src/lib-sieve/storage/dict/sieve-dict-storage.h
+++ b/src/lib-sieve/storage/dict/sieve-dict-storage.h
@@ -22,6 +22,7 @@ struct sieve_dict_storage {
 	struct sieve_storage storage;
 
 	const char *username;
+	const char *uri;
 
 	struct dict *dict;
 };
diff --git a/src/lib-sieve/storage/file/Makefile.am b/src/lib-sieve/storage/file/Makefile.am
index a6fda424f..b401fa8b7 100644
--- a/src/lib-sieve/storage/file/Makefile.am
+++ b/src/lib-sieve/storage/file/Makefile.am
@@ -3,7 +3,8 @@ noinst_LTLIBRARIES = libsieve_storage_file.la
 AM_CPPFLAGS = \
 	$(LIBDOVECOT_INCLUDE) \
 	-I$(top_srcdir) \
-	-I$(top_srcdir)/src/lib-sieve
+	-I$(top_srcdir)/src/lib-sieve \
+	-I$(top_srcdir)/src/lib-sieve/util
 
 libsieve_storage_file_la_SOURCES = \
 	sieve-file-script.c \
diff --git a/src/lib-sieve/storage/file/sieve-file-script.c b/src/lib-sieve/storage/file/sieve-file-script.c
index 007da4e3b..fb30f38f0 100644
--- a/src/lib-sieve/storage/file/sieve-file-script.c
+++ b/src/lib-sieve/storage/file/sieve-file-script.c
@@ -409,12 +409,7 @@ static int sieve_file_script_open
 			fscript->binpath = p_strdup(pool, binpath);
 			fscript->binprefix = p_strdup(pool, binprefix);
 
-			if ( fscript->script.name == NULL || *fscript->script.name == '\0' ||
-				strcmp(fscript->script.name, basename) == 0 )
-				fscript->script.location = fscript->path;
-			else
-				fscript->script.location = p_strconcat
-					(pool, fscript->path, ";name=", fscript->script.name, NULL);
+			fscript->script.location = fscript->path;
 
 			if ( fscript->script.name == NULL )
 				fscript->script.name = p_strdup(pool, basename);
diff --git a/src/lib-sieve/storage/file/sieve-file-storage.c b/src/lib-sieve/storage/file/sieve-file-storage.c
index 981ad24b8..3e1f438a0 100644
--- a/src/lib-sieve/storage/file/sieve-file-storage.c
+++ b/src/lib-sieve/storage/file/sieve-file-storage.c
@@ -10,6 +10,8 @@
 #include "unlink-old-files.h"
 #include "mail-storage-private.h"
 
+#include "realpath.h"
+
 #include "sieve.h"
 #include "sieve-common.h"
 #include "sieve-settings.h"
@@ -308,10 +310,14 @@ static int sieve_file_storage_init_common
 
 	active_fname = NULL;
 	if ( active_path != NULL && *active_path != '\0' ) {
+		const char *active_dir;
+
 		active_fname = strrchr(active_path, '/');
 		if ( active_fname == NULL ) {
 			active_fname = active_path;
+			active_dir = "";
 		} else {
+			active_dir = t_strdup_until(active_path, active_fname);
 			active_fname++;
 		}
 
@@ -325,6 +331,15 @@ static int sieve_file_storage_init_common
 			return -1;
 		}
 
+		if (t_realpath(active_dir, &active_dir) < 0) {
+			sieve_storage_sys_error(storage,
+				"Failed to normalize active script directory (path=%s): %m",
+				active_dir);
+			*error_r = SIEVE_ERROR_TEMP_FAILURE;
+			return -1;
+		}
+		active_path = t_abspath_to(active_fname, active_dir);
+
 		sieve_storage_sys_debug(storage,
 			"Using %sSieve script path: %s",
 			( storage_path != NULL ? "active " : "" ),
@@ -337,6 +352,14 @@ static int sieve_file_storage_init_common
 	/* Determine storage path */
 
 	if (storage_path != NULL && *storage_path != '\0') {
+		if (t_realpath(storage_path, &storage_path) < 0) {
+			sieve_storage_sys_error(storage,
+				"Failed to normalize storage path (path=%s): %m",
+				active_path);
+			*error_r = SIEVE_ERROR_TEMP_FAILURE;
+			return -1;
+		}
+
 		sieve_storage_sys_debug(storage,
 			"Using script storage path: %s", storage_path);
 
@@ -440,8 +463,7 @@ static int sieve_file_storage_init_common
 		(fstorage, fstorage->path, error_r) < 0 )
 		return -1;
 
-	if (storage->location == NULL)
-		storage->location = p_strdup(storage->pool, storage_path);
+	storage->location = fstorage->path;
 
 	return 0;
 }
diff --git a/src/lib-sieve/storage/ldap/sieve-ldap-script.c b/src/lib-sieve/storage/ldap/sieve-ldap-script.c
index 8634deae3..30cc5207f 100644
--- a/src/lib-sieve/storage/ldap/sieve-ldap-script.c
+++ b/src/lib-sieve/storage/ldap/sieve-ldap-script.c
@@ -36,13 +36,19 @@ struct sieve_ldap_script *sieve_ldap_script_init
 {
 	struct sieve_storage *storage = &lstorage->storage;
 	struct sieve_ldap_script *lscript = NULL;
+	const char *location;
 
-	if ( name == NULL )
+	if ( name == NULL ) {
 		name = SIEVE_LDAP_SCRIPT_DEFAULT;
+		location = storage->location;
+	} else {
+		location = t_strconcat
+			(storage->location, ";name=", name, NULL);
+	}
 
 	lscript = sieve_ldap_script_alloc();
 	sieve_script_init(&lscript->script,
-		storage, &sieve_ldap_script, storage->location, name);
+		storage, &sieve_ldap_script, location, name);
 	return lscript;
 }
 
@@ -54,7 +60,6 @@ static int sieve_ldap_script_open
 	struct sieve_storage *storage = script->storage;
 	struct sieve_ldap_storage *lstorage =
 		(struct sieve_ldap_storage *)storage;
-	const char *name = script->name;
 	int ret;
 
 	if ( sieve_ldap_db_connect(lstorage->conn) < 0 ) {
@@ -78,15 +83,6 @@ static int sieve_ldap_script_open
 		return -1;
 	}
 
-	if ( strcmp(name, SIEVE_LDAP_SCRIPT_DEFAULT) == 0 ) {
-		script->location = p_strconcat(script->pool,
-			SIEVE_LDAP_STORAGE_DRIVER_NAME, ":", storage->location, NULL);
-	} else {
-		script->location = p_strconcat(script->pool,
-			SIEVE_LDAP_STORAGE_DRIVER_NAME, ":", storage->location,
-				";name=", name, NULL);
-	}
-
 	return 0;
 }
 
@@ -238,7 +234,7 @@ static bool sieve_ldap_script_equals
 
 	if ( strcmp(storage->location, sother->location) != 0 )
 		return FALSE;
-	
+
 	i_assert( script->name != NULL && other->name != NULL );
 
 	return ( strcmp(script->name, other->name) == 0 );
diff --git a/src/lib-sieve/storage/ldap/sieve-ldap-storage.c b/src/lib-sieve/storage/ldap/sieve-ldap-storage.c
index eac782190..4d18ae0e0 100644
--- a/src/lib-sieve/storage/ldap/sieve-ldap-storage.c
+++ b/src/lib-sieve/storage/ldap/sieve-ldap-storage.c
@@ -82,9 +82,12 @@ static int sieve_ldap_storage_init
 		return -1;
 
 	lstorage->username = p_strdup(storage->pool, username);
-
 	lstorage->conn = sieve_ldap_db_init(lstorage);
 
+	storage->location = p_strconcat(storage->pool,
+		SIEVE_LDAP_STORAGE_DRIVER_NAME, ":", storage->location,
+		";user=", username, NULL);
+
 	return 0;
 }
 
-- 
GitLab