"Fossies" - the Fresh Open Source Software Archive

Member "ettercap-0.8.3.1/src/lua/share/core/ettercap.lua" (1 Aug 2020, 9717 Bytes) of package /linux/privat/ettercap-0.8.3.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Lua source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "ettercap.lua": 0.8.3_vs_0.8.3.1.

    1 ---
    2 -- Basic ettercap functionality!
    3 --
    4 --    Copyright (C) Ryan Linn and Mike Ryan
    5 --
    6 --    This program is free software; you can redistribute it and/or modify
    7 --    it under the terms of the GNU General Public License as published by
    8 --    the Free Software Foundation; either version 2 of the License, or
    9 --    (at your option) any later version.
   10 --
   11 --    This program is distributed in the hope that it will be useful,
   12 --    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 --    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 --    GNU General Public License for more details.
   15 --
   16 
   17 --    You should have received a copy of the GNU General Public License along
   18 --    with this program; if not, write to the Free Software Foundation, Inc.,
   19 --    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   20 
   21 -- 
   22 
   23 
   24 -- All of our core stuff will reside in the "ettercap" namespace.
   25 ettercap = {}
   26 
   27 local ffi = require("ettercap_ffi")
   28 require('packet_meta')
   29 local ettercap_c = require("ettercap_c")
   30 local eclib = require("eclib")
   31 local op = require('io')
   32 ettercap.reg = require("ettercap_reg")
   33 
   34 --- Log's a message using ettercap's ui_msg function.
   35 -- @see string.format
   36 -- @param fmt The format string
   37 -- @param ... Variable arguments to pass in
   38 log = function(fmt, ...) 
   39   -- We don't want any format string "accidents" on the C side of things.. 
   40   -- so, we will let lua handle it.
   41   ettercap_c.log(string.format(fmt, ...))
   42 end
   43 
   44 file_exists = function(filename)
   45   local msg = nil
   46   local fio, errmsg, errno = io.open(filename, "r")
   47   if fio then
   48     fio:close()
   49     return true
   50   end
   51 
   52   assert(errno == 2, "Could not open '" .. filename .. "': " .. errmsg)
   53 
   54   return false
   55 end
   56 
   57 require('dumper')
   58 
   59 --- Dumps data structure(s) to log
   60 -- @param ... The data to dump!
   61 dump = function (...)
   62   log(DataDumper(...), "\n---")
   63 end
   64 
   65 -- Script interface
   66 --
   67 -- All Ettercap LUA scripts are initialized using a common interface. We've 
   68 -- modeled this interface very closely after that of NMAP's NSE script 
   69 -- interface. Our hope is that the community's familiarity with NSE will 
   70 -- lower the barrier for entry for those looking to write Ettercap LUA 
   71 -- scripts.
   72 --
   73 --
   74 --  Data structures:
   75 --    packet_object - Access to the Ettercap "packet_object" (originally 
   76 --                    defined in include/ec_packet.h) is provided via a 
   77 --                    light luajit FFI wrapper. Details on interacting with 
   78 --                    data-types via luajit FFI can be found here:
   79 --                    http://luajit.org/ext_ffi_semantics.html. 
   80 --
   81 --                    Generally, script implementations should avoid direct
   82 --                    modifications to packet_object, or any FFI wrapped 
   83 --                    structure, instead favoring modification through 
   84 --                    defined ettercap.* interfaces.
   85 --
   86 --                    NOTE: Careful consideration must be taken to when 
   87 --                    interacting with FFI-wrapped data-structures! Data 
   88 --                    originating from outside of the LUA VM must have their
   89 --                    memory managed *manually*! See the section of luajit's
   90 --                    FFI Semantics on "Garbage Collection of cdata Objects"
   91 --                    for details. 
   92 --                    
   93 --
   94 --  Script requirements:
   95 --
   96 --    description - (string) Like that of NSE, each script must have a 
   97 --                  description of the its functionality.
   98 --
   99 --    action      - (function (packet_object)) The action of a script operates
  100 --                  on a FFI-wrapped packet_object. 
  101 --
  102 --  Optional:
  103 --
  104 --    packetrule  - (function (packet_object)) If implemented, then this 
  105 --                  function must return true for a given packet_object 
  106 --                  before that packet_object is passed to the script's action.
  107 --
  108 
  109 local Script = {}
  110 
  111 do
  112   local coroutine = require "coroutine";
  113   local debug = require "debug";
  114   local traceback = debug.traceback;
  115 
  116   local ETTERCAP_SCRIPT_RULES = {
  117     packetrule = "packetrule",
  118   };
  119 
  120   -- These are the components of a script that are required. 
  121   local REQUIRED_FIELDS = {
  122     description = "string",
  123     action = "function",
  124 --    categories = "table",
  125 --    dependencies = "table",
  126   };
  127 
  128   function Script.new (filename, arguments)
  129     local script_params = arguments or {};  
  130     local script_path = filename 
  131     local full_path = ETTERCAP_LUA_SCRIPT_PATH .. "/" .. filename;
  132 
  133     local file_closure = nil
  134 
  135     if file_exists(filename) == true then
  136       file_closure = assert(loadfile(filename))
  137       script_path = filename
  138     elseif file_exists(full_path) == true then
  139       file_closure = assert(loadfile(full_path))
  140       script_path = full_path
  141     else
  142       log("ERROR: Could not find script '%s'\n", filename)
  143       return nil
  144     end
  145 
  146     local env = {
  147       SCRIPT_PATH = script_path,
  148       SCRIPT_ARGS = script_params,
  149       dependencies = {},
  150     };
  151 
  152     -- No idea what this does.
  153     setmetatable(env, {__index = _G});
  154     setfenv(file_closure, env);
  155 
  156     local co = coroutine.create(file_closure); -- Create a garbage thread
  157     local status, e = coroutine.resume(co); -- Get the globals it loads in env
  158 
  159     if not status then
  160       log("Failed to load %s:\n%s", filename, traceback(co, e));
  161       --error("could not load script");
  162       return nil
  163     end
  164 
  165     for required_field_name in pairs(REQUIRED_FIELDS) do
  166       local required_type = REQUIRED_FIELDS[required_field_name];
  167       local raw_field = rawget(env, required_field_name)
  168       local actual_type = type(raw_field);
  169       assert(actual_type == required_type, 
  170              "Incorrect of missing field: '" .. required_field_name .. "'." ..
  171              " Must be of type: '" .. required_type .. "'" ..
  172              " got type: '" .. actual_type .. "'." ..
  173              " Script: '" .. env["SCRIPT_PATH"] .. "'"
  174 
  175       );
  176     end
  177 
  178     -- Check our rules....
  179     local rules = {};
  180     for rule in pairs(ETTERCAP_SCRIPT_RULES) do
  181       local rulef = rawget(env, rule);
  182       assert(type(rulef) == "function" or rulef == nil,
  183           rule.." must be a function!");
  184       rules[rule] = rulef;
  185     end
  186     local action = env["action"];
  187 
  188     -- Make sure we have a hook_point!
  189     local hook_point = rawget(env, "hook_point")
  190     assert(type(hook_point) == "number", "hook_point must be a number!")
  191  
  192     local script = {
  193       filename = filename,
  194       action = action,
  195       rules = rules,
  196       hook_point = hook_point,
  197       env = env,
  198       file_closure = file_closure,
  199       script_params = script_params
  200     };
  201     
  202     return setmetatable(script, {__index = Script, __metatable = Script});
  203   end
  204 end
  205 
  206 -- Stores hook mappings.
  207 --- Called during ettercap's shutdown
  208 local ettercap_cleanup = function() 
  209 end
  210 
  211 local packet_object_ctype = ffi.typeof("struct packet_object *")
  212 local ffi_cast = ffi.cast
  213 
  214 local create_hook = function(script)
  215   local packetrule = script.rules["packetrule"]
  216   local hook_func = function(packet_object_ptr) 
  217     local packet_object = ffi_cast(packet_object_ctype, packet_object_ptr);
  218     if (not(packetrule == nil)) then
  219       if not(packetrule(packet_object) == true) then
  220         return false
  221       end
  222     end
  223     script.action(packet_object)
  224   end
  225   return(hook_func)
  226 end
  227 
  228 -- Adds a hook
  229 local hook_add = function (hook_point, func)
  230   ettercap_c.hook_add(hook_point, func)
  231 end
  232 
  233 -- Processes all the --lua-script arguments into a single list of script
  234 -- names. 
  235 --
  236 -- @param scripts An array of script cli arguments
  237 -- @return A table containing all the split arguments
  238 local cli_split_scripts = function (scripts)
  239   -- This keeps track of what script names have already been encountered. 
  240   -- This prevents us from loading the same script more than once.
  241   local loaded_scripts = {}
  242 
  243   local ret = {}
  244   for v = 1, #scripts do
  245     local s = scripts[v]
  246     local script_list = eclib.split(s, ",")
  247     for i = 1, #script_list do 
  248       if (loaded_scripts[script_list[i]] == nil) then
  249         -- We haven't loaded this script, yet, so add it it our list.
  250         table.insert(ret, script_list[i])
  251         loaded_scripts[script_list[i]] = 1
  252       end
  253     end 
  254   end
  255 
  256   return ret
  257 end
  258 
  259 -- Processes all the --lua-args arguments into a single list of args
  260 -- names. 
  261 --
  262 -- @param args An array of args cli arguments
  263 -- @return A table containing all the split arguments
  264 local cli_split_args = function (args)
  265   local ret = {}
  266   for v = 1, #args do
  267     local s = args[v]
  268     local arglist = eclib.split(s, ",")
  269     for i = 1, #arglist do 
  270       -- We haven't loaded this args, yet, so add it it our list.
  271       local temp = eclib.split(arglist[i],"=")
  272       ret[temp[1]] = temp[2]
  273     end 
  274   end
  275 
  276   return ret
  277 end
  278 
  279 -- Loads a script.
  280 --
  281 -- @param name (string) The name of the script we want to load.
  282 -- @param args (table) A table of key,value tuples
  283 local ettercap_load_script = function (name, args)
  284   local script = assert(Script.new(name, args), "Failed to load: " .. name)
  285   hook_add(script.hook_point, create_hook(script))
  286 end
  287 
  288 -- Primary entry point for ettercap lua environment
  289 -- @param lua_scripts Array of CLI script strings
  290 -- @param lua_args Array of CLI argument strings
  291 local ettercap_main = function (lua_scripts, lua_args)
  292   local scripts = cli_split_scripts(lua_scripts)
  293   local args = cli_split_args(lua_args)
  294   for i = 1, #scripts do
  295     ettercap_load_script(scripts[i], args)
  296   end
  297 end
  298 
  299 -- C -> LUA api functions. These should never be called from scripts!
  300 ettercap.main = ettercap_main
  301 ettercap.cleanup = ettercap_cleanup
  302 
  303 -- Global functions
  304 
  305 ettercap.log = log
  306 ettercap.dump = dump
  307 
  308 -- Is this even nescessary? Nobody should be requiring this except for 
  309 -- init.lua... However, I'll act like this is required.
  310 return ettercap