aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-09-22 09:25:14 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-09-22 09:25:14 +0100
commitc51794efd9fa38e294d29422a955648cfdf02510 (patch)
treec73ffb3fbaaa34a0a3aee4738aea829855da74de
parentfa95a35f7a04ac8bd25218927a202fd0bed10a48 (diff)
downloadrspamd-c51794efd9fa38e294d29422a955648cfdf02510.tar.gz
rspamd-c51794efd9fa38e294d29422a955648cfdf02510.zip
Cache correct passwords to avoid too high CPU usage.
-rw-r--r--src/controller.c64
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);
}