From 7282c1eae410874f87de5f4d6d322492d0b2485c Mon Sep 17 00:00:00 2001 From: ramonn Date: Fri, 13 Jun 2008 10:32:47 +0000 Subject: [PATCH] 2008-06-13 Ramon Novoa * win32/PandoraAgent.dev: Updated. * win32/windows/pandora_wmi.cc, win32/windows/pandora_wmi.h, win32/pandora_windows_service.cc, win32/modules/pandora_module.h, win32/modules/pandora_module_logevent.cc, win32/modules/pandora_module_logevent.h, win32/modules/pandora_module_factory.cc, win32/modules/pandora_module_list.cc, win32/modules/pandora_module.c: Added a new module that checks for log events using WMI queries. * bin/pandora_agent.conf: Added encoding option and a Logevent module declaration example. git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@857 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f --- pandora_agents/ChangeLog | 14 +++ pandora_agents/win32/PandoraAgent.dev | 22 +++- pandora_agents/win32/bin/pandora_agent.conf | 11 ++ .../win32/modules/pandora_module.cc | 17 ++- pandora_agents/win32/modules/pandora_module.h | 5 +- .../win32/modules/pandora_module_factory.cc | 28 +++++ .../win32/modules/pandora_module_list.cc | 6 + .../win32/modules/pandora_module_logevent.cc | 59 +++++++++ .../win32/modules/pandora_module_logevent.h | 45 +++++++ .../win32/pandora_windows_service.cc | 15 ++- pandora_agents/win32/windows/pandora_wmi.cc | 115 ++++++++++++++++++ pandora_agents/win32/windows/pandora_wmi.h | 5 + 12 files changed, 335 insertions(+), 7 deletions(-) create mode 100755 pandora_agents/win32/modules/pandora_module_logevent.cc create mode 100755 pandora_agents/win32/modules/pandora_module_logevent.h diff --git a/pandora_agents/ChangeLog b/pandora_agents/ChangeLog index 9d4435b1a5..0a99522363 100644 --- a/pandora_agents/ChangeLog +++ b/pandora_agents/ChangeLog @@ -1,3 +1,17 @@ +2008-06-13 Ramon Novoa + + * win32/PandoraAgent.dev: Updated. + * win32/windows/pandora_wmi.cc, win32/windows/pandora_wmi.h, + win32/pandora_windows_service.cc, win32/modules/pandora_module.h, + win32/modules/pandora_module_logevent.cc, + win32/modules/pandora_module_logevent.h, + win32/modules/pandora_module_factory.cc, + win32/modules/pandora_module_list.cc, + win32/modules/pandora_module.c: Added a new module that checks for + log events using WMI queries. + * bin/pandora_agent.conf: Added encoding option and a Logevent module + declaration example. + 2008-06-11 Ramon Novoa * win32/pandora_strutils.cc, win32/pandora_strutils.h, diff --git a/pandora_agents/win32/PandoraAgent.dev b/pandora_agents/win32/PandoraAgent.dev index 7b75d74dfc..79a8691ab3 100644 --- a/pandora_agents/win32/PandoraAgent.dev +++ b/pandora_agents/win32/PandoraAgent.dev @@ -1,7 +1,7 @@ [Project] FileName=PandoraAgent.dev Name=PandoraAgent -UnitCount=75 +UnitCount=77 Type=1 Ver=1 ObjFiles= @@ -797,3 +797,23 @@ Priority=1000 OverrideBuildCmd=0 BuildCmd= +[Unit76] +FileName=modules\pandora_module_logevent.cc +CompileCpp=1 +Folder=Modules +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit77] +FileName=modules\pandora_module_logevent.h +CompileCpp=1 +Folder=Modules +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/pandora_agents/win32/bin/pandora_agent.conf b/pandora_agents/win32/bin/pandora_agent.conf index 9d1bd0f841..30b52424aa 100644 --- a/pandora_agents/win32/bin/pandora_agent.conf +++ b/pandora_agents/win32/bin/pandora_agent.conf @@ -47,6 +47,9 @@ odbc_ExampleDSN_password Password1234 # If set to 1 allows the agent to be configured via the web console. # remote_config 0 +# Set XML encoding (ISO-8859-1 by default). +# encoding ISO-8859-1 + # Module Definition # ================= @@ -193,3 +196,11 @@ module_end #module_cpuusage 1 #module_description CPU#1 usage #module_end + +# Log events +module_begin +module_name Logevents +module_type generic_data_string +module_logevent +module_description Log Events +module_end diff --git a/pandora_agents/win32/modules/pandora_module.cc b/pandora_agents/win32/modules/pandora_module.cc index 29be4a7ca7..b7b19cc93f 100644 --- a/pandora_agents/win32/modules/pandora_module.cc +++ b/pandora_agents/win32/modules/pandora_module.cc @@ -118,6 +118,9 @@ Pandora_Module::parseModuleKindFromString (string kind) { return MODULE_CPUUSAGE; } else if (kind == module_odbc_str) { return MODULE_ODBC; + } else if (kind == module_logevent_str) { + + return MODULE_LOGEVENT; } else { return MODULE_0; } @@ -219,7 +222,7 @@ Pandora_Module::getDataOutput (Pandora_Data *data) { } } - return data->getValue (); + return trim(data->getValue ()); } /** @@ -320,7 +323,7 @@ Pandora_Module::getXml () { if (this->data_list && this->data_list->size () > 1) { list::iterator iter; - data_list_element = new TiXmlElement ("data_list"); + data_list_element = new TiXmlElement ("datalist"); iter = this->data_list->begin (); for (iter = this->data_list->begin (); @@ -429,6 +432,16 @@ Pandora_Module::setInterval (int interval) { this->module_interval = interval; } +/** + * Get the execution interval. + * + * @return The execution interval. + */ +int +Pandora_Module::getInterval () { + return this->module_interval; +} + /** * Set the module description. * diff --git a/pandora_agents/win32/modules/pandora_module.h b/pandora_agents/win32/modules/pandora_module.h index 1f23ce975c..560551704c 100644 --- a/pandora_agents/win32/modules/pandora_module.h +++ b/pandora_agents/win32/modules/pandora_module.h @@ -69,7 +69,8 @@ namespace Pandora_Modules { MODULE_CPUUSAGE, /**< The module checks the CPU usage */ MODULE_FREEMEMORY, /**< The module checks the amount of * freememory in the system */ - MODULE_ODBC /**< The module performs a SQL query via ODBC */ + MODULE_ODBC, /**< The module performs a SQL query via ODBC */ + MODULE_LOGEVENT /**< The module checks for log events */ } Module_Kind; const string module_exec_str = "module_exec"; @@ -79,6 +80,7 @@ namespace Pandora_Modules { const string module_freememory_str = "module_freememory"; const string module_cpuusage_str = "module_cpuusage"; const string module_odbc_str = "module_odbc"; + const string module_logevent_str = "module_logevent"; /** * Pandora module super-class exception. @@ -144,6 +146,7 @@ namespace Pandora_Modules { parseModuleKindFromString (string kind); void setInterval (int interval); + int getInterval (); TiXmlElement *getXml (); diff --git a/pandora_agents/win32/modules/pandora_module_factory.cc b/pandora_agents/win32/modules/pandora_module_factory.cc index d29185f259..3a5eac0bf4 100644 --- a/pandora_agents/win32/modules/pandora_module_factory.cc +++ b/pandora_agents/win32/modules/pandora_module_factory.cc @@ -27,6 +27,7 @@ #include "pandora_module_freememory.h" #include "pandora_module_cpuusage.h" #include "pandora_module_odbc.h" +#include "pandora_module_logevent.h" #include "../pandora_strutils.h" #include @@ -48,6 +49,10 @@ using namespace Pandora_Strutils; #define TOKEN_MIN ("module_min ") #define TOKEN_DESCRIPTION ("module_description ") #define TOKEN_ODBC_QUERY ("module_odbc_query ") +#define TOKEN_LOGEVENT ("module_logevent") +#define TOKEN_SOURCE ("module_source ") +#define TOKEN_EVENTTYPE ("module_eventtype ") +#define TOKEN_PATTERN ("module_pattern ") string parseLine (string line, string token) { @@ -82,6 +87,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { string module_interval, module_proc, module_service; string module_freedisk, module_cpuusage, module_odbc; string module_odbc_query, module_dsn, module_freememory; + string module_logevent, module_source, module_eventtype, module_pattern; Pandora_Module *module; bool numeric; Module_Type type; @@ -97,6 +103,11 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { module_service = ""; module_odbc = ""; module_odbc_query = ""; + module_odbc = ""; + module_logevent = ""; + module_source = ""; + module_eventtype = ""; + module_pattern = ""; stringtok (tokens, definition, "\n"); @@ -149,6 +160,18 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { if (module_odbc_query == "") { module_odbc_query = parseLine (line, TOKEN_ODBC_QUERY); } + if (module_logevent == "") { + module_logevent = parseLine (line, TOKEN_LOGEVENT); + } + if (module_source == "") { + module_source = parseLine (line, TOKEN_SOURCE); + } + if (module_eventtype == "") { + module_eventtype = parseLine (line, TOKEN_EVENTTYPE); + } + if (module_pattern == "") { + module_pattern = parseLine (line, TOKEN_PATTERN); + } iter++; } @@ -186,6 +209,11 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { module = new Pandora_Module_Odbc (module_name, module_odbc, module_odbc_query); + } else if (module_logevent != "") { + module = new Pandora_Module_Logevent (module_name, + module_source, + module_eventtype, + module_pattern); } else { return NULL; } diff --git a/pandora_agents/win32/modules/pandora_module_list.cc b/pandora_agents/win32/modules/pandora_module_list.cc index 5b6ce7d3d3..f19afdd974 100644 --- a/pandora_agents/win32/modules/pandora_module_list.cc +++ b/pandora_agents/win32/modules/pandora_module_list.cc @@ -27,6 +27,7 @@ #include "pandora_module_freememory.h" #include "pandora_module_cpuusage.h" #include "pandora_module_odbc.h" +#include "pandora_module_logevent.h" #include using namespace std; @@ -115,6 +116,7 @@ Pandora_Modules::Pandora_Module_List::parseModuleDefinition (string definition) Pandora_Module_Cpuusage *module_cpuusage; Pandora_Module_Freememory *module_freememory; Pandora_Module_Odbc *module_odbc; + Pandora_Module_Logevent *module_logevent; module = Pandora_Module_Factory::getModuleFromDefinition (definition); @@ -156,6 +158,10 @@ Pandora_Modules::Pandora_Module_List::parseModuleDefinition (string definition) module_odbc = (Pandora_Module_Odbc *) module; modules->push_back (module_odbc); break; + case MODULE_LOGEVENT: + module_logevent = (Pandora_Module_Logevent *) module; + modules->push_back (module_logevent); + break; default: break; } diff --git a/pandora_agents/win32/modules/pandora_module_logevent.cc b/pandora_agents/win32/modules/pandora_module_logevent.cc new file mode 100755 index 0000000000..7b6d2e5c96 --- /dev/null +++ b/pandora_agents/win32/modules/pandora_module_logevent.cc @@ -0,0 +1,59 @@ +/* Pandora logevent module. This module checks for log events that match a given + pattern. + + Copyright (C) 2008 Artica ST. + Written by Ramon Novoa. + + 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 2, 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 "pandora_module_logevent.h" +#include "../windows/pandora_wmi.h" + +using namespace Pandora; +using namespace Pandora_Modules; + +/** + * Creates a Pandora_Module_Logevent object. + * + * @param name Module name. + * @param service_name Service internal name to check. + */ +Pandora_Module_Logevent::Pandora_Module_Logevent (string name, string source, string type, string pattern) + : Pandora_Module (name) { + + this->source = source; + this->type = type; + this->pattern = pattern; + this->setKind (module_logevent_str); +} + +void +Pandora_Module_Logevent::run () { + list event_list; + list::iterator event; + + try { + Pandora_Module::run (); + } catch (Interval_Not_Fulfilled e) { + return; + } + + Pandora_Wmi::getEventList (this->source, this->type, this->pattern, this->getInterval (), event_list); + + for(event = event_list.begin (); event != event_list.end(); ++event) { + this->setOutput (*event); + } +} diff --git a/pandora_agents/win32/modules/pandora_module_logevent.h b/pandora_agents/win32/modules/pandora_module_logevent.h new file mode 100755 index 0000000000..bdc74d79eb --- /dev/null +++ b/pandora_agents/win32/modules/pandora_module_logevent.h @@ -0,0 +1,45 @@ +/* Pandora logevent module. This module checks for log events that match a given + pattern. + + Copyright (C) 2008 Artica ST. + Written by Ramon Novoa. + + 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 2, 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. +*/ + +#ifndef __PANDORA_MODULE_LOGEVENT_H__ +#define __PANDORA_MODULE_LOGEVENT_H__ + +#include "pandora_module.h" + +namespace Pandora_Modules { + + /** + * This module checks for log events that match a given + * pattern. Events can be filtered by source and type. + */ + + class Pandora_Module_Logevent : public Pandora_Module { + private: + string source; + string type; + string pattern; + public: + Pandora_Module_Logevent (string name, string source, string type, string pattern); + void run (); + }; +} + +#endif diff --git a/pandora_agents/win32/pandora_windows_service.cc b/pandora_agents/win32/pandora_windows_service.cc index b6db308b19..b99078bd88 100644 --- a/pandora_agents/win32/pandora_windows_service.cc +++ b/pandora_agents/win32/pandora_windows_service.cc @@ -236,7 +236,7 @@ Pandora_Windows_Service::copyTentacleDataFile (string host, /* tentacle_client.exe error */ default: - pandoraLog ("Tentacle client was unable to copy %s", + pandoraDebug ("Tentacle client was unable to copy %s", filename.c_str ()); throw Pandora_Exception (); } @@ -432,7 +432,7 @@ Pandora_Windows_Service::recvTentacleDataFile (string host, /* tentacle_client.exe error */ default: - pandoraLog ("Tentacle client was unable to receive file %s", + pandoraDebug ("Tentacle client was unable to receive file %s", filename.c_str ()); throw Pandora_Exception (); } @@ -601,17 +601,19 @@ Pandora_Windows_Service::checkConfig () { void Pandora_Windows_Service::pandora_run () { + TiXmlDeclaration *decl; TiXmlDocument *doc; TiXmlElement *local_xml, *agent; string xml_filename, random_integer; string tmp_filename, tmp_filepath; + string encoding; bool saved; pandoraDebug ("Run begin"); /* Check for configuration changes */ this->checkConfig (); - + execution_number++; if (this->modules != NULL) { @@ -668,8 +670,15 @@ Pandora_Windows_Service::pandora_run () { tmp_filepath = xml_filename + tmp_filename; /* Copy the XML to temporal file */ + encoding = conf->getValue ("encoding"); + if (encoding == "") { + encoding = "ISO-8859-1"; + } + pandoraDebug ("Copying XML on %s", tmp_filepath.c_str ()); + decl = new TiXmlDeclaration( "1.0", encoding.c_str(), "" ); doc = new TiXmlDocument (tmp_filepath); + doc->InsertEndChild (*decl); doc->InsertEndChild (*agent); saved = doc->SaveFile(); delete doc; diff --git a/pandora_agents/win32/windows/pandora_wmi.cc b/pandora_agents/win32/windows/pandora_wmi.cc index a4179e78d5..4abf349a58 100644 --- a/pandora_agents/win32/windows/pandora_wmi.cc +++ b/pandora_agents/win32/windows/pandora_wmi.cc @@ -25,6 +25,7 @@ #include #include #include +#include using namespace std; using namespace Pandora_Wmi; @@ -380,3 +381,117 @@ Pandora_Wmi::getSystemName () { return ret; } + +/** + * Get a list of events that match a given pattern. + * + * @return The list of events. + */ +void +Pandora_Wmi::getEventList (string source, string type, string pattern, int interval, list &event_list) { + CDhInitialize init; + CDispPtr wmi_svc, quickfixes; + char *value = NULL; + string event, limit, message, query, timestamp; + + limit = getTimestampLimit(interval); + if (limit.empty()) { + pandoraDebug ("Pandora_Wmi::getEventList: getTimestampLimit error"); + return; + } + + // Build the WQL query + query = "SELECT * FROM Win32_NTLogEvent WHERE TimeWritten >= '" + limit + "'"; + if (! source.empty()) { + query += " AND Logfile = '" + source + "'"; + } + if (! type.empty()) { + query += " AND Type = '" + type + "'"; + } + + try { + dhCheck (dhGetObject (getWmiStr (L"."), NULL, &wmi_svc)); + dhCheck (dhGetValue (L"%o", &quickfixes, wmi_svc, + L".ExecQuery(%s)", + query.c_str())); + + FOR_EACH (quickfix, quickfixes, NULL) { + // Timestamp + dhGetValue (L"%s", &value, quickfix, + L".TimeWritten"); + timestamp = value; + dhFreeString (value); + + // Message + dhGetValue (L"%s", &value, quickfix, + L".Message"); + message = value; + dhFreeString (value); + + // LIKE is not always available, we have to filter ourselves + if (pattern.empty() || (message.find(pattern) != string::npos)) { + event = convertWMIDate(timestamp) + " " + message; + event_list.push_back(event); + } + + } NEXT_THROW (quickfix); + } catch (string errstr) { + pandoraDebug ("Pandora_Wmi::getEventList: error: %s", errstr.c_str ()); + } + + return; +} + +/** + * Returns the limit date (WMI format) for event searches. + * + * @return The timestamp in WMI format. + */ +string +Pandora_Wmi::getTimestampLimit (int interval) { + char limit_str[26]; + time_t limit_time; + struct tm *limit_tm = NULL; + + // Get current time + limit_time = time(0); + if (limit_time == (time_t)-1) { + return ""; + } + + // Substract the agent interval + limit_time -= interval; + + limit_tm = localtime (&limit_time); + if (limit_tm == NULL) { + return ""; + } + + // WMI date format: yyyymmddHHMMSS.xxxxxx+UUU + snprintf (limit_str, 26, "%.4d%.2d%.2d%.2d%.2d%.2d.000000+000", + limit_tm->tm_year + 1900, limit_tm->tm_mon + 1, + limit_tm->tm_mday, limit_tm->tm_hour, + limit_tm->tm_min, limit_tm->tm_sec); + + return string (limit_str); +} + +/* + * Converts a date in WMI format to 'dd-mm-YYYY HH:MM:SS' + * + * @return The date in the new format. + */ +string +Pandora_Wmi::convertWMIDate (string wmi_date) { + string year, month, day, hour, minute, second; + + year = wmi_date.substr (0, 4); + month = wmi_date.substr (4, 2); + day = wmi_date.substr (6, 2); + hour = wmi_date.substr (8, 2); + minute = wmi_date.substr (10, 2); + second = wmi_date.substr (12, 2); + + return string (year + "-" + month + "-" + day + " " + + hour + ":" + minute + ":" + second); +} diff --git a/pandora_agents/win32/windows/pandora_wmi.h b/pandora_agents/win32/windows/pandora_wmi.h index f4b43cf51c..ae8c0cb45b 100644 --- a/pandora_agents/win32/windows/pandora_wmi.h +++ b/pandora_agents/win32/windows/pandora_wmi.h @@ -47,6 +47,11 @@ namespace Pandora_Wmi { string getOSVersion (); string getOSBuild (); string getSystemName (); + void getEventList (string source, string type, string pattern, int interval, list &event_list); + string getTimestampLimit (int interval); + string convertWMIDate (string wmi_date); + + }; #endif