#include "dkim.h"
#include "dns.h"
#include "utlist.h"
+#include "unix-std.h"
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/engine.h>
-#include <sys/mman.h>
/* special DNS tokens */
#define DKIM_DNSKEYNAME "_domainkey"
RSA *key_rsa;
BIO *key_bio;
EVP_PKEY *key_evp;
+ time_t mtime;
ref_entry_t ref;
};
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];
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) {
nkey = g_slice_alloc0 (sizeof (*nkey));
nkey->type = type;
+ nkey->mtime = mtime;
switch (type) {
case RSPAMD_DKIM_SIGN_KEY_FILE:
return nkey;
}
+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)
+{
+ struct stat st;
+
+ if (type == RSPAMD_DKIM_SIGN_KEY_FILE) {
+ gchar fpath[PATH_MAX];
+
+ rspamd_snprintf (fpath, sizeof (fpath), "%*s", (gint) len, what);
+
+ if (stat (fpath, &st) == -1) {
+ /* Prefer to use cached key since it is absent on FS */
+ return FALSE;
+ }
+
+ if (st.st_mtime > key->mtime) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
rspamd_dkim_sign_context_t *
rspamd_create_dkim_sign_context (struct rspamd_task *task,
rspamd_dkim_sign_key_t *priv_key,
enum rspamd_dkim_sign_key_type 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);
+
/**
* Make DNS request for specified context and obtain and parse key
* @param ctx dkim context from signature
if (dkim_key == NULL) {
msg_err_task ("cannot load dkim key %s: %e",
- key, err);
+ lru_key, err);
+ g_error_free (err);
+
+ return;
+ }
+
+ 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,
+ 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,
+ sign_type, &err);
+
+ if (dkim_key == NULL) {
+ msg_err_task ("cannot load dkim key %s: %e",
+ lru_key, err);
g_error_free (err);
return;