source: nscp/service/NSClient++.cpp @ 2c95d22

0.4.00.4.10.4.2
Last change on this file since 2c95d22 was 2c95d22, checked in by Michael Medin <michael@…>, 22 months ago

2011-08-14 MickeM

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