diff --git a/pandora_agents/ChangeLog b/pandora_agents/ChangeLog index 5ed6e4b9a6..2c4e005252 100644 --- a/pandora_agents/ChangeLog +++ b/pandora_agents/ChangeLog @@ -1,3 +1,20 @@ +2008-12-11 Ramon Novoa + + * win32/windows/pandora_wmi.cc, + win32/pandora_windows_service.h, + win32/PandoraAgent.dev, + win32/pandora_windows_service.cc: Added an UDP Server. The + agent can receive remote commands. + + * win32/udp_server, + win32/udp_server/udp_server.cc, + win32/udp_server/udp_server.h: Added to repository. UDP Server. + +2008-12-10 Ramon Novoa + + * linux/pandora_agent, + linux/pandora_agent.conf: Added support for a secondary server. + 2008-11-25 Sancho Lerena * linux/pandora_agent: Fixed problem parsing async_string. diff --git a/pandora_agents/win32/PandoraAgent.dev b/pandora_agents/win32/PandoraAgent.dev index 79a8691ab3..ab25fcd120 100644 --- a/pandora_agents/win32/PandoraAgent.dev +++ b/pandora_agents/win32/PandoraAgent.dev @@ -1,7 +1,7 @@ [Project] FileName=PandoraAgent.dev Name=PandoraAgent -UnitCount=77 +UnitCount=79 Type=1 Ver=1 ObjFiles= @@ -20,7 +20,7 @@ ObjectOutput= OverrideOutput=0 OverrideOutputName=PandoraAgent.exe HostApplication= -Folders=FTP,Misc,Modules,Modules/Utils,SSH,SSH/libssh2,Windows,Windows/WMI,XML +Folders=FTP,Misc,Modules,Modules/Utils,SSH,SSH/libssh2,"UDP Server",Windows,Windows/WMI,XML CommandLine= UseCustomMakefile=0 CustomMakefile= @@ -817,3 +817,23 @@ Priority=1000 OverrideBuildCmd=0 BuildCmd= +[Unit78] +FileName=udp_server\udp_server.h +CompileCpp=1 +Folder=UDP Server +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit79] +FileName=udp_server\udp_server.cc +CompileCpp=1 +Folder=UDP Server +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/pandora_agents/win32/pandora_windows_service.cc b/pandora_agents/win32/pandora_windows_service.cc index 8886043044..5048d98b6e 100644 --- a/pandora_agents/win32/pandora_windows_service.cc +++ b/pandora_agents/win32/pandora_windows_service.cc @@ -27,6 +27,7 @@ #include "ftp/pandora_ftp_client.h" #include "misc/pandora_file.h" #include "windows/pandora_windows_info.h" +#include "udp_server/udp_server.h" #include #include @@ -37,15 +38,15 @@ using namespace std; using namespace Pandora; using namespace Pandora_Modules; using namespace Pandora_Strutils; - + Pandora_Windows_Service::Pandora_Windows_Service () - : Windows_Service (NULL, NULL, NULL) { + : 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; -} + &Pandora_Windows_Service::pandora_run); + this->started = false; +} /** * Set Pandora service Windows properties. @@ -54,7 +55,7 @@ Pandora_Windows_Service::Pandora_Windows_Service () * @param svc_display_name Service name that will appear in the * Windows service administration tool. * @param svc_description Long description of the service. - */ + */ void Pandora_Windows_Service::setValues (const char * svc_name, const char * svc_display_name, @@ -83,28 +84,30 @@ 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; + +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; } void Pandora_Windows_Service::pandora_init () { string conf_file, interval, debug, transfer_interval; - + string udp_server_enabled, udp_server_port, udp_server_addr, udp_server_auth_addr; + static UDP_Server *udp_server = NULL; + setPandoraDebug (true); conf_file = Pandora::getPandoraInstallDir (); @@ -144,6 +147,16 @@ Pandora_Windows_Service::pandora_init () { this->setSleepTime (this->interval); pandoraLog ("Pandora agent started"); + + /* Launch UDP Server */ + udp_server_enabled = conf->getValue ("udp_server"); + if (udp_server == NULL && udp_server_enabled.compare ("1") == 0) { + udp_server_port = conf->getValue ("udp_server_port"); + udp_server_addr = conf->getValue ("udp_server_address"); + udp_server_auth_addr = conf->getValue ("udp_server_auth_address"); + udp_server = new UDP_Server (this, udp_server_addr, udp_server_auth_addr, atoi (udp_server_port.c_str ())); + udp_server->start (); + } } TiXmlElement * @@ -607,7 +620,7 @@ Pandora_Windows_Service::checkConfig () { /* Reload configuration */ this->pandora_init (); } - + void Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) { TiXmlDeclaration *decl; @@ -616,16 +629,16 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) { 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); - + bool saved; + static HANDLE mutex = 0; + + if (mutex == 0) { + mutex = CreateMutex (NULL, FALSE, NULL); + } + + /* Wait for the mutex to be opened */ + WaitForSingleObject (mutex, INFINITE); + agent = getXmlHeader (); if (modules != NULL) { @@ -644,7 +657,7 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) { } modules->goNext (); } - } + } /* Generate temporal filename */ random_integer = inttostr (rand()); @@ -677,7 +690,7 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) { if (!saved) { pandoraLog ("Error when saving the XML in %s", - tmp_filepath.c_str ()); + tmp_filepath.c_str ()); ReleaseMutex (mutex); return; } @@ -690,10 +703,10 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) { Pandora_File::removeFile (tmp_filepath); } catch (Pandora_File::Delete_Error e) { } - } - - ReleaseMutex (mutex); -} + } + + ReleaseMutex (mutex); +} void Pandora_Windows_Service::pandora_run () { @@ -720,10 +733,10 @@ Pandora_Windows_Service::pandora_run () { } this->elapsed_transfer_time += this->interval; - + if (this->elapsed_transfer_time >= this->transfer_interval) { - this->elapsed_transfer_time = 0; - + this->elapsed_transfer_time = 0; + this->sendXml (this->modules); } @@ -732,3 +745,8 @@ Pandora_Windows_Service::pandora_run () { return; } + +Pandora_Agent_Conf * +Pandora_Windows_Service::getConf () { + return this->conf; +} diff --git a/pandora_agents/win32/pandora_windows_service.h b/pandora_agents/win32/pandora_windows_service.h index 3e6d29f3bf..10c7791350 100644 --- a/pandora_agents/win32/pandora_windows_service.h +++ b/pandora_agents/win32/pandora_windows_service.h @@ -43,7 +43,7 @@ namespace Pandora { string agent_name; long interval; long elapsed_transfer_time; - long transfer_interval; + long transfer_interval; bool started; TiXmlElement *getXmlHeader (); @@ -59,23 +59,24 @@ 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: - static Pandora_Windows_Service *getInstance (); + public: + static Pandora_Windows_Service *getInstance (); + + ~Pandora_Windows_Service (); - ~Pandora_Windows_Service (); - void setValues (const char *svc_name, const char *svc_display_name, - const char *svc_description); - - void start (); + const char *svc_description); + + void start (); void sendXml (Pandora_Module_List *modules); + Pandora_Agent_Conf *getConf (); }; } diff --git a/pandora_agents/win32/udp_server/udp_server.cc b/pandora_agents/win32/udp_server/udp_server.cc new file mode 100644 index 0000000000..26553a410b --- /dev/null +++ b/pandora_agents/win32/udp_server/udp_server.cc @@ -0,0 +1,241 @@ +#include +#include +#include +#include + +#include "udp_server.h" +#include "../pandora.h" +#include "../windows/pandora_wmi.h" + +using namespace Pandora; + +/** + * Get the address of the server. + * + * @return Server address. + */ +unsigned long UDP_Server::getAddress () { + return this->address; +} + +/** + * Get the address authorized to send commands to + * the server. + * + * @return Authorized address. + */ +unsigned long UDP_Server::getAuthAddress () { + return this->auth_address; +} + +/** + * Get the port of the server. + * + * @return Server port. + */ +unsigned long UDP_Server::getPort () { + return this->port; +} + +/** + * Get the windows service associated to the server. + * + * @return Windows service associated to the server. + */ +Pandora_Windows_Service *UDP_Server::getService () { + return this->service; +} + +/** + * Returns the state of the server. + * + * @return 1 if the server is running, 0 if not. + */ +unsigned char UDP_Server::isRunning () { + return this->running; +} + +/** + * UDP_Server constructor. + * + * @param service Service associated to the server. + * @param address Server address. + * @param auth_address Authorized address. + * @param port Server port. + */ +UDP_Server::UDP_Server (Pandora_Windows_Service *service, string address, string auth_address, unsigned int port) { + if (address.empty ()) { + this->address = INADDR_ANY; + } else { + this->address = inet_addr (address.c_str ()); + } + if (auth_address.empty ()) { + this->auth_address = INADDR_ANY; + } else { + this->auth_address = inet_addr (auth_address.c_str ()); + } + this->port = port; + this->running = 0; + this->service = service; +} + +/** + * Starts the server. + * + * @return 1 on error, 0 otherwise. + */ +int UDP_Server::start () { + if (this->running != 0) { + return 1; + } + + /* Run in a new thread */ + this->running = 1; + if (CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) listen, this, 0, NULL) == NULL) { + this->running = 0; + pandoraLog ("UDP Server: Error starting UDP Server thread"); + return 1; + } + + pandoraLog ("UDP Server: UDP Server started on port %d", this->port); + return 0; +} + +/** + * Stops the server. + * + * @return 1 on error, 0 otherwise. + */ +int UDP_Server::stop () { + if (this->running != 0) { + return 1; + } + + this->running = 0; + pandoraLog ("UDP Server: UDP Server going down"); + return 0; +} + +/** + * Listens for incoming packets. + * + * @param server UDP Server. + */ +void Pandora::listen (UDP_Server *server) { + int sockfd,n; + struct sockaddr_in servaddr, cliaddr; + int len, err; + char mesg[MAX_PACKET_SIZE]; + unsigned long auth_addr; + WSADATA wsa; + + err = WSAStartup (MAKEWORD (2,0), &wsa); + if (err != 0) { + /* Could not find a usable Winsock DLL */ + printf("UDP Server: WSAStartup failed with error: %d\n", err); + return; + } + + sockfd = socket (AF_INET, SOCK_DGRAM, 0); + + memset (&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl (server->getAddress ()); + servaddr.sin_port = htons (server->getPort ()); + bind(sockfd, (struct sockaddr *)&servaddr, sizeof (servaddr)); + + /* Get authorised address */ + auth_addr = server->getAuthAddress (); + + while (server->isRunning () == 1) { + len = sizeof(cliaddr); + n = recvfrom(sockfd, mesg, MAX_PACKET_SIZE, 0, (struct sockaddr *)&cliaddr, &len); + if (n == SOCKET_ERROR) { + pandoraLog ("UDP Server: Error %d", WSAGetLastError ()); + break; + } + + /* Authenticate client */ + if (auth_addr != INADDR_ANY && auth_addr != cliaddr.sin_addr.s_addr) { + pandoraLog ("UDP Server: Unauthorised access from %s", inet_ntoa (cliaddr.sin_addr)); + continue; + } + + mesg[n] = 0; + process_command (server->getService (), mesg); + } + + WSACleanup (); +} + +/** + * Processes and executes server commands. + * + * @param service Windows service associated to the server. + * @param command Server command. + * + * @return 1 on error, 0 otherwise. + */ +int Pandora::process_command (Pandora_Windows_Service *service, char *command) { + int rc; + char operation[MAX_PACKET_SIZE], action[MAX_PACKET_SIZE], target[MAX_PACKET_SIZE]; + string var, value; + Pandora_Agent_Conf *conf = NULL; + + rc = sscanf (command, "%s %s %s", operation, action, target); + if (rc < 3) { + pandoraLog ("UDP Server: Received invalid data: %s", command); + return 1; + } + + /* Re-run */ + if (strcmp (operation, "REFRESH") == 0) { + service->pandora_run (); + return 0; + } + + conf = service->getConf(); + + /* Service management */ + if (strcmp (action, "SERVICE") == 0) { + var = "service_"; + var.append (target); + std::transform(var.begin(), var.end(), var.begin(), ::tolower); + value = conf->getValue (var); + if (atoi (value.c_str ()) != 1) { + pandoraLog ("UDP Server: Unauthorised access to service %s", target); + return 1; + } + + if (strcmp (operation, "START") == 0) { + Pandora_Wmi::startService (target); + } else if (strcmp (operation, "STOP") == 0) { + Pandora_Wmi::stopService (target); + } + } + + /* Process management */ + if (strcmp (action, "PROCESS") == 0) { + var = "process_"; + var.append (target); + std::transform(var.begin(), var.end(), var.begin(), ::tolower); + + if (strcmp (operation, "START") == 0) { + var.append ("_start"); + } else if (strcmp (operation, "STOP") == 0) { + var.append ("_stop"); + } else { + return 1; + } + + value = conf->getValue (var); + if (value.empty ()) { + pandoraLog ("UDP Server: Unauthorised access to process %s", target); + return 1; + } + + system (value.c_str()); + } + + return 0; +} diff --git a/pandora_agents/win32/udp_server/udp_server.h b/pandora_agents/win32/udp_server/udp_server.h new file mode 100644 index 0000000000..e70c73d66a --- /dev/null +++ b/pandora_agents/win32/udp_server/udp_server.h @@ -0,0 +1,38 @@ +#ifndef __UDP_SERVER_H__ +#define __UDP_SERVER_H__ + +#define MAX_PACKET_SIZE 1024 + +#include "../pandora_windows_service.h" + +namespace Pandora { + + /** + * UDP Server class. + */ + class UDP_Server { + public: + UDP_Server (Pandora_Windows_Service *service, string address, string auth_address, unsigned int port); + ~UDP_Server (); + unsigned long getAddress (); + unsigned long getAuthAddress (); + unsigned long getPort (); + Pandora_Windows_Service *getService (); + unsigned char isRunning (); + + int start (); + int stop (); + + private: + unsigned long address; + unsigned long auth_address; + unsigned long port; + unsigned char running; + Pandora_Windows_Service *service; + }; + + void listen (UDP_Server *server); + int process_command (Pandora_Windows_Service *service, char *command); +} + +#endif diff --git a/pandora_agents/win32/windows/pandora_wmi.cc b/pandora_agents/win32/windows/pandora_wmi.cc index 75e83f046f..321cdcca40 100644 --- a/pandora_agents/win32/windows/pandora_wmi.cc +++ b/pandora_agents/win32/windows/pandora_wmi.cc @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include using namespace std; @@ -389,8 +389,8 @@ Pandora_Wmi::getSystemName () { * @return The list of events. */ void -Pandora_Wmi::getEventList (string source, string type, string code, - string pattern, int interval, +Pandora_Wmi::getEventList (string source, string type, string code, + string pattern, int interval, list &event_list) { CDhInitialize init; CDispPtr wmi_svc, quickfixes; @@ -514,121 +514,121 @@ Pandora_Wmi::convertWMIDate (string wmi_date, SYSTEMTIME *system_time) system_time->wHour = atoi (wmi_date.substr (8, 2).c_str()); system_time->wMinute = atoi (wmi_date.substr (10, 2).c_str()); system_time->wSecond = atoi (wmi_date.substr (12, 2).c_str()); -} +} + +/** + * Runs a program in a new process. + * + * @param command Command to run, with parameters + */ +bool +Pandora_Wmi::runProgram (string command) { + PROCESS_INFORMATION process_info; + STARTUPINFO startup_info; + bool success; + char *cmd; + + if (command == "") + return false; + + ZeroMemory (&startup_info, sizeof (startup_info)); + startup_info.cb = sizeof (startup_info); + ZeroMemory (&process_info, sizeof (process_info)); + + pandoraDebug ("Start process \"%s\".", command.c_str ()); + cmd = strdup (command.c_str ()); + success = CreateProcess (NULL, cmd, NULL, NULL, FALSE, 0, + NULL, NULL, &startup_info, &process_info); + pandoraFree (cmd); + + if (success) { + pandoraDebug ("The process \"%s\" was started.", command.c_str ()); + return true; + } + pandoraLog ("Could not start process \"%s\". Error %d", command.c_str (), + GetLastError()); + return false; +} + +/** + * Start a Windows service. + * + * @param service_name Service internal name to start. + * + * @retval true If the service started. + * @retval false If the service could not start. A log message is created. + */ +bool +Pandora_Wmi::startService (string service_name) { + SC_HANDLE manager, service; + bool success; + + manager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (manager == NULL) { + pandoraLog ("Could not access to service \"%s\" to start.", + service_name.c_str ()); + return false; + } + + service = OpenService (manager, service_name.c_str (), GENERIC_EXECUTE); + if (service == NULL) { + pandoraLog ("Could not access to service \"%s\" to start.", + service_name.c_str ()); + CloseServiceHandle (manager); + return false; + } + + success = StartService (service, 0, NULL); + + CloseServiceHandle (service); + CloseServiceHandle (manager); + + if (! success) { + pandoraLog ("Could not start service \"%s\". (Error %d)", + service_name.c_str (), GetLastError ()); + } + + return success; +} + +/** + * Stop a Windows service. + * + * @param service_name Service internal name to stop. + * + * @retval true If the service started. + * @retval false If the service could not stop. A log message is created. + */ +bool +Pandora_Wmi::stopService (string service_name) { + SC_HANDLE manager, service; + bool success; + + manager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (manager == NULL) { + pandoraLog ("Could not access to service \"%s\" to stop.", + service_name.c_str ()); + return false; + } + + service = OpenService (manager, service_name.c_str (), SERVICE_STOP); + if (service == NULL) { + pandoraLog ("Could not access to service \"%s\" to stop.", + service_name.c_str ()); + CloseServiceHandle (manager); + return false; + } + + success = ControlService (service, SERVICE_CONTROL_STOP, NULL); + + CloseServiceHandle (service); + CloseServiceHandle (manager); + + if (! success) { + pandoraLog ("Could not stop service \"%s\". (Error %d)", + service_name.c_str (), GetLastError ()); + } + + return success; +} -/** - * Runs a program in a new process. - * - * @param command Command to run, with parameters - */ -bool -Pandora_Wmi::runProgram (string command) { - PROCESS_INFORMATION process_info; - STARTUPINFO startup_info; - bool success; - char *cmd; - - if (command == "") - return false; - - ZeroMemory (&startup_info, sizeof (startup_info)); - startup_info.cb = sizeof (startup_info); - ZeroMemory (&process_info, sizeof (process_info)); - - pandoraDebug ("Start process \"%s\".", command.c_str ()); - cmd = strdup (command.c_str ()); - success = CreateProcess (NULL, cmd, NULL, NULL, FALSE, 0, - NULL, NULL, &startup_info, &process_info); - pandoraFree (cmd); - - if (success) { - pandoraDebug ("The process \"%s\" was started.", command.c_str ()); - return true; - } - pandoraLog ("Could not start process \"%s\". Error %d", command.c_str (), - GetLastError()); - return false; -} - -/** - * Start a Windows service. - * - * @param service_name Service internal name to start. - * - * @retval true If the service started. - * @retval false If the service could not start. A log message is created. - */ -bool -Pandora_Wmi::startService (string service_name) { - SC_HANDLE manager, service; - bool success; - - manager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (manager == NULL) { - pandoraLog ("Could not access to service \"%s\" to start.", - service_name.c_str ()); - return false; - } - - service = OpenService (manager, service_name.c_str (), GENERIC_EXECUTE); - if (service == NULL) { - pandoraLog ("Could not access to service \"%s\" to start.", - service_name.c_str ()); - CloseServiceHandle (manager); - return false; - } - - success = StartService (service, 0, NULL); - - CloseServiceHandle (service); - CloseServiceHandle (manager); - - if (! success) { - pandoraLog ("Could not start service \"%s\". (Error %d)", - service_name.c_str (), GetLastError ()); - } - - return success; -} - -/** - * Stop a Windows service. - * - * @param service_name Service internal name to stop. - * - * @retval true If the service started. - * @retval false If the service could not stop. A log message is created. - */ -bool -Pandora_Wmi::stopService (string service_name) { - SC_HANDLE manager, service; - bool success; - - manager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (manager == NULL) { - pandoraLog ("Could not access to service \"%s\" to stop.", - service_name.c_str ()); - return false; - } - - service = OpenService (manager, service_name.c_str (), GENERIC_EXECUTE); - if (service == NULL) { - pandoraLog ("Could not access to service \"%s\" to stop.", - service_name.c_str ()); - CloseServiceHandle (manager); - return false; - } - - success = ControlService (service, SERVICE_CONTROL_STOP, NULL); - - CloseServiceHandle (service); - CloseServiceHandle (manager); - - if (! success) { - pandoraLog ("Could not stop service \"%s\". (Error %d)", - service_name.c_str (), GetLastError ()); - } - - return success; -} -