From 60c8e9d4e460ea4612836018eb4e5b0d97e9e120 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sat, 22 Nov 2014 00:17:13 +0100
Subject: [PATCH] lib-sieve: Consolidated checking mailbox name.

---
 src/lib-sieve/ext-fileinto.c                  |  7 ++--
 .../plugins/mailbox/tst-mailboxexists.c       | 40 ++++++++++++++++++-
 src/lib-sieve/plugins/metadata/tst-metadata.c | 23 +++++++++++
 .../plugins/metadata/tst-metadataexists.c     | 24 +++++++++++
 src/lib-sieve/sieve-actions.c                 | 11 +++++
 src/lib-sieve/sieve-actions.h                 |  7 ++++
 6 files changed, 108 insertions(+), 4 deletions(-)

diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c
index a6b51fe5d..55691ab46 100644
--- a/src/lib-sieve/ext-fileinto.c
+++ b/src/lib-sieve/ext-fileinto.c
@@ -117,11 +117,12 @@ static bool cmd_fileinto_validate
 
 	/* Check name validity when folder argument is not a variable */
 	if ( sieve_argument_is_string_literal(arg) ) {
-		const char *folder = sieve_ast_argument_strc(arg);
+		const char *folder = sieve_ast_argument_strc(arg), *error;
 
-		if ( !uni_utf8_str_is_valid(folder) ) {
+		if ( !sieve_mailbox_check_name(folder, &error) ) {
 			sieve_command_validate_error(valdtr, cmd,
-				"folder name specified for fileinto command is not utf-8: %s", folder);
+				"invalid folder name `%s' specified for fileinto command: %s",
+				str_sanitize(folder, 256), error);
 			return FALSE;
 		}
 	}
diff --git a/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c b/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c
index 49f270965..3ec1cdbd2 100644
--- a/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c
+++ b/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c
@@ -7,6 +7,7 @@
 #include "mail-namespace.h"
 
 #include "sieve-common.h"
+#include "sieve-actions.h"
 #include "sieve-extensions.h"
 #include "sieve-commands.h"
 #include "sieve-stringlist.h"
@@ -62,17 +63,54 @@ const struct sieve_operation_def mailboxexists_operation = {
  * Test validation
  */
 
+struct _validate_context {
+	struct sieve_validator *valdtr;
+	struct sieve_command *tst;
+};
+
+static int tst_mailboxexists_mailbox_validate
+(void *context, struct sieve_ast_argument *arg)
+{
+	struct _validate_context *valctx =
+		(struct _validate_context *)context;
+
+	if ( sieve_argument_is_string_literal(arg) ) {
+		const char *mailbox = sieve_ast_argument_strc(arg), *error;
+
+		if ( !sieve_mailbox_check_name(mailbox, &error) ) {
+			sieve_argument_validate_warning
+				(valctx->valdtr, arg, "%s test: "
+					"invalid mailbox name `%s' specified: %s",
+					sieve_command_identifier(valctx->tst),
+					str_sanitize(mailbox, 256), error);
+		}
+	}
+
+	return TRUE;
+}
+
 static bool tst_mailboxexists_validate
 (struct sieve_validator *valdtr, struct sieve_command *tst)
 {
 	struct sieve_ast_argument *arg = tst->first_positional;
+	struct sieve_ast_argument *aarg; 
+	struct _validate_context valctx;
 
 	if ( !sieve_validate_positional_argument
 		(valdtr, tst, arg, "mailbox-names", 1, SAAT_STRING_LIST) ) {
 		return FALSE;
 	}
 
-	return sieve_validator_argument_activate(valdtr, tst, arg, FALSE);
+	if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
+		return FALSE;
+
+	aarg = arg;
+	memset(&valctx, 0, sizeof(valctx));
+	valctx.valdtr = valdtr;
+	valctx.tst = tst;
+
+	return sieve_ast_stringlist_map
+		(&aarg, (void*)&valctx, tst_mailboxexists_mailbox_validate);
 }
 
 /*
diff --git a/src/lib-sieve/plugins/metadata/tst-metadata.c b/src/lib-sieve/plugins/metadata/tst-metadata.c
index da659c606..4dfbc7aa9 100644
--- a/src/lib-sieve/plugins/metadata/tst-metadata.c
+++ b/src/lib-sieve/plugins/metadata/tst-metadata.c
@@ -8,6 +8,7 @@
 #include "sieve-common.h"
 #include "sieve-limits.h"
 #include "sieve-commands.h"
+#include "sieve-actions.h"
 #include "sieve-stringlist.h"
 #include "sieve-code.h"
 #include "sieve-comparators.h"
@@ -147,6 +148,19 @@ static bool tst_metadata_validate
 		if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
 			return FALSE;
 
+		/* Check name validity when mailbox argument is not a variable */
+		if ( sieve_argument_is_string_literal(arg) ) {
+			const char *mailbox = sieve_ast_argument_strc(arg), *error;
+
+			if ( !sieve_mailbox_check_name(mailbox, &error) ) {
+				sieve_argument_validate_warning
+					(valdtr, arg, "%s test: "
+						"invalid mailbox name `%s' specified: %s",
+						sieve_command_identifier(tst),
+						str_sanitize(mailbox, 256), error);
+			}
+		}
+
 		arg = sieve_ast_argument_next(arg);
 	}
 
