aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2013-01-06 20:33:31 +0400
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2013-01-06 20:33:31 +0400
commit6af303bd3ab37702ad4a6d50b74e95d2a2808e85 (patch)
tree044acffcfe2dd8527f914cdeb3949d5e93e70cee
parent1d63fed447d8b74d81468a57af9773773f654210 (diff)
downloadrspamd-6af303bd3ab37702ad4a6d50b74e95d2a2808e85.tar.gz
rspamd-6af303bd3ab37702ad4a6d50b74e95d2a2808e85.zip
Add /maps and /getmap commands to webui.
Identify maps by id. Initialize secure random numbers using openssl. Add description to maps.
-rw-r--r--src/cfg_utils.c6
-rw-r--r--src/cfg_xml.c4
-rw-r--r--src/dynamic_cfg.c2
-rw-r--r--src/logger.c3
-rw-r--r--src/lua/lua_config.c15
-rw-r--r--src/main.c20
-rw-r--r--src/map.c24
-rw-r--r--src/map.h10
-rw-r--r--src/plugins/dkim_check.c4
-rw-r--r--src/plugins/fuzzy_check.c2
-rw-r--r--src/plugins/regexp.c2
-rw-r--r--src/plugins/spf.c2
-rw-r--r--src/plugins/surbl.c6
-rw-r--r--src/settings.c4
-rw-r--r--src/settings.h2
-rw-r--r--src/view.c10
-rw-r--r--src/webui.c157
17 files changed, 235 insertions, 38 deletions
diff --git a/src/cfg_utils.c b/src/cfg_utils.c
index 7b1910324..a0191b103 100644
--- a/src/cfg_utils.c
+++ b/src/cfg_utils.c
@@ -494,11 +494,17 @@ parse_flag (const gchar *str)
if (g_ascii_strncasecmp (str, "no", len) == 0) {
return 0;
}
+ else if (g_ascii_strncasecmp (str, "on", len) == 0) {
+ return 1;
+ }
break;
case 3:
if (g_ascii_strncasecmp (str, "yes", len) == 0) {
return 1;
}
+ else if (g_ascii_strncasecmp (str, "off", len) == 0) {
+ return 0;
+ }
break;
case 4:
if (g_ascii_strncasecmp (str, "true", len) == 0) {
diff --git a/src/cfg_xml.c b/src/cfg_xml.c
index 6ae3ce7c3..f81492d77 100644
--- a/src/cfg_xml.c
+++ b/src/cfg_xml.c
@@ -1458,7 +1458,7 @@ handle_view_symbols (struct config_file *cfg, struct rspamd_xml_userdata *ctx, G
gboolean
handle_user_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
{
- if (!read_settings (data, cfg, cfg->user_settings)) {
+ if (!read_settings (data, "Users' settings", cfg, cfg->user_settings)) {
msg_err ("cannot read settings %s", data);
return FALSE;
}
@@ -1469,7 +1469,7 @@ handle_user_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx,
gboolean
handle_domain_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
{
- if (!read_settings (data, cfg, cfg->domain_settings)) {
+ if (!read_settings (data, "Domains' settings", cfg, cfg->domain_settings)) {
msg_err ("cannot read settings %s", data);
return FALSE;
}
diff --git a/src/dynamic_cfg.c b/src/dynamic_cfg.c
index 279b1e0a9..7b9596c6c 100644
--- a/src/dynamic_cfg.c
+++ b/src/dynamic_cfg.c
@@ -334,7 +334,7 @@ init_dynamic_config (struct config_file *cfg)
jb->buf = NULL;
jb->cfg = cfg;
*pjb = jb;
- if (!add_map (cfg, cfg->dynamic_conf, json_config_read_cb, json_config_fin_cb, (void **)pjb)) {
+ if (!add_map (cfg, cfg->dynamic_conf, "Dynamic configuration map", json_config_read_cb, json_config_fin_cb, (void **)pjb)) {
msg_err ("cannot add map for configuration %s", cfg->dynamic_conf);
}
}
diff --git a/src/logger.c b/src/logger.c
index ea47b98b9..88636d2e3 100644
--- a/src/logger.c
+++ b/src/logger.c
@@ -308,7 +308,8 @@ rspamd_set_logger (enum rspamd_log_type type, GQuark ptype, struct rspamd_main *
radix_tree_free (rspamd->logger->debug_ip);
}
rspamd->logger->debug_ip = radix_tree_create ();
- if (!add_map (rspamd->cfg, rspamd->cfg->debug_ip_map, read_radix_list, fin_radix_list, (void **)&rspamd->logger->debug_ip)) {
+ if (!add_map (rspamd->cfg, rspamd->cfg->debug_ip_map, "IP addresses for which debug logs are enabled",
+ read_radix_list, fin_radix_list, (void **)&rspamd->logger->debug_ip)) {
/* Try to parse it as list */
strvec = g_strsplit_set (rspamd->cfg->debug_ip_map, ",; ", 0);
num = g_strv_length (strvec);
diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c
index ba9dfab37..b84879df0 100644
--- a/src/lua/lua_config.c
+++ b/src/lua/lua_config.c
@@ -560,14 +560,15 @@ static gint
lua_config_add_radix_map (lua_State *L)
{
struct config_file *cfg = lua_check_config (L);
- const gchar *map_line;
+ const gchar *map_line, *description;
radix_tree_t **r, ***ud;
if (cfg) {
map_line = luaL_checkstring (L, 2);
+ description = lua_tostring (L, 3);
r = memory_pool_alloc (cfg->cfg_pool, sizeof (radix_tree_t *));
*r = radix_tree_create ();
- if (!add_map (cfg, map_line, read_radix_list, fin_radix_list, (void **)r)) {
+ if (!add_map (cfg, map_line, description, read_radix_list, fin_radix_list, (void **)r)) {
msg_warn ("invalid radix map %s", map_line);
radix_tree_free (*r);
lua_pushnil (L);
@@ -589,14 +590,15 @@ static gint
lua_config_add_hash_map (lua_State *L)
{
struct config_file *cfg = lua_check_config (L);
- const gchar *map_line;
+ const gchar *map_line, *description;
GHashTable **r, ***ud;
if (cfg) {
map_line = luaL_checkstring (L, 2);
+ description = lua_tostring (L, 3);
r = memory_pool_alloc (cfg->cfg_pool, sizeof (GHashTable *));
*r = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
- if (!add_map (cfg, map_line, read_host_list, fin_host_list, (void **)r)) {
+ if (!add_map (cfg, map_line, description, read_host_list, fin_host_list, (void **)r)) {
msg_warn ("invalid hash map %s", map_line);
g_hash_table_destroy (*r);
lua_pushnil (L);
@@ -619,14 +621,15 @@ static gint
lua_config_add_kv_map (lua_State *L)
{
struct config_file *cfg = lua_check_config (L);
- const gchar *map_line;
+ const gchar *map_line, *description;
GHashTable **r, ***ud;
if (cfg) {
map_line = luaL_checkstring (L, 2);
+ description = lua_tostring (L, 3);
r = memory_pool_alloc (cfg->cfg_pool, sizeof (GHashTable *));
*r = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
- if (!add_map (cfg, map_line, read_kv_list, fin_kv_list, (void **)r)) {
+ if (!add_map (cfg, map_line, description, read_kv_list, fin_kv_list, (void **)r)) {
msg_warn ("invalid hash map %s", map_line);
g_hash_table_destroy (*r);
lua_pushnil (L);
diff --git a/src/main.c b/src/main.c
index f85fe7ade..94001298d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -34,6 +34,10 @@
#include "cfg_xml.h"
#include "symbols_cache.h"
#include "lua/lua_common.h"
+#ifdef HAVE_OPENSSL
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#endif
/* 2 seconds to fork new process in place of dead one */
#define SOFT_FORK_TIME 2
@@ -861,6 +865,10 @@ main (gint argc, gchar **argv, gchar **env)
GList *l;
worker_t **pworker;
GQuark type;
+#ifdef HAVE_OPENSSL
+ gchar rand_bytes[sizeof (guint32)];
+ guint32 rand_seed;
+#endif
#ifdef HAVE_SA_SIGINFO
signals_info = g_queue_new ();
@@ -912,6 +920,18 @@ main (gint argc, gchar **argv, gchar **env)
setlocale (LC_TIME, "C");
#endif
+ /* Init random generator */
+#ifdef HAVE_OPENSSL
+ if (RAND_bytes (rand_bytes, sizeof (rand_bytes)) != 1) {
+ msg_err ("cannot seed random generator using openssl: %s, using time", ERR_error_string (ERR_get_error (), NULL));
+ g_random_set_seed (time (NULL));
+ }
+ else {
+ memcpy (&rand_seed, rand_bytes, sizeof (guint32));
+ g_random_set_seed (rand_seed);
+ }
+#endif
+
/* First set logger to console logger */
rspamd_set_logger (RSPAMD_LOG_CONSOLE, type, rspamd_main);
(void)open_log (rspamd_main->logger);
diff --git a/src/map.c b/src/map.c
index 1ee6e7de4..09b4df8df 100644
--- a/src/map.c
+++ b/src/map.c
@@ -915,7 +915,7 @@ start_map_watch (struct config_file *cfg, struct event_base *ev_base)
while (cur) {
map = cur->data;
map->ev_base = ev_base;
- if (map->protocol == PROTO_FILE) {
+ if (map->protocol == MAP_PROTO_FILE) {
evtimer_set (&map->ev, file_callback, map);
event_base_set (map->ev_base, &map->ev);
/* Read initial data */
@@ -929,7 +929,7 @@ start_map_watch (struct config_file *cfg, struct event_base *ev_base)
map->tv.tv_usec = 0;
evtimer_add (&map->ev, &map->tv);
}
- else if (map->protocol == PROTO_HTTP) {
+ else if (map->protocol == MAP_PROTO_HTTP) {
evtimer_set (&map->ev, http_callback, map);
event_base_set (map->ev_base, &map->ev);
/* Read initial data */
@@ -959,19 +959,19 @@ check_map_proto (const gchar *map_line, gint *res, const gchar **pos)
{
if (g_ascii_strncasecmp (map_line, "http://", sizeof ("http://") - 1) == 0) {
if (res && pos) {
- *res = PROTO_HTTP;
+ *res = MAP_PROTO_HTTP;
*pos = map_line + sizeof ("http://") - 1;
}
}
else if (g_ascii_strncasecmp (map_line, "file://", sizeof ("file://") - 1) == 0) {
if (res && pos) {
- *res = PROTO_FILE;
+ *res = MAP_PROTO_FILE;
*pos = map_line + sizeof ("file://") - 1;
}
}
else if (*map_line == '/') {
/* Trivial file case */
- *res = PROTO_FILE;
+ *res = MAP_PROTO_FILE;
*pos = map_line;
}
else {
@@ -983,11 +983,12 @@ check_map_proto (const gchar *map_line, gint *res, const gchar **pos)
}
gboolean
-add_map (struct config_file *cfg, const gchar *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback, void **user_data)
+add_map (struct config_file *cfg, const gchar *map_line, const gchar *description,
+ map_cb_t read_callback, map_fin_cb_t fin_callback, void **user_data)
{
struct rspamd_map *new_map;
enum fetch_proto proto;
- const gchar *def, *p, *hostend;
+ const gchar *def, *p, *hostend;
struct file_map_data *fdata;
struct http_map_data *hdata;
gchar portbuf[6];
@@ -1008,9 +1009,14 @@ add_map (struct config_file *cfg, const gchar *map_line, map_cb_t read_callback,
new_map->user_data = user_data;
new_map->protocol = proto;
new_map->cfg = cfg;
+ new_map->uri = memory_pool_strdup (cfg->cfg_pool, proto == MAP_PROTO_FILE ? def : map_line);
+ new_map->id = g_random_int ();
+ if (description != NULL) {
+ new_map->description = memory_pool_strdup (cfg->cfg_pool, description);
+ }
/* Now check for each proto separately */
- if (proto == PROTO_FILE) {
+ if (proto == MAP_PROTO_FILE) {
fdata = memory_pool_alloc0 (cfg->map_pool, sizeof (struct file_map_data));
if (access (def, R_OK) == -1) {
if (errno != ENOENT) {
@@ -1028,7 +1034,7 @@ add_map (struct config_file *cfg, const gchar *map_line, map_cb_t read_callback,
fdata->filename = memory_pool_strdup (cfg->map_pool, def);
new_map->map_data = fdata;
}
- else if (proto == PROTO_HTTP) {
+ else if (proto == MAP_PROTO_HTTP) {
hdata = memory_pool_alloc0 (cfg->map_pool, sizeof (struct http_map_data));
/* Try to search port */
if ((p = strchr (def, ':')) != NULL) {
diff --git a/src/map.h b/src/map.h
index 69fe5f87c..5005786dc 100644
--- a/src/map.h
+++ b/src/map.h
@@ -12,8 +12,8 @@
*/
enum fetch_proto {
- PROTO_FILE,
- PROTO_HTTP,
+ MAP_PROTO_FILE,
+ MAP_PROTO_HTTP,
};
/**
@@ -70,6 +70,9 @@ struct rspamd_map {
struct timeval tv;
struct event_base *ev_base;
void *map_data;
+ gchar *uri;
+ gchar *description;
+ guint32 id;
};
/**
@@ -79,7 +82,8 @@ gboolean check_map_proto (const gchar *map_line, gint *res, const gchar **pos);
/**
* Add map from line
*/
-gboolean add_map (struct config_file *cfg, const gchar *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback, void **user_data);
+gboolean add_map (struct config_file *cfg, const gchar *map_line, const gchar *description,
+ map_cb_t read_callback, map_fin_cb_t fin_callback, void **user_data);
/**
* Start watching of maps by adding events to libevent event loop
diff --git a/src/plugins/dkim_check.c b/src/plugins/dkim_check.c
index 7bb32db55..a1a022665 100644
--- a/src/plugins/dkim_check.c
+++ b/src/plugins/dkim_check.c
@@ -158,12 +158,12 @@ dkim_module_config (struct config_file *cfg)
dkim_module_ctx->time_jitter = DEFAULT_TIME_JITTER;
}
if ((value = get_module_opt (cfg, "dkim", "whitelist")) != NULL) {
- if (! add_map (cfg, value, read_radix_list, fin_radix_list, (void **)&dkim_module_ctx->whitelist_ip)) {
+ if (! add_map (cfg, value, "DKIM whitelist", read_radix_list, fin_radix_list, (void **)&dkim_module_ctx->whitelist_ip)) {
msg_warn ("cannot load whitelist from %s", value);
}
}
if ((value = get_module_opt (cfg, "dkim", "domains")) != NULL) {
- if (! add_map (cfg, value, read_kv_list, fin_kv_list, (void **)&dkim_module_ctx->dkim_domains)) {
+ if (! add_map (cfg, value, "DKIM domains", read_kv_list, fin_kv_list, (void **)&dkim_module_ctx->dkim_domains)) {
msg_warn ("cannot load dkim domains list from %s", value);
}
else {
diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c
index 2f61ac1b3..984163858 100644
--- a/src/plugins/fuzzy_check.c
+++ b/src/plugins/fuzzy_check.c
@@ -419,7 +419,7 @@ fuzzy_check_module_config (struct config_file *cfg)
if ((value = get_module_opt (cfg, "fuzzy_check", "whitelist")) != NULL) {
fuzzy_module_ctx->whitelist = radix_tree_create ();
- if (!add_map (cfg, value, read_radix_list, fin_radix_list, (void **)&fuzzy_module_ctx->whitelist)) {
+ if (!add_map (cfg, value, "Fuzzy whitelist", read_radix_list, fin_radix_list, (void **)&fuzzy_module_ctx->whitelist)) {
msg_err ("cannot add whitelist '%s'", value);
}
}
diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c
index ebb4ff648..9dce07772 100644
--- a/src/plugins/regexp.c
+++ b/src/plugins/regexp.c
@@ -611,7 +611,7 @@ regexp_module_config (struct config_file *cfg)
jb->buf = NULL;
jb->cfg = cfg;
*pjb = jb;
- if (!add_map (cfg, value, json_regexp_read_cb, json_regexp_fin_cb, (void **)pjb)) {
+ if (!add_map (cfg, value, "Dynamic regexp rules", json_regexp_read_cb, json_regexp_fin_cb, (void **)pjb)) {
msg_err ("cannot add map %s", value);
}
}
diff --git a/src/plugins/spf.c b/src/plugins/spf.c
index d10498699..273243c13 100644
--- a/src/plugins/spf.c
+++ b/src/plugins/spf.c
@@ -138,7 +138,7 @@ spf_module_config (struct config_file *cfg)
cache_expire = DEFAULT_CACHE_MAXAGE;
}
if ((value = get_module_opt (cfg, "spf", "whitelist")) != NULL) {
- if (! add_map (cfg, value, read_radix_list, fin_radix_list, (void **)&spf_module_ctx->whitelist_ip)) {
+ if (! add_map (cfg, value, "SPF whitelist", read_radix_list, fin_radix_list, (void **)&spf_module_ctx->whitelist_ip)) {
msg_warn ("cannot load whitelist from %s", value);
}
}
diff --git a/src/plugins/surbl.c b/src/plugins/surbl.c
index ba2df2dd8..57bd257c7 100644
--- a/src/plugins/surbl.c
+++ b/src/plugins/surbl.c
@@ -363,7 +363,7 @@ surbl_module_config (struct config_file *cfg)
surbl_module_ctx->read_timeout = DEFAULT_REDIRECTOR_READ_TIMEOUT;
}
if ((value = get_module_opt (cfg, "surbl", "redirector_hosts_map")) != NULL) {
- add_map (cfg, value, read_redirectors_list, fin_redirectors_list, (void **)&surbl_module_ctx->redirector_hosts);
+ add_map (cfg, value, "SURBL redirectors list", read_redirectors_list, fin_redirectors_list, (void **)&surbl_module_ctx->redirector_hosts);
}
else {
surbl_module_ctx->read_timeout = DEFAULT_REDIRECTOR_READ_TIMEOUT;
@@ -375,12 +375,12 @@ surbl_module_config (struct config_file *cfg)
surbl_module_ctx->max_urls = DEFAULT_SURBL_MAX_URLS;
}
if ((value = get_module_opt (cfg, "surbl", "exceptions")) != NULL) {
- if (add_map (cfg, value, read_exceptions_list, fin_exceptions_list, (void **)&surbl_module_ctx->exceptions)) {
+ if (add_map (cfg, value, "SURBL exceptions list", read_exceptions_list, fin_exceptions_list, (void **)&surbl_module_ctx->exceptions)) {
surbl_module_ctx->tld2_file = memory_pool_strdup (surbl_module_ctx->surbl_pool, value + sizeof ("file://") - 1);
}
}
if ((value = get_module_opt (cfg, "surbl", "whitelist")) != NULL) {
- if (add_map (cfg, value, read_host_list, fin_host_list, (void **)&surbl_module_ctx->whitelist)) {
+ if (add_map (cfg, value, "SURBL whitelist", read_host_list, fin_host_list, (void **)&surbl_module_ctx->whitelist)) {
surbl_module_ctx->whitelist_file = memory_pool_strdup (surbl_module_ctx->surbl_pool, value + sizeof ("file://") - 1);
}
}
diff --git a/src/settings.c b/src/settings.c
index 0d856bf3f..d7e96222a 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -348,7 +348,7 @@ json_fin_cb (memory_pool_t * pool, struct map_cb_data *data)
}
gboolean
-read_settings (const gchar *path, struct config_file *cfg, GHashTable * table)
+read_settings (const gchar *path, const gchar *description, struct config_file *cfg, GHashTable * table)
{
struct json_buf *jb = g_malloc (sizeof (struct json_buf)), **pjb;
@@ -358,7 +358,7 @@ read_settings (const gchar *path, struct config_file *cfg, GHashTable * table)
jb->buf = NULL;
*pjb = jb;
- if (!add_map (cfg, path, json_read_cb, json_fin_cb, (void **)pjb)) {
+ if (!add_map (cfg, path, description, json_read_cb, json_fin_cb, (void **)pjb)) {
msg_err ("cannot add map %s", path);
return FALSE;
}
diff --git a/src/settings.h b/src/settings.h
index fb8f8681e..7f89dd4b9 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -20,7 +20,7 @@ struct rspamd_settings {
/*
* Read settings from specified path
*/
-gboolean read_settings (const gchar *path, struct config_file *cfg, GHashTable *table);
+gboolean read_settings (const gchar *path, const gchar *description, struct config_file *cfg, GHashTable *table);
/*
* Init configuration structures for settings
diff --git a/src/view.c b/src/view.c
index b0d16dd5b..a59f3eb0b 100644
--- a/src/view.c
+++ b/src/view.c
@@ -55,7 +55,7 @@ add_view_from (struct rspamd_view * view, gchar *line)
{
struct rspamd_regexp *re = NULL;
- if (add_map (view->cfg, line, read_host_list, fin_host_list, (void **)&view->from_hash)) {
+ if (add_map (view->cfg, line, "SMTP From view", read_host_list, fin_host_list, (void **)&view->from_hash)) {
return TRUE;
}
else if ((re = parse_regexp (view->pool, line, TRUE)) != NULL) {
@@ -71,7 +71,7 @@ add_view_rcpt (struct rspamd_view * view, gchar *line)
{
struct rspamd_regexp *re = NULL;
- if (add_map (view->cfg, line, read_host_list, fin_host_list, (void **)&view->rcpt_hash)) {
+ if (add_map (view->cfg, line, "Recipients view", read_host_list, fin_host_list, (void **)&view->rcpt_hash)) {
return TRUE;
}
else if ((re = parse_regexp (view->pool, line, TRUE)) != NULL) {
@@ -88,7 +88,7 @@ add_view_symbols (struct rspamd_view * view, gchar *line)
struct rspamd_regexp *re = NULL;
GList *symbols;
- if (add_map (view->cfg, line, read_host_list, fin_host_list, (void **)&view->symbols_hash)) {
+ if (add_map (view->cfg, line, "Symbols view", read_host_list, fin_host_list, (void **)&view->symbols_hash)) {
return TRUE;
}
else if ((re = parse_regexp (view->pool, line, TRUE)) != NULL) {
@@ -112,7 +112,7 @@ add_view_symbols (struct rspamd_view * view, gchar *line)
gboolean
add_view_ip (struct rspamd_view * view, gchar *line)
{
- if (add_map (view->cfg, line, read_radix_list, fin_radix_list, (void **)&view->ip_tree)) {
+ if (add_map (view->cfg, line, "IP view", read_radix_list, fin_radix_list, (void **)&view->ip_tree)) {
return TRUE;
}
@@ -122,7 +122,7 @@ add_view_ip (struct rspamd_view * view, gchar *line)
gboolean
add_view_client_ip (struct rspamd_view * view, gchar *line)
{
- if (add_map (view->cfg, line, read_radix_list, fin_radix_list, (void **)&view->client_ip_tree)) {
+ if (add_map (view->cfg, line, "Client IP view", read_radix_list, fin_radix_list, (void **)&view->client_ip_tree)) {
return TRUE;
}
diff --git a/src/webui.c b/src/webui.c
index 05c64fc1d..326cd7639 100644
--- a/src/webui.c
+++ b/src/webui.c
@@ -58,6 +58,8 @@
/* HTTP paths */
#define PATH_AUTH "/login"
#define PATH_SYMBOLS "/symbols"
+#define PATH_MAPS "/maps"
+#define PATH_GET_MAP "/getmap"
gpointer init_webui_worker (void);
void start_webui_worker (struct rspamd_worker *worker);
@@ -253,6 +255,7 @@ http_handle_auth (struct evhttp_request *req, gpointer arg)
evb = evbuffer_new ();
if (!evb) {
msg_err ("cannot allocate evbuffer for reply");
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 insufficient memory", NULL);
return;
}
@@ -320,6 +323,7 @@ http_handle_symbols (struct evhttp_request *req, gpointer arg)
evb = evbuffer_new ();
if (!evb) {
msg_err ("cannot allocate evbuffer for reply");
+ evhttp_send_reply (req, HTTP_INTERNAL, "500", NULL);
return;
}
@@ -363,6 +367,157 @@ http_handle_symbols (struct evhttp_request *req, gpointer arg)
evbuffer_free (evb);
}
+/*
+ * Maps command handler:
+ * request: /maps
+ * headers: Password
+ * reply: json [
+ * {
+ * "map": "name",
+ * "description": "description",
+ * "editable": true
+ * },
+ * {...}
+ * ]
+ */
+static void
+http_handle_maps (struct evhttp_request *req, gpointer arg)
+{
+ struct rspamd_webui_worker_ctx *ctx = arg;
+ struct evbuffer *evb;
+ GList *cur;
+ struct rspamd_map *map;
+ gboolean editable;
+
+ evb = evbuffer_new ();
+ if (!evb) {
+ msg_err ("cannot allocate evbuffer for reply");
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 insufficient memory", NULL);
+ return;
+ }
+
+ /* Trailer */
+ evbuffer_add (evb, "[", 1);
+
+ /* Iterate over all maps */
+ cur = ctx->cfg->maps;
+ while (cur) {
+ map = cur->data;
+ if (map->protocol == MAP_PROTO_FILE && map->description != NULL) {
+ if (access (map->uri, R_OK) == 0) {
+ editable = access (map->uri, W_OK) == 0;
+ evbuffer_add_printf (evb, "{\"map\":%u,\"description\":\"%s\",\"editable\":%s%s",
+ map->id, map->description, editable ? "true" : "false",
+ g_list_next (cur) ? "}," : "}");
+ }
+ }
+ cur = g_list_next (cur);
+ }
+
+ evbuffer_add (evb, "]" CRLF, 3);
+ evhttp_add_header (req->output_headers, "Connection", "close");
+ http_calculate_content_length (evb, req);
+
+ evhttp_send_reply (req, HTTP_OK, "OK", evb);
+ evbuffer_free (evb);
+}
+
+/*
+ * Get map command handler:
+ * request: /getmap
+ * headers: Password, Map
+ * reply: plain-text
+ */
+static void
+http_handle_get_map (struct evhttp_request *req, gpointer arg)
+{
+ struct rspamd_webui_worker_ctx *ctx = arg;
+ struct evbuffer *evb;
+ GList *cur;
+ struct rspamd_map *map;
+ const gchar *idstr;
+ gchar *errstr;
+ struct stat st;
+ gint fd;
+ guint32 id;
+ gboolean found = FALSE;
+
+ evb = evbuffer_new ();
+ if (!evb) {
+ msg_err ("cannot allocate evbuffer for reply");
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 insufficient memory", NULL);
+ return;
+ }
+
+ idstr = evhttp_find_header (req->input_headers, "Map");
+
+ if (idstr == NULL) {
+ msg_info ("absent map id");
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 map open error", NULL);
+ return;
+ }
+
+ id = strtoul (idstr, &errstr, 10);
+ if (*errstr != '\0') {
+ msg_info ("invalid map id");
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 map open error", NULL);
+ return;
+ }
+
+ /* Now let's be sure that we have map defined in configuration */
+ cur = ctx->cfg->maps;
+ while (cur) {
+ map = cur->data;
+ if (map->id == id && map->protocol == MAP_PROTO_FILE) {
+ found = TRUE;
+ break;
+ }
+ cur = g_list_next (cur);
+ }
+
+ if (!found) {
+ msg_info ("map not found");
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_NOTFOUND, "404 map not found", NULL);
+ return;
+ }
+
+ if (stat (map->uri, &st) == -1 || (fd = open (map->uri, O_RDONLY)) == -1) {
+ msg_err ("cannot open map %s: %s", map->uri, strerror (errno));
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 map open error", NULL);
+ return;
+ }
+ /* Set buffer size */
+ if (evbuffer_expand (evb, st.st_size) != 0) {
+ msg_err ("cannot allocate buffer for map %s: %s", map->uri, strerror (errno));
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 insufficient memory", NULL);
+ close (fd);
+ return;
+ }
+
+ /* Read the whole buffer */
+ if (evbuffer_read (evb, fd, st.st_size) == -1) {
+ msg_err ("cannot read map %s: %s", map->uri, strerror (errno));
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 map read error", NULL);
+ close (fd);
+ return;
+ }
+
+ evhttp_add_header (req->output_headers, "Connection", "close");
+ http_calculate_content_length (evb, req);
+
+ close (fd);
+
+ evhttp_send_reply (req, HTTP_OK, "OK", evb);
+ evbuffer_free (evb);
+}
+
+
gpointer
init_webui_worker (void)
{
@@ -438,6 +593,8 @@ start_webui_worker (struct rspamd_worker *worker)
/* Add callbacks for different methods */
evhttp_set_cb (ctx->http, PATH_AUTH, http_handle_auth, ctx);
evhttp_set_cb (ctx->http, PATH_SYMBOLS, http_handle_symbols, ctx);
+ evhttp_set_cb (ctx->http, PATH_MAPS, http_handle_maps, ctx);
+ evhttp_set_cb (ctx->http, PATH_GET_MAP, http_handle_get_map, ctx);
ctx->resolver = dns_resolver_init (ctx->ev_base, worker->srv->cfg);