Esempio n. 1
0
static void
rspamadm_confighelp_search_word_step (const ucl_object_t *obj,
		ucl_object_t *res,
		const gchar *str,
		gsize len,
		GString *path)
{
	ucl_object_iter_t it = NULL;
	const ucl_object_t *cur, *elt;
	const gchar *dot_pos;

	while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
		if (cur->keylen > 0) {
			rspamd_printf_gstring (path, ".%*s", (int) cur->keylen, cur->key);

			if (rspamd_substring_search_caseless (cur->key,
					cur->keylen,
					str,
					len) != -1) {
				ucl_object_insert_key (res, ucl_object_ref (cur),
						path->str, path->len, true);
				goto fin;
			}
		}

		if (ucl_object_type (cur) == UCL_OBJECT) {
			elt = ucl_object_lookup (cur, "data");

			if (elt != NULL && ucl_object_type (elt) == UCL_STRING) {
				if (rspamd_substring_search_caseless (elt->value.sv,
						elt->len,
						str,
						len) != -1) {
					ucl_object_insert_key (res, ucl_object_ref (cur),
							path->str, path->len, true);
					goto fin;
				}
			}

			rspamadm_confighelp_search_word_step (cur, res, str, len, path);
		}

		fin:
		/* Remove the last component of the path */
		dot_pos = strrchr (path->str, '.');

		if (dot_pos) {
			g_string_erase (path, dot_pos - path->str,
					path->len - (dot_pos - path->str));
		}
	}
}
Esempio n. 2
0
static gboolean
rspamd_symbols_cache_process_settings (struct rspamd_task *task,
		struct symbols_cache *cache)
{
	const ucl_object_t *wl, *cur, *disabled;
	struct metric *def;
	struct rspamd_symbols_group *gr;
	GHashTableIter gr_it;
	ucl_object_iter_t it = NULL;
	gpointer k, v;

	wl = ucl_object_lookup (task->settings, "whitelist");

	if (wl != NULL) {
		msg_info_task ("<%s> is whitelisted", task->message_id);
		task->flags |= RSPAMD_TASK_FLAG_SKIP;
		return TRUE;
	}

	disabled = ucl_object_lookup (task->settings, "symbols_disabled");

	if (disabled) {
		it = NULL;

		while ((cur = ucl_iterate_object (disabled, &it, true)) != NULL) {
			rspamd_symbols_cache_disable_symbol (task, cache,
					ucl_object_tostring (cur));
		}
	}

	/* Disable groups of symbols */
	disabled = ucl_object_lookup (task->settings, "groups_disabled");
	def = g_hash_table_lookup (task->cfg->metrics, DEFAULT_METRIC);

	if (def && disabled) {
		it = NULL;

		while ((cur = ucl_iterate_object (disabled, &it, true)) != NULL) {
			if (ucl_object_type (cur) == UCL_STRING) {
				gr = g_hash_table_lookup (def->groups,
						ucl_object_tostring (cur));

				if (gr) {
					g_hash_table_iter_init (&gr_it, gr->symbols);

					while (g_hash_table_iter_next (&gr_it, &k, &v)) {
						rspamd_symbols_cache_disable_symbol (task, cache, k);
					}
				}
			}
		}
	}

	return FALSE;
}
Esempio n. 3
0
gpointer
rspamd_redis_init (struct rspamd_stat_ctx *ctx,
		struct rspamd_config *cfg, struct rspamd_statfile *st)
{
	struct redis_stat_ctx *backend;
	struct rspamd_statfile_config *stf = st->stcf;
	struct rspamd_redis_stat_elt *st_elt;
	const ucl_object_t *obj;
	gboolean ret = FALSE;

	backend = g_slice_alloc0 (sizeof (*backend));

	/* First search in backend configuration */
	obj = ucl_object_lookup (st->classifier->cfg->opts, "backend");
	if (obj != NULL && ucl_object_type (obj) == UCL_OBJECT) {
		ret = rspamd_redis_try_ucl (backend, obj, cfg, stf->symbol);
	}

	/* Now try statfiles config */
	if (!ret) {
		ret = rspamd_redis_try_ucl (backend, stf->opts, cfg, stf->symbol);
	}

	/* Now try classifier config */
	if (!ret) {
		ret = rspamd_redis_try_ucl (backend, st->classifier->cfg->opts, cfg,
				stf->symbol);
	}

	if (!ret) {
		msg_err_config ("cannot init redis backend for %s", stf->symbol);
		g_slice_free1 (sizeof (*backend), backend);
		return NULL;
	}

	stf->clcf->flags |= RSPAMD_FLAG_CLASSIFIER_INCREMENTING_BACKEND;
	backend->stcf = stf;

	st_elt = g_slice_alloc0 (sizeof (*st_elt));
	st_elt->ev_base = ctx->ev_base;
	st_elt->ctx = backend;
	backend->stat_elt = rspamd_stat_ctx_register_async (
			rspamd_redis_async_stat_cb,
			rspamd_redis_async_stat_fin,
			st_elt,
			REDIS_STAT_TIMEOUT);
	st_elt->async = backend->stat_elt;

