diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-09-22 09:25:14 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-09-22 09:25:14 +0100 |
commit | c51794efd9fa38e294d29422a955648cfdf02510 (patch) | |
tree | c73ffb3fbaaa34a0a3aee4738aea829855da74de | |
parent | fa95a35f7a04ac8bd25218927a202fd0bed10a48 (diff) | |
download | rspamd-c51794efd9fa38e294d29422a955648cfdf02510.tar.gz rspamd-c51794efd9fa38e294d29422a955648cfdf02510.zip |
Cache correct passwords to avoid too high CPU usage.
-rw-r--r-- | src/controller.c | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/src/controller.c b/src/controller.c index d1c8a5eee..73a867c1a 100644 --- a/src/controller.c +++ b/src/controller.c @@ -139,6 +139,9 @@ struct rspamd_controller_worker_ctx { gchar *password; /* Privilleged password */ gchar *enable_password; + /* Cached versions of the passwords */ + rspamd_fstring_t cached_password; + rspamd_fstring_t cached_enable_password; /* HTTP server */ struct rspamd_http_connection_router *http; /* Server's start time */ @@ -285,13 +288,37 @@ rspamd_encrypted_password_get_str (const gchar * password, gsize skip, static gboolean rspamd_check_encrypted_password (struct rspamd_controller_worker_ctx *ctx, const GString * password, const gchar * check, - const struct rspamd_controller_pbkdf *pbkdf) + const struct rspamd_controller_pbkdf *pbkdf, + gboolean is_enable) { const gchar *salt, *hash; gchar *salt_decoded, *key_decoded; gsize salt_len, key_len; gboolean ret = TRUE; guchar *local_key; + rspamd_fstring_t *cache; + + /* First of all check cached versions to save resources */ + if (is_enable && ctx->cached_enable_password.len != 0) { + if (password->len != ctx->cached_enable_password.len || + !rspamd_constant_memcmp (password->str, + ctx->cached_enable_password.begin, password->len)) { + msg_info_ctx ("incorrect or absent enable password has been specified"); + return FALSE; + } + + return TRUE; + } + else if (!is_enable && ctx->cached_password.len != 0) { + if (password->len != ctx->cached_password.len || + !rspamd_constant_memcmp (password->str, + ctx->cached_password.begin, password->len)) { + msg_info_ctx ("incorrect or absent password has been specified"); + return FALSE; + } + + return TRUE; + } g_assert (pbkdf != NULL); /* get salt */ @@ -334,6 +361,21 @@ rspamd_check_encrypted_password (struct rspamd_controller_worker_ctx *ctx, g_free (key_decoded); } + if (ret) { + /* Save cached version */ + cache = is_enable ? &ctx->cached_enable_password : &ctx->cached_password; + + if (cache->len == 0) { + /* Mmap region */ + cache->begin = mmap (NULL, password->len, PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + memcpy (cache->begin, password->str, password->len); + (void)mprotect (cache->begin, password->len, PROT_READ); + (void)mlock (cache->begin, password->len); + cache->len = password->len; + } + } + return ret; } @@ -348,7 +390,8 @@ static gboolean rspamd_controller_check_password( GString lookup; GHashTable *query_args = NULL; struct rspamd_controller_worker_ctx *ctx = session->ctx; - gboolean check_normal = TRUE, check_enable = TRUE, ret = TRUE; + gboolean check_normal = TRUE, check_enable = TRUE, ret = TRUE, + use_enable = FALSE; const struct rspamd_controller_pbkdf *pbkdf = NULL; /* Access list logic */ @@ -400,6 +443,7 @@ static gboolean rspamd_controller_check_password( /* For privileged commands we strictly require enable password */ if (ctx->enable_password != NULL) { check = ctx->enable_password; + use_enable = TRUE; } else { /* Use just a password (legacy mode) */ @@ -413,7 +457,7 @@ static gboolean rspamd_controller_check_password( } else { ret = rspamd_check_encrypted_password (ctx, password, check, - pbkdf); + pbkdf, use_enable); } } else { @@ -437,7 +481,7 @@ static gboolean rspamd_controller_check_password( else { check_normal = rspamd_check_encrypted_password (ctx, password, - check, pbkdf); + check, pbkdf, FALSE); } } @@ -453,7 +497,7 @@ static gboolean rspamd_controller_check_password( else { check_enable = rspamd_check_encrypted_password (ctx, password, - check, pbkdf); + check, pbkdf, TRUE); } } else { @@ -1017,7 +1061,7 @@ rspamd_controller_handle_graph ( false); ucl_object_insert_key (data_elt, ucl_object_fromdouble (rrd_result->data[i * - rrd_result->ds_count + j]), + rrd_result->ds_count + j]), "y", 1, false); ucl_array_append (elt[j], data_elt); @@ -2510,5 +2554,13 @@ start_controller_worker (struct rspamd_worker *worker) rspamd_rrd_close (ctx->rrd); } + if (ctx->cached_password.len > 0) { + munmap (ctx->cached_password.begin, ctx->cached_password.len); + } + + if (ctx->cached_enable_password.len > 0) { + munmap (ctx->cached_enable_password.begin, ctx->cached_enable_password.len); + } + exit (EXIT_SUCCESS); } |