mod_firewall: Add SEARCH, PATTERN definitions and SCAN condition to check tokenized stanza:find() against a list
--- a/mod_firewall/conditions.lib.lua Mon Feb 20 09:29:38 2017 +0000
+++ b/mod_firewall/conditions.lib.lua Mon Feb 20 09:31:30 2017 +0000
@@ -263,4 +263,13 @@
return ("list_%s:contains(%s) == true"):format(list_name, expr), { "list:"..list_name, unpack(meta_deps) };
end
+-- SCAN: body for word in badwords
+function condition_handlers.SCAN(scan_expression)
+ local search_name, pattern_name, list_name = scan_expression:match("(%S+) for (%S+) in (%S+)$");
+ if not (search_name) then
+ error("Error parsing SCAN expression, syntax: SEARCH for PATTERN in LIST");
+ end
+ return ("scan_list(%s, %s)"):format(list_name, "tokens_"..search_name.."_"..pattern_name), { "scan_list", "tokens:"..search_name.."_"..pattern_name, "list:"..list_name };
+end
+
return condition_handlers;
--- a/mod_firewall/definitions.lib.lua Mon Feb 20 09:29:38 2017 +0000
+++ b/mod_firewall/definitions.lib.lua Mon Feb 20 09:31:30 2017 +0000
@@ -170,4 +170,16 @@
return create_list(list_backend, list_definition:match("^%S+"), opts);
end
+function definition_handlers.PATTERN(name, pattern)
+ local ok, err = pcall(string.match, "", pattern);
+ if not ok then
+ error("Invalid pattern '"..name.."': "..err);
+ end
+ return pattern;
+end
+
+function definition_handlers.SEARCH(name, pattern)
+ return pattern;
+end
+
return definition_handlers;
--- a/mod_firewall/mod_firewall.lua Mon Feb 20 09:29:38 2017 +0000
+++ b/mod_firewall/mod_firewall.lua Mon Feb 20 09:31:30 2017 +0000
@@ -199,6 +199,28 @@
return ("local list_%s = lists[%q];"):format(list, list);
end
};
+ search = {
+ local_code = function (search_name)
+ local search_path = assert(active_definitions.SEARCH[search_name], "Undefined search path: "..search_name);
+ return ("local search_%s = tostring(stanza:find(%q) or \"\")"):format(search_name, search_path);
+ end;
+ };
+ tokens = {
+ local_code = function (search_and_pattern)
+ local search_name, pattern_name = search_and_pattern:match("^([^%-]+)_(.+)$");
+ local code = ([[local tokens_%s_%s = {};
+ if search_%s then
+ for s in search_%s:gmatch(patterns.%s) do
+ tokens_%s_%s[s] = true;
+ end
+ end
+ ]]):format(search_name, pattern_name, search_name, search_name, pattern_name, search_name, pattern_name);
+ return code, { "search:"..search_name };
+ end;
+ };
+ scan_list = {
+ global_code = [[local function scan_list(list, items) for item in pairs(items) do if list:contains(item) then return true; end end]];
+ }
};
local function include_dep(dependency, code)