@@ -363,6 +377,15 @@ static int tst_metadata_operation_execute
 	}
 
 	if ( metadata ) {
+		if ( !sieve_mailbox_check_name(str_c(mailbox), &error) ) {
+			sieve_runtime_warning(renv, NULL, "%s test: "
+				"invalid mailbox name `%s' specified: %s",
+				(metadata ? "metadata" : "servermetadata"),
+				str_sanitize(str_c(mailbox), 256), error);
+			sieve_interpreter_set_test_result(renv->interp, FALSE);
+			return SIEVE_EXEC_OK;
+		}
+
 		sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS,
 			"retrieving annotation `%s' from mailbox `%s'",
 			str_sanitize(str_c(aname), 256),
diff --git a/src/lib-sieve/plugins/metadata/tst-metadataexists.c b/src/lib-sieve/plugins/metadata/tst-metadataexists.c
index 99b7dd035..27006b842 100644
--- a/src/lib-sieve/plugins/metadata/tst-metadataexists.c
+++ b/src/lib-sieve/plugins/metadata/tst-metadataexists.c
@@ -8,6 +8,7 @@
 
 #include "sieve-common.h"
 #include "sieve-commands.h"
+#include "sieve-actions.h"
 #include "sieve-stringlist.h"
 #include "sieve-code.h"
 #include "sieve-validator.h"
@@ -150,6 +151,19 @@ static bool tst_metadataexists_validate
 		if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
 			return FALSE;
 
+		/* Check name validity when mailbox argument is not a variable */
+		if ( sieve_argument_is_string_literal(arg) ) {
+			const char *mailbox = sieve_ast_argument_strc(arg), *error;
+
+			if ( !sieve_mailbox_check_name(mailbox, &error) ) {
+				sieve_argument_validate_warning
+					(valdtr, arg, "%s test: "
+						"invalid mailbox name `%s' specified: %s",
+						sieve_command_identifier(tst),
+						str_sanitize(mailbox, 256), error);
+			}
+		}
+
 		arg = sieve_ast_argument_next(arg);
 	}
 
@@ -327,6 +341,7 @@ static int tst_metadataexists_operation_execute
 	struct sieve_stringlist *anames;
 	string_t *mailbox;
 	bool trace = FALSE, all_exist = TRUE;
+	const char *error;
 	int ret;
 
 	/*
@@ -348,6 +363,15 @@ static int tst_metadataexists_operation_execute
 	 * Perform operation
 	 */
 
+	if ( metadata && !sieve_mailbox_check_name(str_c(mailbox), &error) ) {
+		sieve_runtime_warning(renv, NULL, "%s test: "
+			"invalid mailbox name `%s' specified: %s",
+			(metadata ? "metadataexists" : "servermetadataexists"),
+			str_sanitize(str_c(mailbox), 256), error);
+		sieve_interpreter_set_test_result(renv->interp, FALSE);
+		return SIEVE_EXEC_OK;
+	}
+
 	if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS) ) {
 		if ( metadata )
 			sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "metadataexists test");
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index 0f4f65875..dc0d81cf1 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -932,6 +932,17 @@ bool sieve_action_reject_mail
 	return result;
 }
 
+/*
+ * Mailbox
+ */
 
+bool sieve_mailbox_check_name(const char *mailbox, const char **error_r)
+{
+	if ( !uni_utf8_str_is_valid(mailbox) ) {
+		*error_r = "mailbox is utf-8";
+		return FALSE;
+	}
+	return TRUE;
+}
 
 
diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h
index 99ae31bad..c8216b1b0 100644
--- a/src/lib-sieve/sieve-actions.h
+++ b/src/lib-sieve/sieve-actions.h
@@ -273,4 +273,11 @@ bool sieve_action_reject_mail
 (const struct sieve_action_exec_env *aenv,
 	const char *sender, const char *recipient, const char *reason);
 
+/*
+ * Mailbox
+ */
+
+// FIXME: move this to a more appropriate location
+bool sieve_mailbox_check_name(const char *mailbox, const char **error_r);
+
 #endif /* __SIEVE_ACTIONS_H */
-- 
GitLab