comparison mod_firewall/mod_firewall.lua @ 2558:2b533a7b5236

mod_firewall: Make PASS bubble up through all chains, and add DEFAULT and RETURN
author Matthew Wild <mwild1@gmail.com>
date Fri, 24 Feb 2017 09:38:20 +0000
parents 19a182651a9b
children 3da0e3c917cc
comparison
equal deleted inserted replaced
2557:56db2ab3b853 2558:2b533a7b5236
346 elseif not(state) and line:sub(1, 2) == "::" then 346 elseif not(state) and line:sub(1, 2) == "::" then
347 chain = line:gsub("^::%s*", ""); 347 chain = line:gsub("^::%s*", "");
348 local chain_info = chains[chain]; 348 local chain_info = chains[chain];
349 if not chain_info then 349 if not chain_info then
350 if chain:match("^user/") then 350 if chain:match("^user/") then
351 chains[chain] = { type = "event", priority = 1, "firewall/chains/"..chain }; 351 chains[chain] = { type = "event", priority = 1, pass_return = false };
352 else 352 else
353 return nil, errmsg("Unknown chain: "..chain); 353 return nil, errmsg("Unknown chain: "..chain);
354 end 354 end
355 elseif chain_info.type ~= "event" then 355 elseif chain_info.type ~= "event" then
356 return nil, errmsg("Only event chains supported at the moment"); 356 return nil, errmsg("Only event chains supported at the moment");
502 502
503 for name in pairs(definition_handlers) do 503 for name in pairs(definition_handlers) do
504 table.insert(code.global_header, 1, "local "..name:lower().."s = definitions."..name..";"); 504 table.insert(code.global_header, 1, "local "..name:lower().."s = definitions."..name..";");
505 end 505 end
506 506
507 local code_string = "return function (definitions, fire_event, log, module)\n\t" 507 local code_string = "return function (definitions, fire_event, log, module, pass_return)\n\t"
508 ..table.concat(code.global_header, "\n\t") 508 ..table.concat(code.global_header, "\n\t")
509 .."\n\tlocal db = require 'util.debug';\n\n\t" 509 .."\n\tlocal db = require 'util.debug';\n\n\t"
510 .."return function (event)\n\t\t" 510 .."return function (event)\n\t\t"
511 .."local stanza, session = event.stanza, event.origin;\n" 511 .."local stanza, session = event.stanza, event.origin;\n"
512 ..table.concat(code, "") 512 ..table.concat(code, "")
523 if not ruleset then return nil, err; end 523 if not ruleset then return nil, err; end
524 local chain_handlers = process_firewall_rules(ruleset); 524 local chain_handlers = process_firewall_rules(ruleset);
525 return chain_handlers; 525 return chain_handlers;
526 end 526 end
527 527
528 -- Compile handler code into a factory that produces a valid event handler. Factory accepts
529 -- a value to be returned on PASS
528 local function compile_handler(code_string, filename) 530 local function compile_handler(code_string, filename)
529 -- Prepare event handler function 531 -- Prepare event handler function
530 local chunk, err = loadstring(code_string, "="..filename); 532 local chunk, err = loadstring(code_string, "="..filename);
531 if not chunk then 533 if not chunk then
532 return nil, "Error compiling (probably a compiler bug, please report): "..err; 534 return nil, "Error compiling (probably a compiler bug, please report): "..err;
533 end 535 end
534 local function fire_event(name, data) 536 local function fire_event(name, data)
535 return module:fire_event(name, data); 537 return module:fire_event(name, data);
536 end 538 end
537 chunk = chunk()(active_definitions, fire_event, logger(filename), module); -- Returns event handler with 'zones' upvalue. 539 return function (pass_return)
538 return chunk; 540 return chunk()(active_definitions, fire_event, logger(filename), module, pass_return); -- Returns event handler with upvalues
541 end
539 end 542 end
540 543
541 local function resolve_script_path(script_path) 544 local function resolve_script_path(script_path)
542 local relative_to = prosody.paths.config; 545 local relative_to = prosody.paths.config;
543 if script_path:match("^module:") then 546 if script_path:match("^module:") then
557 560
558 if not chain_functions then 561 if not chain_functions then
559 module:log("error", "Error compiling %s: %s", script, err or "unknown error"); 562 module:log("error", "Error compiling %s: %s", script, err or "unknown error");
560 else 563 else
561 for chain, handler_code in pairs(chain_functions) do 564 for chain, handler_code in pairs(chain_functions) do
562 local handler, err = compile_handler(handler_code, "mod_firewall::"..chain); 565 local new_handler, err = compile_handler(handler_code, "mod_firewall::"..chain);
563 if not handler then 566 if not new_handler then
564 module:log("error", "Compilation error for %s: %s", script, err); 567 module:log("error", "Compilation error for %s: %s", script, err);
565 else 568 else
566 local chain_definition = chains[chain]; 569 local chain_definition = chains[chain];
567 if chain_definition and chain_definition.type == "event" then 570 if chain_definition and chain_definition.type == "event" then
571 local handler = new_handler(chain_definition.pass_return);
568 for _, event_name in ipairs(chain_definition) do 572 for _, event_name in ipairs(chain_definition) do
569 module:hook(event_name, handler, chain_definition.priority); 573 module:hook(event_name, handler, chain_definition.priority);
570 end 574 end
571 elseif not chain:sub(1, 5) == "user/" then 575 elseif not chain:sub(1, 5) == "user/" then
572 module:log("warn", "Unknown chain %q", chain); 576 module:log("warn", "Unknown chain %q", chain);
573 end 577 end
574 module:hook("firewall/chains/"..chain, handler); 578 module:hook("firewall/chains/"..chain, new_handler(false));
575 end 579 end
576 end 580 end
577 end 581 end
578 end 582 end
579 -- Replace contents of definitions table (shared) with active definitions 583 -- Replace contents of definitions table (shared) with active definitions