diff options
author | Vsevolod Stakhov <vsevolod@rspamd.com> | 2024-09-05 16:20:46 +0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-05 16:20:46 +0600 |
commit | 737a2ce03b826f86851d021d628274ab8c8ea7fb (patch) | |
tree | 7918e548808c5981fab465726f545a5c6cc9fe49 /src/lua | |
parent | dd47f82a317ad2ed9a9270c9779bf866ff5989fd (diff) | |
parent | 40a6ddd69be80e6a4ad8a29053bbfa18d24b3bd8 (diff) | |
download | rspamd-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.c | 854 | ||||
-rw-r--r-- | src/lua/lua_cryptobox.c | 154 | ||||
-rw-r--r-- | src/lua/lua_http.c | 5 | ||||
-rw-r--r-- | src/lua/lua_map.c | 3 | ||||
-rw-r--r-- | src/lua/lua_redis.c | 23 | ||||
-rw-r--r-- | src/lua/lua_rsa.c | 164 | ||||
-rw-r--r-- | src/lua/lua_spf.c | 7 | ||||
-rw-r--r-- | src/lua/lua_task.c | 1 |
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), |