]> source.dussan.org Git - rspamd.git/commitdiff
[Minor] Move DKIM keys load to DKIM common code
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 11 Feb 2019 14:21:29 +0000 (14:21 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 11 Feb 2019 14:21:29 +0000 (14:21 +0000)
src/libserver/dkim.c
src/plugins/dkim_check.c

index bbaa6b90f0313c4b1df4fdfe310da6fb05510bc1..2a66146ed44fc6a03c10eef46e5e77b3cbc5133c 100644 (file)
@@ -2604,29 +2604,83 @@ rspamd_dkim_get_dns_key (rspamd_dkim_context_t *ctx)
        return NULL;
 }
 
+#define PEM_SIG "-----BEGIN"
+
 rspamd_dkim_sign_key_t*
 rspamd_dkim_sign_key_load (const gchar *key, gsize len,
                enum rspamd_dkim_key_format type,
                GError **err)
 {
+       guchar *map = NULL, *tmp = NULL;
+       gsize maplen;
        rspamd_dkim_sign_key_t *nkey;
        time_t mtime = time (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,
-                                       "invalid key type to load: %d", type);
-                       return NULL;
+       if (type < 0 || type > RSPAMD_DKIM_KEY_UNKNOWN || len == 0 || key == NULL) {
+               g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
+                               "invalid key type to load: %d", type);
+               return NULL;
        }
 
        nkey = g_malloc0 (sizeof (*nkey));
        nkey->mtime = mtime;
 
-       msg_debug_dkim_taskless ("got public key with length %d and type %d", len, type);
+       msg_debug_dkim_taskless ("got public key with length %d and type %d",
+                       len, type);
+
+       /* Load key file if needed */
+       if (type == RSPAMD_DKIM_KEY_FILE) {
+               struct stat st;
+
+               if (stat (key, &st) != 0) {
+                       g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
+                                       "cannot stat key file: '%s' %s", key, strerror (errno));
+
+                       return NULL;
+               }
+
+               nkey->mtime = st.st_mtime;
+               map = rspamd_file_xmap (key, PROT_READ, &maplen, TRUE);
+
+               if (map == NULL) {
+                       g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
+                                       "cannot map key file: '%s' %s", key, strerror (errno));
+
+                       return NULL;
+               }
+
+               key = map;
+               len = maplen;
+
+               if (maplen > sizeof (PEM_SIG) &&
+                       strncmp (map, PEM_SIG, sizeof (PEM_SIG) - 1) == 0) {
+                       type = RSPAMD_DKIM_KEY_PEM;
+               }
+               else if (rspamd_cryptobox_base64_is_valid (map, maplen)) {
+                       type = RSPAMD_DKIM_KEY_BASE64;
+               }
+               else {
+                       type = RSPAMD_DKIM_KEY_RAW;
+               }
+       }
+
+       if (type == RSPAMD_DKIM_KEY_UNKNOWN) {
+               if (len > sizeof (PEM_SIG) &&
+                       memcmp (key, PEM_SIG, sizeof (PEM_SIG) - 1) == 0) {
+                       type = RSPAMD_DKIM_KEY_PEM;
+               }
+               else {
+                       type = RSPAMD_DKIM_KEY_RAW;
+               }
+       }
+
+       if (type == RSPAMD_DKIM_KEY_BASE64) {
+               type = RSPAMD_DKIM_KEY_RAW;
+               tmp = g_malloc (len);
+               rspamd_cryptobox_base64_decode (key, len, tmp, &len);
+               key = tmp;
+       }
+
        if (type == RSPAMD_DKIM_KEY_RAW && len == 32) {
                unsigned char pk[32];
                nkey->type = RSPAMD_DKIM_KEY_EDDSA;
@@ -2645,8 +2699,9 @@ rspamd_dkim_sign_key_load (const gchar *key, gsize len,
                                                ERR_error_string (ERR_get_error (), NULL));
 
                                rspamd_dkim_sign_key_free (nkey);
+                               nkey = NULL;
 
-                               return NULL;
+                               goto end;
                        }
                }
                else {
@@ -2655,8 +2710,9 @@ rspamd_dkim_sign_key_load (const gchar *key, gsize len,
                                                "cannot parse pem private key: %s",
                                                ERR_error_string (ERR_get_error (), NULL));
                                rspamd_dkim_sign_key_free (nkey);
+                               nkey = NULL;
 
-                               return NULL;
+                               goto end;
                        }
 
                }
@@ -2667,17 +2723,31 @@ rspamd_dkim_sign_key_load (const gchar *key, gsize len,
                                        DKIM_SIGERROR_KEYFAIL,
                                        "cannot extract rsa key from evp key");
                        rspamd_dkim_sign_key_free (nkey);
+                       nkey = NULL;
 
-                       return NULL;
+                       goto end;
                }
                nkey->type = RSPAMD_DKIM_KEY_RSA;
        }
 
        REF_INIT_RETAIN (nkey, rspamd_dkim_sign_key_free);
 
+end:
+
+       if (map != NULL) {
+               munmap (map, maplen);
+       }
+
+       if (tmp != NULL) {
+               rspamd_explicit_memzero (tmp, len);
+               g_free (tmp);
+       }
+
        return nkey;
 }
 
+#undef PEM_SIG
+
 gboolean
 rspamd_dkim_sign_key_maybe_invalidate (rspamd_dkim_sign_key_t *key, time_t mtime)
 {
index 278a8e1e118fc097aa0e38c8a9a0b4f94d33c591..bb66e5ccc118017b9af0c85992e74715a43576ab 100644 (file)
@@ -641,58 +641,23 @@ 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 (struct rspamd_task *task, struct dkim_ctx *dkim_module_ctx,
-               const gchar *key, gsize keylen, enum rspamd_dkim_key_format key_format)
+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;
-       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);
@@ -706,16 +671,19 @@ dkim_module_load_key_format (struct rspamd_task *task, struct dkim_ctx *dkim_mod
         */
        if (key_format == RSPAMD_DKIM_KEY_UNKNOWN &&
                (key[0] == '.' || key[0] == '/')) {
-               if (!is_valid_base64 (key, keylen))
+               if (!rspamd_cryptobox_base64_is_valid (key, keylen)) {
                        key_format = RSPAMD_DKIM_KEY_FILE;
+               }
        }
 
        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");
                        /*
@@ -729,43 +697,8 @@ dkim_module_load_key_format (struct rspamd_task *task, struct dkim_ctx *dkim_mod
        }
 
        /* found key; done */
-       if (ret != NULL)
+       if (ret != NULL) {
                return ret;
-
-       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);
@@ -779,16 +712,8 @@ dkim_module_load_key_format (struct rspamd_task *task, struct dkim_ctx *dkim_mod
                                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)
@@ -844,10 +769,12 @@ lua_dkim_sign_handler (lua_State *L)
        if (key) {
                dkim_key = dkim_module_load_key_format (task, dkim_module_ctx, key,
                                keylen, RSPAMD_DKIM_KEY_UNKNOWN);
-       } else if(rawkey) {
+       }
+       else if(rawkey) {
                dkim_key = dkim_module_load_key_format (task, dkim_module_ctx, rawkey,
                                rawlen, RSPAMD_DKIM_KEY_UNKNOWN);
-       } else {
+       }
+       else {
                msg_err_task ("neither key nor rawkey are specified");
                lua_pushboolean (L, FALSE);