#include "keypairs_cache.h"
#include "keypair_private.h"
#include "ref.h"
+#include "xxhash.h"
/* This number is used as expire time in seconds for cache items (2 days) */
#define DEFAULT_EXPIRE 172800L
gint peer_fd;
struct event peer_ev;
/* Local keypair */
- gpointer key;
+ gpointer default_key;
+ GHashTable *keys;
gboolean encrypted_only;
struct rspamd_keypair_cache *keypair_cache;
struct rspamd_fuzzy_backend *backend;
struct rspamd_fuzzy_encrypted_req_hdr *hdr;
guchar *payload;
gsize payload_len;
- struct rspamd_http_keypair rk;
+ struct rspamd_http_keypair rk, *lk;
- if (s->ctx->key == NULL) {
+ if (s->ctx->default_key == NULL) {
msg_warn ("received encrypted request when encryption is not enabled");
return FALSE;
}
return FALSE;
}
+ /* Try to find the desired key */
+ lk = g_hash_table_lookup (s->ctx->keys, hdr->key_id);
+
+ if (lk == NULL) {
+ /* Unknown key, assume default one */
+ lk = s->ctx->default_key;
+ }
+
/* Now process keypair */
memcpy (rk.pk, hdr->pubkey, sizeof (rk.pk));
- rspamd_keypair_cache_process (s->ctx->keypair_cache, s->ctx->key, &rk);
+ rspamd_keypair_cache_process (s->ctx->keypair_cache, lk, &rk);
/* Now decrypt request */
if (!rspamd_cryptobox_decrypt_nm_inplace (payload, payload_len, hdr->nonce,
return TRUE;
}
+static gboolean
+fuzzy_parse_keypair (rspamd_mempool_t *pool,
+ const ucl_object_t *obj,
+ gpointer ud,
+ struct rspamd_rcl_section *section,
+ GError **err)
+{
+ struct rspamd_rcl_struct_parser *pd = ud;
+ struct rspamd_fuzzy_storage_ctx *ctx;
+ struct rspamd_http_keypair *kp;
+ const ucl_object_t *cur;
+ ucl_object_iter_t it = NULL;
+ gboolean ret;
+
+ ctx = pd->user_struct;
+ pd->offset = G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, default_key);
+
+ /*
+ * Single key
+ */
+ if (ucl_object_type (obj) == UCL_STRING || ucl_object_type (obj)
+ == UCL_OBJECT) {
+ ret = rspamd_rcl_parse_struct_keypair (pool, obj, pd, section, err);
+
+ if (!ret) {
+ return ret;
+ }
+
+ /* Insert key to the hash table */
+ kp = ctx->default_key;
+
+ if (kp == NULL) {
+ return FALSE;
+ }
+
+ g_hash_table_insert (ctx->keys, kp->pk, kp);
+ msg_info_pool ("loaded keypair %8xs", kp->pk);
+ }
+ else if (ucl_object_type (obj) == UCL_ARRAY) {
+ while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) {
+ if (!fuzzy_parse_keypair (pool, cur, pd, section, err)) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static guint
+fuzzy_kp_hash (gconstpointer p)
+{
+ const guchar *pk = p;
+
+ return XXH64 (pk, RSPAMD_FUZZY_KEYLEN, 0xdeadbabe);
+}
+
+static gboolean
+fuzzy_kp_equal (gconstpointer a, gconstpointer b)
+{
+ const guchar *pa = a, *pb = b;
+
+ return (memcmp (pa, pb, RSPAMD_FUZZY_KEYLEN) == 0);
+}
+
gpointer
init_fuzzy (struct rspamd_config *cfg)
{
ctx->sync_timeout = DEFAULT_SYNC_TIMEOUT;
ctx->expire = DEFAULT_EXPIRE;
ctx->keypair_cache_size = DEFAULT_KEYPAIR_CACHE_SIZE;
+ ctx->keys = g_hash_table_new_full (fuzzy_kp_hash, fuzzy_kp_equal,
+ NULL, rspamd_http_connection_key_unref);
rspamd_rcl_register_worker_option (cfg, type, "hashfile",
rspamd_rcl_parse_struct_string, ctx,
G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, update_map), 0);
rspamd_rcl_register_worker_option (cfg, type, "keypair",
- rspamd_rcl_parse_struct_keypair, ctx,
- G_STRUCT_OFFSET (struct rspamd_fuzzy_storage_ctx, key), 0);
+ fuzzy_parse_keypair, ctx,
+ 0, 0);
rspamd_rcl_register_worker_option (cfg, type, "keypair_cache_size",
rspamd_rcl_parse_struct_integer, ctx,
server_stat->fuzzy_hashes = rspamd_fuzzy_backend_count (ctx->backend);
- if (ctx->key && ctx->keypair_cache_size > 0) {
+ if (ctx->default_key && ctx->keypair_cache_size > 0) {
/* Create keypairs cache */
ctx->keypair_cache = rspamd_keypair_cache_new (ctx->keypair_cache_size);
}
if (ctx->keypair_cache) {
rspamd_keypair_cache_destroy (ctx->keypair_cache);
}
- if (ctx->key) {
- rspamd_http_connection_key_unref (ctx->key);
- }
+
+ g_hash_table_unref (ctx->keys);
exit (EXIT_SUCCESS);
}