From a2ae237a165bccb828f6252d4e66815e1809982b Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 19 Nov 2009 18:13:41 +0100
Subject: [PATCH] Made limits on the number of redirects and the number of
 actions in general configurable.

---
 src/lib-sieve/Makefile.am                     |  3 +-
 src/lib-sieve/cmd-redirect.c                  |  3 +-
 .../plugins/include/ext-include-common.c      |  1 +
 .../plugins/subaddress/ext-subaddress.c       |  1 +
 src/lib-sieve/sieve-common.h                  | 20 ++------
 src/lib-sieve/sieve-limits.c                  |  9 ----
 src/lib-sieve/sieve-limits.h                  |  3 --
 src/lib-sieve/sieve-result.c                  |  4 +-
 src/lib-sieve/sieve-settings.c                | 49 +++++++++++++++++++
 src/lib-sieve/sieve-settings.h                | 28 +++++++++++
 src/lib-sieve/sieve.c                         | 20 ++++++++
 11 files changed, 111 insertions(+), 30 deletions(-)
 delete mode 100644 src/lib-sieve/sieve-limits.c
 create mode 100644 src/lib-sieve/sieve-settings.c
 create mode 100644 src/lib-sieve/sieve-settings.h

diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am
index 10d3818e9..9bffcf1eb 100644
--- a/src/lib-sieve/Makefile.am
+++ b/src/lib-sieve/Makefile.am
@@ -71,7 +71,7 @@ libdovecot_sieve_la_LIBADD = $(plugins)
 
 libdovecot_sieve_la_SOURCES = \
 	rfc2822.c \
-	sieve-limits.c \
+	sieve-settings.c \
 	sieve-message.c \
 	sieve-smtp.c \
 	sieve-lexer.c \
@@ -109,6 +109,7 @@ headers = \
 	sieve-types.h \
 	sieve-common.h \
 	sieve-limits.h \
+	sieve-settings.h \
 	sieve-message.h \
 	sieve-smtp.h \
 	sieve-lexer.h \
diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index d035a2212..3bc201d70 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -196,6 +196,7 @@ static bool cmd_redirect_operation_dump
 static int cmd_redirect_operation_execute
 (const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
+	struct sieve_instance *svinst = renv->svinst;
 	struct sieve_side_effects_list *slist = NULL;
 	struct act_redirect_context *act;
 	string_t *redirect;
@@ -234,7 +235,7 @@ static int cmd_redirect_operation_execute
 	
 	ret = sieve_result_add_action
 		(renv, NULL, &act_redirect, slist, source_line, (void *) act,
-			sieve_max_redirects);
+			svinst->max_redirects);
 	
 	return ( ret >= 0 );
 }
diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c
index d6715932f..0941f9d06 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.c
+++ b/src/lib-sieve/plugins/include/ext-include-common.c
@@ -7,6 +7,7 @@
 #include "home-expand.h"
 
 #include "sieve-common.h"
+#include "sieve-settings.h"
 #include "sieve-error.h"
 #include "sieve-script.h"
 #include "sieve-ast.h"
diff --git a/src/lib-sieve/plugins/subaddress/ext-subaddress.c b/src/lib-sieve/plugins/subaddress/ext-subaddress.c
index d7f714b3e..17de8d5e1 100644
--- a/src/lib-sieve/plugins/subaddress/ext-subaddress.c
+++ b/src/lib-sieve/plugins/subaddress/ext-subaddress.c
@@ -13,6 +13,7 @@
  
 #include "sieve-common.h"
 
+#include "sieve-settings.h"
 #include "sieve-code.h"
 #include "sieve-address.h"
 #include "sieve-extensions.h"
diff --git a/src/lib-sieve/sieve-common.h b/src/lib-sieve/sieve-common.h
index e92f83d4b..80d9dc056 100644
--- a/src/lib-sieve/sieve-common.h
+++ b/src/lib-sieve/sieve-common.h
@@ -10,6 +10,7 @@
 #include "sieve-types.h"
 
 #include <sys/types.h>
+#include <stdlib.h>
 
 /* 
  * Types
@@ -144,21 +145,10 @@ struct sieve_instance {
 
 	/* Extension registry */
 	struct sieve_extension_registry *ext_reg;
-};
-
-/*
- * Settings
- */
 
-static inline const char *sieve_get_setting
-(struct sieve_instance *svinst, const char *identifier)
-{
-	const struct sieve_callbacks *callbacks = svinst->callbacks;
-
-	if ( callbacks == NULL || callbacks->get_setting == NULL )
-		return NULL;
-
-	return callbacks->get_setting(svinst->context, identifier);
-}
+	/* Limits */
+	unsigned int max_actions;
+	unsigned int max_redirects;
+};
 
 #endif /* __SIEVE_COMMON_H */
diff --git a/src/lib-sieve/sieve-limits.c b/src/lib-sieve/sieve-limits.c
deleted file mode 100644
index dcc664f24..000000000
--- a/src/lib-sieve/sieve-limits.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
- */
-
-#include "sieve-common.h"
-#include "sieve-limits.h"
-
-unsigned int sieve_max_actions = SIEVE_DEFAULT_MAX_ACTIONS;
-unsigned int sieve_max_redirects = SIEVE_DEFAULT_MAX_REDIRECTS;
-
diff --git a/src/lib-sieve/sieve-limits.h b/src/lib-sieve/sieve-limits.h
index 94f6a2ad1..7ac4ba6f8 100644
--- a/src/lib-sieve/sieve-limits.h
+++ b/src/lib-sieve/sieve-limits.h
@@ -32,7 +32,4 @@
 #define SIEVE_DEFAULT_MAX_ACTIONS   32
 #define SIEVE_DEFAULT_MAX_REDIRECTS 4
 
