]> source.dussan.org Git - rspamd.git/commitdiff
Refactor dkim private key loads
authorJohn McKay <adenosine3p@gmail.com>
Thu, 24 Jan 2019 01:26:21 +0000 (01:26 +0000)
committerJohn McKay <adenosine3p@gmail.com>
Sat, 2 Feb 2019 05:41:41 +0000 (05:41 +0000)
src/libserver/dkim.c
src/libserver/dkim.h
src/plugins/dkim_check.c

index d4c54b422b82387c54a4b31b7a457306605041b8..5144c051722082957c5e57736d7658e9225d91c6 100644 (file)
@@ -144,7 +144,7 @@ struct rspamd_dkim_context_s {
 
 struct rspamd_dkim_key_s {
        guint8 *keydata;
-       guint keylen;
+       gsize keylen;
        gsize decoded_len;
        guint ttl;
        union {
@@ -155,6 +155,7 @@ struct rspamd_dkim_key_s {
        enum rspamd_dkim_key_type type;
        BIO *key_bio;
        EVP_PKEY *key_evp;
+       time_t mtime;
        ref_entry_t ref;
 };
 
@@ -163,22 +164,6 @@ struct rspamd_dkim_sign_context_s {
        rspamd_dkim_sign_key_t *key;
 };
 
-struct rspamd_dkim_sign_key_s {
-       enum rspamd_dkim_key_type type;
-       guint8 *keydata;
-       gpointer map;
-       gsize keylen;
-       union {
-               RSA *key_rsa;
-               guchar *key_eddsa;
-       } key;
-       BIO *key_bio;
-       EVP_PKEY *key_evp;
-       time_t mtime;
-       ref_entry_t ref;
-};
-
-
 struct rspamd_dkim_header {
        const gchar *name;
        guint count;
@@ -1364,15 +1349,9 @@ rspamd_dkim_sign_key_free (rspamd_dkim_sign_key_t *key)
                BIO_free (key->key_bio);
        }
 
-       if (key->keydata && key->keylen > 0) {
-
-               if (key->map) {
-                       munmap (key->map, key->keylen);
-               }
-               else {
-                       rspamd_explicit_memzero (key->keydata, key->keylen);
-                       g_free (key->keydata);
-               }
+       if (key->type == RSPAMD_DKIM_KEY_EDDSA) {
+               rspamd_explicit_memzero (key->key.key_eddsa, key->keylen);
+               g_free (key->keydata);
        }
 
        g_free (key);
@@ -2626,107 +2605,44 @@ rspamd_dkim_get_dns_key (rspamd_dkim_context_t *ctx)
 }
 
 rspamd_dkim_sign_key_t*
-rspamd_dkim_sign_key_load (const gchar *what, gsize len,
-               enum rspamd_dkim_sign_key_type type,
+rspamd_dkim_sign_key_load (const gchar *key, gsize len,
+               enum rspamd_dkim_key_format type,
                GError **err)
 {
-       gpointer map;
-       gsize map_len = 0;
        rspamd_dkim_sign_key_t *nkey;
-       struct stat st;
-       time_t mtime = 0;
-
-       if (type == RSPAMD_DKIM_SIGN_KEY_FILE) {
-               gchar fpath[PATH_MAX];
+       time_t mtime = time (NULL);
 
-               rspamd_snprintf (fpath, sizeof (fpath), "%*s", (gint)len, what);
-
-               if (stat (fpath, &st) == -1) {
-                       g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
-                                       "cannot stat private key %s: %s",
-                                       fpath, strerror (errno));
-
-                       return NULL;
-               }
-
-               mtime = st.st_mtime;
-               map = rspamd_file_xmap (fpath, PROT_READ, &map_len, TRUE);
-
-               if (map == NULL) {
+       switch (type) {
+               case RSPAMD_DKIM_KEY_PEM:
+                       /* fallthrough */
+               case RSPAMD_DKIM_KEY_RAW:
+                       break;
+               default:
                        g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
-                                       "cannot map private key %s: %s",
-                                       fpath, strerror (errno));
-
+                                       "invalid key type to load: %d", type);
                        return NULL;
-               }
        }
 
        nkey = g_malloc0 (sizeof (*nkey));
-       nkey->type = type;
        nkey->mtime = mtime;
 
-       switch (type) {
-       case RSPAMD_DKIM_SIGN_KEY_FILE:
-               (void)mlock (map, len);
-               nkey->map = map;
-               nkey->keydata = map;
-               nkey->keylen = map_len;
-               break;
-       case RSPAMD_DKIM_SIGN_KEY_BASE64:
-               nkey->keydata = g_malloc (len);
-               nkey->keylen = len;
-               rspamd_cryptobox_base64_decode (what, len, nkey->keydata,
-                               &nkey->keylen);
-               break;
-       case RSPAMD_DKIM_SIGN_KEY_DER:
-       case RSPAMD_DKIM_SIGN_KEY_PEM:
-               nkey->keydata = g_malloc (len);
-               memcpy (nkey->keydata, what, len);
-               nkey->keylen = len;
-       }
-
-       msg_debug2_dkim("got public key with length %d and type %d", nkey->keylen, type);
-       (void)mlock (nkey->keydata, nkey->keylen);
-       if (type == RSPAMD_DKIM_SIGN_KEY_FILE && nkey->keylen == ED25519_B64_BYTES) {
-               unsigned char seed[32];
+       msg_debug2_dkim("got public key with length %d and type %d", len, type);
+       if (type == RSPAMD_DKIM_KEY_RAW && len == 32) {
                unsigned char pk[32];
                nkey->type = RSPAMD_DKIM_KEY_EDDSA;
-               nkey->keydata = g_malloc (rspamd_cryptobox_sk_sig_bytes (RSPAMD_CRYPTOBOX_MODE_25519));
-               rspamd_cryptobox_base64_decode (nkey->map, ED25519_B64_BYTES, seed, &nkey->keylen);
-               ed25519_seed_keypair (pk, nkey->keydata, seed);
-               nkey->key.key_eddsa = nkey->keydata;
-               nkey->keylen = rspamd_cryptobox_sk_sig_bytes (RSPAMD_CRYPTOBOX_MODE_25519);
-               rspamd_explicit_memzero (seed, 32);
-               munmap (nkey->map, ED25519_B64_BYTES);
-               nkey->map = NULL;
-       }
-       else if (type == RSPAMD_DKIM_SIGN_KEY_BASE64 && nkey->keylen == ED25519_BYTES) {
-               unsigned char pk[32];
-               nkey->type = RSPAMD_DKIM_KEY_EDDSA;
-               nkey->key.key_eddsa =
-                       g_malloc (rspamd_cryptobox_sk_sig_bytes (RSPAMD_CRYPTOBOX_MODE_25519));
-               ed25519_seed_keypair (pk, nkey->key.key_eddsa, nkey->keydata);
-               rspamd_explicit_memzero (nkey->keydata, nkey->keylen);
-               g_free (nkey->keydata);
-               nkey->keydata = nkey->key.key_eddsa;
+               nkey->key.key_eddsa = g_malloc (
+                               rspamd_cryptobox_sk_sig_bytes (RSPAMD_CRYPTOBOX_MODE_25519));
+               ed25519_seed_keypair (pk, nkey->key.key_eddsa, (char *)key);
                nkey->keylen = rspamd_cryptobox_sk_sig_bytes (RSPAMD_CRYPTOBOX_MODE_25519);
        }
        else {
-               nkey->key_bio = BIO_new_mem_buf (nkey->keydata, nkey->keylen);
+               nkey->key_bio = BIO_new_mem_buf (key, len);
 
-               if (type == RSPAMD_DKIM_SIGN_KEY_DER || type == RSPAMD_DKIM_SIGN_KEY_BASE64) {
+               if (type == RSPAMD_DKIM_KEY_RAW) {
                        if (d2i_PrivateKey_bio (nkey->key_bio, &nkey->key_evp) == NULL) {
-                               if (type == RSPAMD_DKIM_SIGN_KEY_FILE) {
-                                       g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
-                                                       "cannot read private key from %*s: %s",
-                                                       (gint)len, what,
-                                                       ERR_error_string (ERR_get_error (), NULL));
-                               }
-                               else {
-                                       g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
-                                                       "cannot read private key from string: %s",
-                                                       ERR_error_string (ERR_get_error (), NULL));
-                               }
+                               g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
+                                               "cannot parse raw private key: %s",
+                                               ERR_error_string (ERR_get_error (), NULL));
 
                                rspamd_dkim_sign_key_free (nkey);
 
@@ -2735,18 +2651,9 @@ rspamd_dkim_sign_key_load (const gchar *what, gsize len,
                }
                else {
                        if (!PEM_read_bio_PrivateKey (nkey->key_bio, &nkey->key_evp, NULL, NULL)) {
-                               if (type == RSPAMD_DKIM_SIGN_KEY_FILE) {
-                                       g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
-                                                       "cannot read private key from %*s: %s",
-                                                       (gint)len, what,
-                                                       ERR_error_string (ERR_get_error (), NULL));
-                               }
-                               else {
-                                       g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
-                                                       "cannot read private key from string: %s",
-                                                       ERR_error_string (ERR_get_error (), NULL));
-                               }
-
+                               g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
+                                               "cannot parse pem private key: %s",
+                                               ERR_error_string (ERR_get_error (), NULL));
                                rspamd_dkim_sign_key_free (nkey);
 
                                return NULL;
@@ -2772,32 +2679,11 @@ rspamd_dkim_sign_key_load (const gchar *what, gsize len,
 }
 
 gboolean
-rspamd_dkim_sign_key_maybe_invalidate (rspamd_dkim_sign_key_t *key,
-               enum rspamd_dkim_sign_key_type type,
-               const gchar *what, gsize len)
+rspamd_dkim_sign_key_maybe_invalidate (rspamd_dkim_sign_key_t *key, time_t mtime)
 {
-       struct stat st;
-
-       if (type == RSPAMD_DKIM_SIGN_KEY_FILE) {
-               gchar fpath[PATH_MAX];
-
-               if (len >= PATH_MAX) {
-                       /* Bad thing */
+       if (mtime > key->mtime) {
                        return TRUE;
-               }
-
-               rspamd_snprintf (fpath, sizeof (fpath), "%*s", (gint) len, what);
-
-               if (stat (fpath, &st) == -1) {
-                       /* Wrong: do NOT prefer to use cached key since it is absent on FS */
-                       return TRUE;
-               }
-
-               if (st.st_mtime > key->mtime) {
-                       return TRUE;
-               }
        }
-
        return FALSE;
 }
 
index 46953a21ccfaff61b0b8d450b0f2a3c7fbfd83ba..d57c923bbe780bdaea875913983554656df11d3a 100644 (file)
@@ -102,16 +102,17 @@ typedef struct rspamd_dkim_sign_context_s rspamd_dkim_sign_context_t;
 struct rspamd_dkim_key_s;
 typedef struct rspamd_dkim_key_s rspamd_dkim_key_t;
 
-struct rspamd_dkim_sign_key_s;
-typedef struct rspamd_dkim_sign_key_s rspamd_dkim_sign_key_t;
+struct rspamd_dkim_key_s;
+typedef struct rspamd_dkim_key_s rspamd_dkim_sign_key_t;
 
 struct rspamd_task;
 
-enum rspamd_dkim_sign_key_type {
-       RSPAMD_DKIM_SIGN_KEY_FILE = 0,
-       RSPAMD_DKIM_SIGN_KEY_PEM,
-       RSPAMD_DKIM_SIGN_KEY_BASE64,
-       RSPAMD_DKIM_SIGN_KEY_DER
+enum rspamd_dkim_key_format {
+       RSPAMD_DKIM_KEY_FILE = 0,
+       RSPAMD_DKIM_KEY_PEM,
+       RSPAMD_DKIM_KEY_BASE64,
+       RSPAMD_DKIM_KEY_RAW,
+       RSPAMD_DKIM_KEY_UNKNOWN
 };
 
 enum rspamd_dkim_type {
@@ -188,17 +189,16 @@ rspamd_dkim_sign_context_t * rspamd_create_dkim_sign_context (struct rspamd_task
  * @return
  */
 rspamd_dkim_sign_key_t* rspamd_dkim_sign_key_load (const gchar *what, gsize len,
-               enum rspamd_dkim_sign_key_type type,
+               enum rspamd_dkim_key_format type,
                GError **err);
 
 /**
  * Invalidate modified sign key
  * @param key
  * @return
- */
+*/
 gboolean rspamd_dkim_sign_key_maybe_invalidate (rspamd_dkim_sign_key_t *key,
-               enum rspamd_dkim_sign_key_type type,
-               const gchar *what, gsize len);
+               time_t mtime);
 
 /**
  * Make DNS request for specified context and obtain and parse key
index 92354529fcf6e9f44d4cdfb3ed2ae0d7a75819c5..06c039ea45f3923c49bf7cdf047eb02dc1f06c7b 100644 (file)
@@ -38,6 +38,7 @@
 #include "libutil/map_helpers.h"
 #include "rspamd.h"
 #include "utlist.h"
+#include "unix-std.h"
 #include "lua/lua_common.h"
 #include "libserver/mempool_vars_internal.h"
 
@@ -634,16 +635,58 @@ dkim_module_config (struct rspamd_config *cfg)
        return res;
 }
 
+/**
+ * helper to see if valid base64, minus newline
+ */
+static gboolean
+is_valid_base64(const uint8_t *in, size_t len) {
+       int i;
+       if (in[len - 1] == '\n')
+               len--;
+       if (in[len - 1] == '\r')
+               len--;
+       if (len % 4 != 0)
+               return FALSE;
+
+       if (in[len - 1] == '=')
+               len--;
+       if (in[len - 1] == '=')
+               len--;
+
+       for (i = 0; i < len; i++) {
+               if ('a' <= in[i] && in[i] <= 'z')
+                       continue;
+               if ('A' <= in[i] && in[i] <= 'Z')
+                       continue;
+               if ('0' <= in[i] && in[i] <= '9')
+                       continue;
+               if (in[i] == '/')
+                       continue;
+               if (in[i] == '+')
+                       continue;
+               return FALSE;
+       }
+       return TRUE;
+}
+
+
+#define PEM_SIG "-----BEGIN"
+/**
+ * Grab a private key from the cache
+ * or from the key content provided
+ */
 rspamd_dkim_sign_key_t *
-dkim_module_load_key_format (lua_State *L, struct rspamd_task *task,
-               const gchar *key, gsize keylen,
-               enum rspamd_dkim_sign_key_type kt)
+dkim_module_load_key_format (struct rspamd_task *task, struct dkim_ctx *dkim_module_ctx,
+               const gchar *key, gsize keylen, enum rspamd_dkim_key_format key_format)
+
 {
        guchar h[rspamd_cryptobox_HASHBYTES],
                        hex_hash[rspamd_cryptobox_HASHBYTES * 2 + 1];
        rspamd_dkim_sign_key_t *ret;
        GError *err = NULL;
-       struct dkim_ctx *dkim_module_ctx = dkim_get_context (task->cfg);
+       gpointer map = NULL, tmp = NULL;
+       struct stat st;
+       ssize_t maplen;
 
        memset (hex_hash, 0, sizeof (hex_hash));
        rspamd_cryptobox_hash (h, key, keylen, NULL, 0);
@@ -651,23 +694,95 @@ dkim_module_load_key_format (lua_State *L, struct rspamd_task *task,
        ret = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_sign_hash,
                                hex_hash, time (NULL));
 
-       if (ret == NULL) {
-                       ret = rspamd_dkim_sign_key_load (key, keylen, kt, &err);
+       /*
+        * This fails for paths that are also valid base64.
+        * Maybe the caller should have specified a format.
+        */
+       if (key_format == RSPAMD_DKIM_KEY_UNKNOWN &&
+               (key[0] == '.' || key[0] == '/')) {
+               if (!is_valid_base64 (key, keylen))
+                       key_format = RSPAMD_DKIM_KEY_FILE;
+       }
 
-                       if (ret == NULL) {
-                               msg_err_task ("cannot load private key: %e", err);
-                               g_error_free (err);
+       if (ret != NULL && key_format == RSPAMD_DKIM_KEY_FILE) {
+               msg_debug_task("checking for stale file key");
+               if (stat (key, &st) != 0) {
+                       msg_err_task("cannot stat key file: %s", strerror (errno));
+                       return NULL;
+               }
+               if (rspamd_dkim_sign_key_maybe_invalidate (ret, st.st_mtime)) {
+                       msg_debug_task("removing stale file key");
+                       /*
+                        * Invalidate DKIM key
+                        * removal from lru cache also cleanup the key and value
+                        */
+                       rspamd_lru_hash_remove (dkim_module_ctx->dkim_sign_hash,
+                                       hex_hash);
+                       ret = NULL;
+               }
+       }
 
-                               return NULL;
-                       }
+       /* found key; done */
+       if (ret != NULL)
+               return ret;
 
-                       rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash,
-                                       g_strdup (hex_hash), ret,
-                                       time (NULL), 0);
+       if (key_format == RSPAMD_DKIM_KEY_FILE) {
+               if (stat (key, &st) != 0) {
+                       msg_err_task("cannot stat key file: %s", strerror (errno));
+                       return NULL;
                }
+               map = rspamd_file_xmap (key, PROT_READ, &maplen, TRUE);
+               if (map == NULL) {
+                       msg_err_task("cannot open key file \'%s\'", key);
+                       return NULL;
+               }
+               key = map;
+               keylen = maplen;
+               if (maplen > sizeof (PEM_SIG) &&
+                               strncmp (map, PEM_SIG, sizeof (PEM_SIG) - 1) == 0) {
+                       key_format = RSPAMD_DKIM_KEY_PEM;
+               } else if (is_valid_base64 ((uint8_t *)map, maplen)) {
+                       key_format = RSPAMD_DKIM_KEY_BASE64;
+               } else {
+                       key_format = RSPAMD_DKIM_KEY_RAW;
+               }
+       }
+       if (key_format == RSPAMD_DKIM_KEY_UNKNOWN) {
+               if (keylen > sizeof (PEM_SIG) &&
+                               strncmp (key, PEM_SIG, sizeof (PEM_SIG) - 1) == 0) {
+                       key_format = RSPAMD_DKIM_KEY_PEM;
+               } else {
+                       key_format = RSPAMD_DKIM_KEY_RAW;
+               }
+       }
+       if (key_format == RSPAMD_DKIM_KEY_BASE64) {
+               key_format = RSPAMD_DKIM_KEY_RAW;
+               tmp = g_malloc (keylen);
+               rspamd_cryptobox_base64_decode (key, keylen, tmp, &keylen);
+               key = tmp;
+       }
+
+       ret = rspamd_dkim_sign_key_load (key, keylen, key_format, &err);
+
+       if (ret == NULL) {
+               msg_err_task ("cannot load dkim key %s: %e",
+                               key, err);
+               g_error_free (err);
+       } else {
+               rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash,
+                               g_strdup (hex_hash), ret, time (NULL), 0);
+       }
+
+       if (map != NULL)
+               munmap (map, maplen);
+       if (tmp != NULL) {
+               rspamd_explicit_memzero (tmp, keylen);
+               g_free (tmp);
+       }
 
        return ret;
 }
+#undef PEM_SIG
 
 static gint
 lua_dkim_sign_handler (lua_State *L)
@@ -718,86 +833,24 @@ lua_dkim_sign_handler (lua_State *L)
                                (GDestroyNotify)rspamd_dkim_sign_key_unref);
        }
 
-#define PEM_SIG "-----BEGIN"
 
        if (key) {
-               if (key[0] == '.' || key[0] == '/') {
-                       /* Likely raw path */
-                       dkim_key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_sign_hash,
-                                       key, time (NULL));
-
-                       if (dkim_key == NULL) {
-                               dkim_key = rspamd_dkim_sign_key_load (key, strlen (key),
-                                               RSPAMD_DKIM_SIGN_KEY_FILE, &err);
-
-                               if (dkim_key == NULL) {
-                                       msg_err_task ("cannot load dkim key %s: %e",
-                                                       key, err);
-                                       g_error_free (err);
-
-                                       lua_pushboolean (L, FALSE);
-                                       return 1;
-                               }
-
-                               rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash,
-                                               g_strdup (key), dkim_key,
-                                               time (NULL), 0);
-                       }
-               }
-               else if (keylen > sizeof (PEM_SIG) &&
-                               strncmp (key, PEM_SIG, sizeof (PEM_SIG) - 1) == 0) {
-                       /* Pem header found */
-                       dkim_key = dkim_module_load_key_format (L, task, key, keylen,
-                                       RSPAMD_DKIM_SIGN_KEY_PEM);
-
-                       if (dkim_key == NULL) {
-                               lua_pushboolean (L, FALSE);
-                               return 1;
-                       }
-               }
-               else {
-                       dkim_key = dkim_module_load_key_format (L, task, key, keylen,
-                                       RSPAMD_DKIM_SIGN_KEY_BASE64);
-
-                       if (dkim_key == NULL) {
-                               lua_pushboolean (L, FALSE);
-                               return 1;
-                       }
-               }
-       }
-       else if (rawkey) {
-               key = rawkey;
-               keylen = rawlen;
-
-               if (keylen > sizeof (PEM_SIG) &&
-                               strncmp (key, PEM_SIG, sizeof (PEM_SIG) - 1) == 0) {
-                       /* Pem header found */
-                       dkim_key = dkim_module_load_key_format (L, task, key, keylen,
-                                       RSPAMD_DKIM_SIGN_KEY_PEM);
-
-                       if (dkim_key == NULL) {
-                               lua_pushboolean (L, FALSE);
-                               return 1;
-                       }
-               }
-               else {
-                       dkim_key = dkim_module_load_key_format (L, task, key, keylen,
-                                       RSPAMD_DKIM_SIGN_KEY_BASE64);
-
-                       if (dkim_key == NULL) {
-                               lua_pushboolean (L, FALSE);
-                               return 1;
-                       }
-               }
-       }
-       else {
+               dkim_key = dkim_module_load_key_format (task, dkim_module_ctx, key,
+                               keylen, RSPAMD_DKIM_KEY_UNKNOWN);
+       } else if(rawkey) {
+               dkim_key = dkim_module_load_key_format (task, dkim_module_ctx, rawkey,
+                               rawlen, RSPAMD_DKIM_KEY_UNKNOWN);
+       } else {
                msg_err_task ("neither key nor rawkey are specified");
                lua_pushboolean (L, FALSE);
 
                return 1;
        }
 
-#undef PEM_SIG
+       if (dkim_key == NULL) {
+               lua_pushboolean (L, FALSE);
+               return 1;
+       }
 
        if (sign_type_str) {
                if (strcmp (sign_type_str, "dkim") == 0) {
@@ -1311,226 +1364,167 @@ dkim_sign_callback (struct rspamd_task *task,
        GString *tb, *hdr;
        GError *err = NULL;
        const gchar *selector = NULL, *domain = NULL, *key = NULL, *key_type = NULL,
-                       *sign_type_str = NULL, *lru_key, *arc_cv = NULL;
+                       *sign_type_str = NULL, *arc_cv = NULL;
        rspamd_dkim_sign_context_t *ctx;
-       rspamd_dkim_sign_key_t *dkim_key;
-       enum rspamd_dkim_sign_key_type key_sign_type = RSPAMD_DKIM_SIGN_KEY_FILE;
+       rspamd_dkim_key_t *dkim_key;
+       enum rspamd_dkim_key_format key_format = RSPAMD_DKIM_KEY_FILE;
        enum rspamd_dkim_type sign_type = RSPAMD_DKIM_NORMAL;
-       guchar h[rspamd_cryptobox_HASHBYTES],
-               hex_hash[rspamd_cryptobox_HASHBYTES * 2 + 1];
        struct dkim_ctx *dkim_module_ctx = dkim_get_context (task->cfg);
 
-       if (dkim_module_ctx->sign_condition_ref != -1) {
-               sign = FALSE;
-               L = task->cfg->lua_state;
-               lua_pushcfunction (L, &rspamd_lua_traceback);
-               err_idx = lua_gettop (L);
-
-               lua_rawgeti (L, LUA_REGISTRYINDEX, dkim_module_ctx->sign_condition_ref);
-               ptask = lua_newuserdata (L, sizeof (struct rspamd_task *));
-               *ptask = task;
-               rspamd_lua_setclass (L, "rspamd{task}", -1);
-
-               if (lua_pcall (L, 1, 1, err_idx) != 0) {
-                       tb = lua_touserdata (L, -1);
-                       msg_err_task ("call to user extraction script failed: %v", tb);
-                       g_string_free (tb, TRUE);
-               }
-               else {
-                       if (lua_istable (L, -1)) {
-                               /*
-                                * Get the following elements:
-                                * - selector
-                                * - domain
-                                * - key
-                                */
-                               if (!rspamd_lua_parse_table_arguments (L, -1, &err,
-                                               "*key=V;*domain=S;*selector=S;type=S;key_type=S;"
-                                                               "sign_type=S;arc_cv=S;arc_idx=I",
-                                               &len, &key, &domain, &selector,
-                                               &key_type, &key_type, &sign_type_str, &arc_cv,
-                                               &arc_idx)) {
-                                       msg_err_task ("invalid return value from sign condition: %e",
-                                                       err);
-                                       g_error_free (err);
-                                       rspamd_symcache_finalize_item (task, item);
+       if (dkim_module_ctx->sign_condition_ref == -1) {
+               rspamd_symcache_finalize_item (task, item);
+               return;
+       }
 
-                                       return;
-                               }
+       sign = FALSE;
+       L = task->cfg->lua_state;
+       lua_pushcfunction (L, &rspamd_lua_traceback);
+       err_idx = lua_gettop (L);
 
-                               if (key_type) {
-                                       if (strcmp (key_type, "file") == 0) {
-                                               key_sign_type = RSPAMD_DKIM_SIGN_KEY_FILE;
-                                       }
-                                       else if (strcmp (key_type, "base64") == 0) {
-                                               key_sign_type = RSPAMD_DKIM_SIGN_KEY_BASE64;
-                                       }
-                                       else if (strcmp (key_type, "pem") == 0) {
-                                               key_sign_type = RSPAMD_DKIM_SIGN_KEY_PEM;
-                                       }
-                                       else if (strcmp (key_type, "der") == 0 ||
-                                                       strcmp (key_type, "raw") == 0) {
-                                               key_sign_type = RSPAMD_DKIM_SIGN_KEY_DER;
-                                       }
-                                       else {
-                                               lua_settop (L, 0);
-                                               luaL_error (L, "unknown key type: %s",
-                                                               key_type);
-                                               rspamd_symcache_finalize_item (task, item);
+       lua_rawgeti (L, LUA_REGISTRYINDEX, dkim_module_ctx->sign_condition_ref);
+       ptask = lua_newuserdata (L, sizeof (struct rspamd_task *));
+       *ptask = task;
+       rspamd_lua_setclass (L, "rspamd{task}", -1);
 
-                                               return;
-                                       }
-                               }
+       if (lua_pcall (L, 1, 1, err_idx) != 0) {
+               tb = lua_touserdata (L, -1);
+               msg_err_task ("call to user extraction script failed: %v", tb);
+               g_string_free (tb, TRUE);
+       }
+       else {
+               if (lua_istable (L, -1)) {
+                       /*
+                        * Get the following elements:
+                        * - selector
+                        * - domain
+                        * - key
+                        */
+                       if (!rspamd_lua_parse_table_arguments (L, -1, &err,
+                                       "*key=V;*domain=S;*selector=S;type=S;key_type=S;"
+                                                       "sign_type=S;arc_cv=S;arc_idx=I",
+                                       &len, &key, &domain, &selector,
+                                       &key_type, &key_type, &sign_type_str, &arc_cv,
+                                       &arc_idx)) {
+                               msg_err_task ("invalid return value from sign condition: %e",
+                                               err);
+                               g_error_free (err);
+                               rspamd_symcache_finalize_item (task, item);
 
-                               if (sign_type_str) {
-                                       if (strcmp (sign_type_str, "dkim") == 0) {
-                                               sign_type = RSPAMD_DKIM_NORMAL;
-                                       }
-                                       else if (strcmp (sign_type_str, "arc-sign") == 0) {
-                                               sign_type = RSPAMD_DKIM_ARC_SIG;
-                                               if (arc_idx == 0) {
-                                                       lua_settop (L, 0);
-                                                       luaL_error (L, "no arc idx specified");
-                                                       rspamd_symcache_finalize_item (task, item);
-
-                                                       return;
-                                               }
-                                       }
-                                       else if (strcmp (sign_type_str, "arc-seal") == 0) {
-                                               sign_type = RSPAMD_DKIM_ARC_SEAL;
-                                               if (arc_cv == NULL) {
-                                                       lua_settop (L, 0);
-                                                       luaL_error (L, "no arc cv specified");
-                                                       rspamd_symcache_finalize_item (task, item);
-
-                                                       return;
-                                               }
-                                               if (arc_idx == 0) {
-                                                       lua_settop (L, 0);
-                                                       luaL_error (L, "no arc idx specified");
-                                                       rspamd_symcache_finalize_item (task, item);
-
-                                                       return;
-                                               }
-                                       }
-                                       else {
-                                               lua_settop (L, 0);
-                                               luaL_error (L, "unknown sign type: %s",
-                                                               sign_type_str);
-                                               rspamd_symcache_finalize_item (task, item);
+                               return;
+                       }
 
-                                               return;
-                                       }
+                       if (key_type) {
+                               if (strcmp (key_type, "file") == 0) {
+                                       key_format = RSPAMD_DKIM_KEY_FILE;
                                }
-
-                               if (key_sign_type == RSPAMD_DKIM_SIGN_KEY_FILE) {
-
-                                       dkim_key = rspamd_lru_hash_lookup (
-                                                       dkim_module_ctx->dkim_sign_hash,
-                                                       key, time (NULL));
-                                       lru_key = key;
+                               else if (strcmp (key_type, "base64") == 0) {
+                                       key_format = RSPAMD_DKIM_KEY_BASE64;
                                }
-                               else {
-                                       /* Prehash */
-                                       memset (hex_hash, 0, sizeof (hex_hash));
-                                       rspamd_cryptobox_hash (h, key, len, NULL, 0);
-                                       rspamd_encode_hex_buf (h, sizeof (h),
-                                                       hex_hash, sizeof (hex_hash));
-                                       dkim_key = rspamd_lru_hash_lookup (
-                                                       dkim_module_ctx->dkim_sign_hash,
-                                                       hex_hash, time (NULL));
-                                       lru_key = hex_hash;
+                               else if (strcmp (key_type, "pem") == 0) {
+                                       key_format = RSPAMD_DKIM_KEY_PEM;
                                }
+                               else if (strcmp (key_type, "der") == 0 ||
+                                               strcmp (key_type, "raw") == 0) {
+                                       key_format = RSPAMD_DKIM_KEY_RAW;
+                               }
+                               else {
+                                       lua_settop (L, 0);
+                                       luaL_error (L, "unknown key type: %s",
+                                                       key_type);
+                                       rspamd_symcache_finalize_item (task, item);
 
-                               if (dkim_key == NULL) {
-                                       dkim_key = rspamd_dkim_sign_key_load (key, len,
-                                                       key_sign_type, &err);
+                                       return;
+                               }
+                       }
 
-                                       if (dkim_key == NULL) {
-                                               msg_err_task ("cannot load dkim key %s: %e",
-                                                               lru_key, err);
-                                               g_error_free (err);
+                       if (sign_type_str) {
+                               if (strcmp (sign_type_str, "dkim") == 0) {
+                                       sign_type = RSPAMD_DKIM_NORMAL;
+                               }
+                               else if (strcmp (sign_type_str, "arc-sign") == 0) {
+                                       sign_type = RSPAMD_DKIM_ARC_SIG;
+                                       if (arc_idx == 0) {
+                                               lua_settop (L, 0);
+                                               luaL_error (L, "no arc idx specified");
                                                rspamd_symcache_finalize_item (task, item);
 
                                                return;
                                        }
-                                       else {
-                                               rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash,
-                                                               g_strdup (lru_key), dkim_key,
-                                                               time (NULL), 0);
-                                       }
                                }
-                               else if (rspamd_dkim_sign_key_maybe_invalidate (dkim_key,
-                                               key_sign_type, key, len)) {
-                                       /*
-                                        * Invalidate and reload DKIM key,
-                                        * removal from lru cache also cleanup the key and value
-                                        */
-
-                                       rspamd_lru_hash_remove (dkim_module_ctx->dkim_sign_hash,
-                                                       lru_key);
-                                       dkim_key = rspamd_dkim_sign_key_load (key, len,
-                                                       key_sign_type, &err);
-
-                                       if (dkim_key == NULL) {
-                                               msg_err_task ("cannot load dkim key %s: %e",
-                                                               lru_key, err);
-                                               g_error_free (err);
+                               else if (strcmp (sign_type_str, "arc-seal") == 0) {
+                                       sign_type = RSPAMD_DKIM_ARC_SEAL;
+                                       if (arc_cv == NULL) {
+                                               lua_settop (L, 0);
+                                               luaL_error (L, "no arc cv specified");
                                                rspamd_symcache_finalize_item (task, item);
 
                                                return;
                                        }
-                                       else {
-                                               rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash,
-                                                               g_strdup (lru_key), dkim_key,
-                                                               time (NULL), 0);
+                                       if (arc_idx == 0) {
+                                               lua_settop (L, 0);
+                                               luaL_error (L, "no arc idx specified");
+                                               rspamd_symcache_finalize_item (task, item);
+
+                                               return;
                                        }
                                }
-
-                               ctx = rspamd_create_dkim_sign_context (task, dkim_key,
-                                               DKIM_CANON_RELAXED, DKIM_CANON_RELAXED,
-                                               dkim_module_ctx->sign_headers,
-                                               sign_type,
-                                               &err);
-
-                               if (ctx == NULL) {
-                                       msg_err_task ("cannot create sign context: %e",
-                                                       err);
-                                       g_error_free (err);
+                               else {
+                                       lua_settop (L, 0);
+                                       luaL_error (L, "unknown sign type: %s",
+                                                       sign_type_str);
                                        rspamd_symcache_finalize_item (task, item);
 
                                        return;
                                }
+                       }
 
-                               hdr = rspamd_dkim_sign (task, selector, domain, 0, 0,
-                                               arc_idx, arc_cv,
-                                               ctx);
-
-                               if (hdr) {
-                                       rspamd_mempool_set_variable (task->task_pool,
-                                                       "dkim-signature",
-                                                       hdr, rspamd_gstring_free_hard);
-                               }
+                       dkim_key = dkim_module_load_key_format (task, dkim_module_ctx,
+                                       key, len, key_format);
 
-                               sign = TRUE;
+                       if (dkim_key == NULL) {
+                               rspamd_symcache_finalize_item (task, item);
+                               return;
                        }
-                       else {
-                               sign = FALSE;
+
+                       ctx = rspamd_create_dkim_sign_context (task, dkim_key,
+                                       DKIM_CANON_RELAXED, DKIM_CANON_RELAXED,
+                                       dkim_module_ctx->sign_headers,
+                                       sign_type,
+                                       &err);
+
+                       if (ctx == NULL) {
+                               msg_err_task ("cannot create sign context: %e",
+                                               err);
+                               g_error_free (err);
+                               rspamd_symcache_finalize_item (task, item);
+
+                               return;
                        }
-               }
 
-               /* Result + error function */
-               lua_settop (L, 0);
+                       hdr = rspamd_dkim_sign (task, selector, domain, 0, 0,
+                                       arc_idx, arc_cv,
+                                       ctx);
 
-               if (!sign) {
-                       msg_debug_task ("skip signing as dkim condition callback returned"
-                                       " false");
-                       rspamd_symcache_finalize_item (task, item);
+                       if (hdr) {
+                               rspamd_mempool_set_variable (task->task_pool,
+                                               "dkim-signature",
+                                               hdr, rspamd_gstring_free_hard);
+                       }
 
-                       return;
+                       sign = TRUE;
+               }
+               else {
+                       sign = FALSE;
                }
        }
 
+       /* Result + error function */
+       lua_settop (L, 0);
+
+       if (!sign) {
+               msg_debug_task ("skip signing as dkim condition callback returned"
+                               " false");
+       }
        rspamd_symcache_finalize_item (task, item);
 }