	return (gpointer)backend;
}
Esempio n. 4
0
static gint
lua_config_get_all_opt (lua_State * L)
{
	struct rspamd_config *cfg = lua_check_config (L, 1);
	const gchar *mname;
	const ucl_object_t *obj, *cur, *cur_elt;
	ucl_object_iter_t it = NULL;
	gint i;

	if (cfg) {
		mname = luaL_checkstring (L, 2);

		if (mname) {
			obj = ucl_obj_get_key (cfg->rcl_obj, mname);
			/* Flatten object */
			if (obj != NULL && (ucl_object_type (obj) == UCL_OBJECT ||
					ucl_object_type (obj) == UCL_ARRAY)) {

				lua_newtable (L);
				it = ucl_object_iterate_new (obj);

				LL_FOREACH (obj, cur) {
					it = ucl_object_iterate_reset (it, cur);

					while ((cur_elt = ucl_object_iterate_safe (it, true))) {
						lua_pushstring (L, ucl_object_key (cur_elt));
						ucl_object_push_lua (L, cur_elt, true);
						lua_settable (L, -3);
					}
				}

				ucl_object_iterate_free (it);

				return 1;
			}
			else if (obj != NULL) {
Esempio n. 5
0
File: conf.c Progetto: mhilton/conf
/*
 * snprintkeys writes the value contained in obj to dst.
 */
static int
snprintval(char *dst, size_t size, ucl_object_t const *obj)
{

	switch (ucl_object_type(obj)) {
	case UCL_INT:
		return snprintf(dst, size, "%" PRId64, ucl_object_toint(obj));
	case UCL_FLOAT:
	case UCL_TIME:
		return snprintf(dst, size, "%0.10f", ucl_object_todouble(obj));
	case UCL_STRING:
		return snprintf(dst, size, "%s", ucl_object_tostring(obj));
	case UCL_BOOLEAN:
		return snprintf(dst, size, "%s", ucl_object_toboolean(obj) ? "true": "false");
	default:
		*dst = '\0';
		return 0;
	}
}
Esempio n. 6
0
File: conf.c Progetto: mhilton/conf
/*
 * expand extrapolates one or more environment variables from obj. If obj
 * is of type UCL_OBJECT or UCL_ARRAY then a new variable will be created
 * will be created containing a list of keys in obj and then expand will be
 * called recursively for each member. Otherwise a new environment variable
 * will be created with the value of obj.
 */
static void
expand(size_t keylen, ucl_object_t const *obj)
{
	ucl_object_iter_t it = NULL;
	ucl_object_t const *o;
	int i, l;

	switch (ucl_object_type(obj)) {
	case UCL_OBJECT:
		if (snprintkeys(envval, MAX_VALUE_LEN, obj) >= MAX_VALUE_LEN)
			errx(EX_DATAERR, "value too long \"%s\"", envval);
		setenv(envkey, envval, 1);
		while ((o = ucl_iterate_object(obj, &it, true)) != NULL) {
			l = snprintf(envkey + keylen, MAX_KEY_LEN - keylen, "_%s", ucl_object_key(o));
			if (l >= MAX_KEY_LEN - keylen)
				errx(EX_DATAERR, "key too long \"%s\"", envkey);
			expand(keylen + l, o);
		}
		break;
	case UCL_ARRAY:
		if (snprintkeys(envval, MAX_VALUE_LEN, obj) >= MAX_VALUE_LEN)
			errx(EX_DATAERR, "value too long \"%s\"", envval);
		setenv(envkey, envval, 1);
		i = 0;
		while ((o = ucl_iterate_object(obj, &it, true)) != NULL) {
			l = snprintf(envkey + keylen, MAX_KEY_LEN - keylen, "_%d", i++);
			if (l > MAX_KEY_LEN - keylen)
				errx(EX_DATAERR, "key too long \"%s\"", envkey);
			expand(keylen + l, o);
		}
		break;
	default:
		if (snprintval(envval, MAX_VALUE_LEN, obj) >= MAX_VALUE_LEN)
			errx(EX_DATAERR, "value too long \"%s\"", envval);
		setenv(envkey, envval, 1);
		break;
	}
}
Esempio n. 7
0
File: conf.c Progetto: mhilton/conf
/*
 * print outputs the appropriate data for obj. If obj is a UCL_OBJECT or
 * UCL_ARRAY a list if keys is printed, otherwise the value is printed.
 */
static void
print(ucl_object_t const *obj)
{
	int n;

	switch (ucl_object_type(obj)) {
	case UCL_OBJECT:
	case UCL_ARRAY:
		n = snprintkeys(envval, MAX_VALUE_LEN, obj);
		if (n < 0)
			errx(EX_SOFTWARE, "error listing keys");
		break;
	default:
		n = snprintval(envval, MAX_VALUE_LEN, obj);
		if (n < 0)
			errx(EX_SOFTWARE, "error formatting value");
		break;
	}
	if (n >= MAX_VALUE_LEN)
		errx(EX_DATAERR, "output too long");
	if (n > 0 && puts(envval) < 0)
		err(EX_IOERR, "cannot write value");
}
Esempio n. 8
0
bool
merge_recursive(ucl_object_t *top, ucl_object_t *elt, bool copy)
{
    const ucl_object_t *cur;
    ucl_object_iter_t it = NULL;
    ucl_object_t *found = NULL, *cp_obj = NULL;
    bool success = false;

    it = ucl_object_iterate_new(elt);

    while ((cur = ucl_object_iterate_safe(it, false))) {
	cp_obj = ucl_object_ref(cur);
	if (debug > 0) {
	    fprintf(stderr, "DEBUG: Looping over (elt)%s, found key: %s\n",
		ucl_object_key(top), ucl_object_key(cur));
	}
	if (ucl_object_type(cur) == UCL_OBJECT) {
	    found = __DECONST(ucl_object_t *, ucl_object_find_key(top, ucl_object_key(cur)));
	    if (found == NULL) {
		/* new key not found in old object, insert it */
		if (debug > 0) {
		    fprintf(stderr, "DEBUG: unmatched key, inserting: %s into top\n",
			ucl_object_key(cur));
		}
		success = ucl_object_insert_key_merged(top, cp_obj,
		    ucl_object_key(cp_obj), 0, true);
		if (success == false) { return false; }
		continue;
	    }
	    if (debug > 0) {
		fprintf(stderr, "DEBUG: (obj) Found key %s in (top)%s too, merging...\n",
		    ucl_object_key(found), ucl_object_key(top));
	    }
	    success = merge_recursive(found, cp_obj, copy);
	    if (success == false) { return false; }
	} else if (ucl_object_type(cur) == UCL_ARRAY) {
Esempio n. 9
0
File: conf.c Progetto: mhilton/conf
/*
 * snprintkeys writes the keys contained in obj to dst.
 */
static int
snprintkeys(char *dst, size_t size, ucl_object_t const *obj)
{
	ucl_object_iter_t it = NULL;
	ucl_object_t const *o;
	int n = 0;
	int i = 0;

	switch (ucl_object_type(obj)) {
	case UCL_OBJECT:
		for (i = 0; (o = ucl_iterate_object(obj, &it, true)) != NULL; i++) {
			int l;

			l = snprintf(dst + n, (size - n > 0) ? size - n: 0, "%s%s", (i == 0)?"":"\n", ucl_object_key(o));
			if (l < 0)
				return l;
			n += l;
		}
		break;
	case UCL_ARRAY: {
		for (i = 0; (o = ucl_iterate_object(obj, &it, true)) != NULL; i++) {
			int l;

			l = snprintf(dst + n, (size - n > 0) ? size - n: 0, "%s%d", (i == 0)?"":"\n", i);
			if (l < 0)
				return l;
			n += l;
		}
		break;
	}
	default:
		*dst = '\0';
		break;
	}
	return n;
}
Esempio n. 10
0
gpointer
rspamd_stat_cache_redis_init (struct rspamd_stat_ctx *ctx,
		struct rspamd_config *cfg,
		struct rspamd_statfile *st,
		const ucl_object_t *cf)
{
	struct rspamd_redis_cache_ctx *cache_ctx;
	struct rspamd_statfile_config *stf = st->stcf;
	const ucl_object_t *obj;
	gboolean ret = FALSE;

	cache_ctx = g_slice_alloc0 (sizeof (*cache_ctx));

	/* First search in backend configuration */
	obj = ucl_object_lookup (st->classifier->cfg->opts, "backend");
	if (obj != NULL && ucl_object_type (obj) == UCL_OBJECT) {
		ret = rspamd_redis_cache_try_ucl (cache_ctx, obj, cfg, stf->symbol);
	}

	/* Now try statfiles config */
	if (!ret) {
		ret = rspamd_redis_cache_try_ucl (cache_ctx, stf->opts, cfg, stf->symbol);
	}

	/* Now try classifier config */
	if (!ret) {
		ret = rspamd_redis_cache_try_ucl (cache_ctx, st->classifier->cfg->opts, cfg,
				stf->symbol);
	}

	/* Now try global redis settings */
	if (!ret) {
		obj = ucl_object_lookup (cfg->rcl_obj, "redis");

		if (obj) {
			const ucl_object_t *specific_obj;

			specific_obj = ucl_object_lookup (obj, "statistics");

			if (specific_obj) {
				ret = rspamd_redis_cache_try_ucl (cache_ctx, specific_obj, cfg,
						stf->symbol);
			}
			else {
				ret = rspamd_redis_cache_try_ucl (cache_ctx, obj, cfg,
						stf->symbol);
			}
		}
	}


	if (!ret) {
		msg_err_config ("cannot init redis cache for %s", stf->symbol);
		g_slice_free1 (sizeof (*cache_ctx), cache_ctx);
		return NULL;
	}

	cache_ctx->stcf = stf;

	return (gpointer)cache_ctx;
}
Esempio n. 11
0
static gboolean
rspamd_redis_cache_try_ucl (struct rspamd_redis_cache_ctx *cache_ctx,
		const ucl_object_t *obj,
		struct rspamd_config *cfg,
		const gchar *symbol)
{
	const ucl_object_t *elt, *relt;

	elt = ucl_object_lookup_any (obj, "read_servers", "servers", NULL);

	if (elt == NULL) {
		return FALSE;
	}

	cache_ctx->read_servers = rspamd_upstreams_create (cfg->ups_ctx);
	if (!rspamd_upstreams_from_ucl (cache_ctx->read_servers, elt,
			REDIS_DEFAULT_PORT, NULL)) {
		msg_err ("statfile %s cannot get read servers configuration",
				symbol);
		return FALSE;
	}

	relt = elt;

	elt = ucl_object_lookup (obj, "write_servers");
	if (elt == NULL) {
		/* Use read servers as write ones */
		g_assert (relt != NULL);
		cache_ctx->write_servers = rspamd_upstreams_create (cfg->ups_ctx);
		if (!rspamd_upstreams_from_ucl (cache_ctx->write_servers, relt,
				REDIS_DEFAULT_PORT, NULL)) {
			msg_err ("statfile %s cannot get write servers configuration",
					symbol);
			return FALSE;
		}
	}
	else {
		cache_ctx->write_servers = rspamd_upstreams_create (cfg->ups_ctx);
		if (!rspamd_upstreams_from_ucl (cache_ctx->write_servers, elt,
				REDIS_DEFAULT_PORT, NULL)) {
			msg_err ("statfile %s cannot get write servers configuration",
					symbol);
			rspamd_upstreams_destroy (cache_ctx->write_servers);
			cache_ctx->write_servers = NULL;
		}
	}


	elt = ucl_object_lookup (obj, "timeout");
	if (elt) {
		cache_ctx->timeout = ucl_object_todouble (elt);
	}
	else {
		cache_ctx->timeout = REDIS_DEFAULT_TIMEOUT;
	}

	elt = ucl_object_lookup (obj, "password");
	if (elt) {
		cache_ctx->password = ucl_object_tostring (elt);
	}
	else {
		cache_ctx->password = NULL;
	}

	elt = ucl_object_lookup_any (obj, "db", "database", "dbname", NULL);
	if (elt) {
		cache_ctx->dbname = ucl_object_tostring (elt);
	}
	else {
		cache_ctx->dbname = NULL;
	}

	elt = ucl_object_lookup_any (obj, "cache_key", "key", NULL);
	if (elt == NULL || ucl_object_type (elt) != UCL_STRING) {
		cache_ctx->redis_object = DEFAULT_REDIS_KEY;
	}
	else {
		cache_ctx->redis_object = ucl_object_tostring (elt);
	}

	return TRUE;
}
Esempio n. 12
0
static gboolean
rspamd_redis_try_ucl (struct redis_stat_ctx *backend,
		const ucl_object_t *obj,
		struct rspamd_config *cfg,
		const gchar *symbol)
{
	const ucl_object_t *elt, *relt, *users_enabled;
	const gchar *lua_script;

	elt = ucl_object_lookup_any (obj, "read_servers", "servers", NULL);

	if (elt == NULL) {
		return FALSE;
	}

	backend->read_servers = rspamd_upstreams_create (cfg->ups_ctx);
	if (!rspamd_upstreams_from_ucl (backend->read_servers, elt,
			REDIS_DEFAULT_PORT, NULL)) {
		msg_err ("statfile %s cannot get read servers configuration",
				symbol);
		return FALSE;
	}

	relt = elt;

	elt = ucl_object_lookup (obj, "write_servers");
	if (elt == NULL) {
		/* Use read servers as write ones */
		g_assert (relt != NULL);
		backend->write_servers = rspamd_upstreams_create (cfg->ups_ctx);
		if (!rspamd_upstreams_from_ucl (backend->write_servers, relt,
				REDIS_DEFAULT_PORT, NULL)) {
			msg_err ("statfile %s cannot get write servers configuration",
					symbol);
			return FALSE;
		}
	}
	else {
		backend->write_servers = rspamd_upstreams_create (cfg->ups_ctx);
		if (!rspamd_upstreams_from_ucl (backend->write_servers, elt,
				REDIS_DEFAULT_PORT, NULL)) {
			msg_err ("statfile %s cannot get write servers configuration",
					symbol);
			rspamd_upstreams_destroy (backend->write_servers);
			backend->write_servers = NULL;
		}
	}

	elt = ucl_object_lookup (obj, "prefix");
	if (elt == NULL || ucl_object_type (elt) != UCL_STRING) {
		/* Default non-users statistics */
		backend->redis_object = REDIS_DEFAULT_OBJECT;

		/*
		 * Make redis backend compatible with sqlite3 backend in users settings
		 */
		users_enabled = ucl_object_lookup_any (obj, "per_user",
				"users_enabled", NULL);

		if (users_enabled != NULL) {
			if (ucl_object_type (users_enabled) == UCL_BOOLEAN) {
				backend->enable_users = ucl_object_toboolean (users_enabled);
				backend->cbref_user = -1;

				if (backend->enable_users) {
					backend->redis_object = REDIS_DEFAULT_USERS_OBJECT;
				}
			}
			else if (ucl_object_type (users_enabled) == UCL_STRING) {
				lua_script = ucl_object_tostring (users_enabled);

				if (luaL_dostring (cfg->lua_state, lua_script) != 0) {
					msg_err_config ("cannot execute lua script for users "
							"extraction: %s", lua_tostring (cfg->lua_state, -1));
				}
				else {
					if (lua_type (cfg->lua_state, -1) == LUA_TFUNCTION) {
						backend->enable_users = TRUE;
						backend->cbref_user = luaL_ref (cfg->lua_state,
								LUA_REGISTRYINDEX);
					}
					else {
						msg_err_config ("lua script must return "
								"function(task) and not %s",
								lua_typename (cfg->lua_state, lua_type (
										cfg->lua_state, -1)));
					}
				}
			}
		}
		else {
			backend->enable_users = FALSE;
		}
	}
	else {
		/* XXX: sanity check */
		backend->redis_object = ucl_object_tostring (elt);
	}

	elt = ucl_object_lookup (obj, "timeout");
	if (elt) {
		backend->timeout = ucl_object_todouble (elt);
	}
	else {
		backend->timeout = REDIS_DEFAULT_TIMEOUT;
	}

	elt = ucl_object_lookup (obj, "password");
	if (elt) {
		backend->password = ucl_object_tostring (elt);
	}
	else {
		backend->password = NULL;
	}

	elt = ucl_object_lookup_any (obj, "db", "database", "dbname", NULL);
	if (elt) {
		backend->dbname = ucl_object_tostring (elt);
	}
	else {
		backend->dbname = NULL;
	}

	return TRUE;
}
Esempio n. 13
0
gint
regexp_module_config (struct rspamd_config *cfg)
{
	struct regexp_module_item *cur_item;
	const ucl_object_t *sec, *value, *elt;
	ucl_object_iter_t it = NULL;
	gint res = TRUE, id;

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

	sec = ucl_object_find_key (cfg->rcl_obj, "regexp");
	if (sec == NULL) {
		msg_err_config ("regexp module enabled, but no rules are defined");
		return TRUE;
	}

	regexp_module_ctx->max_size = 0;

	while ((value = ucl_iterate_object (sec, &it, true)) != NULL) {
		if (g_ascii_strncasecmp (ucl_object_key (value), "max_size",
			sizeof ("max_size") - 1) == 0) {
			regexp_module_ctx->max_size = ucl_obj_toint (value);
			rspamd_mime_expression_set_re_limit (regexp_module_ctx->max_size);
		}
		else if (g_ascii_strncasecmp (ucl_object_key (value), "max_threads",
			sizeof ("max_threads") - 1) == 0) {
			msg_warn_config ("regexp module is now single threaded, max_threads is ignored");
		}
		else if (value->type == UCL_STRING) {
			cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool,
					sizeof (struct regexp_module_item));
			cur_item->symbol = ucl_object_key (value);
			if (!read_regexp_expression (regexp_module_ctx->regexp_pool,
				cur_item, ucl_object_key (value),
				ucl_obj_tostring (value), cfg)) {
				res = FALSE;
			}
			else {
				rspamd_symbols_cache_add_symbol (cfg->cache,
						cur_item->symbol,
						0,
						process_regexp_item,
						cur_item,
						SYMBOL_TYPE_NORMAL, -1);
			}
		}
		else if (value->type == UCL_USERDATA) {
			/* Just a lua function */
			cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool,
					sizeof (struct regexp_module_item));
			cur_item->symbol = ucl_object_key (value);
			cur_item->lua_function = ucl_object_toclosure (value);
			rspamd_symbols_cache_add_symbol (cfg->cache,
				cur_item->symbol,
				0,
				process_regexp_item,
				cur_item,
				SYMBOL_TYPE_NORMAL, -1);
		}
		else if (value->type == UCL_OBJECT) {
			const gchar *description = NULL, *group = NULL,
					*metric = DEFAULT_METRIC;
			gdouble score = 0.0;
			gboolean one_shot = FALSE, is_lua = FALSE, valid_expression = TRUE;

			/* We have some lua table, extract its arguments */
			elt = ucl_object_find_key (value, "callback");

			if (elt == NULL || elt->type != UCL_USERDATA) {

				/* Try plain regexp expression */
				elt = ucl_object_find_any_key (value, "regexp", "re", NULL);

				if (elt != NULL && ucl_object_type (elt) == UCL_STRING) {
					cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool,
							sizeof (struct regexp_module_item));
					cur_item->symbol = ucl_object_key (value);
					if (!read_regexp_expression (regexp_module_ctx->regexp_pool,
							cur_item, ucl_object_key (value),
							ucl_obj_tostring (elt), cfg)) {
						res = FALSE;
					}
					else {
						valid_expression = TRUE;
					}
				}
				else {
					msg_err_config (
							"no callback/expression defined for regexp symbol: "
									"%s", ucl_object_key (value));
				}
			}
			else {
				is_lua = TRUE;
				cur_item = rspamd_mempool_alloc0 (
						regexp_module_ctx->regexp_pool,
						sizeof (struct regexp_module_item));
				cur_item->symbol = ucl_object_key (value);
				cur_item->lua_function = ucl_object_toclosure (value);
			}

			if (cur_item && (is_lua || valid_expression)) {
				id = rspamd_symbols_cache_add_symbol (cfg->cache,
						cur_item->symbol,
						0,
						process_regexp_item,
						cur_item,
						SYMBOL_TYPE_NORMAL, -1);

				elt = ucl_object_find_key (value, "condition");

				if (elt != NULL && ucl_object_type (elt) == UCL_USERDATA) {
					struct ucl_lua_funcdata *conddata;

					conddata = ucl_object_toclosure (elt);
					rspamd_symbols_cache_add_condition (cfg->cache, id,
							conddata->L, conddata->idx);
				}

				elt = ucl_object_find_key (value, "metric");

				if (elt) {
					metric = ucl_object_tostring (elt);
				}

				elt = ucl_object_find_key (value, "description");

				if (elt) {
					description = ucl_object_tostring (elt);
				}

				elt = ucl_object_find_key (value, "group");

				if (elt) {
					group = ucl_object_tostring (elt);
				}

				elt = ucl_object_find_key (value, "score");

				if (elt) {
					score = ucl_object_todouble (elt);
				}

				elt = ucl_object_find_key (value, "one_shot");

				if (elt) {
					one_shot = ucl_object_toboolean (elt);
				}

				rspamd_config_add_metric_symbol (cfg, metric, cur_item->symbol,
						score, description, group, one_shot, FALSE);
			}
		}
		else {
			msg_warn_config ("unknown type of attribute %s for regexp module",
				ucl_object_key (value));
		}
	}

	return res;
}
Esempio n. 14
0
static struct rspamd_osb_tokenizer_config *
rspamd_tokenizer_osb_config_from_ucl (rspamd_mempool_t * pool,
		const ucl_object_t *obj)
{
	const ucl_object_t *elt;
	struct rspamd_osb_tokenizer_config *cf, *def;
	guchar *key = NULL;
	gsize keylen;


	if (pool != NULL) {
		cf = rspamd_mempool_alloc0 (pool, sizeof (*cf));
	}
	else {
		cf = g_malloc0 (sizeof (*cf));
	}

	/* Use default config */
	def = rspamd_tokenizer_osb_default_config ();
	memcpy (cf, def, sizeof (*cf));

	elt = ucl_object_lookup (obj, "hash");
	if (elt != NULL && ucl_object_type (elt) == UCL_STRING) {
		if (g_ascii_strncasecmp (ucl_object_tostring (elt), "xxh", 3)
				== 0) {
			cf->ht = RSPAMD_OSB_HASH_XXHASH;
			elt = ucl_object_lookup (obj, "seed");
			if (elt != NULL && ucl_object_type (elt) == UCL_INT) {
				cf->seed = ucl_object_toint (elt);
			}
		}
		else if (g_ascii_strncasecmp (ucl_object_tostring (elt), "sip", 3)
				== 0) {
			cf->ht = RSPAMD_OSB_HASH_SIPHASH;
			elt = ucl_object_lookup (obj, "key");

			if (elt != NULL && ucl_object_type (elt) == UCL_STRING) {
				key = rspamd_decode_base32 (ucl_object_tostring (elt),
						0, &keylen);
				if (keylen < sizeof (rspamd_sipkey_t)) {
					msg_warn ("siphash key is too short: %z", keylen);
					g_free (key);
				}
				else {
					memcpy (cf->sk, key, sizeof (cf->sk));
					g_free (key);
				}
			}
			else {
				msg_warn_pool ("siphash cannot be used without key");
			}

		}
	}
	else {
		elt = ucl_object_lookup (obj, "compat");
		if (elt != NULL && ucl_object_toboolean (elt)) {
			cf->ht = RSPAMD_OSB_HASH_COMPAT;
		}
	}

	elt = ucl_object_lookup (obj, "window");
	if (elt != NULL && ucl_object_type (elt) == UCL_INT) {
		cf->window_size = ucl_object_toint (elt);
		if (cf->window_size > DEFAULT_FEATURE_WINDOW_SIZE * 4) {
			msg_err_pool ("too large window size: %d", cf->window_size);
			cf->window_size = DEFAULT_FEATURE_WINDOW_SIZE;
		}
	}

	return cf;
}
Esempio n. 15
0
void
json_config_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data)
{
	struct config_json_buf *jb;
	ucl_object_t *top;
	struct ucl_parser *parser;

	if (data->prev_data) {
		jb = data->prev_data;
		/* Clean prev data */
		if (jb->buf) {
			g_free (jb->buf);
		}
		g_free (jb);
	}

	/* Now parse json */
	if (data->cur_data) {
		jb = data->cur_data;
	}
	else {
		msg_err ("no data read");
		return;
	}
	if (jb->buf == NULL) {
		msg_err ("no data read");
		return;
	}
	/* NULL terminate current buf */
	*jb->pos = '\0';

	parser = ucl_parser_new (0);
	if (!ucl_parser_add_chunk (parser, jb->buf, jb->pos - jb->buf)) {
		msg_err ("cannot load json data: parse error %s",
				ucl_parser_get_error (parser));
		ucl_parser_free (parser);
		return;
	}

	top = ucl_parser_get_object (parser);
	ucl_parser_free (parser);

	if (ucl_object_type (top) != UCL_ARRAY) {
		ucl_object_unref (top);
		msg_err ("loaded json is not an array");
		return;
	}

	jb->cfg->current_dynamic_conf = NULL;
	ucl_object_unref (jb->obj);
	jb->obj = top;

	/*
	 * Note about thread safety: we are updating values that are gdoubles so it is not atomic in general case
	 * but on the other hand all that data is used only in the main thread, so why it is *likely* safe
	 * to do this task in this way without explicit lock.
	 */
	apply_dynamic_conf (jb->obj, jb->cfg);

	jb->cfg->current_dynamic_conf = jb->obj;
}
Esempio n. 16
0
static gboolean
rspamd_symbols_cache_load_items (struct symbols_cache *cache, const gchar *name)
{
	struct rspamd_symbols_cache_header *hdr;
	struct stat st;
	struct ucl_parser *parser;
	ucl_object_t *top;
	const ucl_object_t *cur, *elt;
	ucl_object_iter_t it;
	struct cache_item *item, *parent;
	const guchar *p;
	gint fd;
	gpointer map;
	double w;

	fd = open (name, O_RDONLY);

	if (fd == -1) {
		msg_info ("cannot open file %s, error %d, %s", name,
			errno, strerror (errno));
		return FALSE;
	}

	if (fstat (fd, &st) == -1) {
		close (fd);
		msg_info ("cannot stat file %s, error %d, %s", name,
				errno, strerror (errno));
		return FALSE;
	}

	if (st.st_size < (gint)sizeof (*hdr)) {
		close (fd);
		errno = EINVAL;
		msg_info ("cannot use file %s, error %d, %s", name,
				errno, strerror (errno));
		return FALSE;
	}

	map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);

	if (map == MAP_FAILED) {
		close (fd);
		msg_info ("cannot mmap file %s, error %d, %s", name,
				errno, strerror (errno));
		return FALSE;
	}

	close (fd);
	hdr = map;

	if (memcmp (hdr->magic, rspamd_symbols_cache_magic,
			sizeof (rspamd_symbols_cache_magic)) != 0) {
		msg_info ("cannot use file %s, bad magic", name);
		munmap (map, st.st_size);
		return FALSE;
	}

	parser = ucl_parser_new (0);
	p = (const guchar *)(hdr + 1);

	if (!ucl_parser_add_chunk (parser, p, st.st_size - sizeof (*hdr))) {
		msg_info ("cannot use file %s, cannot parse: %s", name,
				ucl_parser_get_error (parser));
		munmap (map, st.st_size);
		ucl_parser_free (parser);
		return FALSE;
	}

	top = ucl_parser_get_object (parser);
	munmap (map, st.st_size);
	ucl_parser_free (parser);

	if (top == NULL || ucl_object_type (top) != UCL_OBJECT) {
		msg_info ("cannot use file %s, bad object", name);
		ucl_object_unref (top);
		return FALSE;
	}

	it = ucl_object_iterate_new (top);

	while ((cur = ucl_object_iterate_safe (it, true))) {
		item = g_hash_table_lookup (cache->items_by_symbol, ucl_object_key (cur));

		if (item) {
			/* Copy saved info */
			elt = ucl_object_find_key (cur, "weight");

			if (elt) {
				w = ucl_object_todouble (elt);
				if (w != 0) {
					item->weight = w;
				}
			}

			elt = ucl_object_find_key (cur, "time");
			if (elt) {
				item->avg_time = ucl_object_todouble (elt);
			}

			elt = ucl_object_find_key (cur, "count");
			if (elt) {
				item->avg_counter = ucl_object_toint (elt);
			}

			elt = ucl_object_find_key (cur, "frequency");
			if (elt) {
				item->frequency = ucl_object_toint (elt);
			}

			if (item->type == SYMBOL_TYPE_VIRTUAL && item->parent != -1) {
				g_assert (item->parent < (gint)cache->items_by_id->len);
				parent = g_ptr_array_index (cache->items_by_id, item->parent);

				if (parent->weight < item->weight) {
					parent->weight = item->weight;
				}

				/*
				 * We maintain avg_time for virtual symbols equal to the
				 * parent item avg_time
				 */
				parent->avg_time = item->avg_time;
				parent->avg_counter = item->avg_counter;
			}

			if (fabs (item->weight) > cache->max_weight) {
				cache->max_weight = fabs (item->weight);
			}

			cache->total_freq += item->frequency;
		}
	}

	ucl_object_iterate_free (it);
	ucl_object_unref (top);

	return TRUE;
}
Esempio n. 17
0
struct rspamd_map*
rspamd_map_add_from_ucl (struct rspamd_config *cfg,
	const ucl_object_t *obj,
	const gchar *description,
	map_cb_t read_callback,
	map_fin_cb_t fin_callback,
	void **user_data)
{
	ucl_object_iter_t it = NULL;
	const ucl_object_t *cur, *elt;
	struct rspamd_map *map;
	struct rspamd_map_backend *bk;

	g_assert (obj != NULL);

	if (ucl_object_type (obj) == UCL_STRING) {
		/* Just a plain string */
		return rspamd_map_add (cfg, ucl_object_tostring (obj), NULL,
				read_callback, fin_callback, user_data);
	}

	map = g_slice_alloc0 (sizeof (struct rspamd_map));
	map->read_callback = read_callback;
	map->fin_callback = fin_callback;
	map->user_data = user_data;
	map->cfg = cfg;
	map->id = g_random_int ();
	map->locked =
			rspamd_mempool_alloc0_shared (cfg->cfg_pool, sizeof (gint));
	map->cache =
				rspamd_mempool_alloc0_shared (cfg->cfg_pool, sizeof (*map->cache));
	map->backends = g_ptr_array_new ();
	map->poll_timeout = cfg->map_timeout;

	if (description) {
		map->description = g_strdup (description);
	}

	if (ucl_object_type (obj) == UCL_ARRAY) {
		/* Add array of maps as multiple backends */
		while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
			if (ucl_object_type (cur) == UCL_STRING) {
				bk = rspamd_map_parse_backend (cfg, ucl_object_tostring (cur));

				if (bk != NULL) {
					g_ptr_array_add (map->backends, bk);

					if (!map->name) {
						map->name = g_strdup (ucl_object_tostring (cur));
					}
				}
			}
			else {
				msg_err_config ("bad map element type: %s",
						ucl_object_type_to_string (ucl_object_type (cur)));
			}
		}

		if (map->backends->len == 0) {
			msg_err_config ("map has no urls to be loaded");
			goto err;
		}
	}
	else if (ucl_object_type (obj) == UCL_OBJECT) {
		elt = ucl_object_lookup (obj, "name");
		if (elt && ucl_object_type (elt) == UCL_STRING) {
			map->name = g_strdup (ucl_object_tostring (elt));
		}

		elt = ucl_object_lookup (obj, "description");
		if (elt && ucl_object_type (elt) == UCL_STRING) {
			if (map->description) {
				g_free (map->description);
			}

			map->description = g_strdup (ucl_object_tostring (elt));
		}

		elt = ucl_object_lookup_any (obj, "timeout", "poll", "poll_time",
				"watch_interval", NULL);
		if (elt) {
			map->poll_timeout = ucl_object_todouble (elt);
		}

		elt = ucl_object_lookup_any (obj, "upstreams", "url", "urls", NULL);
		if (elt == NULL) {
			msg_err_config ("map has no urls to be loaded");
			goto err;
		}

		if (ucl_object_type (obj) == UCL_ARRAY) {
			/* Add array of maps as multiple backends */
			while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
				if (ucl_object_type (cur) == UCL_STRING) {
					bk = rspamd_map_parse_backend (cfg, ucl_object_tostring (cur));

					if (bk != NULL) {
						g_ptr_array_add (map->backends, bk);

						if (!map->name) {
							map->name = g_strdup (ucl_object_tostring (cur));
						}
					}
				}
				else {
					msg_err_config ("bad map element type: %s",
							ucl_object_type_to_string (ucl_object_type (cur)));
					goto err;
				}
			}

			if (map->backends->len == 0) {
				msg_err_config ("map has no urls to be loaded");
				goto err;
			}
		}
		else if (ucl_object_type (elt) == UCL_STRING) {
			bk = rspamd_map_parse_backend (cfg, ucl_object_tostring (elt));

			if (bk != NULL) {
				g_ptr_array_add (map->backends, bk);

				if (!map->name) {
					map->name = g_strdup (ucl_object_tostring (cur));
				}
			}
		}

		if (map->backends->len == 0) {
			msg_err_config ("map has no urls to be loaded");
			goto err;
		}
	}

	rspamd_map_calculate_hash (map);
	msg_info_map ("added map from ucl");

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

	return map;

err:
	g_ptr_array_free (map->backends, TRUE);
	g_free (map->name);
	g_free (map->description);
	g_slice_free1 (sizeof (*map), map);

	return NULL;
}
Esempio n. 18
0
/**
 * Apply configuration to the specified configuration
 * @param conf_metrics
 * @param cfg
 */