-extern unsigned int sieve_max_actions;
-extern unsigned int sieve_max_redirects;
-
 #endif /* __SIEVE_LIMITS_H */
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 5476b95de..ff875591c 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -491,6 +491,7 @@ static int _sieve_result_add_action
 {
 	int ret = 0;
 	unsigned int instance_count = 0;
+	struct sieve_instance *svinst = renv->svinst;
 	struct sieve_result *result = renv->result;
 	struct sieve_result_action *raction = NULL, *kaction = NULL;
 	struct sieve_action action;
@@ -591,7 +592,8 @@ static int _sieve_result_add_action
 	}
 
 	/* Check policy limit on total number of actions */
-	if ( sieve_max_actions > 0 && result->action_count >= sieve_max_actions ) {
+	if ( svinst->max_actions > 0 && result->action_count >= svinst->max_actions ) 
+		{
 		sieve_runtime_error(renv, action.location, 
 			"total number of actions exceeds policy limit");
 		return -1;
diff --git a/src/lib-sieve/sieve-settings.c b/src/lib-sieve/sieve-settings.c
new file mode 100644
index 000000000..45061cd0d
--- /dev/null
+++ b/src/lib-sieve/sieve-settings.c
@@ -0,0 +1,49 @@
+/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
+ */
+
+#include "lib.h"
+
+#include "sieve-common.h"
+#include "sieve-settings.h"
+
+#include <stdlib.h>
+
+bool sieve_get_uint_setting
+(struct sieve_instance *svinst, const char *identifier,
+	unsigned long long int *value_r)
+{
+	const char *str_value;
+	char *endp;
+
+	str_value = sieve_get_setting(svinst, identifier);
+
+	if ( str_value == NULL || *str_value == '\0' )
+		return FALSE;
+
+	*value_r = strtoull(str_value, &endp, 10);
+
+	if ( *endp != '\0' )
+		return FALSE;
+	
+	return TRUE;	
+}
+
+bool sieve_get_int_setting
+(struct sieve_instance *svinst, const char *identifier,
+	long long int *value_r)
+{
+	const char *str_value;
+	char *endp;
+
+	str_value = sieve_get_setting(svinst, identifier);
+
+	if ( str_value == NULL || *str_value == '\0' )
+		return FALSE;
+
+	*value_r = strtoll(str_value, &endp, 10);
+
+	if ( *endp != '\0' )
+		return FALSE;
+	
+	return TRUE;	
+}
diff --git a/src/lib-sieve/sieve-settings.h b/src/lib-sieve/sieve-settings.h
new file mode 100644
index 000000000..e0cd91187
--- /dev/null
+++ b/src/lib-sieve/sieve-settings.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
+ */
+
+#ifndef __SIEVE_SETTINGS_H
+#define __SIEVE_SETTINGS_H
+
+#include "sieve-common.h"
+
+static inline const char *sieve_get_setting
+(struct sieve_instance *svinst, const char *identifier)
+{
+	const struct sieve_callbacks *callbacks = svinst->callbacks;
+
+	if ( callbacks == NULL || callbacks->get_setting == NULL )
+		return NULL;
+
+	return callbacks->get_setting(svinst->context, identifier);
+}
+
+bool sieve_get_uint_setting
+(struct sieve_instance *svinst, const char *identifier,
+	unsigned long long int *value_r);
+
+bool sieve_get_int_setting
+(struct sieve_instance *svinst, const char *identifier,
+	long long int *value_r);
+
+#endif /* __SIEVE_SETTINGS_H */
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index f5d2879a9..e4c69a19d 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -6,6 +6,8 @@
 #include "istream.h"
 #include "buffer.h"
 
+#include "sieve-limits.h"
+#include "sieve-settings.h"
 #include "sieve-extensions.h"
 
 #include "sieve-script.h"
@@ -39,14 +41,32 @@ struct sieve_instance *sieve_init
 (const struct sieve_callbacks *callbacks, void *context)
 {
 	struct sieve_instance *svinst;
+	unsigned long long int uint_setting;
 	pool_t pool;
 
+	/* Create Sieve engine instance */
 	pool = pool_alloconly_create("sieve", 8192);
 	svinst = p_new(pool, struct sieve_instance, 1);
 	svinst->pool = pool;
 	svinst->callbacks = callbacks;
 	svinst->context = context;
 
+	/* Read limits from configuration */
+
+	svinst->max_actions = SIEVE_DEFAULT_MAX_ACTIONS;
+	svinst->max_redirects = SIEVE_DEFAULT_MAX_REDIRECTS;
+	
+	if ( sieve_get_uint_setting
+		(svinst, "sieve_max_actions", &uint_setting) ) {
+		svinst->max_actions = (unsigned int) uint_setting;
+	}
+
+	if ( sieve_get_uint_setting
+		(svinst, "sieve_max_redirects", &uint_setting) ) {
+		svinst->max_redirects = (unsigned int) uint_setting;
+	}
+	
+	/* Initialize extensions */
 	if ( !sieve_extensions_init(svinst) ) {
 		sieve_deinit(&svinst);
 		return NULL;
-- 
GitLab