]> source.dussan.org Git - rspamd.git/commitdiff
Add function to check validity of hyperscan cache
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 8 Dec 2015 00:32:03 +0000 (00:32 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 8 Dec 2015 00:32:03 +0000 (00:32 +0000)
src/libserver/re_cache.c
src/libserver/re_cache.h

index e5704e0a24f588ed97effaccebd74e8fc67a1998..af11f02c51451d269a17b94333e3913047ab553a 100644 (file)
         G_STRFUNC, \
         __VA_ARGS__)
 
+#ifdef WITH_HYPERSCAN
+#define RSPAMD_HS_MAGIC_LEN (sizeof (rspamd_hs_magic))
+static const guchar rspamd_hs_magic[] = {'r', 's', 'h', 's', 'r', 'e', '1'};
+#endif
+
 struct rspamd_re_class {
        guint64 id;
        enum rspamd_re_type type;
@@ -862,3 +867,67 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache,
        return total;
 #endif
 }
+
+gboolean
+rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache,
+               const char *path)
+{
+       g_assert (cache != NULL);
+       g_assert (path != NULL);
+
+#ifndef WITH_HYPERSCAN
+       return FALSE;
+#else
+       gint fd;
+       guchar magicbuf[RSPAMD_HS_MAGIC_LEN];
+       GHashTableIter it;
+       gpointer k, v;
+       struct rspamd_re_class *re_class;
+       gsize len;
+       const gchar *hash_pos;
+
+       len = strlen (path);
+
+       if (len < sizeof (rspamd_cryptobox_HASHBYTES * 2 + 3)) {
+               return FALSE;
+       }
+
+       if (memcmp (path + len - 3, ".hs", 3) != 0) {
+               return FALSE;
+       }
+
+       hash_pos = path + len - 3 - rspamd_cryptobox_HASHBYTES * 2;
+
+       while (g_hash_table_iter_next (&it, &k, &v)) {
+               re_class = v;
+
+               if (memcmp (hash_pos, re_class->hash, sizeof (re_class->hash)) == 0) {
+                       /* Open file and check magic */
+                       fd = open (path, O_RDONLY);
+
+                       if (fd == -1) {
+                               msg_err_re_cache ("cannot open hyperscan cache file %s: %s",
+                                               path, strerror (errno));
+                               return FALSE;
+                       }
+
+                       if (read (fd, magicbuf, sizeof (magicbuf)) != sizeof (magicbuf)) {
+                               msg_err_re_cache ("cannot read hyperscan cache file %s: %s",
+                                               path, strerror (errno));
+                               close (fd);
+                               return FALSE;
+                       }
+
+                       if (memcmp (magicbuf, rspamd_hs_magic, sizeof (magicbuf)) != 0) {
+                               msg_err_re_cache ("cannot open hyperscan cache file %s: "
+                                               "bad magic ('%*xs', '%*xs' expected)",
+                                               path, strerror (errno),
+                                               (int) RSPAMD_HS_MAGIC_LEN, magicbuf,
+                                               (int) RSPAMD_HS_MAGIC_LEN, rspamd_hs_magic);
+
+                               return FALSE;
+                       }
+               }
+       }
+#endif
+}
index 0e1e6ecc820508b64e5596a388a3a6288914cf78..934cc1485b811506a65200e7e766e63cc60cdb67 100644 (file)
@@ -133,4 +133,10 @@ gint rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache,
                const char *cache_dir,
                GError **err);
 
+
+/**
+ * Returns TRUE if the specified file is valid hyperscan cache
+ */
+gboolean rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache,
+               const char *path);
 #endif