static void
apply_dynamic_conf (const ucl_object_t *top, struct rspamd_config *cfg)
{
	gint test_act;
	const ucl_object_t *cur_elt, *cur_nm, *it_val;
	ucl_object_iter_t it = NULL;
	struct metric *real_metric;
	struct metric_action *cur_action;
	struct rspamd_symbol_def *s;

	while ((cur_elt = ucl_iterate_object (top, &it, true))) {
		if (ucl_object_type (cur_elt) != UCL_OBJECT) {
			msg_err ("loaded json array element is not an object");
			continue;
		}

		cur_nm = ucl_object_find_key (cur_elt, "metric");
		if (!cur_nm || ucl_object_type (cur_nm) != UCL_STRING) {
			msg_err (
					"loaded json metric object element has no 'metric' attribute");
			continue;
		}
		real_metric = g_hash_table_lookup (cfg->metrics,
							ucl_object_tostring (cur_nm));
		if (real_metric == NULL) {
			msg_warn ("cannot find metric %s", ucl_object_tostring (cur_nm));
			continue;
		}

		cur_nm = ucl_object_find_key (cur_elt, "symbols");
		/* Parse symbols */
		if (cur_nm && ucl_object_type (cur_nm) == UCL_ARRAY) {
			ucl_object_iter_t nit = NULL;

			while ((it_val = ucl_iterate_object (cur_nm, &nit, true))) {
				if (ucl_object_find_key (it_val, "name") &&
						ucl_object_find_key (it_val, "value")) {
					const ucl_object_t *n =
							ucl_object_find_key (it_val, "name");
					const ucl_object_t *v =
							ucl_object_find_key (it_val, "value");

					if((s = g_hash_table_lookup (real_metric->symbols,
							ucl_object_tostring (n))) != NULL) {
						*s->weight_ptr = ucl_object_todouble (v);
					}
				}
				else {
					msg_info (
							"json symbol object has no mandatory 'name' and 'value' attributes");
				}
			}
		}
		else {
			ucl_object_t *arr;

			arr = ucl_object_typed_new (UCL_ARRAY);
			ucl_object_insert_key ((ucl_object_t *)cur_elt, arr, "symbols",
					sizeof ("symbols") - 1, false);
		}
		cur_nm = ucl_object_find_key (cur_elt, "actions");
		/* Parse actions */
		if (cur_nm && ucl_object_type (cur_nm) == UCL_ARRAY) {
			ucl_object_iter_t nit = NULL;

			while ((it_val = ucl_iterate_object (cur_nm, &nit, true))) {
				if (ucl_object_find_key (it_val, "name") &&
						ucl_object_find_key (it_val, "value")) {
					if (!rspamd_action_from_str (ucl_object_tostring (
							ucl_object_find_key (it_val, "name")), &test_act)) {
						msg_err ("unknown action: %s",
								ucl_object_tostring (ucl_object_find_key (it_val,
										"name")));
						continue;
					}
					cur_action = &real_metric->actions[test_act];
					cur_action->action = test_act;
					cur_action->score =
							ucl_object_todouble (ucl_object_find_key (it_val,
									"value"));
				}
				else {
					msg_info (
							"json action object has no mandatory 'name' and 'value' attributes");
				}
			}
		}
		else {
			ucl_object_t *arr;

			arr = ucl_object_typed_new (UCL_ARRAY);
			ucl_object_insert_key ((ucl_object_t *)cur_elt, arr, "actions",
					sizeof ("actions") - 1, false);
		}
	}
}
Esempio n. 19
0
static gboolean
rspamd_fuzzy_backend_redis_try_ucl (struct rspamd_fuzzy_backend_redis *backend,
		const ucl_object_t *obj,
		struct rspamd_config *cfg)
{
	const ucl_object_t *elt, *relt;

