Mercurial > prosody-modules
comparison mod_firewall/actions.lib.lua @ 947:c91cac3b823f
mod_firewall: General stanza filtering plugin with a declarative rule-based syntax
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Wed, 03 Apr 2013 16:11:20 +0100 |
| parents | |
| children | b729414b4bf1 |
comparison
equal
deleted
inserted
replaced
| 946:2c5430ff1c11 | 947:c91cac3b823f |
|---|---|
| 1 local action_handlers = {}; | |
| 2 | |
| 3 -- Takes an XML string and returns a code string that builds that stanza | |
| 4 -- using st.stanza() | |
| 5 local function compile_xml(data) | |
| 6 local code = {}; | |
| 7 local first, short_close = true, nil; | |
| 8 for tagline, text in data:gmatch("<([^>]+)>([^<]*)") do | |
| 9 if tagline:sub(-1,-1) == "/" then | |
| 10 tagline = tagline:sub(1, -2); | |
| 11 short_close = true; | |
| 12 end | |
| 13 if tagline:sub(1,1) == "/" then | |
| 14 code[#code+1] = (":up()"); | |
| 15 else | |
| 16 local name, attr = tagline:match("^(%S*)%s*(.*)$"); | |
| 17 local attr_str = {}; | |
| 18 for k, _, v in attr:gmatch("(%S+)=([\"'])([^%2]-)%2") do | |
| 19 if #attr_str == 0 then | |
| 20 table.insert(attr_str, ", { "); | |
| 21 else | |
| 22 table.insert(attr_str, ", "); | |
| 23 end | |
| 24 if k:match("^%a%w*$") then | |
| 25 table.insert(attr_str, string.format("%s = %q", k, v)); | |
| 26 else | |
| 27 table.insert(attr_str, string.format("[%q] = %q", k, v)); | |
| 28 end | |
| 29 end | |
| 30 if #attr_str > 0 then | |
| 31 table.insert(attr_str, " }"); | |
| 32 end | |
| 33 if first then | |
| 34 code[#code+1] = (string.format("st.stanza(%q %s)", name, #attr_str>0 and table.concat(attr_str) or ", nil")); | |
| 35 first = nil; | |
| 36 else | |
| 37 code[#code+1] = (string.format(":tag(%q%s)", name, table.concat(attr_str))); | |
| 38 end | |
| 39 end | |
| 40 if text and text:match("%S") then | |
| 41 code[#code+1] = (string.format(":text(%q)", text)); | |
| 42 elseif short_close then | |
| 43 short_close = nil; | |
| 44 code[#code+1] = (":up()"); | |
| 45 end | |
| 46 end | |
| 47 return table.concat(code, ""); | |
| 48 end | |
| 49 | |
| 50 | |
| 51 function action_handlers.DROP() | |
| 52 return "log('debug', 'Firewall dropping stanza: %s', tostring(stanza)); return true;"; | |
| 53 end | |
| 54 | |
| 55 function action_handlers.STRIP(tag_desc) | |
| 56 local code = {}; | |
| 57 local name, xmlns = tag_desc:match("^(%S+) (.+)$"); | |
| 58 if not name then | |
| 59 name, xmlns = tag_desc, nil; | |
| 60 end | |
| 61 if name == "*" then | |
| 62 name = nil; | |
| 63 end | |
| 64 code[#code+1] = ("local stanza_xmlns = stanza.attr.xmlns; "); | |
| 65 code[#code+1] = "stanza:maptags(function (tag) if "; | |
| 66 if name then | |
| 67 code[#code+1] = ("tag.name == %q and "):format(name); | |
| 68 end | |
| 69 if xmlns then | |
| 70 code[#code+1] = ("(tag.attr.xmlns or stanza_xmlns) == %q "):format(xmlns); | |
| 71 else | |
| 72 code[#code+1] = ("tag.attr.xmlns == stanza_xmlns "); | |
| 73 end | |
| 74 code[#code+1] = "then return nil; end return tag; end );"; | |
| 75 return table.concat(code); | |
| 76 end | |
| 77 | |
| 78 function action_handlers.INJECT(tag) | |
| 79 return "stanza:add_child("..compile_xml(tag)..")", { "st" }; | |
| 80 end | |
| 81 | |
| 82 local error_types = { | |
| 83 ["bad-request"] = "modify"; | |
| 84 ["conflict"] = "cancel"; | |
| 85 ["feature-not-implemented"] = "cancel"; | |
| 86 ["forbidden"] = "auth"; | |
| 87 ["gone"] = "cancel"; | |
| 88 ["internal-server-error"] = "cancel"; | |
| 89 ["item-not-found"] = "cancel"; | |
| 90 ["jid-malformed"] = "modify"; | |
| 91 ["not-acceptable"] = "modify"; | |
| 92 ["not-allowed"] = "cancel"; | |
| 93 ["not-authorized"] = "auth"; | |
| 94 ["payment-required"] = "auth"; | |
| 95 ["policy-violation"] = "modify"; | |
| 96 ["recipient-unavailable"] = "wait"; | |
| 97 ["redirect"] = "modify"; | |
| 98 ["registration-required"] = "auth"; | |
| 99 ["remote-server-not-found"] = "cancel"; | |
| 100 ["remote-server-timeout"] = "wait"; | |
| 101 ["resource-constraint"] = "wait"; | |
| 102 ["service-unavailable"] = "cancel"; | |
| 103 ["subscription-required"] = "auth"; | |
| 104 ["undefined-condition"] = "cancel"; | |
| 105 ["unexpected-request"] = "wait"; | |
| 106 }; | |
| 107 | |
| 108 | |
| 109 local function route_modify(make_new, to, drop) | |
| 110 local reroute, deps = "session.send(newstanza)", { "st" }; | |
| 111 if to then | |
| 112 reroute = ("newstanza.attr.to = %q; core_post_stanza(session, newstanza)"):format(to); | |
| 113 deps[#deps+1] = "core_post_stanza"; | |
| 114 end | |
| 115 return ([[local newstanza = st.%s; %s; %s; ]]) | |
| 116 :format(make_new, reroute, drop and "return true" or ""), deps; | |
| 117 end | |
| 118 | |
| 119 function action_handlers.BOUNCE(with) | |
| 120 local error = with and with:match("^%S+") or "service-unavailable"; | |
| 121 local error_type = error:match(":(%S+)"); | |
| 122 if not error_type then | |
| 123 error_type = error_types[error] or "cancel"; | |
| 124 else | |
| 125 error = error:match("^[^:]+"); | |
| 126 end | |
| 127 error, error_type = string.format("%q", error), string.format("%q", error_type); | |
| 128 local text = with and with:match(" %((.+)%)$"); | |
| 129 if text then | |
| 130 text = string.format("%q", text); | |
| 131 else | |
| 132 text = "nil"; | |
| 133 end | |
| 134 return route_modify(("error_reply(stanza, %s, %s, %s)"):format(error_type, error, text), nil, true); | |
| 135 end | |
| 136 | |
| 137 function action_handlers.REDIRECT(where) | |
| 138 return route_modify("clone(stanza)", where, true, true); | |
| 139 end | |
| 140 | |
| 141 function action_handlers.COPY(where) | |
| 142 return route_modify("clone(stanza)", where, true, false); | |
| 143 end | |
| 144 | |
| 145 function action_handlers.LOG(string) | |
| 146 local level = string:match("^%[(%a+)%]") or "info"; | |
| 147 string = string:gsub("^%[%a+%] ?", ""); | |
| 148 return (("log(%q, %q)"):format(level, string) | |
| 149 :gsub("$top", [["..stanza:top_tag().."]]) | |
| 150 :gsub("$stanza", [["..stanza.."]]) | |
| 151 :gsub("$(%b())", [["..%1.."]])); | |
| 152 end | |
| 153 | |
| 154 function action_handlers.RULEDEP(dep) | |
| 155 return "", { dep }; | |
| 156 end | |
| 157 | |
| 158 return action_handlers; |
