diff --git a/pandora_agents/win32/ChangeLog b/pandora_agents/win32/ChangeLog index 68f67a95a9..af36ed2c48 100644 --- a/pandora_agents/win32/ChangeLog +++ b/pandora_agents/win32/ChangeLog @@ -1,3 +1,10 @@ +2010-07-02 Ramon Novoa + + * modules/pandora_module.h, modules/pandora_module_factory.cc, + modules/pandora_module.cc, pandora_windows_service.cc: Added the + module_condition feature. See http://openideas.info/wiki/ for more + information. + 2010-06-30 Ramon Novoa * windows/pandora_wmi.cc: getDiskFreeSpacePercent should not return diff --git a/pandora_agents/win32/modules/pandora_module.cc b/pandora_agents/win32/modules/pandora_module.cc index a459ca2991..12222b56e7 100644 --- a/pandora_agents/win32/modules/pandora_module.cc +++ b/pandora_agents/win32/modules/pandora_module.cc @@ -44,6 +44,7 @@ Pandora_Module::Pandora_Module (string name) { this->async = false; this->data_list = NULL; this->inventory_list = NULL; + this->condition_list = NULL; } /** @@ -52,7 +53,27 @@ Pandora_Module::Pandora_Module (string name) { * Should be redefined by child classes. */ Pandora_Module::~Pandora_Module () { + Condition *cond = NULL; + list::iterator iter; + + /* Clean data lists */ this->cleanDataList (); + + /* Clean condition list */ + if (this->condition_list != NULL && this->condition_list->size () > 0) { + iter = this->condition_list->begin (); + for (iter = this->condition_list->begin (); + iter != this->condition_list->end (); + iter++) { + /* Free regular expressions */ + cond = *iter; + if (cond->string_value != "") { + regfree (&(cond->regexp)); + } + delete (*iter); + } + delete (this->condition_list); + } } @@ -594,3 +615,116 @@ string Pandora_Module::getSave () { return this->save; } + +/** + * Adds a new condition to the module. + * + * @param condition Condition string. + */ +void +Pandora_Module::addCondition (string condition) { + Condition *cond; + char operation[255], string_value[1024], command[1024]; + + /* Create the condition list if it does not exist */ + if (this->condition_list == NULL) { + this->condition_list = new list (); + if (this->condition_list == NULL) { + return; + } + } + + /* Create the new condition */ + cond = new Condition; + if (cond == NULL) { + return; + } + cond->value_1 = 0; + cond->value_2 = 0; + + /* Numeric comparison */ + if (sscanf (condition.c_str (), "%255s %lf %1024[^]", operation, &(cond->value_1), command) == 3) { + cond->operation = operation; + cond->command = command; + this->condition_list->push_back (cond); + /* Regular expression */ + } else if (sscanf (condition.c_str (), "=~ %1024s %1024[^]", string_value, command) == 2) { + cond->operation = "=~"; + cond->string_value = string_value; + cond->command = command; + if (regcomp (&(cond->regexp), string_value, 0) != 0) { + pandoraDebug ("Invalid regular expression %s", string_value); + delete (cond); + return; + } + this->condition_list->push_back (cond); + /* Interval */ + } else if (sscanf (condition.c_str (), "(%lf , %lf) %1024[^]", &(cond->value_1), &(cond->value_2), command) == 3) { + cond->operation = "()"; + cond->command = command; + this->condition_list->push_back (cond); + } else { + pandoraDebug ("Invalid module condition: %s", condition.c_str ()); + } +} + +/** + * Evaluates and executes module conditions. + */ +void +Pandora_Module::evaluateConditions () { + unsigned char run; + double double_value; + string string_value; + Condition *cond = NULL; + list::iterator iter; + PROCESS_INFORMATION pi; + STARTUPINFO si; + Pandora_Data *pandora_data = NULL; + regex_t regex; + + /* No data */ + if ( (!this->has_output) || this->data_list == NULL) { + return; + } + + /* Get the module data */ + pandora_data = data_list->front (); + + /* Get the string value of the data */ + string_value = pandora_data->getValue (); + + /* Get the double value of the data */ + try { + double_value = Pandora_Strutils::strtodouble (string_value); + } catch (Pandora_Strutils::Invalid_Conversion e) { + double_value = 0; + } + + if (this->condition_list != NULL && this->condition_list->size () > 0) { + iter = this->condition_list->begin (); + for (iter = this->condition_list->begin (); + iter != this->condition_list->end (); + iter++) { + cond = *iter; + run = 0; + if ((cond->operation == ">" && double_value > cond->value_1) || + (cond->operation == "<" && double_value < cond->value_1) || + (cond->operation == "=" && double_value == cond->value_1) || + (cond->operation == "!=" && double_value != cond->value_1) || + (cond->operation == "=~" && regexec (&(cond->regexp), string_value.c_str (), 0, NULL, 0) == 0) || + (cond->operation == "()" && double_value > cond->value_1 && double_value < cond->value_2)) { + + /* Run the condition command */ + ZeroMemory (&si, sizeof (si)); + ZeroMemory (&pi, sizeof (pi)); + if (CreateProcess (NULL , (CHAR *)cond->command.c_str (), NULL, NULL, FALSE, + CREATE_NO_WINDOW, NULL, NULL, &si, &pi) == 0) { + return; + } + WaitForSingleObject(pi.hProcess, this->module_timeout); + CloseHandle (pi.hProcess); + } + } + } +} diff --git a/pandora_agents/win32/modules/pandora_module.h b/pandora_agents/win32/modules/pandora_module.h index 191441baa6..23efc7e9fc 100644 --- a/pandora_agents/win32/modules/pandora_module.h +++ b/pandora_agents/win32/modules/pandora_module.h @@ -23,6 +23,7 @@ #include "../pandora.h" #include "pandora_data.h" +#include "boost/regex.h" #include #include @@ -87,6 +88,18 @@ namespace Pandora_Modules { MODULE_PLUGIN /**< Plugin */ } Module_Kind; + /** + * Defines the structure that holds module conditions. + */ + typedef struct { + double value_1; + double value_2; + string string_value; + string operation; + string command; + regex_t regexp; + } Condition; + const string module_exec_str = "module_exec"; const string module_proc_str = "module_proc"; const string module_service_str = "module_service"; @@ -140,6 +153,7 @@ namespace Pandora_Modules { string module_kind_str; Module_Kind module_kind; string save; + list *condition_list; protected: @@ -221,6 +235,8 @@ namespace Pandora_Modules { void setSave (string save); void exportDataOutput (); + void addCondition (string condition); + void evaluateConditions (); }; } diff --git a/pandora_agents/win32/modules/pandora_module_factory.cc b/pandora_agents/win32/modules/pandora_module_factory.cc index 2e961669c2..aa26601df8 100644 --- a/pandora_agents/win32/modules/pandora_module_factory.cc +++ b/pandora_agents/win32/modules/pandora_module_factory.cc @@ -81,6 +81,7 @@ using namespace Pandora_Strutils; #define TOKEN_REGEXP ("module_regexp ") #define TOKEN_PLUGIN ("module_plugin ") #define TOKEN_SAVE ("module_save ") +#define TOKEN_CONDITION ("module_condition ") string parseLine (string line, string token) { @@ -123,11 +124,13 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { string module_retries, module_startdelay, module_retrydelay; string module_perfcounter, module_tcpcheck; string module_port, module_timeout, module_regexp; - string module_plugin, module_save; + string module_plugin, module_save, module_condition; Pandora_Module *module; bool numeric; Module_Type type; long agent_interval; + list condition_list; + list::iterator condition_iter; module_name = ""; module_type = ""; @@ -143,7 +146,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { module_logevent = ""; module_source = ""; module_eventtype = ""; - module_eventcode = ""; + module_eventcode = ""; module_pattern = ""; module_application = ""; module_async = ""; @@ -160,7 +163,8 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { module_timeout = ""; module_regexp = ""; module_plugin = ""; - module_save = ""; + module_save = ""; + module_condition = ""; stringtok (tokens, definition, "\n"); @@ -285,6 +289,15 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { if (module_save == "") { module_save = parseLine (line, TOKEN_SAVE); } + if (module_condition == "") { + module_condition = parseLine (line, TOKEN_CONDITION); + + /* Queue the condition and keep looking for more */ + if (module_condition != "") { + condition_list.push_back (module_condition); + module_condition = ""; + } + } iter++; } @@ -380,18 +393,31 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { return NULL; } + /* Set module description */ if (module_description != "") { module->setDescription (module_description); } + /* Save module data as an environment variable */ if (module_save != "") { module->setSave (module_save); } + /* Async module */ if (module_async != "") { module->setAsync (true); } - + + /* Module condition */ + if (condition_list.size () > 0) { + condition_iter = condition_list.begin (); + for (condition_iter = condition_list.begin (); + condition_iter != condition_list.end (); + condition_iter++) { + module->addCondition (*condition_iter); + } + } + /* Plugins do not have a module type */ if (module_plugin == "") { type = Pandora_Module::parseModuleTypeFromString (module_type); diff --git a/pandora_agents/win32/pandora_windows_service.cc b/pandora_agents/win32/pandora_windows_service.cc index 9b1a32f345..5a857d8b71 100644 --- a/pandora_agents/win32/pandora_windows_service.cc +++ b/pandora_agents/win32/pandora_windows_service.cc @@ -282,9 +282,11 @@ Pandora_Windows_Service::copyTentacleDataFile (string host, WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess (pi.hProcess, &rc); if (rc != 0) { + CloseHandle (pi.hProcess); return -1; } + CloseHandle (pi.hProcess); return 0; } @@ -862,6 +864,9 @@ Pandora_Windows_Service::pandora_run () { module->exportDataOutput (); } + /* Evaluate module conditions */ + module->evaluateConditions (); + this->modules->goNext (); } }