	elt = ucl_object_lookup_any (obj, "read_servers", "servers", NULL);

	if (elt == NULL) {
		return FALSE;
	}

	backend->read_servers = rspamd_upstreams_create (cfg->ups_ctx);
	if (!rspamd_upstreams_from_ucl (backend->read_servers, elt,
			REDIS_DEFAULT_PORT, NULL)) {
		msg_err_config ("cannot get read servers configuration");
		return FALSE;
	}

	relt = elt;

	elt = ucl_object_lookup (obj, "write_servers");
	if (elt == NULL) {
		/* Use read servers as write ones */
		g_assert (relt != NULL);
		backend->write_servers = rspamd_upstreams_create (cfg->ups_ctx);
		if (!rspamd_upstreams_from_ucl (backend->write_servers, relt,
				REDIS_DEFAULT_PORT, NULL)) {
			msg_err_config ("cannot get write servers configuration");
			return FALSE;
		}
	}
	else {
		backend->write_servers = rspamd_upstreams_create (cfg->ups_ctx);
		if (!rspamd_upstreams_from_ucl (backend->write_servers, elt,
				REDIS_DEFAULT_PORT, NULL)) {
			msg_err_config ("cannot get write servers configuration");
			rspamd_upstreams_destroy (backend->write_servers);
			backend->write_servers = NULL;
		}
	}

