diff --git a/include/LuaEngine.h b/include/LuaEngine.h index 9212f4be46..2878c8e00d 100644 --- a/include/LuaEngine.h +++ b/include/LuaEngine.h @@ -41,7 +41,7 @@ class ThreadedActivityStats; class LuaEngine { protected: - lua_State *L; /**< The LuaEngine state.*/ + lua_State *L; /**< The LuaEngine state. */ char *loaded_script_path; void lua_register_classes(lua_State *L, bool http_mode); diff --git a/include/flow_checks/CustomFlowLuaScript.h b/include/flow_checks/CustomFlowLuaScript.h index d4b30401ae..f1677fb933 100644 --- a/include/flow_checks/CustomFlowLuaScript.h +++ b/include/flow_checks/CustomFlowLuaScript.h @@ -26,13 +26,11 @@ class CustomFlowLuaScript : public FlowCheck { private: + LuaEngine *lua; public: - CustomFlowLuaScript() : FlowCheck(ntopng_edition_community, - false /* All interfaces */, false /* Don't exclude for nEdge */, - false /* NOT only for nEdge */, true /* has_protocol_detected */, - false /* has_periodic_update */, false /* has_flow_end */) {}; - ~CustomFlowLuaScript() {}; + CustomFlowLuaScript(); + ~CustomFlowLuaScript(); bool loadConfiguration(json_object *config); void protocolDetected(Flow *f); diff --git a/scripts/callbacks/custom_flow_lua_script.lua b/scripts/callbacks/custom_flow_lua_script.lua new file mode 100644 index 0000000000..1a104499f2 --- /dev/null +++ b/scripts/callbacks/custom_flow_lua_script.lua @@ -0,0 +1,7 @@ + +function flow_key() + return "[ ".. flow.protocol() .. " ]" .. flow.cli() .. ":" .. flow.cli_port() .. " <-> ".. flow.srv() .. ":" .. flow.srv_port() +end + +io.write(flow_key() .. " [bytes: ".. flow.bytes().."]\n") +return(0) diff --git a/src/LuaEngine.cpp b/src/LuaEngine.cpp index 4cfd9e3634..1f88a0b889 100644 --- a/src/LuaEngine.cpp +++ b/src/LuaEngine.cpp @@ -34,6 +34,7 @@ struct keyval string_to_replace[MAX_NUM_HTTP_REPLACEMENTS] = { { NULL, NULL } }; extern luaL_Reg *ntop_interface_reg; extern luaL_Reg *ntop_reg; extern luaL_Reg *ntop_network_reg; +extern luaL_Reg *ntop_flow_reg; #define HTTP_MAX_UPLOAD_DATA_LEN 25000000 /* ~25MB (see also upload_pcap.template) */ @@ -463,6 +464,7 @@ void LuaEngine::lua_register_classes(lua_State *L, bool http_mode) { luaRegister(L, "interface", ntop_interface_reg); luaRegister(L, "ntop", ntop_reg); luaRegister(L, "network", ntop_network_reg); + luaRegister(L, "flow", ntop_flow_reg); if(http_mode) { /* Overload the standard Lua print() with ntop_lua_http_print that dumps data on HTTP server */ @@ -591,7 +593,7 @@ int LuaEngine::run_loaded_script() { lua_pushvalue(L, -1); /* Perform the actual call */ - if(lua_pcall(L, 0, 0, 0) != 0) { + if(lua_pcall(L, 0, LUA_MULTRET /* Allow the script to be called multiple times */, 0) != 0) { if(lua_type(L, -1) == LUA_TSTRING) { const char *err = lua_tostring(L, -1); ntop->getTrace()->traceEvent(TRACE_WARNING, "Script failure [%s][%s]", loaded_script_path, err ? err : ""); diff --git a/src/LuaEngineFlow.cpp b/src/LuaEngineFlow.cpp new file mode 100644 index 0000000000..243e814489 --- /dev/null +++ b/src/LuaEngineFlow.cpp @@ -0,0 +1,141 @@ +/* + * + * (C) 2013-22 - ntop.org + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "ntop_includes.h" + +/* ****************************************** */ + +static int ntop_flow_get_bytes(lua_State* vm) { + struct ntopngLuaContext *c = getLuaVMContext(vm); + Flow *f = c ? c->flow : NULL; + + if(f) + lua_pushinteger(vm, f->get_bytes()); + else + lua_pushnil(vm); + + return(ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_OK)); +} + +/* **************************************************************** */ + +static int ntop_flow_get_client(lua_State* vm) { + struct ntopngLuaContext *c = getLuaVMContext(vm); + Flow *f = c ? c->flow : NULL; + + if(f && f->get_cli_ip_addr()) { + char buf[64]; + + lua_pushstring(vm, f->get_cli_ip_addr()->print(buf, sizeof(buf))); + } else + lua_pushnil(vm); + + return(ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_OK)); +} + +/* **************************************************************** */ + +static int ntop_flow_get_client_port(lua_State* vm) { + struct ntopngLuaContext *c = getLuaVMContext(vm); + Flow *f = c ? c->flow : NULL; + + if(f) + lua_pushinteger(vm, f->get_cli_port()); + else + lua_pushnil(vm); + + return(ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_OK)); +} + +/* **************************************************************** */ + +static int ntop_flow_get_server(lua_State* vm) { + struct ntopngLuaContext *c = getLuaVMContext(vm); + Flow *f = c ? c->flow : NULL; + + if(f && f->get_srv_ip_addr()) { + char buf[64]; + + lua_pushstring(vm, f->get_srv_ip_addr()->print(buf, sizeof(buf))); + } else + lua_pushnil(vm); + + return(ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_OK)); +} + +/* **************************************************************** */ + +static int ntop_flow_get_server_port(lua_State* vm) { + struct ntopngLuaContext *c = getLuaVMContext(vm); + Flow *f = c ? c->flow : NULL; + + if(f) + lua_pushinteger(vm, f->get_srv_port()); + else + lua_pushnil(vm); + + return(ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_OK)); +} + +/* **************************************************************** */ + +static int ntop_flow_get_protocol(lua_State* vm) { + struct ntopngLuaContext *c = getLuaVMContext(vm); + Flow *f = c ? c->flow : NULL; + + if(f) + lua_pushinteger(vm, f->get_protocol()); + else + lua_pushnil(vm); + + return(ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_OK)); +} + +/* **************************************************************** */ + +static int ntop_flow_get_vlan_id(lua_State* vm) { + struct ntopngLuaContext *c = getLuaVMContext(vm); + Flow *f = c ? c->flow : NULL; + + if(f) + lua_pushinteger(vm, f->get_vlan_id()); + else + lua_pushnil(vm); + + return(ntop_lua_return_value(vm, __FUNCTION__, CONST_LUA_OK)); +} + + +/* **************************************************************** */ + +static luaL_Reg _ntop_flow_reg[] = { + { "cli", ntop_flow_get_client }, + { "cli_port", ntop_flow_get_client_port }, + { "srv", ntop_flow_get_server }, + { "srv_port", ntop_flow_get_server_port }, + { "protocol", ntop_flow_get_protocol }, + { "vlan_id", ntop_flow_get_vlan_id }, + { "bytes", ntop_flow_get_bytes }, + + { NULL, NULL } +}; + +luaL_Reg *ntop_flow_reg = _ntop_flow_reg; diff --git a/src/flow_checks/CustomFlowLuaScript.cpp b/src/flow_checks/CustomFlowLuaScript.cpp index 88460fc815..f03a4bf579 100644 --- a/src/flow_checks/CustomFlowLuaScript.cpp +++ b/src/flow_checks/CustomFlowLuaScript.cpp @@ -22,24 +22,65 @@ #include "ntop_includes.h" #include "flow_checks_includes.h" -void CustomFlowLuaScript::protocolDetected(Flow *f) { - bool triggered = false; +/* ***************************************************** */ - /* Run script */ - if(true) { - char buf[128]; +CustomFlowLuaScript::CustomFlowLuaScript() : FlowCheck(ntopng_edition_community, + false /* All interfaces */, + false /* Don't exclude for nEdge */, + false /* NOT only for nEdge */, + true /* has_protocol_detected */, + false /* has_periodic_update */, + false /* has_flow_end */) { + const char *script_path = "scripts/callbacks/custom_flow_lua_script.lua"; + char where[256]; + struct stat s; - ntop->getTrace()->traceEvent(TRACE_NORMAL, "Running Lua script on %s", f->print(buf, sizeof(buf))); - } + snprintf(where, sizeof(where), "%s/%s", ntop->get_install_dir(), script_path); - if(triggered) { - FlowAlertType alert_type = CustomFlowLuaScriptAlert::getClassType(); - u_int8_t c_score, s_score; - risk_percentage cli_score_pctg = CLIENT_FAIR_RISK_PERCENTAGE; + if(stat(where, &s) != 0) { + ntop->getTrace()->traceEvent(TRACE_WARNING, "Unable to find script %s", where); - computeCliSrvScore(alert_type, cli_score_pctg, &c_score, &s_score); + lua = NULL; + } else { + try { + lua = new LuaEngine(NULL); + lua->load_script((char*)where, NULL /* NetworkInterface filled later via lua->setFlow(f); */); + } catch(std::bad_alloc& ba) { + ntop->getTrace()->traceEvent(TRACE_ERROR, "[HTTP] Unable to start Lua interpreter."); + } + } +} - f->triggerAlertAsync(alert_type, c_score, s_score); +/* ***************************************************** */ + +CustomFlowLuaScript::~CustomFlowLuaScript() { + if(lua) delete lua; +} + +/* ***************************************************** */ + +void CustomFlowLuaScript::protocolDetected(Flow *f) { + if(lua != NULL) { + bool triggered = false; + + if(false) { + char buf[128]; + + ntop->getTrace()->traceEvent(TRACE_NORMAL, "Running Lua script on %s", f->print(buf, sizeof(buf))); + } + lua->setFlow(f); + lua->run_loaded_script(); /* Run script */ + + + if(triggered) { + FlowAlertType alert_type = CustomFlowLuaScriptAlert::getClassType(); + u_int8_t c_score, s_score; + risk_percentage cli_score_pctg = CLIENT_FAIR_RISK_PERCENTAGE; + + computeCliSrvScore(alert_type, cli_score_pctg, &c_score, &s_score); + + f->triggerAlertAsync(alert_type, c_score, s_score); + } } }