]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Allow to pass sign key directly from Lua
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 28 Jan 2017 13:36:32 +0000 (13:36 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 28 Jan 2017 13:36:32 +0000 (13:36 +0000)
src/libserver/dkim.c
src/libserver/dkim.h
src/plugins/dkim_check.c

index 7e2dbec8975774764812733a75c1242bcfe00828..4ef2ad12211a60a8b65266007a6eb10a22b4f15a 100644 (file)
@@ -2025,6 +2025,59 @@ rspamd_dkim_sign_key_load (const gchar *path, GError **err)
        return nkey;
 }
 
+rspamd_dkim_sign_key_t*
+rspamd_dkim_sign_key_from_memory (const guchar *data,
+               gsize len, GError **err)
+{
+       rspamd_dkim_sign_key_t *nkey;
+       gpointer map;
+
+       map = mmap (NULL, len, PROT_READ | PROT_WRITE,
+                       MAP_PRIVATE | MAP_ANON, -1, 0);
+
+       if (map == MAP_FAILED) {
+               g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
+                               "cannot map in-memory private key %s",
+                               strerror (errno));
+
+               return NULL;
+       }
+
+       /* Initialize memory and set the appropriate access mode */
+       memcpy (map, data, len);
+       (void)mprotect (map, len, PROT_READ);
+       (void)mlock (map, len);
+
+       nkey = g_slice_alloc0 (sizeof (*nkey));
+       nkey->keydata = map;
+       nkey->keylen = len;
+       nkey->key_bio = BIO_new_mem_buf (map, len);
+
+       if (!PEM_read_bio_PrivateKey (nkey->key_bio, &nkey->key_evp, NULL, NULL)) {
+               g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
+                               "cannot read private key from memory: %s",
+                               ERR_error_string (ERR_get_error (), NULL));
+               rspamd_dkim_sign_key_free (nkey);
+
+               return NULL;
+       }
+
+       nkey->key_rsa = EVP_PKEY_get1_RSA (nkey->key_evp);
+       if (nkey->key_rsa == NULL) {
+               g_set_error (err,
+                               DKIM_ERROR,
+                               DKIM_SIGERROR_KEYFAIL,
+                               "cannot extract rsa key from evp key");
+               rspamd_dkim_sign_key_free (nkey);
+
+               return NULL;
+       }
+
+       REF_INIT_RETAIN (nkey, rspamd_dkim_sign_key_free);
+
+       return nkey;
+}
+
 rspamd_dkim_sign_context_t *
 rspamd_create_dkim_sign_context (struct rspamd_task *task,
                rspamd_dkim_sign_key_t *priv_key,
index b2ff151ade225a6ff991a7d2e7b16b83f238a17c..ac3f04233e81e1e6b29fc830bcef1b1fbbbd4598 100644 (file)
@@ -141,6 +141,15 @@ rspamd_dkim_sign_context_t * rspamd_create_dkim_sign_context (struct rspamd_task
  */
 rspamd_dkim_sign_key_t* rspamd_dkim_sign_key_load (const gchar *path, GError **err);
 
+/**
+ * Load dkim key from memory chunk
+ * @param path
+ * @param err
+ * @return
+ */
+rspamd_dkim_sign_key_t* rspamd_dkim_sign_key_from_memory (const guchar *data,
+               gsize len, GError **err);
+
 /**
  * Make DNS request for specified context and obtain and parse key
  * @param ctx dkim context from signature
index aa2da3bfe0ee1e6ae69a926ac70bff703a81bb05..1023ce70b5a0905bf563ac2596e4bf17ef88877e 100644 (file)
@@ -553,9 +553,10 @@ lua_dkim_sign_handler (lua_State *L)
 
        GError *err = NULL;
        GString *hdr;
-       const gchar *selector = NULL, *domain = NULL, *key = NULL;
+       const gchar *selector = NULL, *domain = NULL, *key = NULL, *rawkey = NULL;
        rspamd_dkim_sign_context_t *ctx;
        rspamd_dkim_sign_key_t *dkim_key;
+       gsize rawlen = 0;
        /*
         * Get the following elements:
         * - selector
@@ -563,8 +564,8 @@ lua_dkim_sign_handler (lua_State *L)
         * - key
         */
        if (!rspamd_lua_parse_table_arguments (L, 2, &err,
-                       "*key=S;*domain=S;*selector=S",
-                       &key, &domain, &selector)) {
+                       "key=S;rawkey=V;*domain=S;*selector=S",
+                       &key, &rawlen, rawkey, &domain, &selector)) {
                msg_err_task ("invalid return value from sign condition: %e",
                                err);
                g_error_free (err);
@@ -580,24 +581,59 @@ lua_dkim_sign_handler (lua_State *L)
                                (GDestroyNotify)rspamd_dkim_sign_key_unref);
        }
 
-       dkim_key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_sign_hash,
-                       key, time (NULL));
+       if (key) {
+               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, &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 (rawkey) {
+               guchar h[rspamd_cryptobox_HASHBYTES],
+                       hex_hash[rspamd_cryptobox_HASHBYTES * 2 + 1];
 
-       if (dkim_key == NULL) {
-               dkim_key = rspamd_dkim_sign_key_load (key, &err);
+               memset (hex_hash, 0, sizeof (hex_hash));
+               rspamd_cryptobox_hash (h, rawkey, rawlen, 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));
 
                if (dkim_key == NULL) {
-                       msg_err_task ("cannot load dkim key %s: %e",
-                                       key, err);
-                       g_error_free (err);
+                       dkim_key = rspamd_dkim_sign_key_from_memory (rawkey, rawlen, &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;
+                       }
 
-                       lua_pushboolean (L, FALSE);
-                       return 1;
+                       rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash,
+                                       g_strdup (hex_hash), dkim_key,
+                                       time (NULL), 0);
                }
+       }
+       else {
+               msg_err_task ("neither key nor rawkey are specified", err);
+               lua_pushboolean (L, FALSE);
 
-               rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash,
-                               g_strdup (key), dkim_key,
-                               time (NULL), 0);
+               return 1;
        }
 
        ctx = rspamd_create_dkim_sign_context (task, dkim_key,