	elt = ucl_object_lookup (obj, "prefix");
	if (elt == NULL || ucl_object_type (elt) != UCL_STRING) {
		backend->redis_object = REDIS_DEFAULT_OBJECT;
	}
	else {
		backend->redis_object = ucl_object_tostring (elt);
	}

	elt = ucl_object_lookup (obj, "timeout");
	if (elt) {
		backend->timeout = ucl_object_todouble (elt);
	}
	else {
		backend->timeout = REDIS_DEFAULT_TIMEOUT;
	}

	elt = ucl_object_lookup (obj, "password");
	if (elt) {
		backend->password = ucl_object_tostring (elt);
	}
	else {
		backend->password = NULL;
	}

	elt = ucl_object_lookup_any (obj, "db", "database", "dbname", NULL);
	if (elt) {
		backend->dbname = ucl_object_tostring (elt);
	}
	else {
		backend->dbname = NULL;
	}

	return TRUE;
}
Esempio n. 20
0
int
main (int argc, char **argv)
{
	ucl_object_t *obj, *cur, *ar, *ar1, *ref, *test_obj, *comments;
	ucl_object_iter_t it;
	const ucl_object_t *found, *it_obj, *test;
	struct ucl_emitter_functions *fn;
	FILE *out;
	unsigned char *emitted;
	const char *fname_out = NULL;
	struct ucl_parser *parser;
	int ret = 0;

	switch (argc) {
	case 2:
		fname_out = argv[1];
		break;
	}


	if (fname_out != NULL) {
		out = fopen (fname_out, "w");
		if (out == NULL) {
			exit (-errno);
		}
	}
	else {
		out = stdout;
	}

	obj = ucl_object_typed_new (UCL_OBJECT);

	/* Keys replacing */
	cur = ucl_object_fromstring_common ("value1", 0, UCL_STRING_TRIM);
	ucl_object_insert_key (obj, cur, "key0", 0, false);
	cur = ucl_object_fromdouble (0.1);
	assert (ucl_object_replace_key (obj, cur, "key0", 0, false));

	/* Create some strings */
	cur = ucl_object_fromstring_common ("  test string    ", 0, UCL_STRING_TRIM);
	ucl_object_insert_key (obj, cur, "key1", 0, false);
	cur = ucl_object_fromstring_common ("  test \nstring\n\r\n\b\t\f\\\"    ", 0,
			UCL_STRING_TRIM | UCL_STRING_ESCAPE);
	ucl_object_insert_key (obj, cur, "key2", 0, false);
	cur = ucl_object_fromstring_common ("  test string    \n", 0, 0);
	ucl_object_insert_key (obj, cur, "key3", 0, false);
	/* Array of numbers */
	ar = ucl_object_typed_new (UCL_ARRAY);
	cur = ucl_object_fromint (10);
	ucl_array_append (ar, cur);
	assert (ucl_array_index_of (ar, cur) == 0);
	cur = ucl_object_fromdouble (10.1);
	ucl_array_append (ar, cur);
	assert (ucl_array_index_of (ar, cur) == 1);
	cur = ucl_object_fromdouble (9.999);
	ucl_array_prepend (ar, cur);
	assert (ucl_array_index_of (ar, cur) == 0);

	ar1 = ucl_object_copy (ar);
	cur = ucl_object_fromstring ("abc");
	ucl_array_prepend (ar1, cur);
	cur = ucl_object_fromstring ("cde");
	ucl_array_prepend (ar1, cur);
	cur = ucl_object_fromstring ("аАаБаВ"); /* UTF8 */
	ucl_array_prepend (ar1, cur);
	cur = ucl_object_fromstring ("а•аБаВ"); /* UTF8 */
	ucl_array_prepend (ar1, cur);
/*
 * This is ususally broken or fragile as utf collate is far from perfect
	cur = ucl_object_fromstring ("б‘аБаВ");
	ucl_array_prepend (ar1, cur);
	cur = ucl_object_fromstring ("ааБаВ"); // hello to @bapt
	ucl_array_prepend (ar1, cur);
*/
	cur = ucl_object_fromstring ("№Ÿ˜Ž"); /* everybody likes emoji in the code */
	ucl_array_prepend (ar1, cur);

	ucl_object_array_sort (ar1, ucl_object_compare_qsort);

	/* Removing from an array */
	cur = ucl_object_fromdouble (1.0);
	ucl_array_append (ar, cur);
	cur = ucl_array_delete (ar, cur);
	assert (ucl_object_todouble (cur) == 1.0);
	ucl_object_unref (cur);
	cur = ucl_object_fromdouble (2.0);
	ucl_array_append (ar, cur);
	cur = ucl_array_pop_last (ar);
	assert (ucl_object_todouble (cur) == 2.0);
	ucl_object_unref (cur);
	cur = ucl_object_fromdouble (3.0);
	ucl_array_prepend (ar, cur);
	cur = ucl_array_pop_first (ar);
	assert (ucl_object_todouble (cur) == 3.0);
	ucl_object_unref (cur);

	ucl_object_insert_key (obj, ar, "key4", 0, false);
	cur = ucl_object_frombool (true);
	/* Ref object to test refcounts */
	ref = ucl_object_ref (cur);
	ucl_object_insert_key (obj, cur, "key4", 0, false);
	/* Empty strings */
	cur = ucl_object_fromstring_common ("      ", 0, UCL_STRING_TRIM);
	ucl_object_insert_key (obj, cur, "key5", 0, false);
	cur = ucl_object_fromstring_common ("", 0, UCL_STRING_ESCAPE);
	ucl_object_insert_key (obj, cur, "key6", 0, false);
	cur = ucl_object_fromstring_common ("   \n", 0, UCL_STRING_ESCAPE);
	ucl_object_insert_key (obj, cur, "key7", 0, false);
	/* Numbers and booleans */
	cur = ucl_object_fromstring_common ("1mb", 0, UCL_STRING_ESCAPE | UCL_STRING_PARSE);
	ucl_object_insert_key (obj, cur, "key8", 0, false);
	cur = ucl_object_fromstring_common ("3.14", 0, UCL_STRING_PARSE);
	ucl_object_insert_key (obj, cur, "key9", 0, false);
	cur = ucl_object_fromstring_common ("true", 0, UCL_STRING_PARSE);
	ucl_object_insert_key (obj, cur, "key10", 0, false);
	cur = ucl_object_fromstring_common ("  off  ", 0, UCL_STRING_PARSE | UCL_STRING_TRIM);
	ucl_object_insert_key (obj, cur, "key11", 0, false);
	cur = ucl_object_fromstring_common ("*****@*****.**", 0, UCL_STRING_PARSE_INT);
	ucl_object_insert_key (obj, cur, "key12", 0, false);
	cur = ucl_object_fromstring_common ("#test", 0, UCL_STRING_PARSE_INT);
	ucl_object_insert_key (obj, cur, "key13", 0, false);
	cur = ucl_object_frombool (true);
	ucl_object_insert_key (obj, cur, "k=3", 0, false);
	ucl_object_insert_key (obj, ar1, "key14", 0, false);
	cur = ucl_object_new_userdata (ud_dtor, ud_emit, NULL);
	ucl_object_insert_key (obj, cur, "key15", 0, false);

	/* More tests for keys */
	cur = ucl_object_fromlstring ("test", 3);
	ucl_object_insert_key (obj, cur, "key16", 0, false);
	test = ucl_object_lookup_any (obj, "key100", "key200", "key300", "key16", NULL);
	assert (test == cur);
	test = ucl_object_lookup_len (obj, "key160", 5);
	assert (test == cur);
	cur = ucl_object_pop_key (obj, "key16");
	assert (test == cur);
	test = ucl_object_pop_key (obj, "key16");
	assert (test == NULL);
	test = ucl_object_lookup_len (obj, "key160", 5);
	assert (test == NULL);
	/* Objects merging tests */
	test_obj = ucl_object_new_full (UCL_OBJECT, 2);
	ucl_object_insert_key (test_obj, cur, "key16", 0, true);
	ucl_object_merge (obj, test_obj, true);
	ucl_object_unref (test_obj);
	/* Array merging test */
	test_obj = ucl_object_new_full (UCL_ARRAY, 3);
	ucl_array_append (test_obj, ucl_object_fromstring ("test"));
	ucl_array_merge (test_obj, ar1, false);
	ucl_object_insert_key (obj, test_obj, "key17", 0, true);
	/* Object deletion */
	cur = ucl_object_fromstring ("test");
	ucl_object_insert_key (obj, cur, "key18", 0, true);
	assert (ucl_object_delete_key (obj, "key18"));
	assert (!ucl_object_delete_key (obj, "key18"));
	cur = ucl_object_fromlstring ("test", 4);
	ucl_object_insert_key (obj, cur, "key18\0\0", 7, true);
	assert (ucl_object_lookup_len (obj, "key18\0\0", 7) == cur);
	assert (ucl_object_lookup (obj, "key18") == NULL);
	assert (ucl_object_lookup_len (obj, "key18\0\1", 7) == NULL);
	assert (ucl_object_delete_keyl (obj, "key18\0\0", 7));

	/* Comments */

	comments = ucl_object_typed_new (UCL_OBJECT);
	found = ucl_object_lookup (obj, "key17");
	test = ucl_object_lookup (obj, "key16");
	ucl_comments_add (comments, found, "# test comment");
	assert (ucl_comments_find (comments, found) != NULL);
	assert (ucl_comments_find (comments, test) == NULL);
	ucl_comments_move (comments, found, test);
	assert (ucl_comments_find (comments, found) == NULL);
	assert (ucl_comments_find (comments, test) != NULL);

	/* Array replace */
	ar1 = ucl_object_typed_new (UCL_ARRAY);
	cur = ucl_object_fromstring ("test");
	cur = ucl_elt_append (cur, ucl_object_fromstring ("test1"));
	ucl_array_append (ar1, cur);
	test = ucl_array_replace_index (ar1, ucl_object_fromstring ("test2"), 0);
	assert (test == cur);

	/* Try to find using path */
	/* Should exist */
	found = ucl_object_lookup_path (obj, "key4.1");
	assert (found != NULL && ucl_object_toint (found) == 10);
	/* . should be ignored */
	found = ucl_object_lookup_path (obj, ".key4.1");
	assert (found != NULL && ucl_object_toint (found) == 10);
	/* moar dots... */
	found = ucl_object_lookup_path (obj, ".key4........1...");
	assert (found != NULL && ucl_object_toint (found) == 10);
	/* No such index */
	found = ucl_object_lookup_path (obj, ".key4.3");
	assert (found == NULL);
	/* No such key */
	found = ucl_object_lookup_path (obj, "key9..key1");
	assert (found == NULL);

	/* Test iteration */
	it = ucl_object_iterate_new (obj);
	it_obj = ucl_object_iterate_safe (it, true);
	/* key0 = 0.1 */
	assert (ucl_object_type (it_obj) == UCL_FLOAT);
	it_obj = ucl_object_iterate_safe (it, true);
	/* key1 = "" */
	assert (ucl_object_type (it_obj) == UCL_STRING);
	it_obj = ucl_object_iterate_safe (it, true);
	/* key2 = "" */
	assert (ucl_object_type (it_obj) == UCL_STRING);
	it_obj = ucl_object_iterate_safe (it, true);
	/* key3 = "" */
	assert (ucl_object_type (it_obj) == UCL_STRING);
	it_obj = ucl_object_iterate_safe (it, true);
	/* key4 = ([float, int, float], boolean) */
	ucl_object_iterate_reset (it, it_obj);
	it_obj = ucl_object_iterate_safe (it, true);
	assert (ucl_object_type (it_obj) == UCL_FLOAT);
	it_obj = ucl_object_iterate_safe (it, true);
	assert (ucl_object_type (it_obj) == UCL_INT);
	it_obj = ucl_object_iterate_safe (it, true);
	assert (ucl_object_type (it_obj) == UCL_FLOAT);
	it_obj = ucl_object_iterate_safe (it, true);
	assert (ucl_object_type (it_obj) == UCL_BOOLEAN);
	ucl_object_iterate_free (it);

	fn = ucl_object_emit_memory_funcs (&emitted);
	assert (ucl_object_emit_full (obj, UCL_EMIT_CONFIG, fn, comments));
	fprintf (out, "%s\n", emitted);
	ucl_object_emit_funcs_free (fn);
	ucl_object_unref (obj);
	ucl_object_unref (comments);

	parser = ucl_parser_new (UCL_PARSER_NO_IMPLICIT_ARRAYS);

	if (ucl_parser_add_chunk_full (parser, emitted, strlen (emitted),
			3, UCL_DUPLICATE_ERROR, UCL_PARSE_UCL)) {
		/* Should fail due to duplicate */
		assert (0);
	}
	else {
		assert (ucl_parser_get_error (parser) != NULL);
		ucl_parser_clear_error (parser);
		ucl_parser_free (parser);
		parser = ucl_parser_new (0);
		ucl_parser_add_chunk_full (parser, emitted, strlen (emitted),
					3, UCL_DUPLICATE_MERGE, UCL_PARSE_UCL);
	}

	assert (ucl_parser_get_column (parser) == 0);
	assert (ucl_parser_get_linenum (parser) != 0);
	ucl_parser_clear_error (parser);
	assert (ucl_parser_get_error_code (parser) == 0);
	obj = ucl_parser_get_object (parser);
	ucl_parser_free (parser);
	ucl_object_free (obj);

	if (emitted != NULL) {
		free (emitted);
	}
	fclose (out);

	/* Ref should still be accessible */
	ref->value.iv = 100500;
	ucl_object_unref (ref);

	return ret;
}
Esempio n. 21
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;
}
Esempio n. 22
0
int
merge_mode(char *destination_node, char *data)
{
    ucl_object_t *dst_obj = NULL;
    ucl_object_t *sub_obj = NULL;
    ucl_object_t *old_obj = NULL;
    ucl_object_t *tmp_obj = NULL;
    int success = 0;
    char *dst_frag;

    setparser = ucl_parser_new(UCL_PARSER_KEY_LOWERCASE |
	UCL_PARSER_NO_IMPLICIT_ARRAYS);

    /* Lookup the destination to write to */
    dst_obj = get_parent(destination_node);
    sub_obj = get_object(destination_node);

    if (sub_obj == NULL) {
	fprintf(stderr, "Failed to find destination node: %s\n",
	    destination_node);
	return false;
    }

    if (include_file != NULL) {
	/* get UCL to add from file */
	set_obj = parse_file(setparser, include_file);
    } else if (data == NULL || strcmp(data, "-") == 0) {
	/* get UCL to add from stdin */
	set_obj = parse_input(setparser, stdin);
    } else {
	/* User provided data inline */
	set_obj = parse_string(setparser, data);
    }

    if (debug > 0) {
	char *rt = NULL, *dt = NULL, *st = NULL;
	rt = objtype_as_string(dst_obj);
	dt = objtype_as_string(sub_obj);
	st = objtype_as_string(set_obj);
	fprintf(stderr, "root type: %s, destination type: %s, new type: %s\n",
	    rt, dt, st);
	if (rt != NULL) free(rt);
	if (dt != NULL) free(dt);
	if (st != NULL) free(st);

	fprintf(stderr, "Merging key %s to root: %s\n",
	    ucl_object_key(sub_obj), ucl_object_key(dst_obj));
    }

    dst_frag = strrchr(destination_node, input_sepchar);
    if (dst_frag == NULL) {
	dst_frag = destination_node;
    } else {
	dst_frag++;
    }
    /* Add it to the object here */
    if (sub_obj == dst_obj && *dst_frag != '\0') {
	/* Sub-object does not exist, create a new one */
	success = ucl_object_insert_key(dst_obj, set_obj, dst_frag, 0,
	    true);
    } else if (ucl_object_type(sub_obj) == UCL_ARRAY && ucl_object_type(set_obj) == UCL_ARRAY) {
	if (debug > 0) {
	    fprintf(stderr, "Merging array of size %u with array of size %u\n",
		sub_obj->len, set_obj->len);
	}
	success = ucl_array_merge(sub_obj, set_obj, true);
    } else if (ucl_object_type(sub_obj) == UCL_ARRAY) {
	if (debug > 0) {
	    fprintf(stderr, "Appending object to array of size %u\n",
		sub_obj->len);
	}
	success = ucl_array_append(sub_obj, ucl_object_ref(set_obj));
    } else if (ucl_object_type(sub_obj) == UCL_OBJECT && ucl_object_type(set_obj) == UCL_OBJECT) {
	if (debug > 0) {
	    fprintf(stderr, "Merging object %s with object %s\n",
		ucl_object_key(sub_obj), ucl_object_key(set_obj));
	}
	/* XXX not supported:
	 * success = ucl_object_merge(sub_obj, set_obj, false, true);
	 */
	
	/* Old non-recursive way */
	/*
	success = ucl_object_merge(sub_obj, set_obj, false);
	*/
	success = merge_recursive(sub_obj, set_obj, false);
    } else if (ucl_object_type(sub_obj) != UCL_OBJECT && ucl_object_type(sub_obj) != UCL_ARRAY) {
	/* Create an explicit array */
	if (debug > 0) {
	    fprintf(stderr, "Creating an array and appended the new item\n");
	}
	tmp_obj = ucl_object_typed_new(UCL_ARRAY);
	/*
	 * Reference and Append the original scalar
	 * The additional reference is required because the old object will be
	 * unreferenced as part of the ucl_object_replace_key operation
	 */
	ucl_array_append(tmp_obj, ucl_object_ref(sub_obj));
	/* Reference and Append the new scalar (unref in cleanup()) */
	ucl_array_append(tmp_obj, ucl_object_ref(set_obj));
	/* Replace the old object with the newly created one */
	if (ucl_object_type(dst_obj) == UCL_ARRAY) {
	    old_obj = ucl_array_replace_index(dst_obj, tmp_obj,
		ucl_array_index_of(dst_obj, sub_obj));
	    success = false;
	    if (old_obj != NULL) {
		ucl_object_unref(old_obj);
		success = true;
	    }
	} else {
	    success = ucl_object_replace_key(dst_obj, tmp_obj,
		ucl_object_key(sub_obj), 0, true);
	}
    } else {
	if (debug > 0) {
	    fprintf(stderr, "Merging object into key %s\n",
		ucl_object_key(sub_obj));
	}
	success = ucl_object_insert_key_merged(dst_obj, ucl_object_ref(set_obj),
	    ucl_object_key(sub_obj), 0, true);
    }

    return success;
}