From 690f935be61409138e9cd700aff4b2fea9429c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martti=20Rannanj=C3=A4rvi?= Date: Wed, 22 Mar 2017 17:17:41 +0200 Subject: [PATCH] quota: Add quota_max_mail_size setting --- doc/example-config/conf.d/90-quota.conf | 3 +++ src/plugins/quota/Makefile.am | 1 + src/plugins/quota/quota-private.h | 1 + src/plugins/quota/quota-status.c | 1 + src/plugins/quota/quota-storage.c | 3 +++ src/plugins/quota/quota.c | 24 +++++++++++++++++++++++- src/plugins/quota/quota.h | 1 + 7 files changed, 33 insertions(+), 1 deletion(-) diff --git a/doc/example-config/conf.d/90-quota.conf b/doc/example-config/conf.d/90-quota.conf index db1f718815..40cde638b4 100644 --- a/doc/example-config/conf.d/90-quota.conf +++ b/doc/example-config/conf.d/90-quota.conf @@ -22,6 +22,9 @@ plugin { # over quota, if the quota doesn't grow too high. Default is to allow as # long as quota will stay under 10% above the limit. Also allowed e.g. 10M. #quota_grace = 10%% + + # Quota plugin can also limit the maximum accepted mail size. + #quota_max_mail_size = 100M } ## diff --git a/src/plugins/quota/Makefile.am b/src/plugins/quota/Makefile.am index cdc06c7bfb..329cf4719b 100644 --- a/src/plugins/quota/Makefile.am +++ b/src/plugins/quota/Makefile.am @@ -10,6 +10,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib-dict \ -I$(top_srcdir)/src/lib-index \ -I$(top_srcdir)/src/lib-mail \ + -I$(top_srcdir)/src/lib-settings \ -I$(top_srcdir)/src/lib-storage \ -I$(top_srcdir)/src/lib-storage/index \ -I$(top_srcdir)/src/lib-storage/index/maildir \ diff --git a/src/plugins/quota/quota-private.h b/src/plugins/quota/quota-private.h index a9184c8a87..ba7ba3d943 100644 --- a/src/plugins/quota/quota-private.h +++ b/src/plugins/quota/quota-private.h @@ -25,6 +25,7 @@ struct quota_settings { enum quota_alloc_result (*test_alloc)( struct quota_transaction_context *ctx, uoff_t size); + uoff_t max_mail_size; const char *quota_exceeded_msg; unsigned int debug:1; unsigned int initialized:1; diff --git a/src/plugins/quota/quota-status.c b/src/plugins/quota/quota-status.c index 35d59dd924..b1438ac0a7 100644 --- a/src/plugins/quota/quota-status.c +++ b/src/plugins/quota/quota-status.c @@ -102,6 +102,7 @@ static void client_handle_request(struct quota_client *client) if (value == NULL) value = "OK"; break; + case QUOTA_ALLOC_RESULT_OVER_MAXSIZE: /* even over maximum quota */ case QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT: value = mail_user_plugin_getenv(user, diff --git a/src/plugins/quota/quota-storage.c b/src/plugins/quota/quota-storage.c index f19612062e..fe85f4ed29 100644 --- a/src/plugins/quota/quota-storage.c +++ b/src/plugins/quota/quota-storage.c @@ -52,6 +52,9 @@ static void quota_set_storage_error(struct quota_transaction_context *qt, { const char *errstr = quota_alloc_result_errstr(res, qt); switch (res) { + case QUOTA_ALLOC_RESULT_OVER_MAXSIZE: + mail_storage_set_error(storage, MAIL_ERROR_LIMIT, errstr); + break; case QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT: case QUOTA_ALLOC_RESULT_OVER_QUOTA: mail_storage_set_error(storage, MAIL_ERROR_NOQUOTA, errstr); diff --git a/src/plugins/quota/quota.c b/src/plugins/quota/quota.c index bcc8ea4fbe..068185921b 100644 --- a/src/plugins/quota/quota.c +++ b/src/plugins/quota/quota.c @@ -13,6 +13,7 @@ #include "mailbox-list-private.h" #include "quota-private.h" #include "quota-fs.h" +#include "settings-parser.h" #include @@ -226,6 +227,9 @@ const char *quota_alloc_result_errstr(enum quota_alloc_result res, return "OK"; case QUOTA_ALLOC_RESULT_TEMPFAIL: return "Internal quota calculation error"; + case QUOTA_ALLOC_RESULT_OVER_MAXSIZE: + return "Mail size is larger than the maximum size allowed by " + "server configuration"; case QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT: case QUOTA_ALLOC_RESULT_OVER_QUOTA: return qt->quota->set->quota_exceeded_msg; @@ -254,6 +258,18 @@ int quota_user_read_settings(struct mail_user *user, quota_set->quota_exceeded_msg = DEFAULT_QUOTA_EXCEEDED_MSG; quota_set->vsizes = mail_user_plugin_getenv(user, "quota_vsizes") != NULL; + const char *max_size = mail_user_plugin_getenv(user, + "quota_max_mail_size"); + if (max_size != NULL) { + const char *error = NULL; + if (settings_get_size(max_size, "a_set->max_mail_size, + &error) < 0) { + *error_r = t_strdup_printf("quota_max_mail_size: %s", + error); + return -1; + } + } + p_array_init("a_set->root_sets, pool, 4); if (i_strocpy(root_name, "quota", sizeof(root_name)) < 0) i_unreached(); @@ -272,7 +288,8 @@ int quota_user_read_settings(struct mail_user *user, if (i_snprintf(root_name, sizeof(root_name), "quota%d", i) < 0) i_unreached(); } - if (array_count("a_set->root_sets) == 0) { + if (quota_set->max_mail_size == 0 && + array_count("a_set->root_sets) == 0) { pool_unref(&pool); return 0; } @@ -1211,6 +1228,11 @@ enum quota_alloc_result quota_test_alloc(struct quota_transaction_context *ctx, if (quota_transaction_set_limits(ctx) < 0) return QUOTA_ALLOC_RESULT_TEMPFAIL; + + uoff_t max_size = ctx->quota->set->max_mail_size; + if (max_size > 0 && size > max_size) + return QUOTA_ALLOC_RESULT_OVER_MAXSIZE; + if (ctx->no_quota_updates) return QUOTA_ALLOC_RESULT_OK; /* this is a virtual function mainly for trash plugin and similar, diff --git a/src/plugins/quota/quota.h b/src/plugins/quota/quota.h index 6cc72df257..293ccb4116 100644 --- a/src/plugins/quota/quota.h +++ b/src/plugins/quota/quota.h @@ -33,6 +33,7 @@ enum quota_recalculate { enum quota_alloc_result { QUOTA_ALLOC_RESULT_OK, QUOTA_ALLOC_RESULT_TEMPFAIL, + QUOTA_ALLOC_RESULT_OVER_MAXSIZE, QUOTA_ALLOC_RESULT_OVER_QUOTA, /* Mail size is larger than even the maximum allowed quota. */ QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT,