source: nscp/service/NSClient++.cpp @ 8840f09

0.4.00.4.10.4.2
Last change on this file since 8840f09 was 8840f09, checked in by Michael Medin <michael@…>, 21 months ago
  • Fixed some issues in the NSCPClient
  • Fixed debug log issue in core
  • Added support for "pushing" passive checks via NSCP
  • Property mode set to 100644
File size: 48.5 KB
Line 
1///////////////////////////////////////////////////////////////////////////
2// NSClient++ Base Service
3//
4// Copyright (c) 2004 MySolutions NORDIC (http://www.medin.name)
5//
6// Date: 2004-03-13
7// Author: Michael Medin (michael@medin.name)
8//
9// Part of this file is based on work by Bruno Vais (bvais@usa.net)
10//
11// This software is provided "AS IS", without a warranty of any kind.
12// You are free to use/modify this code but leave this header intact.
13//
14//////////////////////////////////////////////////////////////////////////
15#include "StdAfx.h"
16#include "NSClient++.h"
17#include <settings/settings_core.hpp>
18#include <charEx.h>
19//#include <Socket.h>
20#include <config.h>
21#ifdef WIN32
22#include <Userenv.h>
23#include <Lmcons.h>
24//#ifdef DEBUG
25#include <crtdbg.h>
26//#endif
27#endif
28//#include <remote_processes.hpp>
29//#include <winsvc.h>
30//#include <Userenv.h>
31//#include <Lmcons.h>
32//#include <remote_processes.hpp>
33#include "core_api.h"
34#include "../helpers/settings_manager/settings_manager_impl.h"
35#include <settings/macros.h>
36#include "simple_client.hpp"
37#include "settings_client.hpp"
38#include "service_manager.hpp"
39#include "settings_logger_impl.hpp"
40#include <nscapi/nscapi_helper.hpp>
41#include <nscapi/functions.hpp>
42
43#include <settings/client/settings_client.hpp>
44#include "cli_parser.hpp"
45#include "../version.hpp"
46
47#include <protobuf/plugin.pb.h>
48
49#ifdef USE_BREAKPAD
50#include <breakpad/exception_handler_win32.hpp>
51// Used for breakpad crash handling
52static ExceptionManager *g_exception_manager = NULL;
53#endif
54
55NSClient mainClient;    // Global core instance.
56
57
58void NSClientT::log_debug(const char* file, const int line, std::wstring message) {
59        std::string s = nsclient::logger_helper::create_debug(file, line, message);
60        mainClient.reportMessage(s);
61}
62void NSClientT::log_error(const char* file, const int line, std::wstring message) {
63        std::string s = nsclient::logger_helper::create_error(file, line, message);
64        mainClient.reportMessage(s);
65}
66void NSClientT::log_error(const char* file, const int line, std::string message) {
67        std::string s = nsclient::logger_helper::create_error(file, line, utf8::cvt<std::wstring>(message));
68        mainClient.reportMessage(s);
69}
70void NSClientT::log_info(const char* file, const int line, std::wstring message) {
71        std::string s = nsclient::logger_helper::create_info(file, line, message);
72        mainClient.reportMessage(s);
73}
74
75#define LOG_CRITICAL_CORE(msg) { std::string s = nsclient::logger_helper::create_error(__FILE__, __LINE__, msg); mainClient.reportMessage(s); }
76#define LOG_CRITICAL_CORE_STD(msg) LOG_CRITICAL_CORE(std::wstring(msg))
77#define LOG_ERROR_CORE(msg) { std::string s = nsclient::logger_helper::create_error(__FILE__, __LINE__, msg); mainClient.reportMessage(s); }
78#define LOG_ERROR_CORE_STD(msg) LOG_ERROR_CORE(std::wstring(msg))
79#define LOG_INFO_CORE(msg) { std::string s = nsclient::logger_helper::create_info(__FILE__, __LINE__, msg); mainClient.reportMessage(s); }
80#define LOG_INFO_CORE_STD(msg) LOG_INFO_CORE(std::wstring(msg))
81#define LOG_DEBUG_CORE(msg) { if (mainClient.logDebug()) { std::string s = nsclient::logger_helper::create_debug(__FILE__, __LINE__, msg); mainClient.reportMessage(s); } }
82#define LOG_DEBUG_CORE_STD(msg) LOG_DEBUG_CORE(std::wstring(msg))
83
84/**
85 * START OF Tray starter MERGE HELPER
86 */
87class tray_starter {
88        struct start_block {
89                std::wstring cmd;
90                std::wstring cmd_line;
91                DWORD sessionId;
92        };
93
94public:
95        static LPVOID init(DWORD dwSessionId, std::wstring exe, std::wstring cmdline) {
96                start_block *sb = new start_block;
97                sb->cmd = exe;
98                sb->cmd_line = cmdline;
99                sb->sessionId = dwSessionId;
100                return sb;
101        }
102        DWORD threadProc(LPVOID lpParameter) {
103#ifdef WIN32
104                start_block* param = static_cast<start_block*>(lpParameter);
105                DWORD dwSessionId = param->sessionId;
106                std::wstring cmd = param->cmd;
107                std::wstring cmdline = param->cmd_line;
108                delete param;
109                for (int i=0;i<10;i++) {
110                        Sleep(1000);
111                        if (startTrayHelper(dwSessionId, cmd, cmdline, false))
112                                break;
113                }
114#endif
115                return 0;
116        }
117
118        static bool start(std::wstring command, unsigned long  dwSessionId) {
119                std::wstring cmdln = _T("\"") + command + _T("\" -channel __") + strEx::itos(dwSessionId) + _T("__");
120                return tray_starter::startTrayHelper(dwSessionId, command, cmdln);
121        }
122
123        static bool startTrayHelper(unsigned long dwSessionId, std::wstring exe, std::wstring cmdline, bool startThread = true) {
124//              HANDLE hToken = NULL;
125//              if (!remote_processes::GetSessionUserToken(dwSessionId, &hToken)) {
126//                      LOG_ERROR_STD(_T("Failed to query user token: ") + error::lookup::last_error());
127//                      return false;
128//              } else {
129//                      STARTUPINFO          StartUPInfo;
130//                      PROCESS_INFORMATION  ProcessInfo;
131//
132//                      ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO));
133//                      ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION));
134//                      StartUPInfo.wShowWindow = SW_HIDE;
135//                      StartUPInfo.lpDesktop = L"Winsta0\\Default";
136//                      StartUPInfo.cb = sizeof(STARTUPINFO);
137//
138//                      wchar_t *buffer = new wchar_t[cmdline.size()+10];
139//                      wcscpy(buffer, cmdline.c_str());
140//                      LOG_MESSAGE_STD(_T("Running: ") + exe);
141//                      LOG_MESSAGE_STD(_T("Running: ") + cmdline);
142//
143//                      LPVOID pEnv =NULL;
144//                      DWORD dwCreationFlags = CREATE_NO_WINDOW; //0; //DETACHED_PROCESS
145//
146//                      if(CreateEnvironmentBlock(&pEnv,hToken,TRUE)) {
147//                              dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
148//                      } else {
149//                              LOG_ERROR_STD(_T("Failed to create enviornment: ") + error::lookup::last_error());
150//                              pEnv=NULL;
151//                      }
152//                      /*
153//                      LOG_ERROR_STD(_T("Impersonating user: "));
154//                      if (!ImpersonateLoggedOnUser(hToken)) {
155//                              LOG_ERROR_STD(_T("Failed to impersonate the user: ") + error::lookup::last_error());
156//                      }
157//
158//                      wchar_t pszUname[UNLEN + 1];
159//                      ZeroMemory(pszUname,sizeof(pszUname));
160//                      DWORD dwSize = UNLEN;
161//                      if (!GetUserName(pszUname,&dwSize)) {
162//                              DWORD dwErr = GetLastError();
163//                              if (!RevertToSelf())
164//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
165//                              LOG_ERROR_STD(_T("Failed to get username: ") + error::format::from_system(dwErr));
166//                              return false;
167//                      }
168//                     
169//
170//                      PROFILEINFO info;
171//                      info.dwSize = sizeof(PROFILEINFO);
172//                      info.lpUserName = pszUname;
173//                      if (!LoadUserProfile(hToken, &info)) {
174//                              DWORD dwErr = GetLastError();
175//                              if (!RevertToSelf())
176//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
177//                              LOG_ERROR_STD(_T("Failed to get username: ") + error::format::from_system(dwErr));
178//                              return false;
179//                      }
180//                      */
181//                      if (!CreateProcessAsUser(hToken, exe.c_str(), buffer, NULL, NULL, FALSE, dwCreationFlags, pEnv, NULL, &StartUPInfo, &ProcessInfo)) {
182//                              DWORD dwErr = GetLastError();
183//                              delete [] buffer;
184//                              /*
185//                              if (!RevertToSelf()) {
186//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
187//                              }
188//                              */
189//                              if (startThread && dwErr == ERROR_PIPE_NOT_CONNECTED) {
190//                                      LOG_MESSAGE(_T("Failed to start trayhelper: starting a background thread to do it instead..."));
191//                                      Thread<tray_starter> *pThread = new Thread<tray_starter>(_T("tray-starter-thread"));
192//                                      pThread->createThread(tray_starter::init(dwSessionId, exe, cmdline));
193//                                      return false;
194//                              } else if (dwErr == ERROR_PIPE_NOT_CONNECTED) {
195//                                      LOG_ERROR_STD(_T("Thread failed to start trayhelper (will try again): ") + error::format::from_system(dwErr));
196//                                      return false;
197//                              } else {
198//                                      LOG_ERROR_STD(_T("Failed to start trayhelper: ") + error::format::from_system(dwErr));
199//                                      return true;
200//                              }
201//                      } else {
202//                              delete [] buffer;
203//                              /*
204//                              if (!RevertToSelf()) {
205//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
206//                              }
207//                              */
208//                              LOG_MESSAGE_STD(_T("Started tray in other user session: ") + strEx::itos(dwSessionId));
209//                      }
210//
211//
212//                      CloseHandle(hToken);
213//                      return true;
214//              }
215                return false;
216        }
217};
218
219/**
220 * End of class tray started (MERGE HELP)
221 */
222
223bool is_module(boost::filesystem::wpath file )
224{
225#ifdef WIN32
226        return boost::ends_with(file.string(), _T(".dll"));
227#else
228        return boost::ends_with(file.string(), _T(".so"));
229#endif
230}
231/**
232 * Application startup point
233 *
234 * @param argc Argument count
235 * @param argv[] Argument array
236 * @param envp[] Environment array
237 * @return exit status
238 */
239int nscp_main(int argc, wchar_t* argv[]);
240
241#ifdef WIN32
242int wmain(int argc, wchar_t* argv[], wchar_t* envp[]) { return nscp_main(argc, argv); }
243#else
244int main(int argc, char* argv[]) {
245        wchar_t **wargv = new wchar_t*[argc];
246        for (int i=0;i<argc;i++) {
247                std::wstring s = to_wstring(argv[i]);
248                wargv[i] = new wchar_t[s.length()+10];
249                wcscpy(wargv[i], s.c_str());
250        }
251        int ret = nscp_main(argc, wargv);
252        for (int i=0;i<argc;i++) {
253                delete [] wargv[i];
254        }
255        delete [] wargv;
256}
257#endif
258
259int nscp_main(int argc, wchar_t* argv[])
260{
261        srand( (unsigned)time( NULL ) );
262        cli_parser parser(&mainClient);
263        return parser.parse(argc, argv);
264
265//      int nRetCode = 0;
266//      if ( (argc > 1) && ((*argv[1] == '-') || (*argv[1] == '/')) ) {
267//              if (false) {
268//              } else if ( wcscasecmp( _T("encrypt"), argv[1]+1 ) == 0 ) {
269//                      std::wstring password;
270//                      if (!settings_manager::init_settings()) {
271//                              std::wcout << _T("Could not find settings") << std::endl;;
272//                              return 1;
273//                      }
274//                      std::wcout << _T("Enter password to encrypt (has to be a single word): ");
275//                      std::wcin >> password;
276//                      std::wstring xor_pwd = Encrypt(password);
277//                      std::wcout << _T("obfuscated_password=") << xor_pwd << std::endl;
278//                      std::wstring outPasswd = Decrypt(xor_pwd);
279//                      if (password != outPasswd)
280//                              std::wcout << _T("ERROR: Password did not match: ") << outPasswd<< std::endl;
281//                      settings_manager::destroy_settings();
282//                      return 0;
283//              } else if ( wcscasecmp( _T("about"), argv[1]+1 ) == 0 ) {
284//                      try {
285//                              unsigned int next_plugin_id = 0;
286//                              LOG_INFO_CORE(APPLICATION_NAME _T(" (C) Michael Medin - michael<at>medin<dot>name"));
287//                              LOG_INFO_CORE(_T("Version: ") CURRENT_SERVICE_VERSION);
288//                              LOG_INFO_CORE(_T("Architecture: ") SZARCH);
289//
290//                              boost::filesystem::wpath pluginPath = (boost::filesystem::wpath)mainClient.getBasePath() / _T("modules");
291//                              LOG_INFO_CORE_STD(_T("Looking at plugins in: ") + pluginPath.string());
292//
293//                              boost::filesystem::wdirectory_iterator end_itr; // default construction yields past-the-end
294//                              for ( boost::filesystem::wdirectory_iterator itr( pluginPath ); itr != end_itr; ++itr ) {
295//                                      if ( !is_directory(itr->status()) ) {
296//                                              std::wstring file= itr->leaf();
297//                                              LOG_INFO_CORE_STD(_T("Found: ") + file);
298//                                              if (is_module(pluginPath / file)) {
299//                                                      NSCPlugin *plugin = new NSCPlugin(next_plugin_id++, pluginPath / file, _T(""));
300//                                                      std::wstring name = _T("<unknown>");
301//                                                      std::wstring description = _T("<unknown>");
302//                                                      try {
303//                                                              plugin->load_dll();
304//                                                              name = plugin->getName();
305//                                                              description = plugin->getDescription();
306//                                                      } catch(NSPluginException& e) {
307//                                                              LOG_ERROR_CORE_STD(_T("Exception raised: ") + e.error_ + _T(" in module: ") + e.file_);
308//                                                      } catch (std::exception e) {
309//                                                              LOG_ERROR_CORE_STD(_T("exception loading plugin: ") + strEx::string_to_wstring(e.what()));
310//                                                      } catch (...) {
311//                                                              LOG_ERROR_CORE_STD(_T("Unknown exception loading plugin"));
312//                                                      }
313//                                                      LOG_INFO_CORE_STD(_T("* ") + name + _T(" (") + file + _T(")"));
314//                                                      std::list<std::wstring> list = strEx::splitEx(description, _T("\n"));
315//                                                      for (std::list<std::wstring>::const_iterator cit = list.begin(); cit != list.end(); ++cit) {
316//                                                              LOG_INFO_CORE_STD(_T("    ") + *cit);
317//                                                      }
318//                                              }
319//                                      }
320//                              }
321//                              LOG_INFO_CORE_STD(_T("Done listing plugins from: ") + pluginPath.string());
322//                              return true;
323//                      } catch (std::exception &e) {
324//                              LOG_ERROR_CORE_STD(_T("Exception: ") + to_wstring(e.what()));
325//                      } catch (...) {
326//                              LOG_ERROR_CORE_STD(_T("Unknown Exception: "));
327//                      }
328//                      return false;
329//              } else if ( wcscasecmp( _T("d"), argv[1]+1 ) == 0 ) {
330//                      // Run command from command line (like NRPE) but with debug enabled
331//              } else if ( wcscasecmp( _T("c"), argv[1]+1 ) == 0 ) {
332//                      // Run command from command line (like NRPE)
333//                      mainClient.enableDebug(false);
334//                      mainClient.initCore(true);
335//                      std::wstring command, args, msg, perf;
336//                      if (argc > 2)
337//                              command = argv[2];
338//                      for (int i=3;i<argc;i++) {
339//                              if (i!=3) args += _T(" ");
340//                              args += argv[i];
341//                      }
342//                      nRetCode = mainClient.inject(command, args, msg, perf);
343//                      std::wcout << msg << _T("|") << perf << std::endl;
344//                      mainClient.exitCore(true);
345//                      return nRetCode;
346//              } else {
347//                      std::wcerr << _T("Usage: -version, -about, -install, -uninstall, -start, -stop, -encrypt -settings") << std::endl;
348//                      std::wcerr << _T("Usage: [-noboot] <ModuleName> <commnd> [arguments]") << std::endl;
349//                      return -1;
350//              }
351//              return nRetCode;
352//      return nRetCode;
353}
354
355std::list<std::wstring> NSClientT::list_commands() {
356        return commands_.list();
357}
358
359bool contains_plugin(NSClientT::plugin_alias_list_type &ret, std::wstring alias, std::wstring plugin) {
360        std::pair<std::wstring,std::wstring> v;
361        BOOST_FOREACH(v, ret.equal_range(alias)) {
362                if (v.second == plugin)
363                        return true;
364        }
365        return false;
366}
367NSClientT::plugin_alias_list_type NSClientT::find_all_plugins(bool active) {
368        plugin_alias_list_type ret;
369
370        settings::string_list list = settings_manager::get_settings()->get_keys(MAIN_MODULES_SECTION);
371        BOOST_FOREACH(std::wstring plugin, list) {
372                std::wstring alias = settings_manager::get_settings()->get_string(MAIN_MODULES_SECTION, plugin);
373                if (plugin == _T("enabled")) {
374                        plugin = alias;
375                        alias = _T("");
376                } else if ((active && plugin == _T("disabled")) || (active && alias == _T("disabled")))
377                        continue;
378                else if (plugin == _T("disabled")) {
379                        plugin = alias;
380                        alias = _T("");
381                } else if (alias == _T("disabled")) {
382                        alias = _T("");
383                }
384                if (!alias.empty()) {
385                        std::wstring tmp = plugin;
386                        plugin = alias;
387                        alias = tmp;
388                }
389                LOG_DEBUG_CORE_STD(_T("Found: ") + plugin + _T(" as ") + alias);
390                if (plugin.length() > 4 && plugin.substr(plugin.length()-4) == _T(".dll"))
391                        plugin = plugin.substr(0, plugin.length()-4);
392                ret.insert(plugin_alias_list_type::value_type(alias, plugin));
393        }
394        if (!active) {
395                boost::filesystem::wpath pluginPath = expand_path(_T("${module-path}"));
396                boost::filesystem::wdirectory_iterator end_itr; // default construction yields past-the-end
397                for ( boost::filesystem::wdirectory_iterator itr( pluginPath ); itr != end_itr; ++itr ) {
398                        if ( !is_directory(itr->status()) ) {
399                                boost::filesystem::wpath file= itr->leaf();
400                                if (is_module(pluginPath  / file) && !contains_plugin(ret, _T(""), file.string()))
401                                        ret.insert(plugin_alias_list_type::value_type(_T(""), file.string()));
402                        }
403                }
404        }
405        return ret;
406}
407
408// NSClientT::plugin_info_list NSClientT::get_all_plugins() {
409//      boost::filesystem::wpath pluginPath = expand_path(_T("${module-path}"));
410//      plugin_alias_list_type plugins = find_all_plugins(false);
411//      plugin_info_list ret;
412//      std::pair<std::wstring,std::wstring> v;
413//
414//      BOOST_FOREACH(v, plugins) {
415//              plugin_info_type info;
416//              info.dll = v.second;
417//              try {
418//                      LOG_DEBUG_STD(_T("Attempting to fake load: ") + v.second + _T(" as ") + v.first);
419//                      NSCPlugin plugin(next_plugin_id_++, pluginPath / v.second, v.first);
420//                      plugin.load_dll();
421//                      plugin.load_plugin(NSCAPI::dontStart);
422//                      info.name = plugin.getName();
423//                      info.description = plugin.getDescription();
424//                      plugin.unload();
425//              } catch (NSPluginException e) {
426//                      LOG_CRITICAL_STD(_T("Error loading: ") + e.file_ + _T(" root cause: ") + e.error_);
427//              } catch (...) {
428//                      LOG_CRITICAL_STD(_T("Unknown Error loading: ") + info.dll);
429//              }
430//              ret.push_back(info);
431//      }
432//      return ret;
433// }
434
435
436void NSClientT::load_all_plugins(int mode) {
437        boost::filesystem::wpath pluginPath;
438        {
439                try {
440                        pluginPath = expand_path(_T("${module-path}"));
441                } catch (std::exception &e) {
442                        LOG_CRITICAL_CORE_STD(_T("Failed to load plugins: ") + to_wstring(e.what()) + _T(" for ") + expand_path(_T("${module-path}")));
443                        return;
444                }
445                plugin_alias_list_type plugins = find_all_plugins(false);
446                std::pair<std::wstring,std::wstring> v;
447
448                BOOST_FOREACH(v, plugins) {
449                        try {
450                                addPlugin(pluginPath / v.second, v.first);
451                        } catch (NSPluginException &e) {
452                                LOG_CRITICAL_CORE_STD(_T("Failed to register plugin: ") + e.what());
453                        } catch (...) {
454                                LOG_CRITICAL_CORE_STD(_T("Failed to register plugin key: ") + v.second);
455                        }
456                }
457        }
458
459        try {
460                loadPlugins(mode);
461        } catch (...) {
462                LOG_ERROR_CORE_STD(_T("Unknown exception loading plugins"));
463        }
464
465//              std::wstring desc;
466//              std::wstring name = v.second;
467//              try {
468//                      NSCPlugin plugin(next_plugin_id_++, pluginPath / v.second, v.first);
469//                      name = plugin.getModule();
470//                      plugin.load_dll();
471//                      plugin.load_plugin(mode);
472//                      desc = plugin.getName() + _T(" - ");
473//                      desc += plugin.getDescription();
474//                      plugin.unload();
475//              } catch (NSPluginException e) {
476//                      desc += _T("unknown module");
477//                      LOG_CRITICAL_STD(_T("Error loading: ") + e.file_ + _T(" root cause: ") + e.error_);
478//              } catch (...) {
479//                      desc += _T("unknown module");
480//                      LOG_CRITICAL_STD(_T("Unknown Error loading: ") + name);
481//              }
482//              try {
483//                      if (v.first.empty() && !settings_manager::get_settings()->has_key(MAIN_MODULES_SECTION, v.second))
484//                              settings_manager::get_core()->register_key(MAIN_MODULES_SECTION, name, settings::settings_core::key_string, desc, desc, _T("disabled"), false);
485//              } catch (...) {
486//                      LOG_CRITICAL_STD(_T("Failed to register plugin key: ") + name);
487//              }
488        }
489
490void NSClientT::session_error(std::string file, unsigned int line, std::wstring msg) {
491        std::string s = nsclient::logger_helper::create_error(file.c_str(), line, msg);
492        reportMessage(s);
493}
494
495void NSClientT::session_info(std::string file, unsigned int line, std::wstring msg) {
496        std::string s = nsclient::logger_helper::create_info(file.c_str(), line, msg);
497        reportMessage(s);
498}
499
500
501
502
503//////////////////////////////////////////////////////////////////////////
504// Service functions
505
506
507struct nscp_settings_provider : public settings_manager::provider_interface {
508        virtual std::wstring expand_path(std::wstring file) {
509                return mainClient.expand_path(file);
510        }
511        virtual void log_fatal_error(std::wstring error) {
512                LOG_CRITICAL_CORE_STD(error);
513        }
514        virtual settings::logger_interface* create_logger() {
515                return new settings_logger();
516        }
517        std::wstring get_data(std::wstring key) {
518                // TODO
519                return _T("");
520        }
521};
522
523
524nscp_settings_provider provider;
525
526namespace sh = nscapi::settings_helper;
527
528/**
529 * Initialize the program
530 * @param boot true if we shall boot all plugins
531 * @param attachIfPossible is true we will attach to a running instance.
532 * @return success
533 * @author mickem
534 */
535bool NSClientT::initCore(bool boot) {
536        LOG_INFO_CORE(_T("Attempting to start"));
537
538        if (!settings_manager::init_settings(&provider, context_)) {
539                return false;
540        }
541        LOG_INFO_CORE(_T("Booted settings subsystem..."));
542
543        bool crash_submit = false;
544        bool crash_archive = false;
545        bool crash_restart = false;
546        std::wstring crash_url, crash_folder, crash_target, log_level;
547        try {
548
549                sh::settings_registry settings(settings_manager::get_proxy());
550
551                settings.add_path_to_settings()
552                        (_T("log"),                     _T("LOG SETTINGS"), _T("Section for configuring the log handling."))
553                        (_T("shared session"),  _T("SHRED SESSION"), _T("Section for configuring the shared session."))
554                        (_T("crash"),                   _T("CRASH HANDLER"), _T("Section for configuring the crash handler."))
555                        ;
556
557                settings.add_key_to_settings(_T("log"))
558                        (_T("level"), sh::wstring_key(&log_level, _T("INFO")),
559                        _T("LOG LEVEL"), _T("Log level to use"))
560                        ;
561
562                settings.add_key_to_settings(_T("shared session"))
563                        (_T("enabled"), sh::bool_key(&enable_shared_session_ , false),
564                        _T("LOG LEVEL"), _T("Log level to use"))
565                        ;
566
567                settings.add_key_to_settings(_T("crash"))
568                        (_T("submit"), sh::bool_key(&crash_submit, false),
569                        _T("SUBMIT CRASHREPORTS"), _T("Submit crash reports to nsclient.org (or your configured submission server)"))
570
571                        (_T("archive"), sh::bool_key(&crash_archive, true),
572                        _T("ARCHIVE CRASHREPORTS"), _T("Archive crash reports in the archive folder"))
573
574                        (_T("restart"), sh::bool_key(&crash_restart, true),
575                        _T("RESTART"), _T("Submit crash reports to nsclient.org (or your configured submission server)"))
576
577                        (_T("restart target"), sh::wstring_key(&crash_target, get_service_control().get_service_name()),
578                        _T("RESTART SERVICE NAME"), _T("The url to submit crash reports to"))
579
580                        (_T("submit url"), sh::wstring_key(&crash_url, CRASH_SUBMIT_URL),
581                        _T("SUBMISSION URL"), _T("The url to submit crash reports to"))
582
583                        (_T("archive folder"), sh::wpath_key(&crash_folder, CRASH_ARCHIVE_FOLDER),
584                        CRASH_ARCHIVE_FOLDER_KEY, _T("The folder to archive crash dumps in"))
585                        ;
586
587                settings.register_all();
588                settings.notify();
589
590        } catch (settings::settings_exception e) {
591                LOG_ERROR_CORE_STD(_T("Could not find settings: ") + e.getMessage());
592        }
593
594#ifdef USE_BREAKPAD
595
596        if (!g_exception_manager) {
597                g_exception_manager = new ExceptionManager(false);
598
599                g_exception_manager->setup_app(to_wstring(APPLICATION_NAME), to_wstring(STRPRODUCTVER), to_wstring(STRPRODUCTDATE));
600
601                if (crash_restart) {
602                        LOG_DEBUG_CORE(_T("On crash: restart: ") + crash_target);
603                        g_exception_manager->setup_restart(crash_target);
604                }
605
606                bool crashHandling = false;
607                if (crash_submit) {
608                        g_exception_manager->setup_submit(false, crash_url);
609                        LOG_DEBUG_CORE(_T("Submitting crash dumps to central server: ") + crash_url);
610                        crashHandling = true;
611                }
612                if (crash_archive) {
613                        g_exception_manager->setup_archive(crash_folder);
614                        LOG_DEBUG_CORE(_T("Archiving crash dumps in: ") + crash_folder);
615                        crashHandling = true;
616                }
617                if (!crashHandling) {
618                        LOG_ERROR_CORE(_T("No crash handling configured"));
619                } else {
620                        //g_exception_manager->StartMonitoring();
621                }
622        }
623#else
624        LOG_ERROR_CORE(_T("Warning Not compiled with google breakpad support!"));
625#endif
626
627
628        if (enable_shared_session_) {
629                LOG_DEBUG_CORE(_T("Enabling shared session..."));
630                if (boot) {
631                        LOG_INFO_CORE(_T("shared session not ported yet!..."));
632//                      try {
633//                              shared_server_.reset(new nsclient_session::shared_server_session(this));
634//                              if (!shared_server_->session_exists()) {
635//                                      shared_server_->create_new_session();
636//                              } else {
637//                                      LOG_ERROR_STD(_T("Session already exists cant create a new one!"));
638//                              }
639//                              startTrayIcons();
640//                      } catch (nsclient_session::session_exception e) {
641//                              LOG_ERROR_STD(_T("Failed to create new session: ") + e.what());
642//                              shared_server_.reset(NULL);
643//                      } catch (...) {
644//                              LOG_ERROR_STD(_T("Failed to create new session: Unknown exception"));
645//                              shared_server_.reset(NULL);
646//                      }
647                } else {
648                        LOG_INFO_CORE(_T("shared session not ported yet!..."));
649//                      try {
650//                              std::wstring id = _T("_attached_") + strEx::itos(GetCurrentProcessId()) + _T("_");
651//                              shared_client_.reset(new nsclient_session::shared_client_session(id, this));
652//                              if (shared_client_->session_exists()) {
653//                                      shared_client_->attach_to_session(id);
654//                              } else {
655//                                      LOG_ERROR_STD(_T("No session was found cant attach!"));
656//                              }
657//                              LOG_ERROR_STD(_T("Session is: ") + shared_client_->get_client_id());
658//                      } catch (nsclient_session::session_exception e) {
659//                              LOG_ERROR_STD(_T("Failed to attach to session: ") + e.what());
660//                              shared_client_.reset(NULL);
661//                      } catch (...) {
662//                              LOG_ERROR_STD(_T("Failed to attach to session: Unknown exception"));
663//                              shared_client_.reset(NULL);
664//                      }
665                }
666        }
667#ifdef WIN32
668        try {
669                com_helper_.initialize();
670        } catch (com_helper::com_exception e) {
671                LOG_ERROR_CORE_STD(_T("COM exception: ") + e.getMessage());
672                return false;
673        } catch (...) {
674                LOG_ERROR_CORE(_T("Unknown exception iniating COM..."));
675                return false;
676        }
677#endif
678        try {
679                boost::filesystem::wpath pluginPath = expand_path(_T("${module-path}"));
680                plugin_alias_list_type plugins = find_all_plugins(true);
681                std::pair<std::wstring,std::wstring> v;
682                BOOST_FOREACH(v, plugins) {
683                        std::wstring file = NSCPlugin::get_plugin_file(v.second);
684                        std::wstring alias = v.first;
685                        LOG_DEBUG_CORE_STD(_T("Processing plugin: ") + file + _T(" as ") + alias);
686                        try {
687                                addPlugin(pluginPath / boost::filesystem::wpath(file), alias);
688                        } catch(const NSPluginException& e) {
689                                LOG_ERROR_CORE_STD(_T("Exception raised: '") + e.error_ + _T("' in module: ") + e.file_);
690                        } catch (std::exception e) {
691                                LOG_ERROR_CORE_STD(_T("exception loading plugin: ") + file + strEx::string_to_wstring(e.what()));
692                                return false;
693                        } catch (...) {
694                                LOG_ERROR_CORE_STD(_T("Unknown exception loading plugin: ") + file);
695                                return false;
696                        }
697                }
698        } catch (settings::settings_exception e) {
699                LOG_ERROR_CORE_STD(_T("Failed to set settings file") + e.getMessage());
700        } catch (...) {
701                LOG_ERROR_CORE_STD(_T("Unknown exception when loading plugins"));
702                return false;
703        }
704        try {
705                loadPlugins(boot?NSCAPI::normalStart:NSCAPI::dontStart);
706        } catch (...) {
707                LOG_ERROR_CORE_STD(_T("Unknown exception loading plugins"));
708                return false;
709        }
710        LOG_DEBUG_CORE_STD(APPLICATION_NAME _T(" - ") CURRENT_SERVICE_VERSION _T(" Started!"));
711        return true;
712}
713
714void NSClientT::startTrayIcons() {
715//      if (shared_server_.get() == NULL) {
716//              LOG_MESSAGE_STD(_T("No master session so tray icons not started"));
717//              return;
718//      }
719//      remote_processes::PWTS_SESSION_INFO list;
720//      DWORD count;
721//      if (!remote_processes::_WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE , 0, 1, &list, &count)) {
722//              LOG_ERROR_STD(_T("Failed to enumerate sessions:" ) + error::lookup::last_error());
723//      } else {
724//              LOG_DEBUG_STD(_T("Found ") + strEx::itos(count) + _T(" sessions"));
725//              for (DWORD i=0;i<count;i++) {
726//                      LOG_DEBUG_STD(_T("Found session: ") + strEx::itos(list[i].SessionId) + _T(" state: ") + strEx::itos(list[i].State));
727//                      if (list[i].State == remote_processes::_WTS_CONNECTSTATE_CLASS::WTSActive) {
728//                              startTrayIcon(list[i].SessionId);
729//                      }
730//              }
731//      }
732}
733void NSClientT::startTrayIcon(DWORD dwSessionId) {
734//      if (shared_server_.get() == NULL) {
735//              LOG_MESSAGE_STD(_T("No master session so tray icons not started"));
736//              return;
737//      }
738//      if (!shared_server_->re_attach_client(dwSessionId)) {
739//              if (!tray_starter::start(dwSessionId)) {
740//                      LOG_ERROR_STD(_T("Failed to start session (") + strEx::itos(dwSessionId) + _T("): " ) + error::lookup::last_error());
741//              }
742//      }
743}
744
745bool NSClientT::exitCore(bool boot) {
746        LOG_DEBUG_CORE(_T("Attempting to stop"));
747        try {
748                LOG_DEBUG_CORE(_T("Stopping: NON Message Handling Plugins"));
749                mainClient.unloadPlugins(false);
750        } catch(NSPluginException e) {
751                LOG_ERROR_CORE_STD(_T("Exception raised when unloading non msg plguins: ") + e.error_ + _T(" in module: ") + e.file_);
752        } catch(...) {
753                LOG_ERROR_CORE_STD(_T("Unknown exception raised when unloading non msg plugins"));
754        }
755#ifdef WIN32
756        LOG_DEBUG_CORE(_T("Stopping: COM helper"));
757        try {
758                com_helper_.unInitialize();
759        } catch (com_helper::com_exception e) {
760                LOG_ERROR_CORE_STD(_T("COM exception: ") + e.getMessage());
761        } catch (...) {
762                LOG_ERROR_CORE_STD(_T("Unknown exception uniniating COM..."));
763        }
764#endif
765        /*
766        LOG_DEBUG_STD(_T("Stopping: Socket Helpers"));
767        try {
768                simpleSocket::WSACleanup();
769        } catch (simpleSocket::SocketException e) {
770                LOG_ERROR_STD(_T("Socket exception: ") + e.getMessage());
771        } catch (...) {
772                LOG_ERROR_STD(_T("Unknown exception uniniating socket..."));
773        }
774        */
775        LOG_DEBUG_CORE(_T("Stopping: Settings instance"));
776        settings_manager::destroy_settings();
777//      try {
778//              if (shared_client_.get() != NULL) {
779//                      LOG_DEBUG_STD(_T("Stopping: shared client"));
780//                      shared_client_->set_handler(NULL);
781//                      shared_client_->close_session();
782//              }
783//      } catch(nsclient_session::session_exception &e) {
784//              LOG_ERROR_STD(_T("Exception closing shared client session: ") + e.what());
785//      } catch(...) {
786//              LOG_ERROR_STD(_T("Exception closing shared client session: Unknown exception!"));
787//      }
788        try {
789//              if (shared_server_.get() != NULL) {
790//                      LOG_DEBUG_STD(_T("Stopping: shared server"));
791//                      shared_server_->set_handler(NULL);
792//                      shared_server_->close_session();
793//              }
794        } catch(...) {
795                LOG_ERROR_CORE_STD(_T("UNknown exception raised: When closing shared session"));
796        }
797        try {
798                LOG_DEBUG_CORE(_T("Stopping: Message handling Plugins"));
799                mainClient.unloadPlugins(true);
800        } catch(NSPluginException e) {
801                LOG_ERROR_CORE_STD(_T("Exception raised when unloading msg plugins: ") + e.error_ + _T(" in module: ") + e.file_);
802        } catch(...) {
803                LOG_ERROR_CORE_STD(_T("UNknown exception raised: When stopping message plguins"));
804        }
805        LOG_INFO_CORE(_T("Stopped succcessfully"));
806        logger_master_.stop_slave();
807        return true;
808}
809void NSClientT::service_on_session_changed(unsigned long dwSessionId, bool logon, unsigned long dwEventType) {
810//      if (shared_server_.get() == NULL) {
811//              LOG_DEBUG_STD(_T("No shared session: ignoring change event!"));
812//              return;
813//      }
814//      LOG_DEBUG_CORE_STD(_T("Got session change: ") + strEx::itos(dwSessionId));
815//      if (!logon) {
816//              LOG_DEBUG_CORE_STD(_T("Not a logon event: ") + strEx::itos(dwEventType));
817//              return;
818//      }
819//      tray_starter::start(dwSessionId);
820}
821
822//////////////////////////////////////////////////////////////////////////
823// Member functions
824
825
826
827/**
828 * Unload all plug-ins (in reversed order)
829 */
830void NSClientT::unloadPlugins(bool unloadLoggers) {
831        {
832                boost::unique_lock<boost::shared_mutex> writeLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
833                if (!writeLock.owns_lock()) {
834                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex (003)."));
835                        return;
836                }
837                if (unloadLoggers)
838                        logger_master_.remove_all_plugins();
839        }
840        {
841                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
842                if (!readLock.owns_lock()) {
843                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex (004)."));
844                        return;
845                }
846                for (pluginList::reverse_iterator it = plugins_.rbegin(); it != plugins_.rend(); ++it) {
847                        plugin_type p = *it;
848                        if (!p)
849                                continue;
850                        try {
851                                if (unloadLoggers || !p->hasMessageHandler()) {
852                                        LOG_DEBUG_CORE_STD(_T("Unloading plugin: ") + p->getModule() + _T("..."));
853                                        p->unload();
854                                } else {
855                                        LOG_DEBUG_CORE_STD(_T("Skipping log plugin: ") + p->getModule() + _T("..."));
856                                }
857                        } catch(NSPluginException e) {
858                                LOG_ERROR_CORE_STD(_T("Exception raised when unloading plugin: ") + e.error_ + _T(" in module: ") + e.file_);
859                        } catch(...) {
860                                LOG_ERROR_CORE_STD(_T("Unknown exception raised when unloading plugin"));
861                        }
862                }
863        }
864        {
865                boost::unique_lock<boost::shared_mutex> writeLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
866                if (!writeLock.owns_lock()) {
867                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex (005)."));
868                        return;
869                }
870                commands_.remove_all();
871                for (pluginList::iterator it = plugins_.begin(); it != plugins_.end();) {
872                        plugin_type p = (*it);
873                        try {
874                                if (!p && (unloadLoggers|| !p->isLoaded())) {
875                                        it = plugins_.erase(it);
876                                        //delete p;
877                                        continue;
878                                }
879                        } catch(NSPluginException e) {
880                                LOG_ERROR_CORE_STD(_T("Exception raised when unloading plugin: ") + e.error_ + _T(" in module: ") + e.file_);
881                        } catch(...) {
882                                LOG_ERROR_CORE(_T("Unknown exception raised when unloading plugin"));
883                        }
884                        it++;
885                }
886        }
887}
888
889void NSClientT::loadPlugins(NSCAPI::moduleLoadMode mode) {
890        bool hasBroken = false;
891        {
892                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
893                if (!readLock.owns_lock()) {
894                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex (006)."));
895                        return;
896                }
897                for (pluginList::iterator it=plugins_.begin(); it != plugins_.end();) {
898                        LOG_DEBUG_CORE_STD(_T("Loading plugin: ") + (*it)->getName() + _T(" as ") + (*it)->get_alias());
899                        try {
900                                if (!(*it)->load_plugin(mode)) {
901                                        LOG_ERROR_CORE_STD(_T("Plugin refused to load: ") + (*it)->getModule());
902                                        it = plugins_.erase(it);
903                                } else
904                                        ++it;
905                        } catch (NSPluginException e) {
906                                it = plugins_.erase(it);
907                                LOG_ERROR_CORE_STD(_T("Could not load plugin: ") + e.file_ + _T(": ") + e.error_);
908                        } catch (...) {
909                                it = plugins_.erase(it);
910                                LOG_ERROR_CORE_STD(_T("Could not load plugin: ") + (*it)->getModule());
911                        }
912                }
913        }
914        logger_master_.all_plugins_loaded();
915}
916/**
917 * Load and add a plugin to various internal structures
918 * @param plugin The plug-in instance to load. The pointer is managed by the
919 */
920NSClientT::plugin_type NSClientT::addPlugin(boost::filesystem::wpath file, std::wstring alias) {
921        {
922                LOG_DEBUG_CORE_STD(_T("addPlugin(") + file.string() + _T(" as ") + alias + _T(")"));
923                // Check if this is a duplicate plugin (if so return that instance)
924                boost::unique_lock<boost::shared_mutex> writeLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
925                if (!writeLock.owns_lock()) {
926                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex (007a)."));
927                        return plugin_type();
928                }
929
930                BOOST_FOREACH(plugin_type plug, plugins_) {
931                        if (plug->is_duplicate(file, alias)) {
932                                LOG_DEBUG_CORE_STD(_T("Found duplicate plugin returning old ") + to_wstring(plug->get_id()));
933                                return plug;
934                        }
935                }
936
937        }
938
939
940        plugin_type plugin(new NSCPlugin(next_plugin_id_++, file, alias));
941        plugin->load_dll();
942        {
943                boost::unique_lock<boost::shared_mutex> writeLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
944                if (!writeLock.owns_lock()) {
945                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex (007b)."));
946                        return plugin;
947                }
948
949                plugins_.insert(plugins_.end(), plugin);
950                commands_.add_plugin(plugin);
951                channels_.add_plugin(plugin);
952                if (plugin->hasNotificationHandler()) {
953                        channels_.register_listener(plugin->get_id(), _T("NSCA"));
954                }
955                if (plugin->hasMessageHandler())
956                        logger_master_.add_plugin(plugin);
957                //settings_manager::get_core()->register_key(_T("/modules"), plugin->getModule(), settings::settings_core::key_string, plugin->getName(), plugin->getDescription(), _T(""), false);
958                // TODO add comments elsewhere to the settings store for all loaded modules...
959        }
960        return plugin;
961}
962
963
964std::wstring NSClientT::describeCommand(std::wstring command) {
965        return commands_.describe(command);
966}
967std::list<std::wstring> NSClientT::getAllCommandNames() {
968        return commands_.list();
969}
970void NSClientT::registerCommand(unsigned int id, std::wstring cmd, std::wstring desc) {
971        return commands_.register_command(id, cmd, desc);
972}
973
974NSCAPI::nagiosReturn NSClientT::inject(std::wstring command, std::wstring arguments, std::wstring &msg, std::wstring & perf) {
975        /*if (shared_client_.get() != NULL && shared_client_->hasMaster()) {
976                try {
977                        return shared_client_->inject(command, arguments, splitter, escape, msg, perf);
978                } catch (nsclient_session::session_exception &e) {
979                        LOG_ERROR_STD(_T("Failed to inject remote command: ") + e.what());
980                        return NSCAPI::returnCRIT;
981                } catch (...) {
982                        LOG_ERROR_STD(_T("Failed to inject remote command: Unknown exception"));
983                        return NSCAPI::returnCRIT;
984                }
985        } else */{
986
987                std::list<std::wstring> args;
988                strEx::parse_command(arguments, args);
989                std::string request, response;
990                nscapi::functions::create_simple_query_request(command, args, request);
991                NSCAPI::nagiosReturn ret = injectRAW(command.c_str(), request, response);
992                if (response.empty()) {
993                        LOG_ERROR_CORE(_T("No data retutned from command"));
994                        return NSCAPI::returnUNKNOWN;
995                }
996                nscapi::functions::parse_simple_query_response(response, msg, perf);
997                return ret;
998        }
999}
1000
1001/**
1002 * Inject a command into the plug-in stack.
1003 *
1004 * @param command Command to inject
1005 * @param argLen Length of argument buffer
1006 * @param **argument Argument buffer
1007 * @param *returnMessageBuffer Message buffer
1008 * @param returnMessageBufferLen Length of returnMessageBuffer
1009 * @param *returnPerfBuffer Performance data buffer
1010 * @param returnPerfBufferLen Length of returnPerfBuffer
1011 * @return The command status
1012 */
1013NSCAPI::nagiosReturn NSClientT::injectRAW(const wchar_t* raw_command, std::string &request, std::string &response) {
1014        std::wstring cmd = nsclient::commands::make_key(raw_command);
1015        if (logDebug()) {
1016                LOG_DEBUG_CORE_STD(_T("Injecting: ") + cmd + _T("..."));
1017        }
1018        /*if (shared_client_.get() != NULL && shared_client_->hasMaster()) {
1019                try {
1020                        std::wstring msg, perf;
1021                        int returnCode = shared_client_->inject(command, arrayBuffer::arrayBuffer2string(argument, argLen, _T(" ")), L' ', true, msg, perf);
1022                        NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, msg, returnCode);
1023                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, perf, returnCode);
1024                } catch (nsclient_session::session_exception &e) {
1025                        LOG_ERROR_STD(_T("Failed to inject remote command: ") + e.what());
1026                        int returnCode = NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, _T("Failed to inject remote command: ") + e.what(), NSCAPI::returnCRIT);
1027                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, _T(""), returnCode);
1028                } catch (...) {
1029                        LOG_ERROR_STD(_T("Failed to inject remote command: Unknown exception"));
1030                        int returnCode = NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, _T("Failed to inject remote command:  + e.what()"), NSCAPI::returnCRIT);
1031                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, _T(""), returnCode);
1032                }
1033        } else */{
1034                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
1035                if (!readLock.owns_lock()) {
1036                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex (008)."));
1037                        return NSCAPI::returnUNKNOWN;
1038                }
1039                try {
1040                        nsclient::commands::plugin_type plugin = commands_.get(cmd);
1041                        if (!plugin) {
1042                                LOG_ERROR_CORE(_T("No handler for command: ") + cmd + _T(" avalible commands: ") + commands_.to_wstring());
1043                                return NSCAPI::returnIgnored;
1044                        }
1045                        NSCAPI::nagiosReturn c = plugin->handleCommand(cmd.c_str(), request, response);
1046                        LOG_DEBUG_CORE_STD(_T("Result ") + cmd + _T(": ") + nscapi::plugin_helper::translateReturn(c));
1047                        return c;
1048                } catch (nsclient::commands::command_exception &e) {
1049                        LOG_ERROR_CORE(_T("No handler for command: ") + cmd + _T(": ") + to_wstring(e.what()));
1050                        return NSCAPI::returnIgnored;
1051                } catch (...) {
1052                        LOG_ERROR_CORE(_T("Error handling command: ") + cmd);
1053                        return NSCAPI::returnIgnored;
1054                }
1055        }
1056}
1057
1058
1059int NSClientT::simple_exec(std::wstring module, std::wstring command, std::vector<std::wstring> arguments, std::list<std::wstring> &resp) {
1060        bool found = false;
1061        std::string request;
1062        std::list<std::string> responses;
1063        nscapi::functions::create_simple_exec_request(command, arguments, request);
1064        int ret = 0;
1065        {
1066                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(5));
1067                if (!readLock.owns_lock()) {
1068                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex (001)."));
1069                        return -1;
1070                }
1071                BOOST_FOREACH(plugin_type p, plugins_) {
1072                        if (p) {
1073                                if ((module.empty() || p->getModule() == module)&&(p->has_command_line_exec())) {
1074                                        LOG_DEBUG_CORE_STD(_T("Found module: ") + p->getName() + _T("..."));
1075                                        try {
1076                                                std::string response;
1077                                                ret = p->commandLineExec(command.c_str(), request, response);
1078                                                found = true;
1079                                                if (ret != NSCAPI::returnIgnored && !response.empty())
1080                                                        responses.push_back(response);
1081                                        } catch (NSPluginException e) {
1082                                                LOG_ERROR_CORE_STD(_T("Could not execute command: ") + e.error_ + _T(" in ") + e.file_);
1083                                                return -1;
1084                                        }
1085                                }
1086                        }
1087                }
1088        }
1089        if (!found && !module.empty()) {
1090                try {
1091                        boost::filesystem::wpath file = NSCPlugin::get_filename(getBasePath() / boost::filesystem::wpath(_T("modules")), module);
1092                        if (boost::filesystem::is_regular(file)) {
1093                                plugin_type plugin = addPlugin(file, _T(""));
1094                                if (plugin) {
1095                                        LOG_DEBUG_CORE_STD(_T("Loading plugin: ") + plugin->getName() + _T("..."));
1096                                        plugin->load_plugin(NSCAPI::dontStart);
1097                                        std::string response;
1098                                        ret = plugin->commandLineExec(command.c_str(), request, response);
1099                                        if (ret != NSCAPI::returnIgnored && !response.empty())
1100                                                responses.push_back(response);
1101                                } else {
1102                                        LOG_ERROR_CORE_STD(_T("Failed to load: ") + std::wstring(module));
1103                                        return 1;
1104                                }
1105                        } else {
1106                                LOG_ERROR_CORE_STD(_T("Failed to load: ") + std::wstring(module));
1107                                return 1;
1108                        }
1109                } catch (const NSPluginException &e) {
1110                        resp.push_back(_T("Module (") + e.file_ + _T(") was not found: ") + e.error_);
1111                        LOG_INFO_CORE_STD(_T("Module (") + e.file_ + _T(") was not found: ") + e.error_);
1112                } catch(const std::exception &e) {
1113                        resp.push_back(_T("Module (") + module + _T(") was not found: ") + utf8::cvt<std::wstring>(e.what()));
1114                        LOG_INFO_CORE_STD(_T("Module (") + module + _T(") was not found: ") + utf8::cvt<std::wstring>(e.what()));
1115                        return 1;
1116                } catch(...) {
1117                        resp.push_back(_T("Module (") + module + _T(") was not found..."));
1118                        LOG_INFO_CORE_STD(_T("Module (") + module + _T(") was not found..."));
1119                        return 1;
1120                }
1121        }
1122        BOOST_FOREACH(std::string &r, responses) {
1123                try {
1124                        nscapi::functions::parse_simple_exec_result(r, resp);
1125                } catch (std::exception &e) {
1126                        resp.push_back(_T("Failed to extract return message: ") + utf8::cvt<std::wstring>(e.what()));
1127                        LOG_ERROR_CORE_STD(resp.back());
1128                        return NSCAPI::returnUNKNOWN;
1129                }
1130        }
1131        return ret;
1132}
1133
1134
1135NSCAPI::nagiosReturn NSClientT::exec_command(const wchar_t* raw_command, std::string &request, std::string &response) {
1136        std::list<std::string> responses;
1137        bool found = false;
1138        {
1139                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(5));
1140                if (!readLock.owns_lock()) {
1141                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex (001)."));
1142                        return -1;
1143                }
1144                BOOST_FOREACH(plugin_type p, plugins_) {
1145                        if (p && p->has_command_line_exec()) {
1146                                try {
1147                                        std::string response;
1148                                        NSCAPI::nagiosReturn r = p->commandLineExec(raw_command, request, response);
1149                                        if (r != NSCAPI::returnIgnored && !response.empty()) {
1150                                                LOG_DEBUG_CORE_STD(_T("Got response from: ") + p->getName());
1151                                                found = true;
1152                                                responses.push_back(response);
1153                                        }
1154                                } catch (NSPluginException e) {
1155                                        LOG_ERROR_CORE_STD(_T("Could not execute command: ") + e.error_ + _T(" in ") + e.file_);
1156                                }
1157                        }
1158                }
1159        }
1160
1161        Plugin::ExecuteResponseMessage response_message;
1162        nscapi::functions::create_simple_header(response_message.mutable_header(), Plugin::Common_Header_Type_EXEC_RESPONSE);
1163
1164        BOOST_FOREACH(std::string r, responses) {
1165                Plugin::ExecuteResponseMessage tmp;
1166                tmp.ParseFromString(r);
1167                for (int i=0;i<tmp.payload_size();i++) {
1168                        Plugin::ExecuteResponseMessage::Response *r = response_message.add_payload();
1169                        r->CopyFrom(tmp.payload(i));
1170                }
1171        }
1172        response_message.SerializeToString(&response);
1173        if (found)
1174                return NSCAPI::returnOK;
1175        return NSCAPI::returnIgnored;
1176}
1177
1178
1179
1180NSCAPI::errorReturn NSClientT::send_notification(const wchar_t* channel, const wchar_t* command, NSCAPI::nagiosReturn code,  char* result, unsigned int result_len) {
1181        boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
1182        if (!readLock.owns_lock()) {
1183                LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex (009)."));
1184                return NSCAPI::hasFailed;
1185        }
1186        try {
1187                //LOG_ERROR_CORE_STD(_T("Notifying: ") + strEx::strip_hex(to_wstring(std::string(result,result_len))));
1188                bool found = false;
1189                BOOST_FOREACH(nsclient::channels::plugin_type p, channels_.get(channel)) {
1190                        p->handleNotification(channel, command, code, result, result_len);
1191                        found = true;
1192                }
1193                if (!found) {
1194                        LOG_ERROR_CORE_STD(_T("Noone listens for events from: ") + std::wstring(channel));
1195                }
1196                return NSCAPI::isSuccess;
1197        } catch (nsclient::channels::channel_exception &e) {
1198                LOG_ERROR_CORE(_T("No handler for channel: ") + std::wstring(channel) + _T(": ") + to_wstring(e.what()));
1199                return NSCAPI::hasFailed;
1200        } catch (...) {
1201                LOG_ERROR_CORE(_T("Error handling channel: ") + std::wstring(channel));
1202                return NSCAPI::hasFailed;
1203        }
1204}
1205
1206void NSClientT::listPlugins() {
1207        boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
1208        if (!readLock.owns_lock()) {
1209                LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex (010)."));
1210                return;
1211        }
1212        for (pluginList::iterator it=plugins_.begin(); it != plugins_.end(); ++it) {
1213                try {
1214                        if ((*it)->isBroken()) {
1215                                std::wcout << (*it)->getModule() << _T(": ") << _T("broken") << std::endl;
1216                        } else {
1217                                std::wcout << (*it)->getModule() << _T(": ") << (*it)->getName() << std::endl;
1218                        }
1219                } catch (NSPluginException e) {
1220                        LOG_ERROR_CORE_STD(_T("Could not load plugin: ") + e.file_ + _T(": ") + e.error_);
1221                }
1222        }
1223
1224}
1225
1226bool NSClientT::logDebug() {
1227        if (debug_ == log_state_unknown) {
1228                debug_ = log_state_looking;
1229                try {
1230                        if (settings_manager::get_settings_no_wait()->get_bool(_T("log"), _T("debug"), false) == 1)
1231                                debug_ = log_state_debug;
1232                        else
1233                                debug_ = log_state_nodebug;
1234                } catch (settings::settings_exception e) {
1235                        debug_ = log_state_unknown;
1236                        return false;
1237                }
1238        } else if (debug_ == log_state_looking)
1239                return false;
1240        return (debug_ == log_state_debug);
1241}
1242
1243/**
1244 * Report a message to all logging enabled modules.
1245 *
1246 * @param msgType Message type
1247 * @param file Filename generally __FILE__
1248 * @param line  Line number, generally __LINE__
1249 * @param message The message as a human readable string.
1250 */
1251void NSClientT::reportMessage(std::string data) {
1252        try {
1253                logger_master_.log(data);
1254        } catch (...) {
1255                logger_master_.log_fatal_error("Caught UNKNOWN Exception when trying to log a message");
1256        }
1257}
1258boost::filesystem::wpath NSClientT::getBasePath(void) {
1259        boost::unique_lock<boost::timed_mutex> lock(internalVariables, boost::get_system_time() + boost::posix_time::seconds(5));
1260        if (!lock.owns_lock()) {
1261                LOG_ERROR_CORE(_T("FATAL ERROR: Could not get mutex."));
1262                return _T("FATAL ERROR");
1263        }
1264        if (!basePath.empty())
1265                return basePath;
1266        unsigned int buf_len = 4096;
1267#ifdef WIN32
1268        wchar_t* buffer = new wchar_t[buf_len+1];
1269        GetModuleFileName(NULL, buffer, buf_len);
1270        std::wstring path = buffer;
1271        std::wstring::size_type pos = path.rfind('\\');
1272        basePath = path.substr(0, pos) + _T("\\");
1273        delete [] buffer;
1274#else
1275        basePath = to_wstring(boost::filesystem::initial_path().string());
1276#endif
1277        try {
1278                settings_manager::get_core()->set_base(basePath);
1279        } catch (settings::settings_exception e) {
1280                LOG_ERROR_CORE_STD(_T("Failed to set settings file: ") + e.getMessage());
1281        } catch (...) {
1282                LOG_ERROR_CORE_STD(_T("Failed to set settings file"));
1283        }
1284        return basePath;
1285}
1286
1287
1288std::wstring Encrypt(std::wstring str, unsigned int algorithm) {
1289        unsigned int len = 0;
1290        NSAPIEncrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), NULL, &len);
1291        len+=2;
1292        wchar_t *buf = new wchar_t[len+1];
1293        NSCAPI::errorReturn ret = NSAPIEncrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), buf, &len);
1294        if (ret == NSCAPI::isSuccess) {
1295                std::wstring ret = buf;
1296                delete [] buf;
1297                return ret;
1298        }
1299        return _T("");
1300}
1301std::wstring Decrypt(std::wstring str, unsigned int algorithm) {
1302        unsigned int len = 0;
1303        NSAPIDecrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), NULL, &len);
1304        len+=2;
1305        wchar_t *buf = new wchar_t[len+1];
1306        NSCAPI::errorReturn ret = NSAPIDecrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), buf, &len);
1307        if (ret == NSCAPI::isSuccess) {
1308                std::wstring ret = buf;
1309                delete [] buf;
1310                return ret;
1311        }
1312        return _T("");
1313}
1314
1315void NSClientT::nsclient_log_error(std::string file, int line, std::wstring error) {
1316        std::string s = nsclient::logger_helper::create_error(file, line, error);
1317        reportMessage(s.c_str());
1318}
1319
1320
1321
1322// Service API
1323NSClient* NSClientT::get_global_instance() {
1324        return &mainClient;
1325}
1326void NSClientT::handle_startup(std::wstring service_name) {
1327        service_name_ = service_name;
1328        initCore(true);
1329/*
1330        DWORD dwSessionId = remote_processes::getActiveSessionId();
1331        if (dwSessionId != 0xFFFFFFFF)
1332                tray_starter::start(dwSessionId);
1333        else
1334                LOG_ERROR_STD(_T("Failed to start tray helper:" ) + error::lookup::last_error());
1335                */
1336}
1337void NSClientT::handle_shutdown(std::wstring service_name) {
1338        exitCore(true);
1339}
1340
1341NSClientT::service_controller NSClientT::get_service_control() {
1342        return service_controller(service_name_);
1343}
1344
1345void NSClientT::service_controller::stop() {
1346#ifdef WIN32
1347        serviceControll::StopNoWait(get_service_name());
1348#endif
1349}
1350void NSClientT::service_controller::start() {
1351#ifdef WIN32
1352        serviceControll::Start(get_service_name());
1353#endif
1354}
1355bool NSClientT::service_controller::is_started() {
1356#ifdef WIN32
1357        try {
1358                if (serviceControll::isStarted(get_service_name())) {
1359                        return true;
1360                }
1361        } catch (...) {
1362                return false;
1363        }
1364#endif
1365        return false;
1366}
1367
1368std::wstring NSClientT::expand_path(std::wstring file) {
1369        strEx::replace(file, _T("${certificate-path}"), _T("${shared-path}/security"));
1370        strEx::replace(file, _T("${module-path}"), _T("${shared-path}/modules"));
1371       
1372        strEx::replace(file, _T("${base-path}"), getBasePath().string());
1373#ifdef WIN32
1374        strEx::replace(file, _T("${shared-path}"), getBasePath().string());
1375#else
1376        strEx::replace(file, _T("${shared-path}"), getBasePath().string());
1377//      strEx::replace(file, _T("${shared-path}"), _T("/usr/share/nsclient++"));
1378#endif
1379        strEx::replace(file, _T("${exe-path}"), getBasePath().string());
1380        strEx::replace(file, _T("${etc}"), _T("/etc"));
1381        return file;
1382}
1383
1384#ifdef _WIN32
1385void NSClientT::handle_session_change(unsigned long dwSessionId, bool logon) {
1386
1387}
1388#endif
Note: See TracBrowser for help on using the repository browser.