aboutsummaryrefslogtreecommitdiffstats
path: root/src/lua
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rspamd.com>2024-09-05 16:20:46 +0600
committerGitHub <noreply@github.com>2024-09-05 16:20:46 +0600
commit737a2ce03b826f86851d021d628274ab8c8ea7fb (patch)
tree7918e548808c5981fab465726f545a5c6cc9fe49 /src/lua
parentdd47f82a317ad2ed9a9270c9779bf866ff5989fd (diff)
parent40a6ddd69be80e6a4ad8a29053bbfa18d24b3bd8 (diff)
downloadrspamd-737a2ce03b826f86851d021d628274ab8c8ea7fb.tar.gz
rspamd-737a2ce03b826f86851d021d628274ab8c8ea7fb.zip
Merge branch 'master' into vstakhov-utf8-mime
Diffstat (limited to 'src/lua')
-rw-r--r--src/lua/lua_config.c854
-rw-r--r--src/lua/lua_cryptobox.c154
-rw-r--r--src/lua/lua_http.c5
-rw-r--r--src/lua/lua_map.c3
-rw-r--r--src/lua/lua_redis.c23
-rw-r--r--src/lua/lua_rsa.c164
-rw-r--r--src/lua/lua_spf.c7
-rw-r--r--src/lua/lua_task.c1
8 files changed, 555 insertions, 656 deletions
diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c
index f5405f76d..e3f8b2e57 100644
--- a/src/lua/lua_config.c
+++ b/src/lua/lua_config.c
@@ -34,7 +34,11 @@
local function foo(task)
-- do something
end
-rspamd_config:register_symbol('SYMBOL', 1.0, foo)
+rspamd_config:register_symbol{
+ name = 'SYMBOL',
+ score = 1.0,
+ callback = foo
+}
-- Get configuration
local tab = rspamd_config:get_all_opt('module') -- get table for module's options
@@ -1965,210 +1969,454 @@ lua_config_get_symbol_flags(lua_State *L)
return 1;
}
-static int
-lua_config_register_symbol(lua_State *L)
+static bool
+lua_config_register_symbol_from_table(lua_State *L, struct rspamd_config *cfg,
+ const char *name, int tbl_idx, int *id_out)
{
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config(L, 1);
- const char *name = NULL, *type_str = NULL,
- *description = NULL, *group = NULL;
- double weight = 0, score = NAN, parent_float = NAN;
- gboolean one_shot = FALSE;
- int ret = -1, cbref = -1;
- unsigned int type = 0, flags = 0;
- int64_t parent = 0, priority = 0, nshots = 0;
+ unsigned int type = SYMBOL_TYPE_NORMAL, priority = 0;
+ double weight = 1.0, score = NAN;
+ const char *type_str, *group = NULL, *description = NULL;
GArray *allowed_ids = NULL, *forbidden_ids = NULL;
- GError *err = NULL;
- int prev_top = lua_gettop(L);
+ int id, nshots, cb_ref, parent = -1;
+ unsigned int flags = 0;
+ gboolean optional = FALSE;
- if (cfg) {
- if (!rspamd_lua_parse_table_arguments(L, 2, &err,
- RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
- "name=S;weight=N;callback=F;type=S;priority=I;parent=D;"
- "score=D;description=S;group=S;one_shot=B;nshots=I",
- &name, &weight, &cbref, &type_str,
- &priority, &parent_float,
- &score, &description, &group, &one_shot, &nshots)) {
- msg_err_config("bad arguments: %e", err);
- g_error_free(err);
- lua_settop(L, prev_top);
+ /*
+ * Table can have the following attributes:
+ * "callback" - should be a callback function
+ * "weight" - optional weight
+ * "priority" - optional priority
+ * "type" - optional type (normal, virtual, callback)
+ * "flags" - optional flags
+ * -- Metric options
+ * "score" - optional default score (overridden by metric)
+ * "group" - optional default group
+ * "one_shot" - optional one shot mode
+ * "description" - optional description
+ */
+ lua_pushvalue(L, tbl_idx); /* Push table on top of the stack */
- return luaL_error(L, "invalid arguments");
- }
+ if (name == NULL) {
+ /* Try to resolve name */
+ lua_pushstring(L, "name");
+ lua_gettable(L, -2);
- /* Deal with flags and ids */
- lua_pushstring(L, "flags");
- lua_gettable(L, 2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- flags = lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- flags |= lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- }
- lua_pop(L, 1); /* Clean flags */
+ if (lua_type(L, -1) != LUA_TSTRING) {
+ lua_pop(L, 2);
+ luaL_error(L, "name is not specified");
- lua_pushstring(L, "allowed_ids");
- lua_gettable(L, 2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- allowed_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ return false;
}
- else if (lua_type(L, -1) == LUA_TTABLE) {
- allowed_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(allowed_ids, v);
- }
+ else {
+ name = lua_tostring(L, -1);
}
+
lua_pop(L, 1);
+ }
- lua_pushstring(L, "forbidden_ids");
- lua_gettable(L, 2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- forbidden_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ lua_pushstring(L, "callback");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) != LUA_TFUNCTION) {
+ cb_ref = -1;
+ }
+ else {
+ cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ }
+ lua_pop(L, 1);
+
+ /* Optional fields */
+ lua_pushstring(L, "weight");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ weight = lua_tonumber(L, -1);
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "priority");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ priority = lua_tointeger(L, -1);
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "optional");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ optional = lua_toboolean(L, -1);
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "type");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ type_str = lua_tostring(L, -1);
+ }
+ else {
+ type_str = "normal";
+ }
+ lua_pop(L, 1);
+
+ type = lua_parse_symbol_type(type_str);
+
+ if (!name && !(type & SYMBOL_TYPE_CALLBACK)) {
+ luaL_error(L, "no symbol name but type is not callback");
+
+ return false;
+ }
+ else if (!(type & SYMBOL_TYPE_VIRTUAL) && cb_ref == -1) {
+ luaL_error(L, "no callback for symbol %s", name);
+
+ return false;
+ }
+
+ lua_pushstring(L, "parent");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ parent = lua_tointeger(L, -1);
+ }
+ lua_pop(L, 1);
+
+
+ /* Deal with flags and ids */
+ lua_pushstring(L, "flags");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ flags = lua_parse_symbol_flags(lua_tostring(L, -1));
+ }
+ else if (lua_type(L, -1) == LUA_TTABLE) {
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ flags |= lua_parse_symbol_flags(lua_tostring(L, -1));
}
- else if (lua_type(L, -1) == LUA_TTABLE) {
- forbidden_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(forbidden_ids, v);
- }
+ }
+ lua_pop(L, 1); /* Clean flags */
+
+ lua_pushstring(L, "allowed_ids");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ allowed_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ }
+ else if (lua_type(L, -1) == LUA_TTABLE) {
+ allowed_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
+ rspamd_lua_table_size(L, -1));
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ uint32_t v = lua_tointeger(L, -1);
+ g_array_append_val(allowed_ids, v);
}
- lua_pop(L, 1);
+ }
+ lua_pop(L, 1);
- if (nshots == 0) {
- nshots = cfg->default_max_shots;
+ lua_pushstring(L, "forbidden_ids");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ forbidden_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ }
+ else if (lua_type(L, -1) == LUA_TTABLE) {
+ forbidden_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
+ rspamd_lua_table_size(L, -1));
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ uint32_t v = lua_tointeger(L, -1);
+ g_array_append_val(forbidden_ids, v);
}
+ }
+ lua_pop(L, 1);
- type = lua_parse_symbol_type(type_str);
+ id = rspamd_register_symbol_fromlua(L,
+ cfg,
+ name,
+ cb_ref,
+ weight,
+ priority,
+ type | flags,
+ parent,
+ allowed_ids, forbidden_ids,
+ optional);
- if (!name && !(type & SYMBOL_TYPE_CALLBACK)) {
- lua_settop(L, prev_top);
- return luaL_error(L, "no symbol name but type is not callback");
- }
- else if (!(type & SYMBOL_TYPE_VIRTUAL) && cbref == -1) {
- lua_settop(L, prev_top);
- return luaL_error(L, "no callback for symbol %s", name);
- }
+ if (allowed_ids) {
+ g_array_free(allowed_ids, TRUE);
+ }
+
+ if (forbidden_ids) {
+ g_array_free(forbidden_ids, TRUE);
+ }
+
+ if (id != -1) {
+ if (cb_ref != -1) {
+ /* Check for condition */
+ lua_pushstring(L, "condition");
+ lua_gettable(L, -2);
- if (isnan(parent_float)) {
- parent = -1;
+ if (lua_type(L, -1) == LUA_TFUNCTION) {
+ int condref;
+
+ /* Here we pop function from the stack, so no lua_pop is required */
+ condref = luaL_ref(L, LUA_REGISTRYINDEX);
+ g_assert(name != NULL);
+ rspamd_symcache_add_condition_delayed(cfg->cache,
+ name, L, condref);
+ }
+ else {
+ lua_pop(L, 1);
+ }
}
- else {
- parent = parent_float;
+
+ /* Check for augmentations */
+ lua_pushstring(L, "augmentations");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TTABLE) {
+
+ int aug_tbl_idx = lua_gettop(L);
+ for (lua_pushnil(L); lua_next(L, aug_tbl_idx); lua_pop(L, 1)) {
+ rspamd_symcache_add_symbol_augmentation(cfg->cache, id,
+ lua_tostring(L, -1), NULL);
+ }
}
- ret = rspamd_register_symbol_fromlua(L,
- cfg,
- name,
- cbref,
- weight == 0 ? 1.0 : weight,
- priority,
- type | flags,
- parent,
- allowed_ids, forbidden_ids,
- FALSE);
+ lua_pop(L, 1);
+ }
- if (allowed_ids) {
- g_array_free(allowed_ids, TRUE);
+ /*
+ * Now check if a symbol has not been registered in any metric and
+ * insert default value if applicable
+ */
+ struct rspamd_symbol *sym = g_hash_table_lookup(cfg->symbols, name);
+ if (sym == NULL || (sym->flags & RSPAMD_SYMBOL_FLAG_UNSCORED)) {
+ nshots = cfg->default_max_shots;
+
+ lua_pushstring(L, "score");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ score = lua_tonumber(L, -1);
+
+ if (sym) {
+ /* Reset unscored flag */
+ sym->flags &= ~RSPAMD_SYMBOL_FLAG_UNSCORED;
+ }
}
+ lua_pop(L, 1);
- if (forbidden_ids) {
- g_array_free(forbidden_ids, TRUE);
+ lua_pushstring(L, "group");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ group = lua_tostring(L, -1);
}
+ lua_pop(L, 1);
+
+ if (!isnan(score) || group != NULL) {
+ lua_pushstring(L, "description");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ description = lua_tostring(L, -1);
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "one_shot");
+ lua_gettable(L, -2);
- if (ret != -1) {
- if (!isnan(score) || group) {
- if (one_shot) {
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ if (lua_toboolean(L, -1)) {
nshots = 1;
}
+ }
+ lua_pop(L, 1);
- rspamd_config_add_symbol(cfg, name,
- score, description, group, flags,
- 0, nshots);
+ lua_pushstring(L, "one_param");
+ lua_gettable(L, -2);
- lua_pushstring(L, "groups");
- lua_gettable(L, 2);
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ if (lua_toboolean(L, -1)) {
+ flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
+ }
+ }
+ lua_pop(L, 1);
- if (lua_istable(L, -1)) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- if (lua_isstring(L, -1)) {
- rspamd_config_add_symbol_group(cfg, name,
- lua_tostring(L, -1));
- }
- else {
- lua_settop(L, prev_top);
- return luaL_error(L, "invalid groups element");
- }
+ /*
+ * Do not override the existing symbols (using zero priority),
+ * since we are defining default values here
+ */
+ if (!isnan(score)) {
+ rspamd_config_add_symbol(cfg, name, score,
+ description, group, flags, 0, nshots);
+ }
+ else if (group) {
+ /* Add with zero score */
+ rspamd_config_add_symbol(cfg, name, NAN,
+ description, group, flags, 0, nshots);
+ }
+
+ lua_pushstring(L, "groups");
+ lua_gettable(L, -2);
+
+ if (lua_istable(L, -1)) {
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ if (lua_isstring(L, -1)) {
+ rspamd_config_add_symbol_group(cfg, name,
+ lua_tostring(L, -1));
+ }
+ else {
+ lua_pop(L, 2);
+ luaL_error(L, "invalid groups element");
+
+ return false;
}
}
+ }
- lua_pop(L, 1);
+ lua_pop(L, 1);
+ }
+ }
+ else {
+ /* Fill in missing fields from lua definition if they are not set */
+ if (sym->description == NULL) {
+ lua_pushstring(L, "description");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ description = lua_tostring(L, -1);
}
+ lua_pop(L, 1);
- lua_pushstring(L, "augmentations");
- lua_gettable(L, 2);
+ if (description) {
+ sym->description = rspamd_mempool_strdup(cfg->cfg_pool, description);
+ }
+ }
- if (lua_type(L, -1) == LUA_TTABLE) {
- int tbl_idx = lua_gettop(L);
- for (lua_pushnil(L); lua_next(L, tbl_idx); lua_pop(L, 1)) {
- size_t len;
- const char *augmentation = lua_tolstring(L, -1, &len), *eqsign_pos;
+ /* If ungrouped and there is a group defined in lua, change the primary group
+ * Otherwise, add to the list of groups for this symbol. */
+ lua_pushstring(L, "group");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ group = lua_tostring(L, -1);
+ }
+ lua_pop(L, 1);
+ if (group) {
+ if (sym->flags & RSPAMD_SYMBOL_FLAG_UNGROUPED) {
+ /* Unset the "ungrouped" group */
+ sym->gr = NULL;
+ }
+ /* Add the group. If the symbol was ungrouped, this will
+ * clear RSPAMD_SYMBOL_FLAG_UNGROUPED from the flags. */
+ rspamd_config_add_symbol_group(cfg, name, group);
+ }
+ }
- /* Find `=` symbol and use it as a separator */
- eqsign_pos = memchr(augmentation, '=', len);
- if (eqsign_pos != NULL && eqsign_pos + 1 < augmentation + len) {
- rspamd_ftok_t tok;
+ /* Remove table from stack */
+ lua_pop(L, 1);
- tok.begin = augmentation;
- tok.len = eqsign_pos - augmentation;
- char *augentation_name = rspamd_ftokdup(&tok);
+ *id_out = id;
- tok.begin = eqsign_pos + 1;
- tok.len = (augmentation + len) - tok.begin;
+ return true;
+}
- char *augmentation_value = rspamd_ftokdup(&tok);
+/* Legacy symbol registration */
+static bool
+lua_config_register_symbol_legacy(lua_State *L, struct rspamd_config *cfg, int pos, int *id_out)
+{
+ const char *name = NULL, *type_str = NULL,
+ *description = NULL, *group = NULL;
+ double weight = 0, score = NAN, parent_float = NAN;
+ gboolean one_shot = FALSE;
+ int ret, cbref = -1;
+ unsigned int type = 0, flags = 0;
+ int64_t parent = 0, priority = 0, nshots = 0;
- if (!rspamd_symcache_add_symbol_augmentation(cfg->cache, ret,
- augentation_name, augmentation_value)) {
- lua_settop(L, prev_top);
- g_free(augmentation_value);
- g_free(augentation_name);
+ GError *err = NULL;
+ if (!rspamd_lua_parse_table_arguments(L, pos, &err,
+ RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
+ "name=S;weight=N;callback=F;type=S;priority=I;parent=D;"
+ "score=D;description=S;group=S;one_shot=B;nshots=I",
+ &name, &weight, &cbref, &type_str,
+ &priority, &parent_float,
+ &score, &description, &group, &one_shot, &nshots)) {
+ msg_err_config("bad arguments: %e", err);
+ g_error_free(err);
- return luaL_error(L, "unknown or invalid augmentation %s in symbol %s",
- augmentation, name);
- }
+ return false;
+ }
- g_free(augmentation_value);
- g_free(augentation_name);
- }
- else {
- /* Just a value */
- if (!rspamd_symcache_add_symbol_augmentation(cfg->cache, ret,
- augmentation, NULL)) {
- lua_settop(L, prev_top);
+ type = lua_parse_symbol_type(type_str);
- return luaL_error(L, "unknown augmentation %s in symbol %s",
- augmentation, name);
- }
- }
- }
+ if (!name && !(type & SYMBOL_TYPE_CALLBACK)) {
+ luaL_error(L, "no symbol name but type is not callback");
+
+ return false;
+ }
+ else if (!(type & SYMBOL_TYPE_VIRTUAL) && cbref == -1) {
+ luaL_error(L, "no callback for symbol %s", name);
+
+ return false;
+ }
+
+ if (isnan(parent_float)) {
+ parent = -1;
+ }
+ else {
+ parent = parent_float;
+ }
+
+ ret = rspamd_register_symbol_fromlua(L,
+ cfg,
+ name,
+ cbref,
+ weight == 0 ? 1.0 : weight,
+ priority,
+ type | flags,
+ parent,
+ NULL, NULL,
+ FALSE);
+
+ if (ret != -1) {
+ if (!isnan(score) || group) {
+ if (one_shot) {
+ nshots = 1;
+ }
+ if (nshots == 0) {
+ nshots = cfg->default_max_shots;
}
+
+ rspamd_config_add_symbol(cfg, name, score,
+ description, group, flags, 0, nshots);
}
+
+ *id_out = ret;
+
+ return true;
}
- else {
- lua_settop(L, prev_top);
- return luaL_error(L, "invalid arguments");
+ return false;
+}
+
+static int
+lua_config_register_symbol(lua_State *L)
+{
+ LUA_TRACE_POINT;
+ struct rspamd_config *cfg = lua_check_config(L, 1);
+ int id = -1;
+
+ if (lua_type(L, 2) == LUA_TSTRING) {
+ if (lua_config_register_symbol_legacy(L, cfg, 2, &id)) {
+ lua_pushinteger(L, id);
+
+ return 1;
+ }
+ else {
+ return luaL_error(L, "bad arguments");
+ }
}
+ else if (lua_config_register_symbol_from_table(L, cfg, NULL, 2, &id)) {
+ lua_pushinteger(L, id);
- lua_settop(L, prev_top);
- lua_pushinteger(L, ret);
+ return 1;
+ }
- return 1;
+ return 0;
}
static int
@@ -2655,10 +2903,7 @@ lua_config_newindex(lua_State *L)
LUA_TRACE_POINT;
struct rspamd_config *cfg = lua_check_config(L, 1);
const char *name;
- GArray *allowed_ids = NULL, *forbidden_ids = NULL;
- int id, nshots;
- unsigned int flags = 0;
- gboolean optional = FALSE;
+ int id = -1;
name = luaL_checkstring(L, 2);
@@ -2679,291 +2924,14 @@ lua_config_newindex(lua_State *L)
FALSE);
}
else if (lua_type(L, 3) == LUA_TTABLE) {
- unsigned int type = SYMBOL_TYPE_NORMAL, priority = 0;
- int idx;
- double weight = 1.0, score = NAN;
- const char *type_str, *group = NULL, *description = NULL;
-
- /*
- * Table can have the following attributes:
- * "callback" - should be a callback function
- * "weight" - optional weight
- * "priority" - optional priority
- * "type" - optional type (normal, virtual, callback)
- * "flags" - optional flags
- * -- Metric options
- * "score" - optional default score (overridden by metric)
- * "group" - optional default group
- * "one_shot" - optional one shot mode
- * "description" - optional description
- */
- lua_pushvalue(L, 3);
- lua_pushstring(L, "callback");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) != LUA_TFUNCTION) {
- lua_pop(L, 2);
- msg_info_config("cannot find callback definition for %s",
- name);
- return 0;
- }
- idx = luaL_ref(L, LUA_REGISTRYINDEX);
-
- /* Optional fields */
- lua_pushstring(L, "weight");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TNUMBER) {
- weight = lua_tonumber(L, -1);
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "priority");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TNUMBER) {
- priority = lua_tointeger(L, -1);
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "optional");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TBOOLEAN) {
- optional = lua_toboolean(L, -1);
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "type");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TSTRING) {
- type_str = lua_tostring(L, -1);
- type = lua_parse_symbol_type(type_str);
- }
- lua_pop(L, 1);
-
- /* Deal with flags and ids */
- lua_pushstring(L, "flags");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- flags = lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- flags |= lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- }
- lua_pop(L, 1); /* Clean flags */
-
- lua_pushstring(L, "allowed_ids");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- allowed_ids = rspamd_process_id_list(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- allowed_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(allowed_ids, v);
- }
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "forbidden_ids");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- forbidden_ids = rspamd_process_id_list(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- forbidden_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(forbidden_ids, v);
- }
- }
- lua_pop(L, 1);
-
- id = rspamd_register_symbol_fromlua(L,
- cfg,
- name,
- idx,
- weight,
- priority,
- type | flags,
- -1,
- allowed_ids, forbidden_ids,
- optional);
-
- if (allowed_ids) {
- g_array_free(allowed_ids, TRUE);
- }
-
- if (forbidden_ids) {
- g_array_free(forbidden_ids, TRUE);
- }
-
- if (id != -1) {
- /* Check for condition */
- lua_pushstring(L, "condition");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TFUNCTION) {
- int condref;
-
- /* Here we pop function from the stack, so no lua_pop is required */
- condref = luaL_ref(L, LUA_REGISTRYINDEX);
- g_assert(name != NULL);
- rspamd_symcache_add_condition_delayed(cfg->cache,
- name, L, condref);
- }
- else {
- lua_pop(L, 1);
- }
-
- /* Check for augmentations */
- lua_pushstring(L, "augmentations");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TTABLE) {
-
- int tbl_idx = lua_gettop(L);
- for (lua_pushnil(L); lua_next(L, tbl_idx); lua_pop(L, 1)) {
- rspamd_symcache_add_symbol_augmentation(cfg->cache, id,
- lua_tostring(L, -1), NULL);
- }
- }
-
- lua_pop(L, 1);
- }
-
- /*
- * Now check if a symbol has not been registered in any metric and
- * insert default value if applicable
- */
- struct rspamd_symbol *sym = g_hash_table_lookup(cfg->symbols, name);
- if (sym == NULL || (sym->flags & RSPAMD_SYMBOL_FLAG_UNSCORED)) {
- nshots = cfg->default_max_shots;
-
- lua_pushstring(L, "score");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TNUMBER) {
- score = lua_tonumber(L, -1);
-
- if (sym) {
- /* Reset unscored flag */
- sym->flags &= ~RSPAMD_SYMBOL_FLAG_UNSCORED;
- }
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "group");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- group = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
-
- if (!isnan(score) || group != NULL) {
- lua_pushstring(L, "description");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TSTRING) {
- description = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "one_shot");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TBOOLEAN) {
- if (lua_toboolean(L, -1)) {
- nshots = 1;
- }
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "one_param");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TBOOLEAN) {
- if (lua_toboolean(L, -1)) {
- flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
- }
- }
- lua_pop(L, 1);
-
- /*
- * Do not override the existing symbols (using zero priority),
- * since we are defining default values here
- */
- if (!isnan(score)) {
- rspamd_config_add_symbol(cfg, name, score,
- description, group, flags, 0, nshots);
- }
- else if (group) {
- /* Add with zero score */
- rspamd_config_add_symbol(cfg, name, NAN,
- description, group, flags, 0, nshots);
- }
-
- lua_pushstring(L, "groups");
- lua_gettable(L, -2);
-
- if (lua_istable(L, -1)) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- if (lua_isstring(L, -1)) {
- rspamd_config_add_symbol_group(cfg, name,
- lua_tostring(L, -1));
- }
- else {
- return luaL_error(L, "invalid groups element");
- }
- }
- }
-
- lua_pop(L, 1);
- }
- }
- else {
- /* Fill in missing fields from lua definition if they are not set */
- if (sym->description == NULL) {
- lua_pushstring(L, "description");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TSTRING) {
- description = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
-
- if (description) {
- sym->description = rspamd_mempool_strdup(cfg->cfg_pool, description);
- }
- }
-
- /* If ungrouped and there is a group defined in lua, change the primary group
- * Otherwise, add to the list of groups for this symbol. */
- lua_pushstring(L, "group");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- group = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
- if (group) {
- if (sym->flags & RSPAMD_SYMBOL_FLAG_UNGROUPED) {
- /* Unset the "ungrouped" group */
- sym->gr = NULL;
- }
- /* Add the group. If the symbol was ungrouped, this will
- * clear RSPAMD_SYMBOL_FLAG_UNGROUPED from the flags. */
- rspamd_config_add_symbol_group(cfg, name, group);
- }
+ /* Table symbol */
+ if (lua_config_register_symbol_from_table(L, cfg, name, 3, &id)) {
+ lua_pushinteger(L, id);
+ return 1;
}
-
- /* Remove table from stack */
- lua_pop(L, 1);
+ }
+ else {
+ return luaL_error(L, "invalid value for symbol");
}
}
else {
@@ -3941,6 +3909,8 @@ lua_config_get_groups(lua_State *L)
lua_setfield(L, -2, "description");
lua_pushnumber(L, gr->max_score);
lua_setfield(L, -2, "max_score");
+ lua_pushnumber(L, gr->min_score);
+ lua_setfield(L, -2, "min_score");
lua_pushboolean(L, (gr->flags & RSPAMD_SYMBOL_GROUP_PUBLIC) != 0);
lua_setfield(L, -2, "is_public");
/* TODO: maybe push symbols as well */
diff --git a/src/lua/lua_cryptobox.c b/src/lua/lua_cryptobox.c
index bad7d7024..1b9074f58 100644
--- a/src/lua/lua_cryptobox.c
+++ b/src/lua/lua_cryptobox.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -257,7 +257,6 @@ lua_check_cryptobox_secretbox(lua_State *L, int pos)
* Loads public key from base32 encoded file
* @param {string} file filename to load
* @param {string} type optional 'sign' or 'kex' for signing and encryption
- * @param {string} alg optional 'default' or 'nist' for curve25519/nistp256 keys
* @return {cryptobox_pubkey} new public key
*/
static int
@@ -267,7 +266,6 @@ lua_cryptobox_pubkey_load(lua_State *L)
struct rspamd_cryptobox_pubkey *pkey = NULL, **ppkey;
const char *filename, *arg;
int type = RSPAMD_KEYPAIR_SIGN;
- int alg = RSPAMD_CRYPTOBOX_MODE_25519;
unsigned char *map;
gsize len;
@@ -293,19 +291,8 @@ lua_cryptobox_pubkey_load(lua_State *L)
type = RSPAMD_KEYPAIR_KEX;
}
}
- if (lua_type(L, 3) == LUA_TSTRING) {
- /* algorithm */
- arg = lua_tostring(L, 3);
-
- if (strcmp(arg, "default") == 0 || strcmp(arg, "curve25519") == 0) {
- type = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else if (strcmp(arg, "nist") == 0) {
- type = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- }
- pkey = rspamd_pubkey_from_base32(map, len, type, alg);
+ pkey = rspamd_pubkey_from_base32(map, len, type);
if (pkey == NULL) {
msg_err("cannot open pubkey from file: %s", filename);
@@ -333,7 +320,6 @@ lua_cryptobox_pubkey_load(lua_State *L)
* Loads public key from base32 encoded string
* @param {base32 string} base32 string with the key
* @param {string} type optional 'sign' or 'kex' for signing and encryption
- * @param {string} alg optional 'default' or 'nist' for curve25519/nistp256 keys
* @return {cryptobox_pubkey} new public key
*/
static int
@@ -344,7 +330,6 @@ lua_cryptobox_pubkey_create(lua_State *L)
const char *buf, *arg;
gsize len;
int type = RSPAMD_KEYPAIR_SIGN;
- int alg = RSPAMD_CRYPTOBOX_MODE_25519;
buf = luaL_checklstring(L, 1, &len);
if (buf != NULL) {
@@ -359,19 +344,8 @@ lua_cryptobox_pubkey_create(lua_State *L)
type = RSPAMD_KEYPAIR_KEX;
}
}
- if (lua_type(L, 3) == LUA_TSTRING) {
- /* algorithm */
- arg = lua_tostring(L, 3);
-
- if (strcmp(arg, "default") == 0 || strcmp(arg, "curve25519") == 0) {
- type = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else if (strcmp(arg, "nist") == 0) {
- type = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- }
- pkey = rspamd_pubkey_from_base32(buf, len, type, alg);
+ pkey = rspamd_pubkey_from_base32(buf, len, type);
if (pkey == NULL) {
msg_err("cannot load pubkey from string");
@@ -477,7 +451,6 @@ lua_cryptobox_keypair_load(lua_State *L)
* @function rspamd_cryptobox_keypair.create([type='encryption'[, alg='curve25519']])
* Generates new keypair
* @param {string} type type of keypair: 'encryption' (default) or 'sign'
- * @param {string} alg algorithm of keypair: 'curve25519' (default) or 'nist'
* @return {cryptobox_keypair} new keypair
*/
static int
@@ -486,7 +459,6 @@ lua_cryptobox_keypair_create(lua_State *L)
LUA_TRACE_POINT;
struct rspamd_cryptobox_keypair *kp, **pkp;
enum rspamd_cryptobox_keypair_type type = RSPAMD_KEYPAIR_KEX;
- enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
if (lua_isstring(L, 1)) {
const char *str = lua_tostring(L, 1);
@@ -502,21 +474,7 @@ lua_cryptobox_keypair_create(lua_State *L)
}
}
- if (lua_isstring(L, 2)) {
- const char *str = lua_tostring(L, 2);
-
- if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else {
- return luaL_error(L, "invalid keypair algorithm: %s", str);
- }
- }
-
- kp = rspamd_keypair_new(type, alg);
+ kp = rspamd_keypair_new(type);
pkp = lua_newuserdata(L, sizeof(gpointer));
*pkp = kp;
@@ -606,12 +564,7 @@ lua_cryptobox_keypair_get_alg(lua_State *L)
struct rspamd_cryptobox_keypair *kp = lua_check_cryptobox_keypair(L, 1);
if (kp) {
- if (kp->alg == RSPAMD_CRYPTOBOX_MODE_25519) {
- lua_pushstring(L, "curve25519");
- }
- else {
- lua_pushstring(L, "nist");
- }
+ lua_pushstring(L, "curve25519");
}
else {
return luaL_error(L, "invalid arguments");
@@ -636,7 +589,7 @@ lua_cryptobox_keypair_get_pk(lua_State *L)
if (kp) {
data = rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_PK, &dlen);
- pk = rspamd_pubkey_from_bin(data, dlen, kp->type, kp->alg);
+ pk = rspamd_pubkey_from_bin(data, dlen, kp->type);
if (pk == NULL) {
return luaL_error(L, "invalid keypair");
@@ -654,7 +607,7 @@ lua_cryptobox_keypair_get_pk(lua_State *L)
}
/***
- * @function rspamd_cryptobox_signature.load(file, [alg = 'curve25519'])
+ * @function rspamd_cryptobox_signature.load(file)
* Loads signature from raw file
* @param {string} file filename to load
* @return {cryptobox_signature} new signature
@@ -668,7 +621,6 @@ lua_cryptobox_signature_load(lua_State *L)
gpointer data;
int fd;
struct stat st;
- enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
filename = luaL_checkstring(L, 1);
if (filename != NULL) {
@@ -686,22 +638,6 @@ lua_cryptobox_signature_load(lua_State *L)
lua_pushnil(L);
}
else {
- if (lua_isstring(L, 2)) {
- const char *str = lua_tostring(L, 2);
-
- if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else {
- munmap(data, st.st_size);
- close(fd);
-
- return luaL_error(L, "invalid keypair algorithm: %s", str);
- }
- }
if (st.st_size > 0) {
sig = rspamd_fstring_new_init(data, st.st_size);
psig = lua_newuserdata(L, sizeof(rspamd_fstring_t *));
@@ -711,7 +647,7 @@ lua_cryptobox_signature_load(lua_State *L)
else {
msg_err("size of %s mismatches: %d while %d is expected",
filename, (int) st.st_size,
- rspamd_cryptobox_signature_bytes(alg));
+ crypto_sign_bytes());
lua_pushnil(L);
}
@@ -821,7 +757,7 @@ lua_cryptobox_signature_create(lua_State *L)
}
if (data != NULL) {
- if (dlen == rspamd_cryptobox_signature_bytes(RSPAMD_CRYPTOBOX_MODE_25519)) {
+ if (dlen == crypto_sign_bytes()) {
sig = rspamd_fstring_new_init(data, dlen);
psig = lua_newuserdata(L, sizeof(rspamd_fstring_t *));
rspamd_lua_setclass(L, rspamd_cryptobox_signature_classname, -1);
@@ -1723,7 +1659,7 @@ lua_cryptobox_hash_gc(lua_State *L)
}
/***
- * @function rspamd_cryptobox.verify_memory(pk, sig, data, [alg = 'curve25519'])
+ * @function rspamd_cryptobox.verify_memory(pk, sig, data)
* Check memory using specified cryptobox key and signature
* @param {pubkey} pk public key to verify
* @param {sig} signature to check
@@ -1738,7 +1674,6 @@ lua_cryptobox_verify_memory(lua_State *L)
rspamd_fstring_t *signature;
struct rspamd_lua_text *t;
const char *data;
- enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
gsize len;
int ret;
@@ -1759,23 +1694,9 @@ lua_cryptobox_verify_memory(lua_State *L)
data = luaL_checklstring(L, 3, &len);
}
- if (lua_isstring(L, 4)) {
- const char *str = lua_tostring(L, 4);
-
- if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else {
- return luaL_error(L, "invalid algorithm: %s", str);
- }
- }
-
if (pk != NULL && signature != NULL && data != NULL) {
ret = rspamd_cryptobox_verify(signature->str, signature->len, data, len,
- rspamd_pubkey_get_pk(pk, NULL), alg);
+ rspamd_pubkey_get_pk(pk, NULL));
if (ret) {
lua_pushboolean(L, 1);
@@ -1792,7 +1713,7 @@ lua_cryptobox_verify_memory(lua_State *L)
}
/***
- * @function rspamd_cryptobox.verify_file(pk, sig, file, [alg = 'curve25519'])
+ * @function rspamd_cryptobox.verify_file(pk, sig, file)
* Check file using specified cryptobox key and signature
* @param {pubkey} pk public key to verify
* @param {sig} signature to check
@@ -1807,7 +1728,6 @@ lua_cryptobox_verify_file(lua_State *L)
struct rspamd_cryptobox_pubkey *pk;
rspamd_fstring_t *signature;
unsigned char *map = NULL;
- enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519;
gsize len;
int ret;
@@ -1815,26 +1735,12 @@ lua_cryptobox_verify_file(lua_State *L)
signature = lua_check_cryptobox_sign(L, 2);
fname = luaL_checkstring(L, 3);
- if (lua_isstring(L, 4)) {
- const char *str = lua_tostring(L, 4);
-
- if (strcmp(str, "nist") == 0 || strcmp(str, "openssl") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_NIST;
- }
- else if (strcmp(str, "curve25519") == 0 || strcmp(str, "default") == 0) {
- alg = RSPAMD_CRYPTOBOX_MODE_25519;
- }
- else {
- return luaL_error(L, "invalid algorithm: %s", str);
- }
- }
-
map = rspamd_file_xmap(fname, PROT_READ, &len, TRUE);
if (map != NULL && pk != NULL && signature != NULL) {
ret = rspamd_cryptobox_verify(signature->str, signature->len,
map, len,
- rspamd_pubkey_get_pk(pk, NULL), alg);
+ rspamd_pubkey_get_pk(pk, NULL));
if (ret) {
lua_pushboolean(L, 1);
@@ -1896,12 +1802,11 @@ lua_cryptobox_sign_memory(lua_State *L)
return luaL_error(L, "invalid arguments");
}
- sig = rspamd_fstring_sized_new(rspamd_cryptobox_signature_bytes(
- rspamd_keypair_alg(kp)));
+ sig = rspamd_fstring_sized_new(crypto_sign_bytes());
unsigned long long siglen = sig->len;
rspamd_cryptobox_sign(sig->str, &siglen, data,
- len, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL), rspamd_keypair_alg(kp));
+ len, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL));
sig->len = siglen;
psig = lua_newuserdata(L, sizeof(void *));
@@ -1942,13 +1847,12 @@ lua_cryptobox_sign_file(lua_State *L)
lua_pushnil(L);
}
else {
- sig = rspamd_fstring_sized_new(rspamd_cryptobox_signature_bytes(
- rspamd_keypair_alg(kp)));
+ sig = rspamd_fstring_sized_new(crypto_sign_bytes());
unsigned long long siglen = sig->len;
rspamd_cryptobox_sign(sig->str, &siglen, data,
- len, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL), rspamd_keypair_alg(kp));
+ len, rspamd_keypair_component(kp, RSPAMD_KEYPAIR_COMPONENT_SK, NULL));
sig->len = siglen;
psig = lua_newuserdata(L, sizeof(void *));
@@ -1961,7 +1865,7 @@ lua_cryptobox_sign_file(lua_State *L)
}
/***
- * @function rspamd_cryptobox.encrypt_memory(kp, data[, nist=false])
+ * @function rspamd_cryptobox.encrypt_memory(kp, data)
* Encrypt data using specified keypair/pubkey
* @param {keypair|string} kp keypair or pubkey in base32 to use
* @param {string|text} data
@@ -1993,8 +1897,7 @@ lua_cryptobox_encrypt_memory(lua_State *L)
gsize blen;
b32 = lua_tolstring(L, 1, &blen);
- pk = rspamd_pubkey_from_base32(b32, blen, RSPAMD_KEYPAIR_KEX,
- lua_toboolean(L, 3) ? RSPAMD_CRYPTOBOX_MODE_NIST : RSPAMD_CRYPTOBOX_MODE_25519);
+ pk = rspamd_pubkey_from_base32(b32, blen, RSPAMD_KEYPAIR_KEX);
owned_pk = true;
}
@@ -2063,7 +1966,7 @@ err:
}
/***
- * @function rspamd_cryptobox.encrypt_file(kp|pk_string, filename[, nist=false])
+ * @function rspamd_cryptobox.encrypt_file(kp|pk_string, filename)
* Encrypt data using specified keypair/pubkey
* @param {keypair|string} kp keypair or pubkey in base32 to use
* @param {string} filename
@@ -2096,8 +1999,7 @@ lua_cryptobox_encrypt_file(lua_State *L)
gsize blen;
b32 = lua_tolstring(L, 1, &blen);
- pk = rspamd_pubkey_from_base32(b32, blen, RSPAMD_KEYPAIR_KEX,
- lua_toboolean(L, 3) ? RSPAMD_CRYPTOBOX_MODE_NIST : RSPAMD_CRYPTOBOX_MODE_25519);
+ pk = rspamd_pubkey_from_base32(b32, blen, RSPAMD_KEYPAIR_KEX);
own_pk = true;
}
@@ -2658,11 +2560,11 @@ lua_cryptobox_gen_dkim_keypair(lua_State *L)
char *b64_data;
gsize b64_len;
- rspamd_cryptobox_keypair_sig(pk, sk, RSPAMD_CRYPTOBOX_MODE_25519);
+ rspamd_cryptobox_keypair_sig(pk, sk);
/* Process private key */
b64_data = rspamd_encode_base64(sk,
- rspamd_cryptobox_sk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519),
+ crypto_sign_secretkeybytes(),
-1, &b64_len);
priv_out = lua_newuserdata(L, sizeof(*priv_out));
@@ -2673,7 +2575,7 @@ lua_cryptobox_gen_dkim_keypair(lua_State *L)
/* Process public key */
b64_data = rspamd_encode_base64(pk,
- rspamd_cryptobox_pk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519),
+ crypto_sign_publickeybytes(),
-1, &b64_len);
pub_out = lua_newuserdata(L, sizeof(*pub_out));
@@ -2691,7 +2593,7 @@ lua_cryptobox_gen_dkim_keypair(lua_State *L)
char *b64_data;
gsize b64_len;
- rspamd_cryptobox_keypair_sig(pk, sk, RSPAMD_CRYPTOBOX_MODE_25519);
+ rspamd_cryptobox_keypair_sig(pk, sk);
/* Process private key */
b64_data = rspamd_encode_base64(sk,
@@ -2706,7 +2608,7 @@ lua_cryptobox_gen_dkim_keypair(lua_State *L)
/* Process public key */
b64_data = rspamd_encode_base64(pk,
- rspamd_cryptobox_pk_sig_bytes(RSPAMD_CRYPTOBOX_MODE_25519),
+ crypto_sign_publickeybytes(),
-1, &b64_len);
pub_out = lua_newuserdata(L, sizeof(*pub_out));
diff --git a/src/lua/lua_http.c b/src/lua/lua_http.c
index 2032f7dc1..8ba612c1b 100644
--- a/src/lua/lua_http.c
+++ b/src/lua/lua_http.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Vsevolod Stakhov
+ * Copyright 2024 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -907,8 +907,7 @@ lua_http_request(lua_State *L)
gsize inlen;
in = lua_tolstring(L, -1, &inlen);
- peer_key = rspamd_pubkey_from_base32(in, inlen,
- RSPAMD_KEYPAIR_KEX, RSPAMD_CRYPTOBOX_MODE_25519);
+ peer_key = rspamd_pubkey_from_base32(in, inlen, RSPAMD_KEYPAIR_KEX);
}
lua_pop(L, 1);
diff --git a/src/lua/lua_map.c b/src/lua/lua_map.c
index cce78ff2c..1cc2ce1bd 100644
--- a/src/lua/lua_map.c
+++ b/src/lua/lua_map.c
@@ -1293,8 +1293,7 @@ lua_map_set_sign_key(lua_State *L)
pk_str = lua_tolstring(L, 2, &len);
if (map && pk_str) {
- pk = rspamd_pubkey_from_base32(pk_str, len, RSPAMD_KEYPAIR_SIGN,
- RSPAMD_CRYPTOBOX_MODE_25519);
+ pk = rspamd_pubkey_from_base32(pk_str, len, RSPAMD_KEYPAIR_SIGN);
if (!pk) {
return luaL_error(L, "invalid pubkey string");
diff --git a/src/lua/lua_redis.c b/src/lua/lua_redis.c
index f95abb577..d20c496ed 100644
--- a/src/lua/lua_redis.c
+++ b/src/lua/lua_redis.c
@@ -104,7 +104,7 @@ struct lua_redis_userdata {
char *server;
char log_tag[RSPAMD_LOG_ID_LEN + 1];
struct lua_redis_request_specific_userdata *specific;
- double timeout;
+ ev_tstamp timeout;
uint16_t port;
uint16_t terminated;
};
@@ -280,16 +280,23 @@ lua_redis_fin(void *arg)
* @param code
* @param ud
*/
+#ifdef __GNUC__
+__attribute__((format(printf, 1, 5)))
+#endif
static void
lua_redis_push_error(const char *err,
struct lua_redis_ctx *ctx,
struct lua_redis_request_specific_userdata *sp_ud,
- gboolean connected)
+ gboolean connected,
+ ...)
{
struct lua_redis_userdata *ud = sp_ud->c;
struct lua_callback_state cbs;
lua_State *L;
+ va_list ap;
+ va_start(ap, connected);
+
if (!(sp_ud->flags & (LUA_REDIS_SPECIFIC_REPLIED | LUA_REDIS_SPECIFIC_FINISHED))) {
if (sp_ud->cbref != -1) {
@@ -302,7 +309,7 @@ lua_redis_push_error(const char *err,
lua_rawgeti(cbs.L, LUA_REGISTRYINDEX, sp_ud->cbref);
/* String of error */
- lua_pushstring(cbs.L, err);
+ lua_pushvfstring(cbs.L, err, ap);
/* Data is nil */
lua_pushnil(cbs.L);
@@ -331,6 +338,8 @@ lua_redis_push_error(const char *err,
lua_redis_fin(sp_ud);
}
}
+
+ va_end(ap);
}
static void
@@ -479,7 +488,7 @@ lua_redis_callback(redisAsyncContext *c, gpointer r, gpointer priv)
lua_redis_push_data(reply, ctx, sp_ud);
}
else {
- lua_redis_push_error(reply->str, ctx, sp_ud, TRUE);
+ lua_redis_push_error("%s", ctx, sp_ud, TRUE, reply->str);
}
}
else {
@@ -488,10 +497,10 @@ lua_redis_callback(redisAsyncContext *c, gpointer r, gpointer priv)
}
else {
if (c->err == REDIS_ERR_IO) {
- lua_redis_push_error(strerror(errno), ctx, sp_ud, TRUE);
+ lua_redis_push_error("%s", ctx, sp_ud, TRUE, strerror(errno));
}
else {
- lua_redis_push_error(c->errstr, ctx, sp_ud, TRUE);
+ lua_redis_push_error("%s", ctx, sp_ud, TRUE, c->errstr);
}
}
}
@@ -750,7 +759,7 @@ lua_redis_timeout(EV_P_ ev_timer *w, int revents)
REDIS_RETAIN(ctx);
msg_debug_lua_redis("timeout while querying redis server: %p, redis: %p", sp_ud,
sp_ud->c->ctx);
- lua_redis_push_error("timeout while connecting the server", ctx, sp_ud, TRUE);
+ lua_redis_push_error("timeout while connecting the server (%.2f sec)", ctx, sp_ud, TRUE, ud->timeout);
if (sp_ud->c->ctx) {
ac = sp_ud->c->ctx;
diff --git a/src/lua/lua_rsa.c b/src/lua/lua_rsa.c
index 0f67e91d1..0c56b223b 100644
--- a/src/lua/lua_rsa.c
+++ b/src/lua/lua_rsa.c
@@ -91,22 +91,22 @@ static const struct luaL_reg rsasignlib_m[] = {
{"__gc", lua_rsa_signature_gc},
{NULL, NULL}};
-static RSA *
+static EVP_PKEY *
lua_check_rsa_pubkey(lua_State *L, int pos)
{
void *ud = rspamd_lua_check_udata(L, pos, rspamd_rsa_pubkey_classname);
luaL_argcheck(L, ud != NULL, 1, "'rsa_pubkey' expected");
- return ud ? *((RSA **) ud) : NULL;
+ return ud ? *((EVP_PKEY **) ud) : NULL;
}
-static RSA *
+static EVP_PKEY *
lua_check_rsa_privkey(lua_State *L, int pos)
{
void *ud = rspamd_lua_check_udata(L, pos, rspamd_rsa_privkey_classname);
luaL_argcheck(L, ud != NULL, 1, "'rsa_privkey' expected");
- return ud ? *((RSA **) ud) : NULL;
+ return ud ? *((EVP_PKEY **) ud) : NULL;
}
static rspamd_fstring_t *
@@ -121,7 +121,7 @@ lua_check_rsa_sign(lua_State *L, int pos)
static int
lua_rsa_pubkey_load(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
const char *filename;
FILE *f;
@@ -135,15 +135,15 @@ lua_rsa_pubkey_load(lua_State *L)
lua_pushnil(L);
}
else {
- if (!PEM_read_RSA_PUBKEY(f, &rsa, NULL, NULL)) {
+ if (!PEM_read_PUBKEY(f, &pkey, NULL, NULL)) {
msg_err("cannot open pubkey from file: %s, %s", filename,
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_pubkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
fclose(f);
}
@@ -161,15 +161,14 @@ lua_rsa_privkey_save(lua_State *L)
const char *type = "pem";
FILE *f;
int ret;
-
- RSA *rsa = lua_check_rsa_privkey(L, 1);
+ EVP_PKEY *pkey = lua_check_rsa_privkey(L, 1);
filename = luaL_checkstring(L, 2);
if (lua_gettop(L) > 2) {
type = luaL_checkstring(L, 3);
}
- if (rsa != NULL && filename != NULL) {
+ if (pkey != NULL && filename != NULL) {
if (strcmp(filename, "-") == 0) {
f = stdout;
}
@@ -189,10 +188,10 @@ lua_rsa_privkey_save(lua_State *L)
}
if (strcmp(type, "der") == 0) {
- ret = i2d_RSAPrivateKey_fp(f, rsa);
+ ret = i2d_PrivateKey_fp(f, pkey);
}
else {
- ret = PEM_write_RSAPrivateKey(f, rsa, NULL, NULL, 0, NULL, NULL);
+ ret = PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL);
}
if (!ret) {
@@ -223,7 +222,7 @@ lua_rsa_privkey_save(lua_State *L)
static int
lua_rsa_pubkey_create(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey, **ppkey;
const char *buf;
BIO *bp;
@@ -231,15 +230,15 @@ lua_rsa_pubkey_create(lua_State *L)
if (buf != NULL) {
bp = BIO_new_mem_buf((void *) buf, -1);
- if (!PEM_read_bio_RSA_PUBKEY(bp, &rsa, NULL, NULL)) {
+ if (!PEM_read_bio_PUBKEY(bp, &pkey, NULL, NULL)) {
msg_err("cannot parse pubkey: %s",
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_pubkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
BIO_free(bp);
}
@@ -252,10 +251,10 @@ lua_rsa_pubkey_create(lua_State *L)
static int
lua_rsa_pubkey_gc(lua_State *L)
{
- RSA *rsa = lua_check_rsa_pubkey(L, 1);
+ EVP_PKEY *pkey = lua_check_rsa_pubkey(L, 1);
- if (rsa != NULL) {
- RSA_free(rsa);
+ if (pkey != NULL) {
+ EVP_PKEY_free(pkey);
}
return 0;
@@ -264,18 +263,18 @@ lua_rsa_pubkey_gc(lua_State *L)
static int
lua_rsa_pubkey_tostring(lua_State *L)
{
- RSA *rsa = lua_check_rsa_pubkey(L, 1);
+ EVP_PKEY *pkey = lua_check_rsa_pubkey(L, 1);
- if (rsa != NULL) {
+ if (pkey != NULL) {
BIO *pubout = BIO_new(BIO_s_mem());
const char *pubdata;
gsize publen;
- int rc = i2d_RSA_PUBKEY_bio(pubout, rsa);
+ int rc = i2d_PUBKEY_bio(pubout, pkey);
if (rc != 1) {
BIO_free(pubout);
- return luaL_error(L, "i2d_RSA_PUBKEY_bio failed");
+ return luaL_error(L, "i2d_PUBKEY_bio failed");
}
publen = BIO_get_mem_data(pubout, &pubdata);
@@ -292,7 +291,7 @@ lua_rsa_pubkey_tostring(lua_State *L)
static int
lua_rsa_privkey_load_file(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
const char *filename;
FILE *f;
@@ -306,15 +305,15 @@ lua_rsa_privkey_load_file(lua_State *L)
lua_pushnil(L);
}
else {
- if (!PEM_read_RSAPrivateKey(f, &rsa, NULL, NULL)) {
+ if (!PEM_read_PrivateKey(f, &pkey, NULL, NULL)) {
msg_err("cannot open private key from file: %s, %s", filename,
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
fclose(f);
}
@@ -328,7 +327,7 @@ lua_rsa_privkey_load_file(lua_State *L)
static int
lua_rsa_privkey_load_pem(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
BIO *b;
struct rspamd_lua_text *t;
const char *data;
@@ -351,15 +350,15 @@ lua_rsa_privkey_load_pem(lua_State *L)
if (data != NULL) {
b = BIO_new_mem_buf(data, len);
- if (!PEM_read_bio_RSAPrivateKey(b, &rsa, NULL, NULL)) {
+ if (!PEM_read_bio_PrivateKey(b, &pkey, NULL, NULL)) {
msg_err("cannot open private key from data, %s",
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
BIO_free(b);
@@ -374,7 +373,7 @@ lua_rsa_privkey_load_pem(lua_State *L)
static int
lua_rsa_privkey_load_raw(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
BIO *b;
struct rspamd_lua_text *t;
const char *data;
@@ -396,17 +395,17 @@ lua_rsa_privkey_load_raw(lua_State *L)
if (data != NULL) {
b = BIO_new_mem_buf(data, len);
- rsa = d2i_RSAPrivateKey_bio(b, NULL);
+ pkey = d2i_PrivateKey_bio(b, NULL);
- if (rsa == NULL) {
+ if (pkey == NULL) {
msg_err("cannot open private key from data, %s",
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
BIO_free(b);
@@ -421,9 +420,8 @@ lua_rsa_privkey_load_raw(lua_State *L)
static int
lua_rsa_privkey_load_base64(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
BIO *b;
- EVP_PKEY *evp = NULL;
struct rspamd_lua_text *t;
const char *data;
unsigned char *decoded;
@@ -454,21 +452,18 @@ lua_rsa_privkey_load_base64(lua_State *L)
b = BIO_new_mem_buf(decoded, dec_len);
- if (d2i_PrivateKey_bio(b, &evp) != NULL) {
- rsa = EVP_PKEY_get1_RSA(evp);
-
- if (rsa == NULL) {
+ if (d2i_PrivateKey_bio(b, &pkey) != NULL) {
+ if (pkey == NULL) {
msg_err("cannot open RSA private key from data, %s",
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
- EVP_PKEY_free(evp);
}
else {
msg_err("cannot open EVP private key from data, %s",
@@ -489,7 +484,7 @@ lua_rsa_privkey_load_base64(lua_State *L)
static int
lua_rsa_privkey_create(lua_State *L)
{
- RSA *rsa = NULL, **prsa;
+ EVP_PKEY *pkey = NULL, **ppkey;
const char *buf;
BIO *bp;
@@ -497,15 +492,15 @@ lua_rsa_privkey_create(lua_State *L)
if (buf != NULL) {
bp = BIO_new_mem_buf((void *) buf, -1);
- if (!PEM_read_bio_RSAPrivateKey(bp, &rsa, NULL, NULL)) {
+ if (!PEM_read_bio_PrivateKey(bp, &pkey, NULL, NULL)) {
msg_err("cannot parse private key: %s",
ERR_error_string(ERR_get_error(), NULL));
lua_pushnil(L);
}
else {
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = rsa;
+ *ppkey = pkey;
}
BIO_free(bp);
}
@@ -518,10 +513,10 @@ lua_rsa_privkey_create(lua_State *L)
static int
lua_rsa_privkey_gc(lua_State *L)
{
- RSA *rsa = lua_check_rsa_privkey(L, 1);
+ EVP_PKEY *pkey = lua_check_rsa_privkey(L, 1);
- if (rsa != NULL) {
- RSA_free(rsa);
+ if (pkey != NULL) {
+ EVP_PKEY_free(pkey);
}
return 0;
@@ -699,19 +694,22 @@ lua_rsa_signature_base64(lua_State *L)
static int
lua_rsa_verify_memory(lua_State *L)
{
- RSA *rsa;
+ EVP_PKEY *pkey;
rspamd_fstring_t *signature;
const char *data;
gsize sz;
int ret;
- rsa = lua_check_rsa_pubkey(L, 1);
+ pkey = lua_check_rsa_pubkey(L, 1);
signature = lua_check_rsa_sign(L, 2);
data = luaL_checklstring(L, 3, &sz);
- if (rsa != NULL && signature != NULL && data != NULL) {
- ret = RSA_verify(NID_sha256, data, sz,
- signature->str, signature->len, rsa);
+ if (pkey != NULL && signature != NULL && data != NULL) {
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ g_assert(pctx != NULL);
+ g_assert(EVP_PKEY_verify_init(pctx) == 1);
+
+ ret = EVP_PKEY_verify(pctx, signature->str, signature->len, data, sz);
if (ret == 0) {
lua_pushboolean(L, FALSE);
@@ -722,6 +720,7 @@ lua_rsa_verify_memory(lua_State *L)
else {
lua_pushboolean(L, TRUE);
}
+ EVP_PKEY_CTX_free(pctx);
}
else {
lua_pushnil(L);
@@ -743,22 +742,26 @@ lua_rsa_verify_memory(lua_State *L)
static int
lua_rsa_sign_memory(lua_State *L)
{
- RSA *rsa;
+ EVP_PKEY *pkey;
rspamd_fstring_t *signature, **psig;
const char *data;
gsize sz;
int ret;
- rsa = lua_check_rsa_privkey(L, 1);
+ pkey = lua_check_rsa_privkey(L, 1);
data = luaL_checklstring(L, 2, &sz);
- if (rsa != NULL && data != NULL) {
- signature = rspamd_fstring_sized_new(RSA_size(rsa));
+ if (pkey != NULL && data != NULL) {
+ signature = rspamd_fstring_sized_new(EVP_PKEY_get_size(pkey));
+
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ g_assert(pctx != NULL);
- unsigned int siglen = signature->len;
- ret = RSA_sign(NID_sha256, data, sz,
- signature->str, &siglen, rsa);
+ g_assert(EVP_PKEY_sign_init(pctx) == 1);
+ size_t slen = signature->allocated;
+ ret = EVP_PKEY_sign(pctx, signature->str, &slen, data, sz);
+ EVP_PKEY_CTX_free(pctx);
if (ret != 1) {
rspamd_fstring_free(signature);
@@ -766,7 +769,7 @@ lua_rsa_sign_memory(lua_State *L)
ERR_error_string(ERR_get_error(), NULL));
}
else {
- signature->len = siglen;
+ signature->len = slen;
psig = lua_newuserdata(L, sizeof(rspamd_fstring_t *));
rspamd_lua_setclass(L, rspamd_rsa_signature_classname, -1);
*psig = signature;
@@ -783,7 +786,7 @@ static int
lua_rsa_keypair(lua_State *L)
{
BIGNUM *e;
- RSA *rsa, *pub_rsa, *priv_rsa, **prsa;
+ EVP_PKEY *pkey = NULL, *pub_pkey, *priv_pkey, **ppkey;
int bits = lua_gettop(L) > 0 ? lua_tointeger(L, 1) : 1024;
if (bits > 4096 || bits < 512) {
@@ -791,21 +794,30 @@ lua_rsa_keypair(lua_State *L)
}
e = BN_new();
- rsa = RSA_new();
+
g_assert(BN_set_word(e, RSA_F4) == 1);
- g_assert(RSA_generate_key_ex(rsa, bits, e, NULL) == 1);
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
+ g_assert(pctx != NULL);
+ g_assert(EVP_PKEY_keygen_init(pctx) == 1);
+
+ g_assert(EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, bits) == 1);
+ g_assert(EVP_PKEY_CTX_set1_rsa_keygen_pubexp(pctx, e) == 1);
+
+ g_assert(EVP_PKEY_keygen(pctx, &pkey) == 1);
+ g_assert(pkey != NULL);
- priv_rsa = RSAPrivateKey_dup(rsa);
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ priv_pkey = EVP_PKEY_dup(pkey);
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_privkey_classname, -1);
- *prsa = priv_rsa;
+ *ppkey = priv_pkey;
- pub_rsa = RSAPublicKey_dup(rsa);
- prsa = lua_newuserdata(L, sizeof(RSA *));
+ pub_pkey = EVP_PKEY_dup(pkey);
+ ppkey = lua_newuserdata(L, sizeof(EVP_PKEY *));
rspamd_lua_setclass(L, rspamd_rsa_pubkey_classname, -1);
- *prsa = pub_rsa;
+ *ppkey = pub_pkey;
- RSA_free(rsa);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(pctx);
BN_free(e);
return 2;
diff --git a/src/lua/lua_spf.c b/src/lua/lua_spf.c
index 46e72202f..850ce2120 100644
--- a/src/lua/lua_spf.c
+++ b/src/lua/lua_spf.c
@@ -89,6 +89,8 @@ lua_load_spf(lua_State *L)
lua_setfield(L, -2, "perm_fail");
lua_pushinteger(L, RSPAMD_SPF_FLAG_CACHED);
lua_setfield(L, -2, "cached");
+ lua_pushinteger(L, RSPAMD_SPF_RESOLVED_PLUSALL);
+ lua_setfield(L, -2, "plusall");
lua_setfield(L, -2, "flags");
@@ -368,6 +370,11 @@ spf_check_element(lua_State *L, struct spf_resolved *rec, struct spf_addr *addr,
lua_pushinteger(L, RSPAMD_SPF_RESOLVED_TEMP_FAILED);
lua_pushfstring(L, "%cany", spf_mech_char(addr->mech));
}
+ else if (rec->flags & RSPAMD_SPF_RESOLVED_PLUSALL) {
+ lua_pushboolean(L, false);
+ lua_pushinteger(L, RSPAMD_SPF_RESOLVED_PLUSALL);
+ lua_pushfstring(L, "%cany", spf_mech_char(addr->mech));
+ }
else {
lua_pushboolean(L, true);
lua_pushinteger(L, addr->mech);
diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c
index 21e24fc45..3968c01eb 100644
--- a/src/lua/lua_task.c
+++ b/src/lua/lua_task.c
@@ -1318,6 +1318,7 @@ static const struct luaL_reg tasklib_m[] = {
LUA_INTERFACE_DEF(task, get_metric_threshold),
LUA_INTERFACE_DEF(task, set_metric_score),
LUA_INTERFACE_DEF(task, set_metric_subject),
+ {"set_subject", lua_task_set_metric_subject},
LUA_INTERFACE_DEF(task, learn),
LUA_INTERFACE_DEF(task, set_settings),
LUA_INTERFACE_DEF(task, get_settings),