diff options
Diffstat (limited to 'pigeonhole/src/lib-sieve/sieve-settings.c')
-rw-r--r-- | pigeonhole/src/lib-sieve/sieve-settings.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/sieve-settings.c b/pigeonhole/src/lib-sieve/sieve-settings.c new file mode 100644 index 0000000..47f70da --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-settings.c @@ -0,0 +1,270 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-error.h" +#include "sieve-address.h" +#include "sieve-address-source.h" +#include "sieve-settings.h" + +#include <ctype.h> + +/* + * Access to settings + */ + +bool sieve_setting_get_uint_value(struct sieve_instance *svinst, + const char *setting, + unsigned long long int *value_r) +{ + const char *str_value; + + str_value = sieve_setting_get(svinst, setting); + + if (str_value == NULL || *str_value == '\0') + return FALSE; + + if (str_to_ullong(str_value, value_r) < 0) { + e_warning(svinst->event, + "invalid unsigned integer value for setting '%s': " + "'%s'", setting, str_value); + return FALSE; + } + return TRUE; +} + +bool sieve_setting_get_int_value(struct sieve_instance *svinst, + const char *setting, long long int *value_r) +{ + const char *str_value; + + str_value = sieve_setting_get(svinst, setting); + if (str_value == NULL || *str_value == '\0') + return FALSE; + + if (str_to_llong(str_value, value_r) < 0) { + e_warning(svinst->event, + "invalid integer value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + return TRUE; +} + +bool sieve_setting_get_size_value(struct sieve_instance *svinst, + const char *setting, size_t *value_r) +{ + const char *str_value; + uintmax_t value, multiply = 1; + const char *endp; + + str_value = sieve_setting_get(svinst, setting); + if (str_value == NULL || *str_value == '\0') + return FALSE; + + if (str_parse_uintmax(str_value, &value, &endp) < 0) { + e_warning(svinst->event, + "invalid size value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + switch (i_toupper(*endp)) { + case '\0': /* default */ + case 'B': /* byte (useless) */ + multiply = 1; + break; + case 'K': /* kilobyte */ + multiply = 1024; + break; + case 'M': /* megabyte */ + multiply = 1024*1024; + break; + case 'G': /* gigabyte */ + multiply = 1024*1024*1024; + break; + case 'T': /* terabyte */ + multiply = 1024ULL*1024*1024*1024; + break; + default: + e_warning(svinst->event, + "invalid size value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + + if (value > SSIZE_T_MAX / multiply) { + e_warning(svinst->event, + "overflowing size value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + + *value_r = (size_t)(value * multiply); + return TRUE; +} + +bool sieve_setting_get_bool_value(struct sieve_instance *svinst, + const char *setting, bool *value_r) +{ + const char *str_value; + + str_value = sieve_setting_get(svinst, setting); + if (str_value == NULL) + return FALSE; + + str_value = t_str_trim(str_value, "\t "); + if (*str_value == '\0') + return FALSE; + + if (strcasecmp(str_value, "yes") == 0) { + *value_r = TRUE; + return TRUE; + } + + if (strcasecmp(str_value, "no") == 0) { + *value_r = FALSE; + return TRUE; + } + + e_warning(svinst->event, + "invalid boolean value for setting '%s': '%s'", + setting, str_value); + return FALSE; +} + +bool sieve_setting_get_duration_value(struct sieve_instance *svinst, + const char *setting, + sieve_number_t *value_r) +{ + const char *str_value; + uintmax_t value, multiply = 1; + const char *endp; + + str_value = sieve_setting_get(svinst, setting); + if (str_value == NULL) + return FALSE; + + str_value = t_str_trim(str_value, "\t "); + if (*str_value == '\0') + return FALSE; + + if (str_parse_uintmax(str_value, &value, &endp) < 0) { + e_warning(svinst->event, + "invalid duration value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + + switch (i_tolower(*endp)) { + case '\0': /* default */ + case 's': /* seconds */ + multiply = 1; + break; + case 'm': /* minutes */ + multiply = 60; + break; + case 'h': /* hours */ + multiply = 60*60; + break; + case 'd': /* days */ + multiply = 24*60*60; + break; + default: + e_warning(svinst->event, + "invalid duration value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + + if (value > SIEVE_MAX_NUMBER / multiply) { + e_warning(svinst->event, + "overflowing duration value for setting '%s': '%s'", + setting, str_value); + return FALSE; + } + + *value_r = (unsigned int)(value * multiply); + return TRUE; +} + +/* + * Main Sieve engine settings + */ + +void sieve_settings_load(struct sieve_instance *svinst) +{ + const char *str_setting, *error; + unsigned long long int uint_setting; + size_t size_setting; + sieve_number_t period; + + svinst->max_script_size = SIEVE_DEFAULT_MAX_SCRIPT_SIZE; + if (sieve_setting_get_size_value(svinst, "sieve_max_script_size", + &size_setting)) + svinst->max_script_size = size_setting; + + svinst->max_actions = SIEVE_DEFAULT_MAX_ACTIONS; + if (sieve_setting_get_uint_value(svinst, "sieve_max_actions", + &uint_setting)) + svinst->max_actions = (unsigned int)uint_setting; + + svinst->max_redirects = SIEVE_DEFAULT_MAX_REDIRECTS; + if (sieve_setting_get_uint_value(svinst, "sieve_max_redirects", + &uint_setting)) + svinst->max_redirects = (unsigned int)uint_setting; + + svinst->max_cpu_time_secs = + (svinst->env_location == SIEVE_ENV_LOCATION_MS ? + 0 : SIEVE_DEFAULT_MAX_CPU_TIME_SECS); + if (sieve_setting_get_duration_value(svinst, "sieve_max_cpu_time", + &period)) { + if (period > (UINT_MAX / 1000)) + svinst->max_cpu_time_secs = (UINT_MAX / 1000); + else + svinst->max_cpu_time_secs = (unsigned int)period; + } + svinst->resource_usage_timeout_secs = + SIEVE_DEFAULT_RESOURCE_USAGE_TIMEOUT_SECS; + if (sieve_setting_get_duration_value( + svinst, "sieve_resource_usage_timeout", &period)) { + if (period > UINT_MAX) + svinst->resource_usage_timeout_secs = UINT_MAX; + else { + svinst->resource_usage_timeout_secs = + (unsigned int)period; + } + } + + (void)sieve_address_source_parse_from_setting( + svinst, svinst->pool, "sieve_redirect_envelope_from", + &svinst->redirect_from); + + svinst->redirect_duplicate_period = DEFAULT_REDIRECT_DUPLICATE_PERIOD; + if (sieve_setting_get_duration_value( + svinst, "sieve_redirect_duplicate_period", &period)) { + if (period > UINT_MAX) + svinst->redirect_duplicate_period = UINT_MAX; + else { + svinst->redirect_duplicate_period = + (unsigned int)period; + } + } + + str_setting = sieve_setting_get(svinst, "sieve_user_email"); + if (str_setting != NULL && *str_setting != '\0') { + struct smtp_address *address; + if (smtp_address_parse_path( + svinst->pool, str_setting, + SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL, + &address, &error) < 0) { + e_warning(svinst->event, + "Invalid address value for setting " + "`sieve_user_email': %s", error); + } else { + svinst->user_email = address; + } + } +} |