aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2017-01-28 13:36:32 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2017-01-28 13:36:32 +0000
commit02b3c524724a65ae8b8291ee28c0eb4d4cf72516 (patch)
treeff45aeb42a48eb615fc8517d6d7ed62e891613c4
parent605a33e6216729383d6c0adbba1215ac805dc134 (diff)
downloadrspamd-02b3c524724a65ae8b8291ee28c0eb4d4cf72516.tar.gz
rspamd-02b3c524724a65ae8b8291ee28c0eb4d4cf72516.zip
[Feature] Allow to pass sign key directly from Lua
-rw-r--r--src/libserver/dkim.c53
-rw-r--r--src/libserver/dkim.h9
-rw-r--r--src/plugins/dkim_check.c66
3 files changed, 113 insertions, 15 deletions
diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c
index 7e2dbec89..4ef2ad122 100644
--- a/src/libserver/dkim.c
+++ b/src/libserver/dkim.c
@@ -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,
diff --git a/src/libserver/dkim.h b/src/libserver/dkim.h
index b2ff151ad..ac3f04233 100644
--- a/src/libserver/dkim.h
+++ b/src/libserver/dkim.h
@@ -142,6 +142,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
* @param resolver dns resolver object
diff --git a/src/plugins/dkim_check.c b/src/plugins/dkim_check.c
index aa2da3bfe..1023ce70b 100644
--- a/src/plugins/dkim_check.c
+++ b/src/plugins/dkim_check.c
@@ -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,