Suricata lua continued
Today I improved the lua jit support in Suricata further. The scripts will now need to express their “needs” through an “init” function in the script that is called only at Suricata startup.
The “init” function fills a lua table. This will allow the user to indicate what buffers the script needs to inspect. The script will then only be invoked when these buffers are actually available, so the script won’t have to worry about whether or not some data is unavailable or not. Also, only these buffers are passed to the script, so safing the overhead of copying unnecessary buffers.
The earlier example extended:
[sourcecode] function init (args) local needs = {} needs[“packet”] = tostring(true) needs[“payload”] = tostring(true) return needs end
-- match if packet and payload both contain HTTP function match(args) pkt = 0 pay = 0
for k,v in pairs(args) do if tostring(k) == “packet” then a = tostring(v) if #a > 0 then if a:find(“HTTP”) then pkt = 1 end end elseif tostring(k) == “payload” then a = tostring(v) if #a > 0 then if a:find(“HTTP”) then pay = 1 end end end
if pay == 1 and pkt == 1 then return 1 end end
return 0 end
return 0 [/sourcecode]
The new part is: [sourcecode] function init (args) local needs = {} needs[“packet”] = tostring(true) needs[“payload”] = tostring(true) return needs end [/sourcecode]
Currently only “packet”, which is the complete raw packet including protocol headers such as ethernet, and “payload” are available. I will extend this to include “stream”, “http.uri”, “http.headers” and so on. Also, I was thinking that the script could also require a flowvar or flowint.
Another change is that the user can also return a table instead of just a 1 or 0. In that table “retval” is used as the return code. The idea here is that later we’ll be able to return flowvars and flowints as well. Example:
[sourcecode] function init (args) local needs = {} needs[“packet”] = tostring(true) return needs end
-- return match via table function match(args) local result = {} result[“retval”] = tostring(1) return result end [/sourcecode]
Here the the script always matches, and passes the match back to Suricata through a table.
So far mostly internal changes and no extra detection features, but it’s getting some more shape. Looking forward to feedback! :)