diff --git a/pandora_agents/win32/ChangeLog b/pandora_agents/win32/ChangeLog index d33ba58b63..50fef03bce 100644 --- a/pandora_agents/win32/ChangeLog +++ b/pandora_agents/win32/ChangeLog @@ -1,3 +1,30 @@ +2008-11-28 Esteban Sanchez + + * modules/pandora_module.[cc,h]: Added an async property. Added + getLatestOutput() to get the latest output of a module. + + * modules/pandora_module_factory.cc: Parse async token in modules. + + * modules/pandora_module_list.[cc,h]: It can create empty lists now + and add modules using new addModule() function. + + * modules/pandora_module_service.[cc,h]: Added an async thread to + watch services events and track services status changes quickly and + asynchronously. + + * windows/pandora_wmi.cc: Style correction. + + * pandora_windows_service.[cc,h]: Pandora Windows service object is + now single instance, so the instance to the running service can be + accessed anywhere (useful in async threads). The XML generation and + sending process has been moved to a new function called sendXml() + which is thread-safe. + + * windows_service.h: Some properties are now protected instead of + public to make it easier the singleton pattern in child classes. + + * main.cc: Adopted to singleton pattern in Pandora windows service. + 2008-11-26 Esteban Sanchez * pandora_strutils.cc, pandora_strutils.h, ftp/pandora_ftp_client.cc, diff --git a/pandora_agents/win32/main.cc b/pandora_agents/win32/main.cc index 4be38cc6b2..3bf8dc20c5 100644 --- a/pandora_agents/win32/main.cc +++ b/pandora_agents/win32/main.cc @@ -1,129 +1,131 @@ -/* Pandora Windows agent main file. - - Copyright (C) 2006 Artica ST. - Written by Esteban Sanchez. - - 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.h" -#include "pandora_windows_service.h" -#include "ssh/pandora_ssh_test.h" -#include "ftp/pandora_ftp_test.h" - -#define PATH_SIZE _MAX_PATH+1 -#define SERVICE_INSTALL_CMDLINE_PARAM "--install" -#define SERVICE_UNINSTALL_CMDLINE_PARAM "--uninstall" -#define SSH_TEST_CMDLINE_PARAM "--test-ssh" -#define FTP_TEST_CMDLINE_PARAM "--test-ftp" -#define HELP_CMDLINE_PARAM "--help" - -int -main (int argc, char *argv[]) { - Pandora_Windows_Service *service; - char buffer[PATH_SIZE]; - string aux; - unsigned int pos; - - service = new Pandora_Windows_Service (Pandora::name, Pandora::display_name, - Pandora::description); - - GetModuleFileName (NULL, buffer, MAX_PATH); - aux = buffer; - Pandora::setPandoraInstallPath (aux); - pos = aux.rfind ("\\"); - aux.erase (pos + 1); - Pandora::setPandoraInstallDir (aux); - - /* Check the parameters */ - for (int i = 1; i < argc; i++) { - if (_stricmp(argv[i], SERVICE_INSTALL_CMDLINE_PARAM) == 0) { - /* Install parameter */ - service->install (Pandora::getPandoraInstallPath ().c_str ()); - - delete service; - - return 0; - } else if (_stricmp(argv[i], SERVICE_UNINSTALL_CMDLINE_PARAM) == 0) { - /* Uninstall parameter */ - service->uninstall (); - - delete service; - - return 0; - } else if (_stricmp(argv[i], SSH_TEST_CMDLINE_PARAM) == 0) { - /* SSH test parameter */ - SSH::Pandora_SSH_Test ssh_test; - - delete service; - - try { - ssh_test.test (); - } catch (Pandora_Exception e) { - return 1; - } - - return 0; - } else if (_stricmp(argv[i], FTP_TEST_CMDLINE_PARAM) == 0) { - /* SSH test parameter */ - FTP::Pandora_FTP_Test ftp_test; - - delete service; - - try { - ftp_test.test (); - } catch (Pandora_Exception e) { - return 1; - } - - return 0; - - } else if (_stricmp(argv[i], HELP_CMDLINE_PARAM) == 0) { - /* Help parameter */ - cout << "Pandora agent for Windows. "; - cout << "Version " << getPandoraAgentVersion () << endl; - cout << "Usage: " << argv[0] << " [OPTION]" << endl << endl; - cout << "Available options are:" << endl; - cout << "\t" << SERVICE_INSTALL_CMDLINE_PARAM; - cout << ": Install the Pandora Agent service." << endl; - cout << "\t" << SERVICE_UNINSTALL_CMDLINE_PARAM; - cout << ": Uninstall the Pandora Agent service." << endl; - cout << "\t" << SSH_TEST_CMDLINE_PARAM; - cout << ": Test the SSH Pandora Agent configuration." << endl; - cout << "\t" << FTP_TEST_CMDLINE_PARAM; - cout << ": Test the FTP Pandora Agent configuration." << endl; - - return 0; - } else { - /* No parameter recognized */ - cout << "Pandora agent for Windows. "; - cout << "Version " << getPandoraAgentVersion () << endl; - cout << "Usage: " << argv[0] << " [" << SERVICE_INSTALL_CMDLINE_PARAM; - cout << "] [" << SERVICE_UNINSTALL_CMDLINE_PARAM; - cout << "] [" << SSH_TEST_CMDLINE_PARAM; - cout << "] [" << FTP_TEST_CMDLINE_PARAM << "]"; - cout << endl << endl; - cout << "Run " << argv[0] << " with " << HELP_CMDLINE_PARAM; - cout << " parameter for more info." << endl; - - return 1; - } - } - service->run (); - - delete service; - - return 0; -} +/* Pandora Windows agent main file. + + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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.h" +#include "pandora_windows_service.h" +#include "ssh/pandora_ssh_test.h" +#include "ftp/pandora_ftp_test.h" + +#define PATH_SIZE _MAX_PATH+1 +#define SERVICE_INSTALL_CMDLINE_PARAM "--install" +#define SERVICE_UNINSTALL_CMDLINE_PARAM "--uninstall" +#define SSH_TEST_CMDLINE_PARAM "--test-ssh" +#define FTP_TEST_CMDLINE_PARAM "--test-ftp" +#define HELP_CMDLINE_PARAM "--help" + +int +main (int argc, char *argv[]) { + Pandora_Windows_Service *service; + char buffer[PATH_SIZE]; + string aux; + unsigned int pos; + + service = Pandora_Windows_Service::getInstance (); + service->setValues (Pandora::name, Pandora::display_name, + Pandora::description); + service->start (); + + GetModuleFileName (NULL, buffer, MAX_PATH); + aux = buffer; + Pandora::setPandoraInstallPath (aux); + pos = aux.rfind ("\\"); + aux.erase (pos + 1); + Pandora::setPandoraInstallDir (aux); + + /* Check the parameters */ + for (int i = 1; i < argc; i++) { + if (_stricmp(argv[i], SERVICE_INSTALL_CMDLINE_PARAM) == 0) { + /* Install parameter */ + service->install (Pandora::getPandoraInstallPath ().c_str ()); + + delete service; + + return 0; + } else if (_stricmp(argv[i], SERVICE_UNINSTALL_CMDLINE_PARAM) == 0) { + /* Uninstall parameter */ + service->uninstall (); + + delete service; + + return 0; + } else if (_stricmp(argv[i], SSH_TEST_CMDLINE_PARAM) == 0) { + /* SSH test parameter */ + SSH::Pandora_SSH_Test ssh_test; + + delete service; + + try { + ssh_test.test (); + } catch (Pandora_Exception e) { + return 1; + } + + return 0; + } else if (_stricmp(argv[i], FTP_TEST_CMDLINE_PARAM) == 0) { + /* SSH test parameter */ + FTP::Pandora_FTP_Test ftp_test; + + delete service; + + try { + ftp_test.test (); + } catch (Pandora_Exception e) { + return 1; + } + + return 0; + + } else if (_stricmp(argv[i], HELP_CMDLINE_PARAM) == 0) { + /* Help parameter */ + cout << "Pandora agent for Windows. "; + cout << "Version " << getPandoraAgentVersion () << endl; + cout << "Usage: " << argv[0] << " [OPTION]" << endl << endl; + cout << "Available options are:" << endl; + cout << "\t" << SERVICE_INSTALL_CMDLINE_PARAM; + cout << ": Install the Pandora Agent service." << endl; + cout << "\t" << SERVICE_UNINSTALL_CMDLINE_PARAM; + cout << ": Uninstall the Pandora Agent service." << endl; + cout << "\t" << SSH_TEST_CMDLINE_PARAM; + cout << ": Test the SSH Pandora Agent configuration." << endl; + cout << "\t" << FTP_TEST_CMDLINE_PARAM; + cout << ": Test the FTP Pandora Agent configuration." << endl; + + return 0; + } else { + /* No parameter recognized */ + cout << "Pandora agent for Windows. "; + cout << "Version " << getPandoraAgentVersion () << endl; + cout << "Usage: " << argv[0] << " [" << SERVICE_INSTALL_CMDLINE_PARAM; + cout << "] [" << SERVICE_UNINSTALL_CMDLINE_PARAM; + cout << "] [" << SSH_TEST_CMDLINE_PARAM; + cout << "] [" << FTP_TEST_CMDLINE_PARAM << "]"; + cout << endl << endl; + cout << "Run " << argv[0] << " with " << HELP_CMDLINE_PARAM; + cout << " parameter for more info." << endl; + + return 1; + } + } + service->run (); + + delete service; + + return 0; +} diff --git a/pandora_agents/win32/modules/pandora_module.cc b/pandora_agents/win32/modules/pandora_module.cc index f264617c4f..d18a38c63a 100644 --- a/pandora_agents/win32/modules/pandora_module.cc +++ b/pandora_agents/win32/modules/pandora_module.cc @@ -39,7 +39,8 @@ Pandora_Module::Pandora_Module (string name) { this->module_interval = 1; this->max = 0; this->min = 0; - this->has_limits = false; + this->has_limits = false; + this->async = false; this->data_list = NULL; } @@ -175,6 +176,21 @@ Module_Kind Pandora_Module::getModuleKind () const { return this->module_kind; } + +/** + * Get the output of the module. + * + * @return The module output in a string value. + */ +string +Pandora_Module::getLatestOutput () const { + list::iterator iter; + + if (this->data_list == NULL) + return ""; + iter = this->data_list->begin (); + return (*iter)->getValue (); +} /** * Get the type of the module in a integer_value. @@ -222,7 +238,7 @@ Pandora_Module::getDataOutput (Pandora_Data *data) { } } - return trim(data->getValue ()); + return trim (data->getValue ()); } /** @@ -351,15 +367,16 @@ Pandora_Module::getXml () { data_element = new TiXmlElement ("data"); element = new TiXmlElement ("value"); try { - data_clean = strreplace (this->getDataOutput (data), "%", "%%" ); - } catch (Output_Error e) { - delete element; - continue; - } - - text = new TiXmlText (data_clean); - element->InsertEndChild (*text); - data_element->InsertEndChild (*element); + data_clean = strreplace (this->getDataOutput (data), + "%", "%%" ); + } catch (Output_Error e) { + delete element; + continue; + } + + text = new TiXmlText (data_clean); + element->InsertEndChild (*text); + data_element->InsertEndChild (*element); delete text; delete element; @@ -379,11 +396,11 @@ Pandora_Module::getXml () { data = data_list->front (); element = new TiXmlElement ("data"); try { - data_clean = strreplace (this->getDataOutput (data), "%", "%%" ); - text = new TiXmlText (data_clean); - element->InsertEndChild (*text); - root->InsertEndChild (*element); - delete text; + data_clean = strreplace (this->getDataOutput (data), "%", "%%" ); + text = new TiXmlText (data_clean); + element->InsertEndChild (*text); + root->InsertEndChild (*element); + delete text; } catch (Output_Error e) { } delete element; @@ -412,7 +429,7 @@ void Pandora_Module::setMax (int value) { this->has_limits = true; this->max = value; -} +} /** * Set the min value the module can have. @@ -426,6 +443,19 @@ Pandora_Module::setMin (int value) { this->has_limits = true; this->min = value; } + +/** + * Set the async flag to the module. + * + * If a module is set to be async, it would try to works only when the + * events happen. Note that not all the modules can work in async mode. + * + * @param async Flag to set. + */ +void +Pandora_Module::setAsync (bool async) { + this->async = async; +} /** * Set the module type from a string type. diff --git a/pandora_agents/win32/modules/pandora_module.h b/pandora_agents/win32/modules/pandora_module.h index 261e289155..213641eb23 100644 --- a/pandora_agents/win32/modules/pandora_module.h +++ b/pandora_agents/win32/modules/pandora_module.h @@ -80,7 +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"; + const string module_logevent_str = "module_logevent"; /** * Pandora module super-class exception. @@ -134,7 +134,12 @@ namespace Pandora_Modules { /** * The description of the module. */ - string module_description; + string module_description; + + /** + * Flag to set a module as asynchronous + */ + bool async; public: Pandora_Module (string name); virtual ~Pandora_Module (); @@ -145,29 +150,32 @@ namespace Pandora_Modules { static Module_Kind parseModuleKindFromString (string kind); - void setInterval (int interval); - int getInterval (); + void setInterval (int interval); + int getInterval (); - TiXmlElement *getXml (); + TiXmlElement *getXml (); - virtual void run (); + virtual void run (); - virtual void setOutput (string output); - virtual void setOutput (string output, SYSTEMTIME *system_time); + virtual void setOutput (string output); + virtual void setOutput (string output, + SYSTEMTIME *system_time); - string getName () const; - string getDescription () const; - string getTypeString () const; - Module_Type getTypeInt () const; - Module_Type getModuleType () const; - Module_Kind getModuleKind () const; + string getName () const; + string getDescription () const; + string getTypeString () const; + string getLatestOutput () const; + Module_Type getTypeInt () const; + Module_Type getModuleType () const; + Module_Kind getModuleKind () const; - void setType (string type); - void setKind (string kind); - void setDescription (string description); - void setMax (int value); - void setMin (int value); + void setType (string type); + void setKind (string kind); + void setDescription (string description); + void setMax (int value); + void setMin (int value); + void setAsync (bool async); }; } diff --git a/pandora_agents/win32/modules/pandora_module_factory.cc b/pandora_agents/win32/modules/pandora_module_factory.cc index 5e189fc8c1..004bef94cd 100644 --- a/pandora_agents/win32/modules/pandora_module_factory.cc +++ b/pandora_agents/win32/modules/pandora_module_factory.cc @@ -52,7 +52,8 @@ using namespace Pandora_Strutils; #define TOKEN_LOGEVENT ("module_logevent") #define TOKEN_SOURCE ("module_source ") #define TOKEN_EVENTTYPE ("module_eventtype ") -#define TOKEN_PATTERN ("module_pattern ") +#define TOKEN_PATTERN ("module_pattern ") +#define TOKEN_ASYNC ("module_async") string parseLine (string line, string token) { @@ -87,7 +88,8 @@ 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; + string module_logevent, module_source, module_eventtype; + string module_pattern, module_async; Pandora_Module *module; bool numeric; Module_Type type; @@ -104,10 +106,10 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { module_odbc = ""; module_odbc_query = ""; module_odbc = ""; - module_logevent = ""; - module_source = ""; - module_eventtype = ""; - module_pattern = ""; + module_logevent = ""; + module_source = ""; + module_eventtype = ""; + module_pattern = ""; stringtok (tokens, definition, "\n"); @@ -160,18 +162,21 @@ 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); - } + 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); + } + if (module_async == "") { + module_async = parseLine (line, TOKEN_ASYNC); + } iter++; } @@ -220,8 +225,12 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { if (module_description != "") { module->setDescription (module_description); - } - + } + + if (module_async != "") { + module->setAsync (true); + } + type = Pandora_Module::parseModuleTypeFromString (module_type); switch (type) { case TYPE_GENERIC_DATA: @@ -258,7 +267,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { } } if (module_min != "") { - try { + try { int value = strtoint (module_min); module->setMin (value); diff --git a/pandora_agents/win32/modules/pandora_module_list.cc b/pandora_agents/win32/modules/pandora_module_list.cc index 34bc06e3de..d3122c5952 100644 --- a/pandora_agents/win32/modules/pandora_module_list.cc +++ b/pandora_agents/win32/modules/pandora_module_list.cc @@ -80,8 +80,26 @@ Pandora_Modules::Pandora_Module_List::Pandora_Module_List (string filename) { file.close (); current = new std::list::iterator (); - *current = modules->begin (); -} + (*current) = modules->begin (); +} + +/** + * Creates an empty module list object. + */ +Pandora_Modules::Pandora_Module_List::Pandora_Module_List () { + this->modules = new list (); + current = new std::list::iterator (); + (*current) = modules->begin (); +} + +/** + * Adds a module object to a list object. + */ +void +Pandora_Modules::Pandora_Module_List::addModule (Pandora_Module *module) { + modules->push_back (module); +} + /** * Destroy the list. diff --git a/pandora_agents/win32/modules/pandora_module_list.h b/pandora_agents/win32/modules/pandora_module_list.h index 6c83289ae5..68c92ebdc8 100644 --- a/pandora_agents/win32/modules/pandora_module_list.h +++ b/pandora_agents/win32/modules/pandora_module_list.h @@ -42,11 +42,15 @@ namespace Pandora_Modules { list::iterator *current; void parseModuleDefinition (string definition); public: - Pandora_Module_List (string filename); + Pandora_Module_List (string filename); + Pandora_Module_List (); ~Pandora_Module_List (); Pandora_Module * getCurrentValue (); + + /* Add a module to the list */ + void addModule (Pandora_Module *module); /* Move to the first element of the list */ void goFirst (); diff --git a/pandora_agents/win32/modules/pandora_module_service.cc b/pandora_agents/win32/modules/pandora_module_service.cc index 06166b249e..6364434cc1 100644 --- a/pandora_agents/win32/modules/pandora_module_service.cc +++ b/pandora_agents/win32/modules/pandora_module_service.cc @@ -19,9 +19,11 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "pandora_module_service.h" +#include "pandora_module_service.h" +#include "pandora_module_list.h" #include "../windows/pandora_wmi.h" -#include "../pandora_strutils.h" +#include "../pandora_strutils.h" +#include "../pandora_windows_service.h" #include #include @@ -43,8 +45,84 @@ Pandora_Module_Service::Pandora_Module_Service (string name, string service_name transform (service_name.begin (), service_name.end (), this->service_name.begin (), (int (*) (int)) tolower); - this->setKind (module_service_str); + this->setKind (module_service_str); + this->thread = 0; } + +string +Pandora_Module_Service::getServiceName () const { + return this->service_name; +} + +#define BUFFER_SIZE (16384) + +void +async_run (Pandora_Module_Service *module) { + HANDLE event_log; + HANDLE event; + DWORD result; + int res; + string str_res; + BYTE buffer[BUFFER_SIZE]; + EVENTLOGRECORD *record; + DWORD read; + DWORD needed; + int event_id; + bool service_event; + string prev_res; + Pandora_Module_List *modules; + + prev_res = module->getLatestOutput (); + modules = new Pandora_Module_List (); + modules->addModule (module); + + while (1) { + event_log = OpenEventLog (NULL, "Service Control Manager"); + if (event_log == NULL) { + pandoraLog ("Could not open event log for %s.", + module->getServiceName ().c_str ()); + return; + } + event = CreateEvent (NULL, FALSE, FALSE, NULL); + NotifyChangeEventLog (event_log, event); + result = WaitForSingleObject (event, 10000); + + if (result == 0) { + service_event = false; + record = (EVENTLOGRECORD *) buffer; + + while (ReadEventLog (event_log, + EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ, + 0, record, BUFFER_SIZE, &read, &needed)) { + + if (record->EventType != EVENTLOG_INFORMATION_TYPE) + continue; + event_id = record->EventID & 0x0000ffff; + + /* Those numbers are the code for service start/stopping */ + if (event_id == 7035 || event_id == 7036) { + service_event = true; + break; + } + } + + if (service_event) { + res = Pandora_Wmi::isServiceRunning (module->getServiceName ()); + str_res = inttostr (res); + if (str_res != prev_res) { + module->setOutput (str_res); + prev_res = str_res; + pandoraLog ("Service \"%s\" changed status to: %d", + module->getServiceName ().c_str (), res); + Pandora_Windows_Service::getInstance ()->sendXml (modules); + } + } + } + CloseHandle (event); + CloseEventLog (event_log); + } + delete modules; +} void Pandora_Module_Service::run () { @@ -57,5 +135,13 @@ Pandora_Module_Service::run () { } res = Pandora_Wmi::isServiceRunning (this->service_name); - this->setOutput (inttostr (res)); + this->setOutput (inttostr (res)); + + /* Launch thread if it's asynchronous */ + if (this->async) { + this->thread = CreateThread (NULL, 0, + (LPTHREAD_START_ROUTINE) async_run, + this, 0, NULL); + this->async = false; + } } diff --git a/pandora_agents/win32/modules/pandora_module_service.h b/pandora_agents/win32/modules/pandora_module_service.h index 8506eba091..3cb1101a91 100644 --- a/pandora_agents/win32/modules/pandora_module_service.h +++ b/pandora_agents/win32/modules/pandora_module_service.h @@ -31,11 +31,13 @@ namespace Pandora_Modules { */ class Pandora_Module_Service : public Pandora_Module { private: - string service_name; + string service_name; + HANDLE thread; public: Pandora_Module_Service (string name, string service_name); - void run (); + void run (); + string getServiceName () const; }; } diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index 7a74a88d03..dca3fd74fb 100644 --- a/pandora_agents/win32/pandora.cc +++ b/pandora_agents/win32/pandora.cc @@ -1,274 +1,274 @@ -/* Common functions to any Pandora program. - Copyright (C) 2006 Artica ST. - Written by Esteban Sanchez. - - 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 -#include -#include -#include -#include -#include "pandora.h" -#include "pandora_strutils.h" - -using namespace std; -using namespace Pandora; -using namespace Pandora_Strutils; - -#define PATH_SIZE _MAX_PATH+1 -#define PANDORA_VERSION ("2.0(Build 080610)") - -string pandora_path; -string pandora_dir; -bool pandora_debug; -string pandora_version = PANDORA_VERSION; - -/** - * Parses a string and initialize the key and the value. - * - * The string should be in the format: - * - key value - * - key "value with blankspaces" - */ -void -Key_Value::parseLine (string str) { - unsigned int pos; - list tokens; - list::iterator iter; - string trimmedstr; - - trimmedstr = trim (str); - -/* Check if the string has " */ - pos = trimmedstr.find ("\""); - if (pos == string::npos) { - stringtok (tokens, trimmedstr, " \t"); - } else { - stringtok (tokens, trimmedstr, "\""); - } - -/* Pick the first and the last value of the token list */ - iter = tokens.begin (); - key = trim (*iter); - transform (key.begin(), key.end(), key.begin(), (int(*)(int)) tolower); - iter = tokens.end (); - iter--; -/* Check if the line has only one token */ - if (iter != tokens.begin ()) { - value = trim (*iter); - } else { - value = ""; - } -} - -/** - * Get the key of the object. - * - * @return The key - */ -string -Key_Value::getKey () { - return key; -} - -/** - * Get the value of the object. - * - * @return The value - */ -string -Key_Value::getValue () { - return value; -} - -void -pandoraWriteLog (string filename, string line) { - string buffer; - char str_time[25]; - FILE *file; - string filepath; - SYSTEMTIME st; - - GetSystemTime(&st); - sprintf (str_time, "%d-%02d-%02d %02d:%02d:%02d ", st.wYear, st.wMonth, st.wDay, - st.wHour, st.wMinute, st.wSecond); - - buffer = (char *) str_time; - buffer += line; - - filepath = pandora_dir + filename; - - file = fopen (filepath.c_str (), "a+"); - if (file != NULL) { - fprintf (file, "%s\n", buffer.c_str ()); - fclose (file); - } -} - -/** - * Write a message in the log file. - * - * The log file is used to write the output of errors and problems of the - * agent. - * - * @param format String output format (like printf). - * @param ... Variable argument list - */ -void -Pandora::pandoraLog (char *format, ...) { - va_list args; - char msg[5000]; - - va_start (args, format); - vsprintf (msg, format, args); - va_end (args); - - pandoraWriteLog ("pandora_agent.log", (char *) msg); -} - -/** - * Write a message in the debug file. - * - * The log file is used to write the output of debugging information of the - * agent. - * - * @param format String output format. - * @param ... Variable argument list - */ -void -Pandora::pandoraDebug (char *format, ...) { - if (pandora_debug) { - va_list args; - char msg[5000]; - - va_start (args, format); - vsprintf (msg, format, args); - va_end (args); - - pandoraWriteLog ("pandora_debug.log", (char *) msg); - } - return; -} - -/** - * Secure free of a pointer. - * - * @param pointer pointer to free. - */ -void -Pandora::pandoraFree (void * pointer) { - if (pointer != NULL) - free (pointer); - return; -} - -/** - * Set the installation directory of the application. - * - * This directory is the path to the directory which holds - * the binary file. - * - * @param dir The path to the directory. - * - * @see getPandoraInstallDir - */ -void -Pandora::setPandoraInstallDir (string dir) { - pandora_dir = dir; -} - -/** - * Get the installation directory of the application. - * - * This directory is the path to the directory which holds - * the binary file. - * - * @return The path to the directory. - * - * @see setPandoraInstallDir - */ -string -Pandora::getPandoraInstallDir () { - return pandora_dir; -} - -/** - * Set the installation path of the application. - * - * This the complete path to the binary file. - * - * @param path The path to the binary file. - * - * @see getPandoraInstallPath - */ -void -Pandora::setPandoraInstallPath (string path) { - pandora_path = path; -} - -/** - * Get the installation path of the application. - * - * This the complete path to the binary file. - * - * @return The path. - * - * @see setPandoraInstallPath - */ -string -Pandora::getPandoraInstallPath () { - return pandora_path; -} - -/** - * Set the debug flag. - * - * If the flag is true output wil be generated and XML files will not be deleted. - * - * @param dbg Turns the debug flag on/off. - * - * @see getPandoraDebug - * @see pandoraDebug - */ -void -Pandora::setPandoraDebug (bool dbg) { - pandora_debug = dbg; -} - -/** - * Get the debug flag value. - * - * If the flag is truee output wil be generated and XML files will not be deleted. - * - * @see setPandoraDebug - * @see pandoraDebug - */ -bool -Pandora::getPandoraDebug () { - return pandora_debug; -} - - -/** - * Get the version of the agent. - * - * @return The version. - */ -string -Pandora::getPandoraAgentVersion () { - return pandora_version; -} +/* Common functions to any Pandora program. + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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 +#include +#include +#include +#include +#include "pandora.h" +#include "pandora_strutils.h" + +using namespace std; +using namespace Pandora; +using namespace Pandora_Strutils; + +#define PATH_SIZE _MAX_PATH+1 +#define PANDORA_VERSION ("2.0(Build 080610)") + +string pandora_path; +string pandora_dir; +bool pandora_debug; +string pandora_version = PANDORA_VERSION; + +/** + * Parses a string and initialize the key and the value. + * + * The string should be in the format: + * - key value + * - key "value with blankspaces" + */ +void +Key_Value::parseLine (string str) { + unsigned int pos; + list tokens; + list::iterator iter; + string trimmedstr; + + trimmedstr = trim (str); + +/* Check if the string has " */ + pos = trimmedstr.find ("\""); + if (pos == string::npos) { + stringtok (tokens, trimmedstr, " \t"); + } else { + stringtok (tokens, trimmedstr, "\""); + } + +/* Pick the first and the last value of the token list */ + iter = tokens.begin (); + key = trim (*iter); + transform (key.begin(), key.end(), key.begin(), (int(*)(int)) tolower); + iter = tokens.end (); + iter--; +/* Check if the line has only one token */ + if (iter != tokens.begin ()) { + value = trim (*iter); + } else { + value = ""; + } +} + +/** + * Get the key of the object. + * + * @return The key + */ +string +Key_Value::getKey () { + return key; +} + +/** + * Get the value of the object. + * + * @return The value + */ +string +Key_Value::getValue () { + return value; +} + +void +pandoraWriteLog (string filename, string line) { + string buffer; + char str_time[25]; + FILE *file; + string filepath; + SYSTEMTIME st; + + GetSystemTime(&st); + sprintf (str_time, "%d-%02d-%02d %02d:%02d:%02d ", st.wYear, st.wMonth, st.wDay, + st.wHour, st.wMinute, st.wSecond); + + buffer = (char *) str_time; + buffer += line; + + filepath = pandora_dir + filename; + + file = fopen (filepath.c_str (), "a+"); + if (file != NULL) { + fprintf (file, "%s\n", buffer.c_str ()); + fclose (file); + } +} + +/** + * Write a message in the log file. + * + * The log file is used to write the output of errors and problems of the + * agent. + * + * @param format String output format (like printf). + * @param ... Variable argument list + */ +void +Pandora::pandoraLog (char *format, ...) { + va_list args; + char msg[5000]; + + va_start (args, format); + vsprintf (msg, format, args); + va_end (args); + + pandoraWriteLog ("pandora_agent.log", (char *) msg); +} + +/** + * Write a message in the debug file. + * + * The log file is used to write the output of debugging information of the + * agent. + * + * @param format String output format. + * @param ... Variable argument list + */ +void +Pandora::pandoraDebug (char *format, ...) { + if (pandora_debug) { + va_list args; + char msg[5000]; + + va_start (args, format); + vsprintf (msg, format, args); + va_end (args); + + pandoraWriteLog ("pandora_debug.log", (char *) msg); + } + return; +} + +/** + * Secure free of a pointer. + * + * @param pointer pointer to free. + */ +void +Pandora::pandoraFree (void * pointer) { + if (pointer != NULL) + free (pointer); + return; +} + +/** + * Set the installation directory of the application. + * + * This directory is the path to the directory which holds + * the binary file. + * + * @param dir The path to the directory. + * + * @see getPandoraInstallDir + */ +void +Pandora::setPandoraInstallDir (string dir) { + pandora_dir = dir; +} + +/** + * Get the installation directory of the application. + * + * This directory is the path to the directory which holds + * the binary file. + * + * @return The path to the directory. + * + * @see setPandoraInstallDir + */ +string +Pandora::getPandoraInstallDir () { + return pandora_dir; +} + +/** + * Set the installation path of the application. + * + * This the complete path to the binary file. + * + * @param path The path to the binary file. + * + * @see getPandoraInstallPath + */ +void +Pandora::setPandoraInstallPath (string path) { + pandora_path = path; +} + +/** + * Get the installation path of the application. + * + * This the complete path to the binary file. + * + * @return The path. + * + * @see setPandoraInstallPath + */ +string +Pandora::getPandoraInstallPath () { + return pandora_path; +} + +/** + * Set the debug flag. + * + * If the flag is true output wil be generated and XML files will not be deleted. + * + * @param dbg Turns the debug flag on/off. + * + * @see getPandoraDebug + * @see pandoraDebug + */ +void +Pandora::setPandoraDebug (bool dbg) { + pandora_debug = dbg; +} + +/** + * Get the debug flag value. + * + * If the flag is truee output wil be generated and XML files will not be deleted. + * + * @see setPandoraDebug + * @see pandoraDebug + */ +bool +Pandora::getPandoraDebug () { + return pandora_debug; +} + + +/** + * Get the version of the agent. + * + * @return The version. + */ +string +Pandora::getPandoraAgentVersion () { + return pandora_version; +} diff --git a/pandora_agents/win32/pandora_windows_service.cc b/pandora_agents/win32/pandora_windows_service.cc index bad9f92c5c..61c304dda3 100644 --- a/pandora_agents/win32/pandora_windows_service.cc +++ b/pandora_agents/win32/pandora_windows_service.cc @@ -39,24 +39,31 @@ using namespace Pandora_Modules; using namespace Pandora_Strutils; string enabled_values[] = {"enabled", "1", "on", "yes", "si", "sí", "ok", ""}; + +Pandora_Windows_Service::Pandora_Windows_Service () + : Windows_Service (NULL, NULL, NULL) { + this->setInitFunction ((void (Windows_Service::*) ()) + &Pandora_Windows_Service::pandora_init); + this->setRunFunction ((void (Windows_Service::*) ()) + &Pandora_Windows_Service::pandora_run); + this->started = false; +} /** - * Creates a new Pandora_Windows_Service. + * Set Pandora service Windows properties. * * @param svc_name Internal service name * @param svc_display_name Service name that will appear in the * Windows service administration tool. * @param svc_description Long description of the service. - */ -Pandora_Windows_Service::Pandora_Windows_Service (const char * svc_name, - const char * svc_display_name, - const char * svc_description) - : Windows_Service (svc_name, svc_display_name, svc_description) { - this->setInitFunction ((void (Windows_Service::*) ()) - &Pandora_Windows_Service::pandora_init); - this->setRunFunction ((void (Windows_Service::*) ()) - &Pandora_Windows_Service::pandora_run); - + */ +void +Pandora_Windows_Service::setValues (const char * svc_name, + const char * svc_display_name, + const char * svc_description) { + this->service_name = (char *) svc_name; + this->service_display_name = (char *) svc_display_name; + this->service_description = (char *) svc_description; execution_number = 0; this->modules = NULL; this->conf = NULL; @@ -78,6 +85,23 @@ Pandora_Windows_Service::~Pandora_Windows_Service () { } pandoraLog ("Pandora agent stopped"); } + +Pandora_Windows_Service * +Pandora_Windows_Service::getInstance () { + static Pandora_Windows_Service *service = NULL; + + if (service != NULL) + return service; + + service = new Pandora_Windows_Service (); + + return service; +} + +void +Pandora_Windows_Service::start () { + this->started = true; +} bool is_enabled (string value) { @@ -161,7 +185,7 @@ Pandora_Windows_Service::getXmlHeader () { // Get current time ctime = time(0); - ctime_tm = localtime(&ctime); + ctime_tm = localtime(&ctime); sprintf (timestamp, "%d-%02d-%02d %02d:%02d:%02d", ctime_tm->tm_year + 1900, ctime_tm->tm_mon + 1, ctime_tm->tm_mday, ctime_tm->tm_hour, @@ -589,7 +613,7 @@ Pandora_Windows_Service::checkConfig () { Pandora_File::removeFile (tmp); /* Save new configuration */ Pandora_File::writeBinFile (conf_file, conf_str, conf_size); - } catch (...) { + } catch (...) { pandoraDebug("Pandora_Windows_Service::checkConfig: Error retrieving configuration file from server"); if (conf_str != NULL) { delete[] conf_str; @@ -602,17 +626,95 @@ Pandora_Windows_Service::checkConfig () { /* Reload configuration */ this->pandora_init (); } + +void +Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) { + TiXmlDeclaration *decl; + TiXmlDocument *doc; + TiXmlElement *local_xml, *agent; + string xml_filename, random_integer; + string tmp_filename, tmp_filepath; + string encoding; + bool saved; + static HANDLE mutex = 0; + + if (mutex == 0) { + mutex = CreateMutex (NULL, FALSE, NULL); + } + /* Wait for the mutex to be opened */ + WaitForSingleObject (mutex, INFINITE); + + pandoraLog ("aasdfasdf"); + agent = getXmlHeader (); + + if (modules != NULL) { + modules->goFirst (); + + while (! modules->isLast ()) { + Pandora_Module *module; + + module = modules->getCurrentValue (); + + local_xml = module->getXml (); + if (local_xml != NULL) { + agent->InsertEndChild (*local_xml); + + delete local_xml; + } + modules->goNext (); + } + } + + /* Generate temporal filename */ + random_integer = inttostr (rand()); + tmp_filename = conf->getValue ("agent_name"); + if (tmp_filename == "") { + tmp_filename = Pandora_Windows_Info::getSystemName (); + } + tmp_filename += "." + random_integer + ".data"; + + xml_filename = conf->getValue ("temporal"); + if (xml_filename[xml_filename.length () - 1] != '\\') { + xml_filename += "\\"; + } + 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; + delete agent; + + if (!saved) { + pandoraLog ("Error when saving the XML in %s", + tmp_filepath.c_str ()); + return; + } + + /* Only send if debug is not activated */ + if (getPandoraDebug () == false) { + this->copyDataFile (tmp_filename); + + try { + Pandora_File::removeFile (tmp_filepath); + } catch (Pandora_File::Delete_Error e) { + } + } + + ReleaseMutex (mutex); +} 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 */ @@ -635,74 +737,12 @@ Pandora_Windows_Service::pandora_run () { } } - this->elapsed_transfer_time += interval; - + this->elapsed_transfer_time += this->interval; + if (this->elapsed_transfer_time >= this->transfer_interval) { - agent = getXmlHeader (); - - if (this->modules != NULL) { - this->modules->goFirst (); - - while (! this->modules->isLast ()) { - Pandora_Module *module; - - module = this->modules->getCurrentValue (); - - local_xml = module->getXml (); - if (local_xml != NULL) { - agent->InsertEndChild (*local_xml); - - delete local_xml; - } - this->modules->goNext (); - } - } - - this->elapsed_transfer_time = 0; - /* Generate temporal filename */ - random_integer = inttostr (rand()); - tmp_filename = conf->getValue ("agent_name"); - if (tmp_filename == "") { - tmp_filename = Pandora_Windows_Info::getSystemName (); - } - tmp_filename += "." + random_integer + ".data"; - - xml_filename = conf->getValue ("temporal"); - if (xml_filename[xml_filename.length () - 1] != '\\') { - xml_filename += "\\"; - } - 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; - delete agent; - - if (!saved) { - pandoraLog ("Error when saving the XML in %s", - tmp_filepath.c_str ()); - return; - } - - /* Only send if debug is not activated */ - if (getPandoraDebug () == false) { - this->copyDataFile (tmp_filename); - - try { - Pandora_File::removeFile (tmp_filepath); - } catch (Pandora_File::Delete_Error e) { - } - } + this->elapsed_transfer_time = 0; + + this->sendXml (this->modules); } /* Get the interval value (in minutes) */ diff --git a/pandora_agents/win32/pandora_windows_service.h b/pandora_agents/win32/pandora_windows_service.h index e5119c0f2d..3e6d29f3bf 100644 --- a/pandora_agents/win32/pandora_windows_service.h +++ b/pandora_agents/win32/pandora_windows_service.h @@ -43,7 +43,8 @@ namespace Pandora { string agent_name; long interval; long elapsed_transfer_time; - long transfer_interval; + long transfer_interval; + bool started; TiXmlElement *getXmlHeader (); void copyDataFile (string filename); @@ -58,15 +59,23 @@ namespace Pandora { void recvDataFile (string filename); void recvTentacleDataFile (string host, string filename); - void checkConfig (); + void checkConfig (); + + Pandora_Windows_Service (); public: void pandora_run (); void pandora_init (); - public: - Pandora_Windows_Service (const char * svc_name, - const char * svc_display_name, - const char * svc_description); - ~Pandora_Windows_Service (); + public: + static Pandora_Windows_Service *getInstance (); + + ~Pandora_Windows_Service (); + + void setValues (const char *svc_name, + const char *svc_display_name, + const char *svc_description); + + void start (); + void sendXml (Pandora_Module_List *modules); }; } diff --git a/pandora_agents/win32/windows/pandora_wmi.cc b/pandora_agents/win32/windows/pandora_wmi.cc index 736ac071e7..e60c9411cd 100644 --- a/pandora_agents/win32/windows/pandora_wmi.cc +++ b/pandora_agents/win32/windows/pandora_wmi.cc @@ -64,7 +64,7 @@ Pandora_Wmi::isProcessRunning (string process_name) { query = "SELECT * FROM Win32_Process WHERE Name=\"" + process_name + "\""; - try { + try { dhCheck (dhGetObject (getWmiStr (L"."), NULL, &wmi_svc)); dhCheck (dhGetValue (L"%o", &quickfixes, wmi_svc, L".ExecQuery(%T)", @@ -99,7 +99,7 @@ Pandora_Wmi::isServiceRunning (string service_name) { query = "SELECT * FROM Win32_Service WHERE Name = \"" + service_name + "\""; - try { + try { dhCheck (dhGetObject (getWmiStr (L"."), NULL, &wmi_svc)); dhCheck (dhGetValue (L"%o", &quickfixes, wmi_svc, L".ExecQuery(%T)", diff --git a/pandora_agents/win32/windows_service.h b/pandora_agents/win32/windows_service.h index 20b499e81a..38c1a77a7b 100644 --- a/pandora_agents/win32/windows_service.h +++ b/pandora_agents/win32/windows_service.h @@ -35,10 +35,11 @@ * Notice: A program should have only one object of this class. */ class Windows_Service { -private: +protected: char *service_name; char *service_display_name; - char *service_description; + char *service_description; +private: HANDLE stop_event; int sleep_time; SC_HANDLE sc_service;