Hello,
The use case is simple: we have to forbid sieve redirects to outside, but
should be able to redirect inside. The patch below adds a new sieve
configuration option sieve_allowed_redirects to list the domains to which
redirects are permitted and otherwise are not allowed. Please consider it.
diff --git a/pigeonhole/doc/example-config/conf.d/90-sieve.conf
b/pigeonhole/doc/example-config/conf.d/90-sieve.conf
index 238bcf4..3b4ac65 100644
--- a/pigeonhole/doc/example-config/conf.d/90-sieve.conf
+++ b/pigeonhole/doc/example-config/conf.d/90-sieve.conf
@@ -126,6 +126,10 @@ plugin {
# script execution. If set to 0, no redirect actions are allowed.
#sieve_max_redirects = 4
+ # The comma/space separated list of email domains where redirection is
allowed.
+ # If the list is empty, there is no restriction.
+ sieve_allowed_redirects =
+
# The maximum number of personal Sieve scripts a single user can have. If set
# to 0, no limit on the number of scripts is enforced.
# (Currently only relevant for ManageSieve)
diff --git a/pigeonhole/src/lib-sieve/cmd-redirect.c
b/pigeonhole/src/lib-sieve/cmd-redirect.c
index 6a3b0a4..17e9031 100644
--- a/pigeonhole/src/lib-sieve/cmd-redirect.c
+++ b/pigeonhole/src/lib-sieve/cmd-redirect.c
@@ -107,6 +107,24 @@ const struct sieve_action_def act_redirect = {
.commit = act_redirect_commit,
};
+static bool
+cmd_redirect_allowed(struct sieve_instance *svinst,
+const struct smtp_address *to_address)
+{
+ const char **domain;
+ bool result = TRUE;
+
+ if (!svinst->allowed_redirects)
+ return TRUE;
+ for (domain = svinst->allowed_redirects; *domain != NULL; ++domain) {
+ if (strcasecmp(*domain, to_address->domain) == 0) {
+ return TRUE;
+ }
+ result = FALSE;
+ }
+ return result;
+}
+
/*
* Validation
*/
@@ -127,6 +145,12 @@ cmd_redirect_validate(struct sieve_validator *validator,
if (!sieve_validator_argument_activate(validator, cmd, arg, FALSE))
return FALSE;
+ if (svinst->max_redirects == 0) {
+ sieve_command_validate_error(validator, cmd,
+ "local policy prohibits the use of a redirect action");
+ return FALSE;
+ }
+
/* We can only assess the validity of the outgoing address when it is
* a string literal. For runtime-generated strings this needs to be
* done at runtime.
@@ -148,14 +172,17 @@ cmd_redirect_validate(struct sieve_validator *validator,
}
} T_END;
+ if (!result &&
+ !cmd_redirect_allowed(svinst,
+ sieve_address_parse_str(raw_address,
&error))) {
+ sieve_command_validate_error(validator, cmd,
+ "local policy prohibits the use of a redirect
action");
+ return FALSE;
+ }
+
return result;
}
- if (svinst->max_redirects == 0) {
- sieve_command_validate_error(validator, cmd,
- "local policy prohibits the use of a redirect action");
- return FALSE;
- }
return TRUE;
}
@@ -238,6 +265,11 @@ cmd_redirect_operation_execute(const struct
sieve_runtime_env *renv,
"local policy prohibits the use of a redirect action");
return SIEVE_EXEC_FAILURE;
}
+ if (!cmd_redirect_allowed(svinst, to_address)) {
+ sieve_runtime_error(renv, NULL,
+ "local policy prohibits the use of a redirect action");
+ return SIEVE_EXEC_FAILURE;
+ }
if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS)) {
sieve_runtime_trace(renv, 0, "redirect action");
diff --git a/pigeonhole/src/lib-sieve/sieve-common.h
b/pigeonhole/src/lib-sieve/sieve-common.h
index e79fb4d..d980c9d 100644
--- a/pigeonhole/src/lib-sieve/sieve-common.h
+++ b/pigeonhole/src/lib-sieve/sieve-common.h
@@ -209,6 +209,7 @@ struct sieve_instance {
const struct smtp_address *user_email, *user_email_implicit;
struct sieve_address_source redirect_from;
unsigned int redirect_duplicate_period;
+ const char **allowed_redirects;
};
/*
diff --git a/pigeonhole/src/lib-sieve/sieve-settings.c
b/pigeonhole/src/lib-sieve/sieve-settings.c
index 47f70da..70addc7 100644
--- a/pigeonhole/src/lib-sieve/sieve-settings.c
+++ b/pigeonhole/src/lib-sieve/sieve-settings.c
@@ -267,4 +267,10 @@ void sieve_settings_load(struct sieve_instance *svinst)
svinst->user_email = address;
}
}
+ svinst->allowed_redirects = NULL;
+ str_setting = sieve_setting_get(svinst, "sieve_allowed_redirects");
+ if (str_setting != NULL && *str_setting != '\0') {
+ svinst-