changeset 2528:44a71584521d

mod_firewall: Add SEARCH, PATTERN definitions and SCAN condition to check tokenized stanza:find() against a list
author Matthew Wild <mwild1@gmail.com>
date Mon, 20 Feb 2017 09:31:30 +0000
parents 5ff7eb601d60
children 3fe4ca2b55c2
files mod_firewall/conditions.lib.lua mod_firewall/definitions.lib.lua mod_firewall/mod_firewall.lua
diffstat 3 files changed, 43 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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)