aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2020-04-21 14:27:20 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2020-04-21 14:27:20 +0100
commitc5c2eaf6b05640a9a0934042a099e818719357aa (patch)
tree35ef3d1e2c32c08f05f4868755a6afbeedcccb59
parentd4bd976fd9b084d845829fc659fc56b736a6d0af (diff)
downloadrspamd-c5c2eaf6b05640a9a0934042a099e818719357aa.tar.gz
rspamd-c5c2eaf6b05640a9a0934042a099e818719357aa.zip
[Rework] Rework url flags handling API
-rw-r--r--src/libserver/url.c79
-rw-r--r--src/libserver/url.h16
-rw-r--r--src/lua/lua_url.c66
3 files changed, 139 insertions, 22 deletions
diff --git a/src/libserver/url.c b/src/libserver/url.c
index db89073f5..195727c13 100644
--- a/src/libserver/url.c
+++ b/src/libserver/url.c
@@ -214,6 +214,35 @@ struct url_matcher static_matchers[] = {
0}
};
+struct rspamd_url_flag_name {
+ const gchar *name;
+ gint flag;
+ gint hash;
+} url_flag_names[] = {
+ {"phished", RSPAMD_URL_FLAG_PHISHED, -1},
+ {"numeric", RSPAMD_URL_FLAG_NUMERIC, -1},
+ {"obscured", RSPAMD_URL_FLAG_OBSCURED, -1},
+ {"redirected", RSPAMD_URL_FLAG_REDIRECTED, -1},
+ {"html_displayed", RSPAMD_URL_FLAG_HTML_DISPLAYED, -1},
+ {"text", RSPAMD_URL_FLAG_FROM_TEXT, -1},
+ {"subject", RSPAMD_URL_FLAG_SUBJECT, -1},
+ {"host_encoded", RSPAMD_URL_FLAG_HOSTENCODED, -1},
+ {"schema_encoded", RSPAMD_URL_FLAG_SCHEMAENCODED, -1},
+ {"path_encoded", RSPAMD_URL_FLAG_PATHENCODED, -1},
+ {"query_encoded", RSPAMD_URL_FLAG_QUERYENCODED, -1},
+ {"missing_slahes", RSPAMD_URL_FLAG_MISSINGSLASHES, -1},
+ {"idn", RSPAMD_URL_FLAG_IDN, -1},
+ {"has_port", RSPAMD_URL_FLAG_HAS_PORT, -1},
+ {"has_user", RSPAMD_URL_FLAG_HAS_USER, -1},
+ {"schemaless", RSPAMD_URL_FLAG_SCHEMALESS, -1},
+ {"unnormalised", RSPAMD_URL_FLAG_UNNORMALISED, -1},
+ {"zw_spaces", RSPAMD_URL_FLAG_ZW_SPACES, -1},
+ {"url_displayed", RSPAMD_URL_FLAG_DISPLAY_URL, -1},
+ {"image", RSPAMD_URL_FLAG_IMAGE, -1},
+ {"query", RSPAMD_URL_FLAG_QUERY, -1},
+ {"content", RSPAMD_URL_FLAG_CONTENT, -1}
+};
+
static inline khint_t rspamd_url_hash (struct rspamd_url *u);
@@ -610,6 +639,26 @@ rspamd_url_init (const gchar *tld_file)
url_scanner->matchers_strict->len);
}
}
+
+ /* Generate hashes for flags */
+ for (gint i = 0; i < G_N_ELEMENTS (url_flag_names); i ++) {
+ url_flag_names[i].hash =
+ rspamd_cryptobox_fast_hash_specific (RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT,
+ url_flag_names[i].name,
+ strlen (url_flag_names[i].name), 0);
+ }
+ /* Ensure that we have no hashes collisions O(N^2) but this array is small */
+ for (gint i = 0; i < G_N_ELEMENTS (url_flag_names) - 1; i ++) {
+ for (gint j = i + 1; j < G_N_ELEMENTS (url_flag_names); j ++) {
+ if (url_flag_names[i].hash == url_flag_names[j].hash) {
+ msg_err ("collision: both %s and %s map to %d",
+ url_flag_names[i].name, url_flag_names[j].name,
+ url_flag_names[i].hash);
+ abort ();
+ }
+ }
+ }
+
}
#define SET_U(u, field) do { \
@@ -3991,3 +4040,33 @@ rspamd_url_host_set_has (khash_t (rspamd_url_host_hash) *set, struct rspamd_url
return false;
}
+
+bool
+rspamd_url_flag_from_string (const gchar *str, gint *flag)
+{
+ gint h = rspamd_cryptobox_fast_hash_specific (RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT,
+ str, strlen (str), 0);
+
+ for (int i = 0; i < G_N_ELEMENTS (url_flag_names); i ++) {
+ if (url_flag_names[i].hash == h) {
+ *flag |= url_flag_names[i].flag;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+const gchar *
+rspamd_url_flag_to_string (int flag)
+{
+ for (int i = 0; i < G_N_ELEMENTS (url_flag_names); i ++) {
+ if (url_flag_names[i].flag & flag) {
+ return url_flag_names[i].name;
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/libserver/url.h b/src/libserver/url.h
index bb9c57399..2a5892fc5 100644
--- a/src/libserver/url.h
+++ b/src/libserver/url.h
@@ -36,6 +36,7 @@ enum rspamd_url_flags {
RSPAMD_URL_FLAG_DISPLAY_URL = 1u << 18u,
RSPAMD_URL_FLAG_IMAGE = 1u << 19u,
RSPAMD_URL_FLAG_QUERY = 1u << 20u,
+ RSPAMD_URL_FLAG_CONTENT = 1u << 21u,
};
struct rspamd_url_tag {
@@ -268,6 +269,21 @@ const gchar *rspamd_url_protocol_name (enum rspamd_url_protocol proto);
*/
enum rspamd_url_protocol rspamd_url_protocol_from_string (const gchar *str);
+/**
+ * Converts string to a url flag
+ * @param str
+ * @param flag
+ * @return
+ */
+bool rspamd_url_flag_from_string (const gchar *str, gint *flag);
+
+/**
+ * Converts url flag to a string
+ * @param flag
+ * @return
+ */
+const gchar * rspamd_url_flag_to_string (int flag);
+
/* Defines sets of urls indexed by url as is */
KHASH_DECLARE (rspamd_url_hash, struct rspamd_url *, char);
KHASH_DECLARE (rspamd_url_host_hash, struct rspamd_url *, char);
diff --git a/src/lua/lua_url.c b/src/lua/lua_url.c
index 6540919ea..94cb51dbd 100644
--- a/src/lua/lua_url.c
+++ b/src/lua/lua_url.c
@@ -728,6 +728,7 @@ lua_url_create (lua_State *L)
const gchar *text;
size_t length;
gboolean own_pool = FALSE;
+ struct rspamd_lua_url *u;
if (lua_type (L, 1) == LUA_TUSERDATA) {
pool = rspamd_lua_check_mempool (L, 1);
@@ -753,6 +754,26 @@ lua_url_create (lua_State *L)
if (lua_type (L, -1) != LUA_TUSERDATA) {
/* URL is actually not found */
lua_pushnil (L);
+
+ return 1;
+ }
+
+ u = (struct rspamd_lua_url *)lua_touserdata (L, -1);
+
+ if (lua_type (L, 3) == LUA_TTABLE) {
+ /* Add flags */
+ for (lua_pushnil (L); lua_next (L, 3); lua_pop (L, 1)) {
+ int nmask = 0;
+ const gchar *fname = lua_tostring (L, -1);
+
+ if (rspamd_url_flag_from_string (fname, &nmask)) {
+ u->url->flags |= nmask;
+ }
+ else {
+ lua_pop (L, 1);
+ return luaL_error (L, "invalid flag: %s", fname);
+ }
+ }
}
}
@@ -854,9 +875,9 @@ lua_url_all (lua_State *L)
* - `image`: URL is from src attribute of img HTML tag
* @return {table} URL flags
*/
-#define PUSH_FLAG(fl, name) do { \
+#define PUSH_FLAG(fl) do { \
if (flags & (fl)) { \
- lua_pushstring (L, (name)); \
+ lua_pushstring (L, rspamd_url_flag_to_string (fl)); \
lua_pushboolean (L, true); \
lua_settable (L, -3); \
} \
@@ -874,26 +895,27 @@ lua_url_get_flags (lua_State *L)
lua_createtable (L, 0, 4);
- PUSH_FLAG (RSPAMD_URL_FLAG_PHISHED, "phished");
- PUSH_FLAG (RSPAMD_URL_FLAG_NUMERIC, "numeric");
- PUSH_FLAG (RSPAMD_URL_FLAG_OBSCURED, "obscured");
- PUSH_FLAG (RSPAMD_URL_FLAG_REDIRECTED, "redirected");
- PUSH_FLAG (RSPAMD_URL_FLAG_HTML_DISPLAYED, "html_displayed");
- PUSH_FLAG (RSPAMD_URL_FLAG_FROM_TEXT, "text");
- PUSH_FLAG (RSPAMD_URL_FLAG_SUBJECT, "subject");
- PUSH_FLAG (RSPAMD_URL_FLAG_HOSTENCODED, "host_encoded");
- PUSH_FLAG (RSPAMD_URL_FLAG_SCHEMAENCODED, "schema_encoded");
- PUSH_FLAG (RSPAMD_URL_FLAG_PATHENCODED, "path_encoded");
- PUSH_FLAG (RSPAMD_URL_FLAG_QUERYENCODED, "query_encoded");
- PUSH_FLAG (RSPAMD_URL_FLAG_MISSINGSLASHES, "missing_slahes");
- PUSH_FLAG (RSPAMD_URL_FLAG_IDN, "idn");
- PUSH_FLAG (RSPAMD_URL_FLAG_HAS_PORT, "has_port");
- PUSH_FLAG (RSPAMD_URL_FLAG_HAS_USER, "has_user");
- PUSH_FLAG (RSPAMD_URL_FLAG_SCHEMALESS, "schemaless");
- PUSH_FLAG (RSPAMD_URL_FLAG_UNNORMALISED, "unnormalised");
- PUSH_FLAG (RSPAMD_URL_FLAG_ZW_SPACES, "zw_spaces");
- PUSH_FLAG (RSPAMD_URL_FLAG_DISPLAY_URL, "url_displayed");
- PUSH_FLAG (RSPAMD_URL_FLAG_IMAGE, "image");
+ PUSH_FLAG (RSPAMD_URL_FLAG_PHISHED);
+ PUSH_FLAG (RSPAMD_URL_FLAG_NUMERIC);
+ PUSH_FLAG (RSPAMD_URL_FLAG_OBSCURED);
+ PUSH_FLAG (RSPAMD_URL_FLAG_REDIRECTED);
+ PUSH_FLAG (RSPAMD_URL_FLAG_HTML_DISPLAYED);
+ PUSH_FLAG (RSPAMD_URL_FLAG_FROM_TEXT);
+ PUSH_FLAG (RSPAMD_URL_FLAG_SUBJECT);
+ PUSH_FLAG (RSPAMD_URL_FLAG_HOSTENCODED);
+ PUSH_FLAG (RSPAMD_URL_FLAG_SCHEMAENCODED);
+ PUSH_FLAG (RSPAMD_URL_FLAG_PATHENCODED);
+ PUSH_FLAG (RSPAMD_URL_FLAG_QUERYENCODED);
+ PUSH_FLAG (RSPAMD_URL_FLAG_MISSINGSLASHES);
+ PUSH_FLAG (RSPAMD_URL_FLAG_IDN);
+ PUSH_FLAG (RSPAMD_URL_FLAG_HAS_PORT);
+ PUSH_FLAG (RSPAMD_URL_FLAG_HAS_USER);
+ PUSH_FLAG (RSPAMD_URL_FLAG_SCHEMALESS);
+ PUSH_FLAG (RSPAMD_URL_FLAG_UNNORMALISED);
+ PUSH_FLAG (RSPAMD_URL_FLAG_ZW_SPACES);
+ PUSH_FLAG (RSPAMD_URL_FLAG_DISPLAY_URL);
+ PUSH_FLAG (RSPAMD_URL_FLAG_IMAGE);
+ PUSH_FLAG (RSPAMD_URL_FLAG_CONTENT);
}
else {
return luaL_error (L, "invalid arguments");