Mercurial > prosody-modules
comparison mod_firewall/mod_firewall.lua @ 6536:24c34968dd45
mod_firewall: Preserve original source of actions/conditions for debug purposes
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Mon, 11 May 2026 13:18:25 +0100 |
| parents | 82b6a03b9dfa |
| children | 9bc83fba89ac |
comparison
equal
deleted
inserted
replaced
| 6535:82b6a03b9dfa | 6536:24c34968dd45 |
|---|---|
| 386 module:require"marks"; | 386 module:require"marks"; |
| 387 end | 387 end |
| 388 | 388 |
| 389 local function new_rule(ruleset, chain, line_no) | 389 local function new_rule(ruleset, chain, line_no) |
| 390 assert(chain, "no chain specified"); | 390 assert(chain, "no chain specified"); |
| 391 local rule = { conditions = {}, actions = {}, deps = {}, line_no = line_no }; | 391 local rule = { conditions = {}, actions = {}, deps = {}, line_no = line_no, source = { conditions = {}, actions = {} } }; |
| 392 table.insert(ruleset[chain], rule); | 392 table.insert(ruleset[chain], rule); |
| 393 return rule; | 393 return rule; |
| 394 end | 394 end |
| 395 | 395 |
| 396 local function parse_firewall_rules(filename) | 396 local function parse_firewall_rules(filename) |
| 498 local ok, action_string, action_deps = pcall(action_handlers[action], line:match("=(.+)$")); | 498 local ok, action_string, action_deps = pcall(action_handlers[action], line:match("=(.+)$")); |
| 499 if not ok then | 499 if not ok then |
| 500 return nil, errmsg(action_string); | 500 return nil, errmsg(action_string); |
| 501 end | 501 end |
| 502 table.insert(rule.actions, action_string); | 502 table.insert(rule.actions, action_string); |
| 503 table.insert(rule.source.actions, line); | |
| 503 for _, dep in ipairs(action_deps or {}) do | 504 for _, dep in ipairs(action_deps or {}) do |
| 504 table.insert(rule.deps, dep); | 505 table.insert(rule.deps, dep); |
| 505 end | 506 end |
| 506 elseif state == "actions" then -- state is actions but action pattern did not match | 507 elseif state == "actions" then -- state is actions but action pattern did not match |
| 507 state = nil; -- Awaiting next rule, etc. | 508 state = nil; -- Awaiting next rule, etc. |
| 513 state = "rules"; | 514 state = "rules"; |
| 514 rule = new_rule(ruleset, chain, line_no); | 515 rule = new_rule(ruleset, chain, line_no); |
| 515 end | 516 end |
| 516 -- Check standard modifiers for the condition (e.g. NOT) | 517 -- Check standard modifiers for the condition (e.g. NOT) |
| 517 local negated; | 518 local negated; |
| 518 local condition = line:match("^[^:=%.?]*"); | 519 local raw_condition = line:match("^[^:=%.?]*"); |
| 520 local condition = raw_condition; | |
| 521 | |
| 519 if condition:find("%f[%w]NOT%f[^%w]") then | 522 if condition:find("%f[%w]NOT%f[^%w]") then |
| 520 local s, e = condition:match("%f[%w]()NOT()%f[^%w]"); | 523 local s, e = condition:match("%f[%w]()NOT()%f[^%w]"); |
| 521 condition = (condition:sub(1,s-1)..condition:sub(e+1, -1)):match("^%s*(.-)%s*$"); | 524 condition = (condition:sub(1,s-1)..condition:sub(e+1, -1)):match("^%s*(.-)%s*$"); |
| 522 negated = true; | 525 negated = true; |
| 523 end | 526 end |
| 530 if not ok then | 533 if not ok then |
| 531 return nil, errmsg(condition_code); | 534 return nil, errmsg(condition_code); |
| 532 end | 535 end |
| 533 if negated then condition_code = "not("..condition_code..")"; end | 536 if negated then condition_code = "not("..condition_code..")"; end |
| 534 table.insert(rule.conditions, condition_code); | 537 table.insert(rule.conditions, condition_code); |
| 538 table.insert(rule.source.conditions, line); | |
| 535 for _, dep in ipairs(condition_deps or {}) do | 539 for _, dep in ipairs(condition_deps or {}) do |
| 536 table.insert(rule.deps, dep); | 540 table.insert(rule.deps, dep); |
| 537 end | 541 end |
| 538 end | 542 end |
| 539 end | 543 end |
| 614 | 618 |
| 615 for name in pairs(definition_handlers) do | 619 for name in pairs(definition_handlers) do |
| 616 table.insert(code.global_header, 1, "local "..name:lower().."s = definitions."..name..";"); | 620 table.insert(code.global_header, 1, "local "..name:lower().."s = definitions."..name..";"); |
| 617 end | 621 end |
| 618 | 622 |
| 619 local code_string = "return function (definitions, fire_event, log, module, pass_return)\n\t" | 623 -- The function signature here must match what gets passed in compile_handler() |
| 624 local code_string = "return function (definitions, fire_event, log, module, pass_return, source_rules)\n\t" | |
| 620 ..table.concat(code.global_header, "\n\t") | 625 ..table.concat(code.global_header, "\n\t") |
| 621 .."\n\tlocal db = require 'util.debug';\n\n\t" | 626 .."\n\tlocal db = require 'util.debug';\n\n\t" |
| 622 .."return function (event)\n\t\t" | 627 .."return function (event)\n\t\t" |
| 623 .."local stanza, session = event.stanza, event.origin;\n" | 628 .."local stanza, session = event.stanza, event.origin;\n" |
| 624 ..table.concat(code, "") | 629 ..table.concat(code, "") |
| 625 .."\n\tend;\nend"; | 630 .."\n\tend;\nend"; |
| 626 | 631 |
| 627 chain_handlers[chain_name] = code_string; | 632 chain_handlers[chain_name] = { code = code_string, rules = rules }; |
| 628 end | 633 end |
| 629 | 634 |
| 630 return chain_handlers; | 635 return chain_handlers; |
| 631 end | 636 end |
| 632 | 637 |
| 637 return chain_handlers; | 642 return chain_handlers; |
| 638 end | 643 end |
| 639 | 644 |
| 640 -- Compile handler code into a factory that produces a valid event handler. Factory accepts | 645 -- Compile handler code into a factory that produces a valid event handler. Factory accepts |
| 641 -- a value to be returned on PASS | 646 -- a value to be returned on PASS |
| 642 local function compile_handler(code_string, filename) | 647 local function compile_handler(code_string, filename, source_rules) |
| 643 -- Prepare event handler function | 648 -- Prepare event handler function |
| 644 local chunk, err = envload(code_string, "="..filename, _G); | 649 local chunk, err = envload(code_string, "="..filename, _G); |
| 645 if not chunk then | 650 if not chunk then |
| 646 return nil, "Error compiling (probably a compiler bug, please report): "..err; | 651 return nil, "Error compiling (probably a compiler bug, please report): "..err; |
| 647 end | 652 end |
| 651 local init_ok, initialized_chunk = pcall(chunk); | 656 local init_ok, initialized_chunk = pcall(chunk); |
| 652 if not init_ok then | 657 if not init_ok then |
| 653 return nil, "Error initializing compiled rules: "..initialized_chunk; | 658 return nil, "Error initializing compiled rules: "..initialized_chunk; |
| 654 end | 659 end |
| 655 return function (pass_return) | 660 return function (pass_return) |
| 656 return initialized_chunk(active_definitions, fire_event, logger(filename), module, pass_return); -- Returns event handler with upvalues | 661 return initialized_chunk(active_definitions, fire_event, logger(filename), module, pass_return, source_rules); -- Returns event handler with upvalues |
| 657 end | 662 end |
| 658 end | 663 end |
| 659 | 664 |
| 660 local function resolve_script_path(script_path) | 665 local function resolve_script_path(script_path) |
| 661 local relative_to = prosody.paths.config; | 666 local relative_to = prosody.paths.config; |
| 691 local errs; | 696 local errs; |
| 692 | 697 |
| 693 -- Loop through the chains in the script, and for each chain attach the compiled code to the | 698 -- Loop through the chains in the script, and for each chain attach the compiled code to the |
| 694 -- relevant events, keeping track in events_hooked so we can cleanly unload later | 699 -- relevant events, keeping track in events_hooked so we can cleanly unload later |
| 695 local events_hooked = {}; | 700 local events_hooked = {}; |
| 696 for chain, handler_code in pairs(chain_functions) do | 701 for chain, chain_info in pairs(chain_functions) do |
| 697 local new_handler, err = compile_handler(handler_code, "mod_firewall::"..chain); | 702 local handler_code = chain_info.code; |
| 703 local new_handler, err = compile_handler(handler_code, "mod_firewall:"..base_name.."::"..chain, chain_info.rules); | |
| 698 if not new_handler then | 704 if not new_handler then |
| 699 module:log("error", "Compilation error for %s: %s", script, err); | 705 module:log("error", "Compilation error for %s: %s", script, err); |
| 700 errs = true; | 706 errs = true; |
| 701 break; | 707 break; |
| 702 else | 708 else |
| 821 print(); | 827 print(); |
| 822 print("local active_definitions = "..serialize(active_definitions)..";"); | 828 print("local active_definitions = "..serialize(active_definitions)..";"); |
| 823 print(); | 829 print(); |
| 824 end | 830 end |
| 825 local c = 0; | 831 local c = 0; |
| 826 for chain, handler_code in pairs(chain_functions) do | 832 for chain_name, chain_info in pairs(chain_functions) do |
| 833 local handler_code = chain_info.code; | |
| 827 c = c + 1; | 834 c = c + 1; |
| 828 print("---- Chain "..chain:gsub("_", " ")); | 835 print("---- Chain "..chain_name:gsub("_", " ")); |
| 829 local chain_func_name = "chain_"..tostring(c).."_"..chain:gsub("%p", "_"); | 836 local chain_func_name = "chain_"..tostring(c).."_"..chain_name:gsub("%p", "_"); |
| 830 if not verbose then | 837 if not verbose then |
| 831 print(("%s = %s;"):format(chain_func_name, handler_code:sub(8))); | 838 print(("%s = %s;"):format(chain_func_name, handler_code:sub(8))); |
| 832 else | 839 else |
| 833 | 840 |
| 834 print(("local %s = (%s)(active_definitions, fire_event, logger(%q));"):format(chain_func_name, handler_code:sub(8), filename)); | 841 print(("local %s = (%s)(active_definitions, fire_event, logger(%q));"):format(chain_func_name, handler_code:sub(8), filename)); |
| 835 print(); | 842 print(); |
| 836 | 843 |
| 837 local chain_definition = chains[chain]; | 844 local chain_definition = chains[chain_name]; |
| 838 if chain_definition and chain_definition.type == "event" then | 845 if chain_definition and chain_definition.type == "event" then |
| 839 for _, event_name in ipairs(chain_definition) do | 846 for _, event_name in ipairs(chain_definition) do |
| 840 print(("module:hook(%q, %s, %d);"):format(event_name, chain_func_name, chain_definition.priority or 0)); | 847 print(("module:hook(%q, %s, %d);"):format(event_name, chain_func_name, chain_definition.priority or 0)); |
| 841 end | 848 end |
| 842 end | 849 end |
| 843 print(("module:hook(%q, %s, %d);"):format("firewall/chains/"..chain, chain_func_name, chain_definition.priority or 0)); | 850 print(("module:hook(%q, %s, %d);"):format("firewall/chains/"..chain_name, chain_func_name, chain_definition.priority or 0)); |
| 844 end | 851 end |
| 845 | 852 |
| 846 print("---- End of chain "..chain); | 853 print("---- End of chain "..chain_name); |
| 847 print(); | 854 print(); |
| 848 end | 855 end |
| 849 print("end -- End of file "..filename); | 856 print("end -- End of file "..filename); |
| 850 end | 857 end |
| 851 end | 858 end |
