Ejemplo n.º 1
0
static void
rspamd_ucl_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data)
{
	struct rspamd_ucl_map_cbdata *cbdata = data->cur_data, *prev =
		data->prev_data;
	ucl_object_t *obj;
	struct ucl_parser *parser;
	guint32 checksum;
	ucl_object_iter_t it = NULL;
	const ucl_object_t *cur;
	struct rspamd_config *cfg = data->map->cfg;

	if (prev != NULL) {
		if (prev->buf != NULL) {
			g_string_free (prev->buf, TRUE);
		}
		g_free (prev);
	}

	if (cbdata == NULL) {
		msg_err_config ("map fin error: new data is NULL");
		return;
	}

	checksum = XXH64 (cbdata->buf->str, cbdata->buf->len, 0);
	if (data->map->checksum != checksum) {
		/* New data available */
		parser = ucl_parser_new (0);
		if (!ucl_parser_add_chunk (parser, cbdata->buf->str,
			cbdata->buf->len)) {
			msg_err_config ("cannot parse map %s: %s",
				data->map->uri,
				ucl_parser_get_error (parser));
			ucl_parser_free (parser);
		}
		else {
			obj = ucl_parser_get_object (parser);
			ucl_parser_free (parser);
			it = NULL;

			while ((cur = ucl_iterate_object (obj, &it, true))) {
				ucl_object_replace_key (cbdata->cfg->rcl_obj, (ucl_object_t *)cur,
						cur->key, cur->keylen, false);
			}
			ucl_object_unref (obj);
			data->map->checksum = checksum;
		}
	}
	else {
		msg_info_config ("do not reload map %s, checksum is the same: %d",
			data->map->uri,
			checksum);
	}
}
Ejemplo n.º 2
0
gint
chartable_module_config (struct rspamd_config *cfg)
{
	const ucl_object_t *value;
	gint res = TRUE;

	if (!rspamd_config_is_module_enabled (cfg, "chartable")) {
		return TRUE;
	}

	if ((value =
		rspamd_config_get_module_opt (cfg, "chartable", "symbol")) != NULL) {
		chartable_module_ctx->symbol = ucl_obj_tostring (value);
	}
	else {
		chartable_module_ctx->symbol = DEFAULT_SYMBOL;
	}
	if ((value =
		rspamd_config_get_module_opt (cfg, "chartable", "threshold")) != NULL) {
		if (!ucl_obj_todouble_safe (value, &chartable_module_ctx->threshold)) {
			msg_warn_config ("invalid numeric value");
			chartable_module_ctx->threshold = DEFAULT_THRESHOLD;
		}
	}
	else {
		chartable_module_ctx->threshold = DEFAULT_THRESHOLD;
	}

	rspamd_symbols_cache_add_symbol (cfg->cache,
		chartable_module_ctx->symbol,
		0,
		chartable_symbol_callback,
		NULL,
		SYMBOL_TYPE_NORMAL,
		-1);

	msg_info_config ("init internal chartable module");

	return res;
}
Ejemplo n.º 3
0
gint
dkim_module_config (struct rspamd_config *cfg)
{
	const ucl_object_t *value;
	gint res = TRUE, cb_id = -1, check_id = -1;
	guint cache_size;
	gboolean got_trusted = FALSE;

	if (!rspamd_config_is_module_enabled (cfg, "dkim")) {
		return TRUE;
	}

	dkim_module_ctx->whitelist_ip = radix_create_compressed ();

	if ((value =
		rspamd_config_get_module_opt (cfg, "dkim", "symbol_reject")) != NULL) {
		dkim_module_ctx->symbol_reject = ucl_obj_tostring (value);
	}
	else {
		dkim_module_ctx->symbol_reject = DEFAULT_SYMBOL_REJECT;
	}
	if ((value =
		rspamd_config_get_module_opt (cfg, "dkim",
		"symbol_tempfail")) != NULL) {
		dkim_module_ctx->symbol_tempfail = ucl_obj_tostring (value);
	}
	else {
		dkim_module_ctx->symbol_tempfail = DEFAULT_SYMBOL_TEMPFAIL;
	}
	if ((value =
		rspamd_config_get_module_opt (cfg, "dkim", "symbol_allow")) != NULL) {
		dkim_module_ctx->symbol_allow = ucl_obj_tostring (value);
	}
	else {
		dkim_module_ctx->symbol_allow = DEFAULT_SYMBOL_ALLOW;
	}
	if ((value =
		rspamd_config_get_module_opt (cfg, "dkim", "symbol_na")) != NULL) {
		dkim_module_ctx->symbol_na = ucl_obj_tostring (value);
	}
	else {
		dkim_module_ctx->symbol_na = DEFAULT_SYMBOL_NA;
	}
	if ((value =
		rspamd_config_get_module_opt (cfg, "dkim",
		"dkim_cache_size")) != NULL) {
		cache_size = ucl_obj_toint (value);
	}
	else {
		cache_size = DEFAULT_CACHE_SIZE;
	}

	if ((value =
		rspamd_config_get_module_opt (cfg, "dkim", "time_jitter")) != NULL) {
		dkim_module_ctx->time_jitter = ucl_obj_todouble (value);
	}
	else {
		dkim_module_ctx->time_jitter = DEFAULT_TIME_JITTER;
	}

	if ((value =
			rspamd_config_get_module_opt (cfg, "dkim", "max_sigs")) != NULL) {
		dkim_module_ctx->max_sigs = ucl_object_toint (value);
	}

	if ((value =
		rspamd_config_get_module_opt (cfg, "dkim", "whitelist")) != NULL) {

		rspamd_config_radix_from_ucl (cfg, value, "DKIM whitelist",
				&dkim_module_ctx->whitelist_ip, NULL);
	}

	if ((value =
		rspamd_config_get_module_opt (cfg, "dkim", "domains")) != NULL) {
		if (!rspamd_map_add_from_ucl (cfg, value,
			"DKIM domains", rspamd_kv_list_read, rspamd_kv_list_fin,
			(void **)&dkim_module_ctx->dkim_domains)) {
			msg_warn_config ("cannot load dkim domains list from %s",
				ucl_obj_tostring (value));
		}
		else {
			got_trusted = TRUE;
		}
	}

	if (!got_trusted && (value =
			rspamd_config_get_module_opt (cfg, "dkim", "trusted_domains")) != NULL) {
		if (!rspamd_map_add_from_ucl (cfg, value,
				"DKIM domains", rspamd_kv_list_read, rspamd_kv_list_fin,
				(void **)&dkim_module_ctx->dkim_domains)) {
			msg_warn_config ("cannot load dkim domains list from %s",
					ucl_obj_tostring (value));
		}
		else {
			got_trusted = TRUE;
		}
	}

	if ((value =
		rspamd_config_get_module_opt (cfg, "dkim",
		"strict_multiplier")) != NULL) {
		dkim_module_ctx->strict_multiplier = ucl_obj_toint (value);
	}
	else {
		dkim_module_ctx->strict_multiplier = 1;
	}

	if ((value =
		rspamd_config_get_module_opt (cfg, "dkim", "trusted_only")) != NULL) {
		dkim_module_ctx->trusted_only = ucl_obj_toboolean (value);
	}
	else {
		dkim_module_ctx->trusted_only = FALSE;
	}

	if ((value =
		rspamd_config_get_module_opt (cfg, "dkim", "skip_multi")) != NULL) {
		dkim_module_ctx->skip_multi = ucl_obj_toboolean (value);
	}
	else {
		dkim_module_ctx->skip_multi = FALSE;
	}

	if (dkim_module_ctx->trusted_only && !got_trusted) {
		msg_err_config (
			"trusted_only option is set and no trusted domains are defined; disabling dkim module completely as it is useless in this case");
	}
	else {
		cb_id = rspamd_symbols_cache_add_symbol (cfg->cache,
			dkim_module_ctx->symbol_reject,
			0,
			dkim_symbol_callback,
			NULL,
			SYMBOL_TYPE_NORMAL|SYMBOL_TYPE_FINE,
			-1);
		rspamd_symbols_cache_add_symbol (cfg->cache,
			dkim_module_ctx->symbol_na,
			0,
			NULL, NULL,
			SYMBOL_TYPE_VIRTUAL|SYMBOL_TYPE_FINE,
			cb_id);
		rspamd_symbols_cache_add_symbol (cfg->cache,
			dkim_module_ctx->symbol_tempfail,
			0,
			NULL, NULL,
			SYMBOL_TYPE_VIRTUAL|SYMBOL_TYPE_FINE,
			cb_id);
		rspamd_symbols_cache_add_symbol (cfg->cache,
			dkim_module_ctx->symbol_allow,
			0,
			NULL, NULL,
			SYMBOL_TYPE_VIRTUAL|SYMBOL_TYPE_FINE,
			cb_id);

		dkim_module_ctx->dkim_hash = rspamd_lru_hash_new (
				cache_size,
				g_free, /* Keys are just C-strings */
				dkim_module_key_dtor);

		msg_info_config ("init internal dkim module");
#ifndef HAVE_OPENSSL
		msg_warn_config (
			"openssl is not found so dkim rsa check is disabled, only check body hash, it is NOT safe to trust these results");
#endif
	}

	if ((value = rspamd_config_get_module_opt (cfg, "dkim", "sign_condition"))
			!= NULL) {
		const gchar *lua_script;

		lua_script = ucl_object_tostring (value);

		if (lua_script) {
			if (luaL_dostring (cfg->lua_state, lua_script) != 0) {
				msg_err_config ("cannot execute lua script for fuzzy "
						"learn condition: %s", lua_tostring (cfg->lua_state, -1));
			}
			else {
				if (lua_type (cfg->lua_state, -1) == LUA_TFUNCTION) {
					dkim_module_ctx->sign_condition_ref = luaL_ref (cfg->lua_state,
							LUA_REGISTRYINDEX);

					dkim_module_ctx->dkim_sign_hash = rspamd_lru_hash_new (
									128,
									g_free, /* Keys are just C-strings */
									(GDestroyNotify)rspamd_dkim_sign_key_unref);
					check_id = rspamd_symbols_cache_add_symbol (cfg->cache,
							"DKIM_SIGN",
							0,
							dkim_sign_callback,
							NULL,
							SYMBOL_TYPE_CALLBACK|SYMBOL_TYPE_FINE,
							-1);
					msg_info_config ("init condition script for DKIM signing");

					/*
					 * Allow dkim signing to be executed only after dkim check
					 */
					if (cb_id > 0) {
						rspamd_symbols_cache_add_delayed_dependency (cfg->cache,
								"DKIM_SIGN", dkim_module_ctx->symbol_reject);
					}

					rspamd_config_add_metric_symbol (cfg, DEFAULT_METRIC,
							"DKIM_SIGN", 0.0, "DKIM signature fake symbol",
							"dkim", RSPAMD_SYMBOL_FLAG_IGNORE, 1);

				}
				else {
					msg_err_config ("lua script must return "
							"function(task) and not %s",
							lua_typename (cfg->lua_state,
									lua_type (cfg->lua_state, -1)));
				}
			}
		}
	}

	return res;
}
Ejemplo n.º 4
0
Archivo: map.c Proyecto: Sp1l/rspamd
struct rspamd_map *
rspamd_map_add (struct rspamd_config *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;
	const gchar *def;
	struct file_map_data *fdata;
	struct http_map_data *hdata;
	gchar *cksum_encoded, cksum[rspamd_cryptobox_HASHBYTES];
	rspamd_mempool_t *pool;
	struct http_parser_url up;
	rspamd_ftok_t tok;

	if (cfg->map_pool == NULL) {
		cfg->map_pool = rspamd_mempool_new (rspamd_mempool_suggest_size (),
				"map");
		memcpy (cfg->map_pool->tag.uid, cfg->cfg_pool->tag.uid,
				sizeof (cfg->map_pool->tag.uid));
	}

	new_map = rspamd_mempool_alloc0 (cfg->map_pool, sizeof (struct rspamd_map));

	/* First of all detect protocol line */
	if (rspamd_map_check_proto (cfg, map_line, new_map) == NULL) {
		return NULL;
	}

	new_map->read_callback = read_callback;
	new_map->fin_callback = fin_callback;
	new_map->user_data = user_data;
	new_map->cfg = cfg;
	new_map->id = g_random_int ();
	new_map->locked =
		rspamd_mempool_alloc0_shared (cfg->cfg_pool, sizeof (gint));
	def = new_map->uri;

	if (description != NULL) {
		new_map->description =
			rspamd_mempool_strdup (cfg->cfg_pool, description);
	}

	/* Now check for each proto separately */
	if (new_map->protocol == MAP_PROTO_FILE) {
		fdata =
			rspamd_mempool_alloc0 (cfg->map_pool,
				sizeof (struct file_map_data));
		if (access (def, R_OK) == -1) {
			if (errno != ENOENT) {
				msg_err_config ("cannot open file '%s': %s", def, strerror
						(errno));
				return NULL;

			}
			msg_info_config (
				"map '%s' is not found, but it can be loaded automatically later",
				def);
			/* We still can add this file */
			fdata->st.st_mtime = -1;
		}
		else {
			stat (def, &fdata->st);
		}
		fdata->filename = rspamd_mempool_strdup (cfg->map_pool, def);
		new_map->map_data = fdata;
	}
	else if (new_map->protocol == MAP_PROTO_HTTP) {
		hdata =
			rspamd_mempool_alloc0 (cfg->map_pool,
				sizeof (struct http_map_data));

		memset (&up, 0, sizeof (up));
		if (http_parser_parse_url (new_map->uri, strlen (new_map->uri), FALSE,
				&up) != 0) {
			msg_err_config ("cannot parse HTTP url: %s", new_map->uri);
			return NULL;
		}
		else {
			if (!(up.field_set & 1 << UF_HOST)) {
				msg_err_config ("cannot parse HTTP url: %s: no host", new_map->uri);
				return NULL;
			}

			tok.begin = new_map->uri + up.field_data[UF_HOST].off;
			tok.len = up.field_data[UF_HOST].len;
			hdata->host = rspamd_mempool_ftokdup (cfg->map_pool, &tok);

			if (up.field_set & 1 << UF_PORT) {
				hdata->port = up.port;
			}
			else {
				hdata->port = 80;
			}

			if (up.field_set & 1 << UF_PATH) {
				tok.begin = new_map->uri + up.field_data[UF_PATH].off;
				tok.len = strlen (tok.begin);

				hdata->path = rspamd_mempool_ftokdup (cfg->map_pool, &tok);
			}
		}

		new_map->map_data = hdata;

	}

	/* Temp pool */
	rspamd_cryptobox_hash (cksum, new_map->uri, strlen (new_map->uri), NULL, 0);
	cksum_encoded = rspamd_encode_base32 (cksum, sizeof (cksum));
	new_map->pool = rspamd_mempool_new (rspamd_mempool_suggest_size (), "map");
	rspamd_strlcpy (new_map->pool->tag.uid, cksum_encoded,
			sizeof (new_map->pool->tag.uid));
	g_free (cksum_encoded);
	pool = new_map->pool;
	msg_info_pool ("added map %s", new_map->uri);


	cfg->maps = g_list_prepend (cfg->maps, new_map);

	return new_map;
}
Ejemplo n.º 5
0
gboolean
rspamd_map_add (struct rspamd_config *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;
    struct file_map_data *fdata;
    struct http_map_data *hdata;
    gchar portbuf[6], *cksum_encoded, cksum[BLAKE2B_OUTBYTES];
    gint i, s, r;
    struct addrinfo hints, *res;
    rspamd_mempool_t *pool;

    /* First of all detect protocol line */
    if (!rspamd_map_check_proto (map_line, (int *)&proto, &def)) {
        return FALSE;
    }
    /* Constant pool */
    if (cfg->map_pool == NULL) {
        cfg->map_pool = rspamd_mempool_new (rspamd_mempool_suggest_size (),
                                            "map");
        memcpy (cfg->map_pool->tag.uid, cfg->cfg_pool->tag.uid,
                sizeof (cfg->map_pool->tag.uid));
    }

    new_map = rspamd_mempool_alloc0 (cfg->map_pool, sizeof (struct rspamd_map));
    new_map->read_callback = read_callback;
    new_map->fin_callback = fin_callback;
    new_map->user_data = user_data;
    new_map->protocol = proto;
    new_map->cfg = cfg;
    new_map->id = g_random_int ();
    new_map->locked =
        rspamd_mempool_alloc0_shared (cfg->cfg_pool, sizeof (gint));

    if (proto == MAP_PROTO_FILE) {
        new_map->uri = rspamd_mempool_strdup (cfg->cfg_pool, def);
        def = new_map->uri;
    }
    else {
        new_map->uri = rspamd_mempool_strdup (cfg->cfg_pool, map_line);
    }
    if (description != NULL) {
        new_map->description =
            rspamd_mempool_strdup (cfg->cfg_pool, description);
    }

    /* Now check for each proto separately */
    if (proto == MAP_PROTO_FILE) {
        fdata =
            rspamd_mempool_alloc0 (cfg->map_pool,
                                   sizeof (struct file_map_data));
        if (access (def, R_OK) == -1) {
            if (errno != ENOENT) {
                msg_err_config ("cannot open file '%s': %s", def, strerror
                                (errno));
                return FALSE;

            }
            msg_info_config (
                "map '%s' is not found, but it can be loaded automatically later",
                def);
            /* We still can add this file */
            fdata->st.st_mtime = -1;
        }
        else {
            stat (def, &fdata->st);
        }
        fdata->filename = rspamd_mempool_strdup (cfg->map_pool, def);
        new_map->map_data = fdata;
    }
    else if (proto == MAP_PROTO_HTTP) {
        hdata =
            rspamd_mempool_alloc0 (cfg->map_pool,
                                   sizeof (struct http_map_data));
        /* Try to search port */
        if ((p = strchr (def, ':')) != NULL) {
            hostend = p;
            i = 0;
            p++;
            while (g_ascii_isdigit (*p) && i < (gint)sizeof (portbuf) - 1) {
                portbuf[i++] = *p++;
            }
            if (*p != '/') {
                msg_info_config ("bad http map definition: %s", def);
                return FALSE;
            }
            portbuf[i] = '\0';
            hdata->port = atoi (portbuf);
        }
        else {
            /* Default http port */
            rspamd_snprintf (portbuf, sizeof (portbuf), "80");
            hdata->port = 80;
            /* Now separate host from path */
            if ((p = strchr (def, '/')) == NULL) {
                msg_info_config ("bad http map definition: %s", def);
                return FALSE;
            }
            hostend = p;
        }
        hdata->host = rspamd_mempool_alloc (cfg->map_pool, hostend - def + 1);
        rspamd_strlcpy (hdata->host, def, hostend - def + 1);
        hdata->path = rspamd_mempool_strdup (cfg->map_pool, p);
        /* Now try to resolve */
        memset (&hints, 0, sizeof (hints));
        hints.ai_family = AF_UNSPEC;     /* Allow IPv4 or IPv6 */
        hints.ai_socktype = SOCK_STREAM; /* Stream socket */
        hints.ai_flags = 0;
        hints.ai_protocol = 0;           /* Any protocol */
        hints.ai_canonname = NULL;
        hints.ai_addr = NULL;
        hints.ai_next = NULL;

        if ((r = getaddrinfo (hdata->host, portbuf, &hints, &res)) == 0) {
            hdata->addr = res;
            rspamd_mempool_add_destructor (cfg->cfg_pool,
                                           (rspamd_mempool_destruct_t)freeaddrinfo, hdata->addr);
        }
        else {
            msg_err_config ("address resolution for %s failed: %s",
                            hdata->host,
                            gai_strerror (r));
            return FALSE;
        }
        /* Now try to connect */
        if ((s = rspamd_socket_tcp (hdata->addr, FALSE, FALSE)) == -1) {
            msg_info_config ("cannot connect to http server %s: %d, %s",
                             hdata->host,
                             errno,
                             strerror (errno));
            return FALSE;
        }
        close (s);
        hdata->conn = rspamd_http_connection_new (http_map_read, http_map_error,
                      http_map_finish,
                      RSPAMD_HTTP_BODY_PARTIAL | RSPAMD_HTTP_CLIENT_SIMPLE,
                      RSPAMD_HTTP_CLIENT, NULL);
        new_map->map_data = hdata;
    }
    /* Temp pool */
    blake2b (cksum, new_map->uri, NULL, sizeof (cksum), strlen (new_map->uri), 0);
    cksum_encoded = rspamd_encode_base32 (cksum, sizeof (cksum));
    new_map->pool = rspamd_mempool_new (rspamd_mempool_suggest_size (), "map");
    memcpy (new_map->pool->tag.uid, cksum_encoded,
            sizeof (new_map->pool->tag.uid));
    g_free (cksum_encoded);
    pool = new_map->pool;
    msg_info_pool ("added map %s", new_map->uri);


    cfg->maps = g_list_prepend (cfg->maps, new_map);

    return TRUE;
}
Ejemplo n.º 6
0
gboolean
rspamd_config_is_module_enabled (struct rspamd_config *cfg,
		const gchar *module_name)
{
	gboolean is_c = FALSE;
	struct metric *metric;
	const ucl_object_t *conf, *enabled;
	GList *cur;
	struct rspamd_symbols_group *gr;

	metric = cfg->default_metric;

	if (g_hash_table_lookup (cfg->c_modules, module_name)) {
		is_c = TRUE;
	}

	if (g_hash_table_lookup (cfg->explicit_modules, module_name) != NULL) {
		/* Always load module */
		return TRUE;
	}

	if (is_c) {
		gboolean found = FALSE;

		cur = g_list_first (cfg->filters);

		while (cur) {
			if (strcmp (cur->data, module_name) == 0) {
				found = TRUE;
				break;
			}

			cur = g_list_next (cur);
		}

		if (!found) {
			msg_info_config ("internal module %s is disable in `filters` line",
					module_name);

			return FALSE;
		}
	}

	conf = ucl_object_find_key (cfg->rcl_obj, module_name);

	if (conf == NULL) {
		msg_info_config ("%s module %s is enabled but has not been configured",
				is_c ? "internal" : "lua", module_name);

		if (!is_c) {
			msg_info_config ("%s disabling unconfigured lua module", module_name);
			return FALSE;
		}
	}
	else {
		enabled = ucl_object_find_key (conf, "enabled");

		if (enabled && ucl_object_type (enabled) == UCL_BOOLEAN) {
			if (!ucl_object_toboolean (enabled)) {
				msg_info_config ("%s module %s is disabled in the configuration",
						is_c ? "internal" : "lua", module_name);
				return FALSE;
			}
		}
	}

	/* Now we check symbols group */
	gr = g_hash_table_lookup (metric->groups, module_name);

	if (gr) {
		if (gr->disabled) {
			msg_info_config ("%s module %s is disabled in the configuration as "
					"its group has been disabled",
					is_c ? "internal" : "lua", module_name);
			return FALSE;
		}
	}

	return TRUE;
}
Ejemplo n.º 7
0
static struct rspamd_map_backend *
rspamd_map_parse_backend (struct rspamd_config *cfg, const gchar *map_line)
{
	struct rspamd_map_backend *bk;
	struct file_map_data *fdata = NULL;
	struct http_map_data *hdata = NULL;
	struct http_parser_url up;
	rspamd_ftok_t tok;

	bk = g_slice_alloc0 (sizeof (*bk));
	REF_INIT_RETAIN (bk, rspamd_map_backend_dtor);

	if (!rspamd_map_check_proto (cfg, map_line, bk)) {
		goto err;
	}

	/* Now check for each proto separately */
	if (bk->protocol == MAP_PROTO_FILE) {
		fdata = g_slice_alloc0 (sizeof (struct file_map_data));
		fdata->st.st_mtime = -1;

		if (access (bk->uri, R_OK) == -1) {
			if (errno != ENOENT) {
				msg_err_config ("cannot open file '%s': %s", bk->uri, strerror (errno));
				return NULL;

			}
			msg_info_config (
					"map '%s' is not found, but it can be loaded automatically later",
					bk->uri);
		}

		fdata->filename = g_strdup (bk->uri);
		bk->data.fd = fdata;
	}
	else if (bk->protocol == MAP_PROTO_HTTP || bk->protocol == MAP_PROTO_HTTPS) {
		hdata = g_slice_alloc0 (sizeof (struct http_map_data));

		memset (&up, 0, sizeof (up));
		if (http_parser_parse_url (bk->uri, strlen (bk->uri), FALSE,
				&up) != 0) {
			msg_err_config ("cannot parse HTTP url: %s", bk->uri);
			goto err;
		}
		else {
			if (!(up.field_set & 1 << UF_HOST)) {
				msg_err_config ("cannot parse HTTP url: %s: no host", bk->uri);
				return NULL;
			}

			tok.begin = bk->uri + up.field_data[UF_HOST].off;
			tok.len = up.field_data[UF_HOST].len;
			hdata->host = rspamd_ftokdup (&tok);

			if (up.field_set & 1 << UF_PORT) {
				hdata->port = up.port;
			}
			else {
				if (bk->protocol == MAP_PROTO_HTTP) {
					hdata->port = 80;
				}
				else {
					hdata->port = 443;
				}
			}

			if (up.field_set & 1 << UF_PATH) {
				tok.begin = bk->uri + up.field_data[UF_PATH].off;
				tok.len = strlen (tok.begin);

				hdata->path = rspamd_ftokdup (&tok);
			}
		}

		bk->data.hd = hdata;
	}

	return bk;

err:
	MAP_RELEASE (bk, "rspamd_map_backend");

	if (hdata) {
		g_slice_free1 (sizeof (*hdata), hdata);
	}

	if (fdata) {
		g_slice_free1 (sizeof (*fdata), fdata);
	}

	return NULL;
}
Ejemplo n.º 8
0
/* Process a single item in 'metrics' table */
static void
lua_process_metric (lua_State *L, const gchar *name, struct rspamd_config *cfg)
{
	GList *metric_list;
	gchar *symbol;
	const gchar *desc;
	struct metric *metric;
	gdouble *score;
	struct rspamd_symbol_def *s;

	/* Get module opt structure */
	if ((metric = g_hash_table_lookup (cfg->metrics, name)) == NULL) {
		metric = rspamd_config_new_metric (cfg, metric, name);
	}

	/* Now iterate throught module table */
	for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
		/* key - -2, value - -1 */
		symbol =
			rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, -2));
		if (symbol != NULL) {
			if (lua_istable (L, -1)) {
				/* We got a table, so extract individual attributes */
				lua_pushstring (L, "weight");
				lua_gettable (L, -2);
				if (lua_isnumber (L, -1)) {
					score =
						rspamd_mempool_alloc (cfg->cfg_pool, sizeof (double));
					*score = lua_tonumber (L, -1);
				}
				else {
					msg_warn_config("cannot get weight of symbol: %s", symbol);
					continue;
				}
				lua_pop (L, 1);
				lua_pushstring (L, "description");
				lua_gettable (L, -2);
				if (lua_isstring (L, -1)) {
					desc = lua_tostring (L, -1);
					s->description = rspamd_mempool_strdup (cfg->cfg_pool, desc);
				}
				lua_pop (L, 1);
			}
			else if (lua_isnumber (L, -1)) {
				/* Just got weight */
				score = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (double));
				*score = lua_tonumber (L, -1);
			}
			else {
				msg_warn_config("cannot get weight of symbol: %s", symbol);
				continue;
			}
			/* Insert symbol */
			if ((s =
				g_hash_table_lookup (metric->symbols, symbol)) != NULL) {
				msg_info_config("replacing weight for symbol %s: %.2f -> %.2f",
					symbol,
					*s->weight_ptr,
					*score);
				s->weight_ptr = score;
			}
			else {
				s = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (*s));
				s->name = symbol;
				s->weight_ptr = score;
				g_hash_table_insert (metric->symbols, symbol, s);
			}

			if ((metric_list =
				g_hash_table_lookup (cfg->metrics_symbols, symbol)) == NULL) {
				metric_list = g_list_prepend (NULL, metric);
				rspamd_mempool_add_destructor (cfg->cfg_pool,
					(rspamd_mempool_destruct_t)g_list_free, metric_list);
				g_hash_table_insert (cfg->metrics_symbols, symbol, metric_list);
			}
			else {
				/* Slow but keep start element of list in safe */
				if (!g_list_find (metric_list, metric)) {
					metric_list = g_list_append (metric_list, metric);
				}
			}
		}
	}
}
Ejemplo n.º 9
0
/* Do post load initialization based on lua */
void
rspamd_lua_post_load_config (struct rspamd_config *cfg)
{
	lua_State *L = cfg->lua_state;
	const gchar *name, *val;
	gchar *sym;
	struct rspamd_expression *expr, *old_expr;
	ucl_object_t *obj;
	gsize keylen;
	GError *err = NULL;

	/* First check all module options that may be overriden in 'config' global */
	lua_getglobal (L, "config");

	if (lua_istable (L, -1)) {
		/* Iterate */
		for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
			/* 'key' is at index -2 and 'value' is at index -1 */
			/* Key must be a string and value must be a table */
			name = luaL_checklstring (L, -2, &keylen);
			if (name != NULL && lua_istable (L, -1)) {
				obj = ucl_object_lua_import (L, lua_gettop (L));
				if (obj != NULL) {
					ucl_object_insert_key_merged (cfg->rcl_obj,
						obj,
						name,
						keylen,
						true);
				}
			}
		}
	}

	/* Check metrics settings */
	lua_getglobal (L, "metrics");

	if (lua_istable (L, -1)) {
		/* Iterate */
		for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
			/* 'key' is at index -2 and 'value' is at index -1 */
			/* Key must be a string and value must be a table */
			name = luaL_checkstring (L, -2);
			if (name != NULL && lua_istable (L, -1)) {
				lua_process_metric (L, name, cfg);
			}
		}
	}

	/* Check composites */
	lua_getglobal (L, "composites");

	if (lua_istable (L, -1)) {
		/* Iterate */
		for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
			/* 'key' is at index -2 and 'value' is at index -1 */
			/* Key must be a string and value must be a table */
			name = luaL_checkstring (L, -2);
			if (name != NULL && lua_isstring (L, -1)) {
				val = lua_tostring (L, -1);
				sym = rspamd_mempool_strdup (cfg->cfg_pool, name);
				if (!rspamd_parse_expression (val, 0, &composite_expr_subr, NULL,
							cfg->cfg_pool, &err, &expr)) {
					msg_err_config("cannot parse composite expression '%s': %s", val,
							err->message);
					g_error_free (err);
					err = NULL;
					continue;
				}
				/* Now check hash table for this composite */
				if ((old_expr =
					g_hash_table_lookup (cfg->composite_symbols,
					name)) != NULL) {
					msg_info_config("replacing composite symbol %s", name);
					g_hash_table_replace (cfg->composite_symbols, sym, expr);
				}
				else {
					g_hash_table_insert (cfg->composite_symbols, sym, expr);
					rspamd_symbols_cache_add_symbol (cfg->cache, sym,
							0, NULL, NULL, SYMBOL_TYPE_COMPOSITE, -1);
				}
			}
		}
	}
}