source: nscp/service/NSClient++.cpp @ 6822839

0.4.00.4.10.4.2
Last change on this file since 6822839 was 6822839, checked in by Michael Medin <michael@…>, 3 years ago

Fixed some unix issue

  • Property mode set to 100644
File size: 47.3 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.h>
18#include <charEx.h>
19//#include <Socket.h>
20#include <config.h>
21#include <msvc_wrappers.h>
22#ifdef WIN32
23#include <Userenv.h>
24#include <Lmcons.h>
25//#ifdef DEBUG
26#include <crtdbg.h>
27//#endif
28#endif
29//#include <remote_processes.hpp>
30//#include <winsvc.h>
31//#include <Userenv.h>
32//#include <Lmcons.h>
33//#include <remote_processes.hpp>
34#include "core_api.h"
35#include "settings_manager_impl.h"
36#include <settings/macros.h>
37#include <NSCHelper.h>
38#include "simple_client.hpp"
39#include "settings_client.hpp"
40#include "service_manager.hpp"
41
42NSClient mainClient(SZSERVICENAME);     // Global core instance.
43bool g_bConsoleLog = false;
44
45
46//////////////////////////////////////////////////////////////////////////
47// Log macros to simplify logging
48// Generally names are of the form LOG_<severity>[_STD]
49// Where _STD indicates that strings are force wrapped inside a std::wstring
50//
51#define LOG_ERROR_STD(msg) LOG_ERROR(((std::wstring)msg).c_str())
52#define LOG_ERROR(msg) \
53        NSAPIMessage(NSCAPI::error, __FILEW__, __LINE__, msg)
54
55#define LOG_CRITICAL_STD(msg) LOG_CRITICAL(((std::wstring)msg).c_str())
56#define LOG_CRITICAL(msg) \
57        NSAPIMessage(NSCAPI::critical, __FILEW__, __LINE__, msg)
58#define LOG_MESSAGE_STD(msg) LOG_MESSAGE(((std::wstring)msg).c_str())
59#define LOG_MESSAGE(msg) \
60        NSAPIMessage(NSCAPI::log, __FILEW__, __LINE__, msg)
61
62#define LOG_DEBUG_STD(msg) LOG_DEBUG(((std::wstring)msg).c_str())
63#define LOG_DEBUG(msg) \
64        NSAPIMessage(NSCAPI::debug, __FILEW__, __LINE__, msg)
65
66#define LOG_ERROR_CORE(msg) reportMessage(NSCAPI::error, __FILEW__, __LINE__, msg)
67#define LOG_ERROR_CORE_STD(msg) LOG_ERROR_CORE(std::wstring(msg))
68
69
70#define SETTINGS_GET_BOOL_CORE(key) \
71        settings_manager::get_settings()->get_bool(setting_keys::key ## _PATH, setting_keys::key, setting_keys::key ## _DEFAULT)
72
73#define SETTINGS_GET_STRING_CORE(key) \
74        settings_manager::get_settings()->get_string(setting_keys::key ## _PATH, setting_keys::key, setting_keys::key ## _DEFAULT)
75/*
76#define SETTINGS_SET_STRING_CORE(key, value) \
77        Settings::get_settings()->set_string(setting_keys::key ## _PATH, setting_keys::key, value);
78*/
79/**
80 * START OF Tray starter MERGE HELPER
81 */
82class tray_starter {
83        struct start_block {
84                std::wstring cmd;
85                std::wstring cmd_line;
86                DWORD sessionId;
87        };
88
89public:
90        static LPVOID init(DWORD dwSessionId, std::wstring exe, std::wstring cmdline) {
91                start_block *sb = new start_block;
92                sb->cmd = exe;
93                sb->cmd_line = cmdline;
94                sb->sessionId = dwSessionId;
95                return sb;
96        }
97        DWORD threadProc(LPVOID lpParameter) {
98#ifdef WIN32
99                start_block* param = static_cast<start_block*>(lpParameter);
100                DWORD dwSessionId = param->sessionId;
101                std::wstring cmd = param->cmd;
102                std::wstring cmdline = param->cmd_line;
103                delete param;
104                for (int i=0;i<10;i++) {
105                        Sleep(1000);
106                        if (startTrayHelper(dwSessionId, cmd, cmdline, false))
107                                break;
108                }
109#endif
110                return 0;
111        }
112
113        static bool start(unsigned long  dwSessionId) {
114                boost::filesystem::wpath program = mainClient.getBasePath() / SETTINGS_GET_STRING_CORE(settings_def::SYSTRAY_EXE);
115                std::wstring cmdln = _T("\"") + program.string() + _T("\" -channel __") + strEx::itos(dwSessionId) + _T("__");
116                return tray_starter::startTrayHelper(dwSessionId, program.string(), cmdln);
117        }
118
119        static bool startTrayHelper(unsigned long dwSessionId, std::wstring exe, std::wstring cmdline, bool startThread = true) {
120//              HANDLE hToken = NULL;
121//              if (!remote_processes::GetSessionUserToken(dwSessionId, &hToken)) {
122//                      LOG_ERROR_STD(_T("Failed to query user token: ") + error::lookup::last_error());
123//                      return false;
124//              } else {
125//                      STARTUPINFO          StartUPInfo;
126//                      PROCESS_INFORMATION  ProcessInfo;
127//
128//                      ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO));
129//                      ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION));
130//                      StartUPInfo.wShowWindow = SW_HIDE;
131//                      StartUPInfo.lpDesktop = L"Winsta0\\Default";
132//                      StartUPInfo.cb = sizeof(STARTUPINFO);
133//
134//                      wchar_t *buffer = new wchar_t[cmdline.size()+10];
135//                      wcscpy(buffer, cmdline.c_str());
136//                      LOG_MESSAGE_STD(_T("Running: ") + exe);
137//                      LOG_MESSAGE_STD(_T("Running: ") + cmdline);
138//
139//                      LPVOID pEnv =NULL;
140//                      DWORD dwCreationFlags = CREATE_NO_WINDOW; //0; //DETACHED_PROCESS
141//
142//                      if(CreateEnvironmentBlock(&pEnv,hToken,TRUE)) {
143//                              dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
144//                      } else {
145//                              LOG_ERROR_STD(_T("Failed to create enviornment: ") + error::lookup::last_error());
146//                              pEnv=NULL;
147//                      }
148//                      /*
149//                      LOG_ERROR_STD(_T("Impersonating user: "));
150//                      if (!ImpersonateLoggedOnUser(hToken)) {
151//                              LOG_ERROR_STD(_T("Failed to impersonate the user: ") + error::lookup::last_error());
152//                      }
153//
154//                      wchar_t pszUname[UNLEN + 1];
155//                      ZeroMemory(pszUname,sizeof(pszUname));
156//                      DWORD dwSize = UNLEN;
157//                      if (!GetUserName(pszUname,&dwSize)) {
158//                              DWORD dwErr = GetLastError();
159//                              if (!RevertToSelf())
160//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
161//                              LOG_ERROR_STD(_T("Failed to get username: ") + error::format::from_system(dwErr));
162//                              return false;
163//                      }
164//                     
165//
166//                      PROFILEINFO info;
167//                      info.dwSize = sizeof(PROFILEINFO);
168//                      info.lpUserName = pszUname;
169//                      if (!LoadUserProfile(hToken, &info)) {
170//                              DWORD dwErr = GetLastError();
171//                              if (!RevertToSelf())
172//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
173//                              LOG_ERROR_STD(_T("Failed to get username: ") + error::format::from_system(dwErr));
174//                              return false;
175//                      }
176//                      */
177//                      if (!CreateProcessAsUser(hToken, exe.c_str(), buffer, NULL, NULL, FALSE, dwCreationFlags, pEnv, NULL, &StartUPInfo, &ProcessInfo)) {
178//                              DWORD dwErr = GetLastError();
179//                              delete [] buffer;
180//                              /*
181//                              if (!RevertToSelf()) {
182//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
183//                              }
184//                              */
185//                              if (startThread && dwErr == ERROR_PIPE_NOT_CONNECTED) {
186//                                      LOG_MESSAGE(_T("Failed to start trayhelper: starting a background thread to do it instead..."));
187//                                      Thread<tray_starter> *pThread = new Thread<tray_starter>(_T("tray-starter-thread"));
188//                                      pThread->createThread(tray_starter::init(dwSessionId, exe, cmdline));
189//                                      return false;
190//                              } else if (dwErr == ERROR_PIPE_NOT_CONNECTED) {
191//                                      LOG_ERROR_STD(_T("Thread failed to start trayhelper (will try again): ") + error::format::from_system(dwErr));
192//                                      return false;
193//                              } else {
194//                                      LOG_ERROR_STD(_T("Failed to start trayhelper: ") + error::format::from_system(dwErr));
195//                                      return true;
196//                              }
197//                      } else {
198//                              delete [] buffer;
199//                              /*
200//                              if (!RevertToSelf()) {
201//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
202//                              }
203//                              */
204//                              LOG_MESSAGE_STD(_T("Started tray in other user session: ") + strEx::itos(dwSessionId));
205//                      }
206//
207//
208//                      CloseHandle(hToken);
209//                      return true;
210//              }
211                return false;
212        }
213};
214
215/**
216 * End of class tray started (MERGE HELP)
217 */
218
219#define XNSC_DEFINE_SETTING_KEY(name, tag) \
220        name ## _SECTION \
221       
222 /**
223 * RANDOM JUNK (MERGE HELP)
224 */
225
226void display(std::wstring title, std::wstring message) {
227#ifdef WIN32
228        ::MessageBox(NULL, message.c_str(), title.c_str(), MB_OK|MB_ICONERROR);
229#endif
230        std::wcout << title << std::endl << message << std::endl;
231}
232
233
234bool is_module(boost::filesystem::wpath file )
235{
236        return boost::ends_with(file.string(), _T(".dll")) || boost::ends_with(file.string(), _T(".so"));
237}
238/**
239 * Application startup point
240 *
241 * @param argc Argument count
242 * @param argv[] Argument array
243 * @param envp[] Environment array
244 * @return exit status
245 */
246int nscp_main(int argc, wchar_t* argv[]);
247
248#ifdef WIN32
249int wmain(int argc, wchar_t* argv[], wchar_t* envp[]) { return nscp_main(argc, argv); }
250#else
251int main(int argc, char* argv[]) {
252        wchar_t **wargv = new wchar_t*[argc];
253        for (int i=0;i<argc;i++) {
254                std::wstring s = to_wstring(argv[i]);
255                wargv[i] = new wchar_t[s.length()+10];
256                wcscpy(wargv[i], s.c_str());
257        }
258        int ret = nscp_main(argc, wargv);
259        for (int i=0;i<argc;i++) {
260                delete [] wargv[i];
261        }
262        delete [] wargv;
263}
264#endif
265int nscp_main(int argc, wchar_t* argv[])
266{
267        srand( (unsigned)time( NULL ) );
268        int nRetCode = 0;
269        if ( (argc > 1) && ((*argv[1] == '-') || (*argv[1] == '/')) ) {
270                if (false) {
271                } if ( wcscasecmp( _T("install"), argv[1]+1 ) == 0 ) {
272                        nsclient::client::service_manager mgr(argc-1,&argv[1]);
273                        return mgr.install();
274                } else if ( wcscasecmp( _T("uninstall"), argv[1]+1 ) == 0 ) {
275                        nsclient::client::service_manager mgr(argc-1,&argv[1]);
276                        return mgr.uninstall();
277                } else if ( wcscasecmp( _T("start"), argv[1]+1 ) == 0 ) {
278                        nsclient::client::service_manager mgr(argc-1,&argv[1]);
279                        return mgr.start();
280                } else if ( wcscasecmp( _T("stop"), argv[1]+1 ) == 0 ) {
281                        nsclient::client::service_manager mgr(argc-1,&argv[1]);
282                        return mgr.stop();
283                } else if ( wcscasecmp( _T("svc"), argv[1]+1 ) == 0 ) {
284                        nsclient::client::service_manager mgr(argc-1,&argv[1]);
285                        return mgr.print_command();
286                } else if ( wcscasecmp( _T("encrypt"), argv[1]+1 ) == 0 ) {
287                        g_bConsoleLog = true;
288                        std::wstring password;
289                        if (!settings_manager::init_settings(mainClient.getBasePath())) {
290                                std::wcout << _T("Could not find settings") << std::endl;;
291                                return 1;
292                        }
293                        std::wcout << _T("Enter password to encrypt (has to be a single word): ");
294                        std::wcin >> password;
295                        std::wstring xor_pwd = Encrypt(password);
296                        std::wcout << _T("obfuscated_password=") << xor_pwd << std::endl;
297                        std::wstring outPasswd = Decrypt(xor_pwd);
298                        if (password != outPasswd)
299                                std::wcout << _T("ERROR: Password did not match: ") << outPasswd<< std::endl;
300                        settings_manager::destroy_settings();
301                        return 0;
302                } else if ( wcscasecmp( _T("about"), argv[1]+1 ) == 0 ) {
303                        try {
304                                g_bConsoleLog = true;
305                                LOG_MESSAGE(SZAPPNAME _T(" (C) Michael Medin - michael<at>medin<dot>name"));
306                                LOG_MESSAGE(_T("Version: ") SZVERSION);
307                                LOG_MESSAGE(_T("Architecture: ") SZARCH);
308
309                                boost::filesystem::wpath pluginPath = (boost::filesystem::wpath)mainClient.getBasePath() / _T("modules");
310                                LOG_MESSAGE_STD(_T("Looking at plugins in: ") + pluginPath.string());
311
312                                boost::filesystem::wdirectory_iterator end_itr; // default construction yields past-the-end
313                                for ( boost::filesystem::wdirectory_iterator itr( pluginPath ); itr != end_itr; ++itr ) {
314                                        if ( !is_directory(itr->status()) ) {
315                                                std::wstring file= itr->leaf();
316                                                LOG_MESSAGE_STD(_T("Found: ") + file);
317                                                if (is_module(pluginPath / file)) {
318                                                        NSCPlugin *plugin = new NSCPlugin(pluginPath / file);
319                                                        std::wstring name = _T("<unknown>");
320                                                        std::wstring description = _T("<unknown>");
321                                                        try {
322                                                                plugin->load_dll();
323                                                                name = plugin->getName();
324                                                                description = plugin->getDescription();
325                                                        } catch(const NSPluginException& e) {
326                                                                LOG_ERROR_STD(_T("Exception raised: ") + e.error_ + _T(" in module: ") + e.file_);
327                                                        } catch (std::exception e) {
328                                                                LOG_ERROR_STD(_T("exception loading plugin: ") + strEx::string_to_wstring(e.what()));
329                                                        } catch (...) {
330                                                                LOG_ERROR_STD(_T("Unknown exception loading plugin"));
331                                                        }
332                                                        LOG_MESSAGE_STD(_T("* ") + name + _T(" (") + file + _T(")"));
333                                                        std::list<std::wstring> list = strEx::splitEx(description, _T("\n"));
334                                                        for (std::list<std::wstring>::const_iterator cit = list.begin(); cit != list.end(); ++cit) {
335                                                                LOG_MESSAGE_STD(_T("    ") + *cit);
336                                                        }
337                                                }
338                                        }
339                                }
340                                LOG_MESSAGE_STD(_T("Done listing plugins from: ") + pluginPath.string());
341                                return true;
342                        } catch (std::exception &e) {
343                                LOG_ERROR_STD(_T("Exception: ") + to_wstring(e.what()));
344                        } catch (...) {
345                                LOG_ERROR_STD(_T("Unknown Exception: "));
346                        }
347                        return false;
348                } else if ( wcscasecmp( _T("version"), argv[1]+1 ) == 0 ) {
349                        g_bConsoleLog = true;
350                        LOG_MESSAGE(SZAPPNAME _T(" Version: ") SZVERSION _T(", Plattform: ") SZARCH);
351                } else if ( wcscasecmp( _T("d"), argv[1]+1 ) == 0 ) {
352                        // Run command from command line (like NRPE) but with debug enabled
353                } else if ( wcscasecmp( _T("noboot"), argv[1]+1 ) == 0 ) {
354                        g_bConsoleLog = true;
355                        mainClient.enableDebug(false);
356                        mainClient.initCore(false);
357                        if (argc>=3)
358                                nRetCode = mainClient.commandLineExec(argv[2], argc-3, &argv[3]);
359                        else
360                                nRetCode = mainClient.commandLineExec(argv[2], 0, NULL);
361                        mainClient.exitCore(true);
362                        return nRetCode;
363                } else if ( wcscasecmp( _T("c"), argv[1]+1 ) == 0 ) {
364                        // Run command from command line (like NRPE)
365                        g_bConsoleLog = true;
366                        mainClient.enableDebug(false);
367                        mainClient.initCore(true);
368                        std::wstring command, args, msg, perf;
369                        if (argc > 2)
370                                command = argv[2];
371                        for (int i=3;i<argc;i++) {
372                                if (i!=3) args += _T(" ");
373                                args += argv[i];
374                        }
375                        nRetCode = mainClient.inject(command, args, L' ', true, msg, perf);
376                        std::wcout << msg << _T("|") << perf << std::endl;
377                        mainClient.exitCore(true);
378                        return nRetCode;
379                } else if ( wcscasecmp( _T("test"), argv[1]+1 ) == 0 ) {
380                        bool server = false;
381                        if (argc > 2 && wcscasecmp( _T("server"), argv[2] ) == 0 ) {
382                                server = true;
383                        }
384                        std::wcout << "Launching test mode - " << (server?_T("server mode"):_T("client mode")) << std::endl;
385                        LOG_MESSAGE_STD(_T("Booting: ") SZSERVICEDISPLAYNAME );
386#ifdef WIN32
387                        try {
388                                if (serviceControll::isStarted(SZSERVICENAME)) {
389                                        std::wcerr << "Service seems to be started, this is probably not a good idea..." << std::endl;
390                                }
391                        } catch (...) {
392                                // Empty by design
393                        }
394#endif
395                        nsclient::simple_client client(&mainClient);
396                        g_bConsoleLog = true;
397                        client.start();
398                        return 0;
399                } else if ( wcscasecmp( _T("settings"), argv[1]+1 ) == 0 ) {
400                        nsclient::settings_client client(&mainClient);
401                        g_bConsoleLog = true;
402                        if (argc > 2)
403                                client.parse(argv[2], argc-3, argv+3);
404                        else
405                                client.help();
406                        return 0;
407                } else {
408                        std::wcerr << _T("Usage: -version, -about, -install, -uninstall, -start, -stop, -encrypt -settings") << std::endl;
409                        std::wcerr << _T("Usage: [-noboot] <ModuleName> <commnd> [arguments]") << std::endl;
410                        return -1;
411                }
412                return nRetCode;
413        } else if (argc > 2) {
414                g_bConsoleLog = true;
415                std::wcout << _T(" * * * * * * * ") << std::endl;
416                mainClient.initCore(true);
417                if (argc>=3)
418                        nRetCode = mainClient.commandLineExec(argv[1], argc-2, &argv[2]);
419                else
420                        nRetCode = mainClient.commandLineExec(argv[1], 0, NULL);
421                mainClient.exitCore(true);
422                return nRetCode;
423        } else if (argc > 1) {
424                g_bConsoleLog = true;
425                mainClient.enableDebug(true);
426                std::wcerr << _T("Invalid command line argument: ") << argv[1] << std::endl;
427                std::wcerr << _T("Usage: -version, -about, -install, -uninstall, -start, -stop, -encrypt") << std::endl;
428                std::wcerr << _T("Usage: [-noboot] <ModuleName> <commnd> [arguments]") << std::endl;
429                return -1;
430        }
431        try {
432                std::wcout << _T("Running as service...") << std::endl;
433                mainClient.enableDebug(true);
434                mainClient.start_and_wait();
435        } catch (...) {
436                std::wcerr << _T("Unknown exception in service") << std::endl;
437        }
438        return nRetCode;
439}
440
441void migrate() {}
442
443std::list<std::wstring> NSClientT::list_commands() {
444        return commands_.list();
445}
446
447NSClientT::plugin_info_list NSClientT::get_all_plugins() {
448        plugin_info_list ret;
449        boost::filesystem::wpath pluginPath = getBasePath() / boost::filesystem::wpath(_T("modules"));
450        boost::filesystem::wdirectory_iterator end_itr; // default construction yields past-the-end
451        for ( boost::filesystem::wdirectory_iterator itr( pluginPath ); itr != end_itr; ++itr ) {
452                if ( !is_directory(itr->status()) ) {
453                        boost::filesystem::wpath file= itr->leaf();
454                        if (is_module(pluginPath  / file)) {
455                                plugin_info_type info;
456                                info.dll = itr->leaf();
457                                try {
458                                        LOG_DEBUG_STD(_T("Attempting to fake load: ") + file.string());
459                                        NSCPlugin plugin(pluginPath / file);
460                                        plugin.load_dll();
461                                        plugin.load_plugin(NSCAPI::dontStart);
462                                        info.name = plugin.getName();
463                                        info.description = plugin.getDescription();
464                                        plugin.unload();
465                                } catch (NSPluginException e) {
466                                        LOG_CRITICAL_STD(_T("Error loading: ") + e.file_ + _T(" root cause: ") + e.error_);
467                                } catch (...) {
468                                        LOG_CRITICAL_STD(_T("Unknown Error loading: ") + file.string());
469                                }
470                                ret.push_back(info);
471                        }
472                }
473        }
474        return ret;
475}
476
477
478void NSClientT::load_all_plugins(int mode) {
479        boost::filesystem::wpath modPath = getBasePath() / boost::filesystem::wpath(_T("modules"));
480
481        boost::filesystem::wdirectory_iterator end_itr; // default construction yields past-the-end
482        for ( boost::filesystem::wdirectory_iterator itr( modPath ); itr != end_itr; ++itr ) {
483                if ( !is_directory(itr->status()) ) {
484                        boost::filesystem::wpath file= itr->leaf();
485                        if (is_module(modPath / file)) {
486                                if (settings_manager::get_settings()->has_key(MAIN_MODULES_SECTION, file.string())) {
487                                        if (settings_manager::get_settings()->get_string(MAIN_MODULES_SECTION, file.string()) == _T("disabled")) {
488                                                try {
489                                                        LOG_DEBUG_STD(_T("Attempting to fake load: ") + file.string());
490                                                        NSCPlugin plugin(modPath / file);
491                                                        plugin.load_dll();
492                                                        plugin.load_plugin(mode);
493                                                        plugin.unload();
494                                                } catch (NSPluginException e) {
495                                                        LOG_CRITICAL_STD(_T("Error loading: ") + e.file_ + _T(" root cause: ") + e.error_);
496                                                } catch (...) {
497                                                        LOG_CRITICAL_STD(_T("Unknown Error loading: ") + file.string());
498                                                }
499                                        }
500                                } else {
501                                        std::wstring desc;
502                                        std::wstring name = file.string();
503                                        try {
504                                                NSCPlugin plugin(modPath / file);
505                                                name = plugin.getModule();
506                                                plugin.load_dll();
507                                                plugin.load_plugin(mode);
508                                                desc = plugin.getName() + _T(" - ");
509                                                desc += plugin.getDescription();
510                                                plugin.unload();
511                                        } catch (NSPluginException e) {
512                                                desc += _T("unknown module");
513                                                LOG_CRITICAL_STD(_T("Error loading: ") + e.file_ + _T(" root cause: ") + e.error_);
514                                        } catch (...) {
515                                                desc += _T("unknown module");
516                                                LOG_CRITICAL_STD(_T("Unknown Error loading: ") + file.string());
517                                        }
518                                        settings_manager::get_core()->register_key(MAIN_MODULES_SECTION, name, Settings::SettingsCore::key_string, desc, desc, _T("disabled"), false);
519                                }
520                        }
521                }
522        }
523}
524
525void NSClientT::session_error(std::wstring file, unsigned int line, std::wstring msg) {
526        NSAPIMessage(NSCAPI::error, file.c_str(), line, msg.c_str());
527}
528
529void NSClientT::session_info(std::wstring file, unsigned int line, std::wstring msg) {
530        NSAPIMessage(NSCAPI::log, file.c_str(), line, msg.c_str());
531}
532
533
534
535
536//////////////////////////////////////////////////////////////////////////
537// Service functions
538
539/**
540 * Initialize the program
541 * @param boot true if we shall boot all plugins
542 * @param attachIfPossible is true we will attach to a running instance.
543 * @return success
544 * @author mickem
545 */
546bool NSClientT::initCore(bool boot) {
547        LOG_MESSAGE(_T("Attempting to start NSCLient++ - ") SZVERSION);
548        if (!settings_manager::init_settings(getBasePath())) {
549                return false;
550        }
551        LOG_MESSAGE(_T("Got settings subsystem..."));
552        try {
553                if (debug_)
554                        settings_manager::get_settings()->set_int(_T("log"), _T("debug"), 1);
555                        settings_manager::get_settings()->set_int(_T("Settings"), _T("shared_Session"), 1);
556                enable_shared_session_ = SETTINGS_GET_BOOL_CORE(settings_def::SHARED_SESSION);
557        } catch (SettingsException e) {
558                LOG_ERROR_CORE_STD(_T("Could not find settings: ") + e.getMessage());
559        }
560
561        if (enable_shared_session_) {
562                LOG_DEBUG_STD(_T("Enabling shared session..."));
563                if (boot) {
564                        LOG_MESSAGE_STD(_T("shared session not ported yet!..."));
565//                      try {
566//                              shared_server_.reset(new nsclient_session::shared_server_session(this));
567//                              if (!shared_server_->session_exists()) {
568//                                      shared_server_->create_new_session();
569//                              } else {
570//                                      LOG_ERROR_STD(_T("Session already exists cant create a new one!"));
571//                              }
572//                              startTrayIcons();
573//                      } catch (nsclient_session::session_exception e) {
574//                              LOG_ERROR_STD(_T("Failed to create new session: ") + e.what());
575//                              shared_server_.reset(NULL);
576//                      } catch (...) {
577//                              LOG_ERROR_STD(_T("Failed to create new session: Unknown exception"));
578//                              shared_server_.reset(NULL);
579//                      }
580                } else {
581                        LOG_MESSAGE_STD(_T("shared session not ported yet!..."));
582//                      try {
583//                              std::wstring id = _T("_attached_") + strEx::itos(GetCurrentProcessId()) + _T("_");
584//                              shared_client_.reset(new nsclient_session::shared_client_session(id, this));
585//                              if (shared_client_->session_exists()) {
586//                                      shared_client_->attach_to_session(id);
587//                              } else {
588//                                      LOG_ERROR_STD(_T("No session was found cant attach!"));
589//                              }
590//                              LOG_ERROR_STD(_T("Session is: ") + shared_client_->get_client_id());
591//                      } catch (nsclient_session::session_exception e) {
592//                              LOG_ERROR_STD(_T("Failed to attach to session: ") + e.what());
593//                              shared_client_.reset(NULL);
594//                      } catch (...) {
595//                              LOG_ERROR_STD(_T("Failed to attach to session: Unknown exception"));
596//                              shared_client_.reset(NULL);
597//                      }
598                }
599        }
600/*
601        try {
602                simpleSocket::WSAStartup();
603        } catch (simpleSocket::SocketException e) {
604                LOG_ERROR_STD(_T("Socket exception: ") + e.getMessage());
605                return false;
606        } catch (...) {
607                LOG_ERROR_STD(_T("Unknown exception iniating socket..."));
608                return false;
609        }
610*/
611#ifdef WIN32
612        try {
613                com_helper_.initialize();
614        } catch (com_helper::com_exception e) {
615                LOG_ERROR_CORE_STD(_T("COM exception: ") + e.getMessage());
616                return false;
617        } catch (...) {
618                LOG_ERROR_CORE(_T("Unknown exception iniating COM..."));
619                return false;
620        }
621#endif
622        if (boot) {
623                try {
624                        Settings::string_list list = settings_manager::get_settings()->get_keys(MAIN_MODULES_SECTION);
625                        for (Settings::string_list::const_iterator cit = list.begin(); cit != list.end(); ++cit) {
626                                LOG_DEBUG_STD(_T("Processing plugin: " + *cit));
627                                try {
628                                        if (settings_manager::get_settings()->get_string(MAIN_MODULES_SECTION, *cit) == _T("disabled")) {
629                                                LOG_DEBUG_STD(_T("Not booting: ") + *cit + _T(" since it is disabled."));
630                                                continue;
631                                        }
632                                } catch (...) {
633                                        // If we except we load the plugin in as-is
634                                }
635                                try {
636                                        loadPlugin(getBasePath() / boost::filesystem::wpath(_T("modules")) / boost::filesystem::wpath(*cit));
637                                } catch(const NSPluginException& e) {
638                                        LOG_ERROR_CORE_STD(_T("Exception raised: '") + e.error_ + _T("' in module: ") + e.file_);
639                                        //return false;
640                                } catch (std::exception e) {
641                                        LOG_ERROR_CORE_STD(_T("exception loading plugin: ") + (*cit) + strEx::string_to_wstring(e.what()));
642                                        return false;
643                                } catch (...) {
644                                        LOG_ERROR_CORE_STD(_T("Unknown exception loading plugin: ") + (*cit));
645                                        return false;
646                                }
647                        }
648                } catch (SettingsException e) {
649                        LOG_ERROR_CORE_STD(_T("Failed to set settings file") + e.getMessage());
650                } catch (...) {
651                        LOG_ERROR_CORE_STD(_T("Unknown exception when loading plugins"));
652                        return false;
653                }
654                try {
655                        loadPlugins(boot?NSCAPI::normalStart:NSCAPI::dontStart);
656                } catch (...) {
657                        LOG_ERROR_CORE_STD(_T("Unknown exception loading plugins"));
658                        return false;
659                }
660                LOG_DEBUG_STD(_T("NSCLient++ - ") SZVERSION _T(" Started!"));
661        }
662        LOG_MESSAGE_STD(_T("NSCLient++ - ") SZVERSION _T(" Started!"));
663        return true;
664}
665
666void NSClientT::startTrayIcons() {
667//      if (shared_server_.get() == NULL) {
668//              LOG_MESSAGE_STD(_T("No master session so tray icons not started"));
669//              return;
670//      }
671//      remote_processes::PWTS_SESSION_INFO list;
672//      DWORD count;
673//      if (!remote_processes::_WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE , 0, 1, &list, &count)) {
674//              LOG_ERROR_STD(_T("Failed to enumerate sessions:" ) + error::lookup::last_error());
675//      } else {
676//              LOG_DEBUG_STD(_T("Found ") + strEx::itos(count) + _T(" sessions"));
677//              for (DWORD i=0;i<count;i++) {
678//                      LOG_DEBUG_STD(_T("Found session: ") + strEx::itos(list[i].SessionId) + _T(" state: ") + strEx::itos(list[i].State));
679//                      if (list[i].State == remote_processes::_WTS_CONNECTSTATE_CLASS::WTSActive) {
680//                              startTrayIcon(list[i].SessionId);
681//                      }
682//              }
683//      }
684}
685void NSClientT::startTrayIcon(DWORD dwSessionId) {
686//      if (shared_server_.get() == NULL) {
687//              LOG_MESSAGE_STD(_T("No master session so tray icons not started"));
688//              return;
689//      }
690//      if (!shared_server_->re_attach_client(dwSessionId)) {
691//              if (!tray_starter::start(dwSessionId)) {
692//                      LOG_ERROR_STD(_T("Failed to start session (") + strEx::itos(dwSessionId) + _T("): " ) + error::lookup::last_error());
693//              }
694//      }
695}
696
697bool NSClientT::exitCore(bool boot) {
698        plugins_loaded_ = false;
699        LOG_DEBUG(_T("Attempting to stop NSCLient++ - ") SZVERSION);
700        if (boot) {
701                try {
702                        LOG_DEBUG_STD(_T("Stopping: NON Message Handling Plugins"));
703                        mainClient.unloadPlugins(false);
704                } catch(NSPluginException e) {
705                        LOG_ERROR_CORE_STD(_T("Exception raised when unloading non msg plguins: ") + e.error_ + _T(" in module: ") + e.file_);
706                } catch(...) {
707                        LOG_ERROR_CORE_STD(_T("Unknown exception raised when unloading non msg plugins"));
708                }
709        }
710#ifdef WIN32
711        LOG_DEBUG_STD(_T("Stopping: COM helper"));
712        try {
713                com_helper_.unInitialize();
714        } catch (com_helper::com_exception e) {
715                LOG_ERROR_CORE_STD(_T("COM exception: ") + e.getMessage());
716        } catch (...) {
717                LOG_ERROR_CORE_STD(_T("Unknown exception uniniating COM..."));
718        }
719#endif
720        /*
721        LOG_DEBUG_STD(_T("Stopping: Socket Helpers"));
722        try {
723                simpleSocket::WSACleanup();
724        } catch (simpleSocket::SocketException e) {
725                LOG_ERROR_STD(_T("Socket exception: ") + e.getMessage());
726        } catch (...) {
727                LOG_ERROR_STD(_T("Unknown exception uniniating socket..."));
728        }
729        */
730        LOG_DEBUG_STD(_T("Stopping: Settings instance"));
731        settings_manager::destroy_settings();
732//      try {
733//              if (shared_client_.get() != NULL) {
734//                      LOG_DEBUG_STD(_T("Stopping: shared client"));
735//                      shared_client_->set_handler(NULL);
736//                      shared_client_->close_session();
737//              }
738//      } catch(nsclient_session::session_exception &e) {
739//              LOG_ERROR_STD(_T("Exception closing shared client session: ") + e.what());
740//      } catch(...) {
741//              LOG_ERROR_STD(_T("Exception closing shared client session: Unknown exception!"));
742//      }
743        try {
744//              if (shared_server_.get() != NULL) {
745//                      LOG_DEBUG_STD(_T("Stopping: shared server"));
746//                      shared_server_->set_handler(NULL);
747//                      shared_server_->close_session();
748//              }
749        } catch(...) {
750                LOG_ERROR_CORE_STD(_T("UNknown exception raised: When closing shared session"));
751        }
752        if (boot) {
753                try {
754                        LOG_DEBUG_STD(_T("Stopping: Message handling Plugins"));
755                        mainClient.unloadPlugins(true);
756                } catch(NSPluginException e) {
757                        LOG_ERROR_CORE_STD(_T("Exception raised when unloading msg plugins: ") + e.error_ + _T(" in module: ") + e.file_);
758                } catch(...) {
759                        LOG_ERROR_CORE_STD(_T("UNknown exception raised: When stopping message plguins"));
760                }
761        }
762        LOG_MESSAGE_STD(_T("NSCLient++ - ") SZVERSION _T(" Stopped succcessfully"));
763        return true;
764}
765#ifdef WIN32x
766/**
767 * Forward this to the main service dispatcher helper class
768 * @param dwArgc
769 * @param *lpszArgv
770 */
771void WINAPI NSClientT::service_main_dispatch(DWORD dwArgc, LPTSTR *lpszArgv) {
772        try {
773                //WTF!!! mainClient.service_main(dwArgc, lpszArgv);
774        } catch (service_helper::service_exception e) {
775                LOG_ERROR_STD(_T("Unknown service error: ") + e.what());
776        } catch (...) {
777                LOG_ERROR_STD(_T("Unknown service error!"));
778        }
779}
780DWORD WINAPI NSClientT::service_ctrl_dispatch_ex(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext) {
781        return mainClient.service_ctrl_ex(dwControl, dwEventType, lpEventData, lpContext);
782}
783/**
784 * Forward this to the main service dispatcher helper class
785 * @param dwCtrlCode
786 */
787void WINAPI NSClientT::service_ctrl_dispatch(unsigned long dwCtrlCode) {
788        mainClient.service_ctrl_ex(dwCtrlCode, NULL, NULL, NULL);
789}
790#endif
791
792void NSClientT::service_on_session_changed(unsigned long dwSessionId, bool logon, unsigned long dwEventType) {
793//      if (shared_server_.get() == NULL) {
794//              LOG_DEBUG_STD(_T("No shared session: ignoring change event!"));
795//              return;
796//      }
797        LOG_DEBUG_STD(_T("Got session change: ") + strEx::itos(dwSessionId));
798        if (!logon) {
799                LOG_DEBUG_STD(_T("Not a logon event: ") + strEx::itos(dwEventType));
800                return;
801        }
802        tray_starter::start(dwSessionId);
803}
804
805//////////////////////////////////////////////////////////////////////////
806// Member functions
807
808int NSClientT::commandLineExec(const wchar_t* module, const unsigned int argLen, wchar_t** args) {
809        std::wstring sModule = module;
810        std::wstring moduleList = _T("");
811        {
812                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(5));
813                if (!readLock.owns_lock()) {
814                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex."));
815                        return -1;
816                }
817                for (pluginList::size_type i=0;i<plugins_.size();++i) {
818                        plugin_type p = plugins_[i];
819                        if (!moduleList.empty())
820                                moduleList += _T(", ");
821                        if (p) {
822                                moduleList += p->getModule();
823                                if (p->getModule() == sModule) {
824                                        LOG_DEBUG_STD(_T("Found module: ") + p->getName() + _T("..."));
825                                        try {
826                                                return p->commandLineExec(argLen, args);
827                                        } catch (NSPluginException e) {
828                                                LOG_ERROR_CORE_STD(_T("Could not execute command: ") + e.error_ + _T(" in ") + e.file_);
829                                                return -1;
830                                        }
831                                }
832                        }
833                }
834        }
835        try {
836                plugin_type plugin = loadPlugin(getBasePath() / boost::filesystem::wpath(_T("modules")) / boost::filesystem::wpath(module));
837                LOG_DEBUG_STD(_T("Loading plugin: ") + plugin->getName() + _T("..."));
838                plugin->load_plugin(NSCAPI::dontStart);
839                return plugin->commandLineExec(argLen, args);
840        } catch (NSPluginException e) {
841                LOG_MESSAGE_STD(_T("Module (") + e.file_ + _T(") was not found: ") + e.error_);
842        }
843        LOG_ERROR_CORE_STD(_T("Module not found: ") + std::wstring(module) + _T(" available modules are: ") + moduleList);
844        return 0;
845}
846
847/**
848 * Load a list of plug-ins
849 * @param plugins A list with plug-ins (DLL files) to load
850 */
851void NSClientT::addPlugins(const std::list<std::wstring> plugins) {
852        boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
853        if (!readLock.owns_lock()) {
854                LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex."));
855                return;
856        }
857        std::list<std::wstring>::const_iterator it;
858        for (it = plugins.begin(); it != plugins.end(); ++it) {
859                loadPlugin(*it);
860        }
861}
862/**
863 * Unload all plug-ins (in reversed order)
864 */
865void NSClientT::unloadPlugins(bool unloadLoggers) {
866        {
867                boost::unique_lock<boost::shared_mutex> writeLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
868                if (!writeLock.owns_lock()) {
869                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex."));
870                        return;
871                }
872                commandHandlers_.clear();
873                if (unloadLoggers)
874                        messageHandlers_.clear();
875        }
876        {
877                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
878                if (!readLock.owns_lock()) {
879                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex."));
880                        return;
881                }
882                for (pluginList::reverse_iterator it = plugins_.rbegin(); it != plugins_.rend(); ++it) {
883                        plugin_type p = *it;
884                        if (!p)
885                                continue;
886                        try {
887                                if (unloadLoggers || !p->hasMessageHandler()) {
888                                        LOG_DEBUG_STD(_T("Unloading plugin: ") + p->getModule() + _T("..."));
889                                        p->unload();
890                                } else {
891                                        LOG_DEBUG_STD(_T("Skipping log plugin: ") + p->getModule() + _T("..."));
892                                }
893                        } catch(NSPluginException e) {
894                                LOG_ERROR_CORE_STD(_T("Exception raised when unloading plugin: ") + e.error_ + _T(" in module: ") + e.file_);
895                        } catch(...) {
896                                LOG_ERROR_CORE_STD(_T("Unknown exception raised when unloading plugin"));
897                        }
898                }
899        }
900        {
901                boost::unique_lock<boost::shared_mutex> writeLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
902                if (!writeLock.owns_lock()) {
903                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex."));
904                        return;
905                }
906                commands_.remove_all();
907                for (pluginList::iterator it = plugins_.begin(); it != plugins_.end();) {
908                        plugin_type p = (*it);
909                        try {
910                                if (!p && (unloadLoggers|| !p->isLoaded())) {
911                                        it = plugins_.erase(it);
912                                        //delete p;
913                                        continue;
914                                }
915                        } catch(NSPluginException e) {
916                                LOG_ERROR_CORE_STD(_T("Exception raised when unloading plugin: ") + e.error_ + _T(" in module: ") + e.file_);
917                        } catch(...) {
918                                LOG_ERROR_CORE(_T("Unknown exception raised when unloading plugin"));
919                        }
920                        it++;
921                }
922        }
923}
924
925void NSClientT::loadPlugins(NSCAPI::moduleLoadMode mode) {
926        bool hasBroken = false;
927        {
928                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
929                if (!readLock.owns_lock()) {
930                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex."));
931                        return;
932                }
933                for (pluginList::iterator it=plugins_.begin(); it != plugins_.end();) {
934                        LOG_DEBUG_STD(_T("Loading plugin: ") + (*it)->getName() + _T("..."));
935                        try {
936                                if (!(*it)->load_plugin(NSCAPI::normalStart)) {
937                                        LOG_ERROR_CORE_STD(_T("Plugin refused to load: ") + (*it)->getModule());
938                                        it = plugins_.erase(it);
939                                } else
940                                        ++it;
941                        } catch (NSPluginException e) {
942                                it = plugins_.erase(it);
943                                LOG_ERROR_CORE_STD(_T("Could not load plugin: ") + e.file_ + _T(": ") + e.error_);
944                        } catch (...) {
945                                it = plugins_.erase(it);
946                                LOG_ERROR_CORE_STD(_T("Could not load plugin: ") + (*it)->getModule());
947                        }
948                }
949        }
950        /*
951        for (pluginList::iterator it=plugins_.begin(); it != plugins_.end();) {
952                LOG_DEBUG_STD(_T("Loading plugin: ") + (*it)->getName() + _T("..."));
953                try {
954                        (*it)->load_plugin(mode);
955                        ++it;
956                } catch(NSPluginException e) {
957                        it = plugins_.erase(it);
958                        LOG_ERROR_CORE_STD(_T("Exception raised when loading plugin: ") + e.error_ + _T(" in module: ") + e.file_ + _T(" plugin has been removed."));
959                } catch(...) {
960                        it = plugins_.erase(it);
961                        LOG_ERROR_CORE(_T("Unknown exception raised when unloading plugin plugin has been removed"));
962                }
963        }
964        */
965        plugins_loaded_ = true;
966}
967/**
968 * Load a single plug-in using a DLL filename
969 * @param file The DLL file
970 */
971NSClientT::plugin_type NSClientT::loadPlugin(const boost::filesystem::wpath file) {
972        plugin_type plugin(new NSCPlugin(file));
973        return addPlugin(plugin);
974}
975/**
976 * Load and add a plugin to various internal structures
977 * @param plugin The plug-in instance to load. The pointer is managed by the
978 */
979NSClientT::plugin_type NSClientT::addPlugin(plugin_type plugin) {
980        plugin->load_dll();
981        {
982                boost::unique_lock<boost::shared_mutex> writeLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
983                if (!writeLock.owns_lock()) {
984                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex."));
985                        return plugin;
986                }
987                plugins_.insert(plugins_.end(), plugin);
988                if (plugin->hasCommandHandler())
989                        commandHandlers_.insert(commandHandlers_.end(), plugin);
990                if (plugin->hasMessageHandler())
991                        messageHandlers_.insert(messageHandlers_.end(), plugin);
992                settings_manager::get_core()->register_key(_T("/modules"), plugin->getModule(), Settings::SettingsCore::key_string, plugin->getName(), plugin->getDescription(), _T(""), false);
993        }
994        return plugin;
995}
996
997
998std::wstring NSClientT::describeCommand(std::wstring command) {
999        return commands_.describe(command);
1000}
1001std::list<std::wstring> NSClientT::getAllCommandNames() {
1002        return commands_.list();
1003}
1004void NSClientT::registerCommand(unsigned int id, std::wstring cmd, std::wstring desc) {
1005        return commands_.register_command(id, cmd, desc);
1006}
1007
1008unsigned int NSClientT::getBufferLength() {
1009        static unsigned int len = 0;
1010        if (len == 0) {
1011                try {
1012                        len = settings_manager::get_settings()->get_int(SETTINGS_KEY(settings_def::PAYLOAD_LEN));
1013                } catch (SettingsException &e) {
1014                        LOG_DEBUG_STD(_T("Failed to get length: ") + e.getMessage());
1015                        return setting_keys::settings_def::PAYLOAD_LEN_DEFAULT;
1016                } catch (...) {
1017                        LOG_ERROR_CORE(_T("Failed to get length: :("));
1018                        return setting_keys::settings_def::PAYLOAD_LEN_DEFAULT;
1019                }
1020        }
1021        return len;
1022}
1023
1024NSCAPI::nagiosReturn NSClientT::inject(std::wstring command, std::wstring arguments, wchar_t splitter, bool escape, std::wstring &msg, std::wstring & perf) {
1025        /*if (shared_client_.get() != NULL && shared_client_->hasMaster()) {
1026                try {
1027                        return shared_client_->inject(command, arguments, splitter, escape, msg, perf);
1028                } catch (nsclient_session::session_exception &e) {
1029                        LOG_ERROR_STD(_T("Failed to inject remote command: ") + e.what());
1030                        return NSCAPI::returnCRIT;
1031                } catch (...) {
1032                        LOG_ERROR_STD(_T("Failed to inject remote command: Unknown exception"));
1033                        return NSCAPI::returnCRIT;
1034                }
1035        } else */{
1036                unsigned int aLen = 0;
1037                wchar_t ** aBuf = arrayBuffer::split2arrayBuffer(arguments, splitter, aLen, escape);
1038                unsigned int buf_len = getBufferLength();
1039                wchar_t * mBuf = new wchar_t[buf_len+1]; mBuf[0] = '\0';
1040                wchar_t * pBuf = new wchar_t[buf_len+1]; pBuf[0] = '\0';
1041                NSCAPI::nagiosReturn ret = injectRAW(command.c_str(), aLen, aBuf, mBuf, buf_len, pBuf, buf_len);
1042                arrayBuffer::destroyArrayBuffer(aBuf, aLen);
1043                if ( (ret == NSCAPI::returnInvalidBufferLen) || (ret == NSCAPI::returnIgnored) ) {
1044                        delete [] mBuf;
1045                        delete [] pBuf;
1046                        return ret;
1047                }
1048                msg = mBuf;
1049                perf = pBuf;
1050                delete [] mBuf;
1051                delete [] pBuf;
1052                return ret;
1053        }
1054}
1055
1056/**
1057 * Inject a command into the plug-in stack.
1058 *
1059 * @param command Command to inject
1060 * @param argLen Length of argument buffer
1061 * @param **argument Argument buffer
1062 * @param *returnMessageBuffer Message buffer
1063 * @param returnMessageBufferLen Length of returnMessageBuffer
1064 * @param *returnPerfBuffer Performance data buffer
1065 * @param returnPerfBufferLen Length of returnPerfBuffer
1066 * @return The command status
1067 */
1068NSCAPI::nagiosReturn NSClientT::injectRAW(const wchar_t* command, const unsigned int argLen, wchar_t **argument, wchar_t *returnMessageBuffer, unsigned int returnMessageBufferLen, wchar_t *returnPerfBuffer, unsigned int returnPerfBufferLen) {
1069        if (logDebug()) {
1070                LOG_DEBUG_STD(_T("Injecting: ") + (std::wstring) command + _T(": ") + arrayBuffer::arrayBuffer2string(argument, argLen, _T(", ")));
1071        }
1072        /*if (shared_client_.get() != NULL && shared_client_->hasMaster()) {
1073                try {
1074                        std::wstring msg, perf;
1075                        int returnCode = shared_client_->inject(command, arrayBuffer::arrayBuffer2string(argument, argLen, _T(" ")), L' ', true, msg, perf);
1076                        NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, msg, returnCode);
1077                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, perf, returnCode);
1078                } catch (nsclient_session::session_exception &e) {
1079                        LOG_ERROR_STD(_T("Failed to inject remote command: ") + e.what());
1080                        int returnCode = NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, _T("Failed to inject remote command: ") + e.what(), NSCAPI::returnCRIT);
1081                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, _T(""), returnCode);
1082                } catch (...) {
1083                        LOG_ERROR_STD(_T("Failed to inject remote command: Unknown exception"));
1084                        int returnCode = NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, _T("Failed to inject remote command:  + e.what()"), NSCAPI::returnCRIT);
1085                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, _T(""), returnCode);
1086                }
1087        } else */{
1088                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
1089                if (!readLock.owns_lock()) {
1090                        LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex."));
1091                        return NSCAPI::returnUNKNOWN;
1092                }
1093                for (pluginList::size_type i = 0; i < commandHandlers_.size(); i++) {
1094                        try {
1095                                NSCAPI::nagiosReturn c = commandHandlers_[i]->handleCommand(command, argLen, argument, returnMessageBuffer, returnMessageBufferLen, returnPerfBuffer, returnPerfBufferLen);
1096                                switch (c) {
1097                                        case NSCAPI::returnInvalidBufferLen:
1098                                                LOG_ERROR_CORE(_T("UNKNOWN: Return buffer to small to handle this command."));
1099                                                return c;
1100                                        case NSCAPI::returnIgnored:
1101                                                break;
1102                                        case NSCAPI::returnOK:
1103                                        case NSCAPI::returnWARN:
1104                                        case NSCAPI::returnCRIT:
1105                                        case NSCAPI::returnUNKNOWN:
1106                                                LOG_DEBUG_STD(_T("Injected Result: ") + NSCHelper::translateReturn(c) + _T(" '") + (std::wstring)(returnMessageBuffer) + _T("'"));
1107                                                LOG_DEBUG_STD(_T("Injected Performance Result: '") +(std::wstring)(returnPerfBuffer) + _T("'"));
1108                                                return c;
1109                                        default:
1110                                                LOG_ERROR_CORE_STD(_T("Unknown error from handleCommand: ") + strEx::itos(c) + _T(" the injected command was: ") + (std::wstring)command);
1111                                                return c;
1112                                }
1113                        } catch(const NSPluginException& e) {
1114                                LOG_ERROR_CORE_STD(_T("Exception raised: ") + e.error_ + _T(" in module: ") + e.file_);
1115                                return NSCAPI::returnCRIT;
1116                        } catch(...) {
1117                                LOG_ERROR_CORE(_T("Unknown exception raised in module"));
1118                                return NSCAPI::returnCRIT;
1119                        }
1120                }
1121                LOG_MESSAGE_STD(_T("No handler for command: '") + command + _T("'"));
1122                return NSCAPI::returnIgnored;
1123        }
1124}
1125
1126void NSClientT::listPlugins() {
1127        boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
1128        if (!readLock.owns_lock()) {
1129                LOG_ERROR_CORE(_T("FATAL ERROR: Could not get read-mutex."));
1130                return;
1131        }
1132        for (pluginList::iterator it=plugins_.begin(); it != plugins_.end(); ++it) {
1133                try {
1134                        if ((*it)->isBroken()) {
1135                                std::wcout << (*it)->getModule() << _T(": ") << _T("broken") << std::endl;
1136                        } else {
1137                                std::wcout << (*it)->getModule() << _T(": ") << (*it)->getName() << std::endl;
1138                        }
1139                } catch (NSPluginException e) {
1140                        LOG_ERROR_CORE_STD(_T("Could not load plugin: ") + e.file_ + _T(": ") + e.error_);
1141                }
1142        }
1143
1144}
1145
1146bool NSClientT::logDebug() {
1147        if (debug_ == log_unknown) {
1148                debug_ = log_looking;
1149                try {
1150                        if (settings_manager::get_settings()->get_int(_T("log"), _T("debug"), 0) == 1)
1151                                debug_ = log_debug;
1152                        else
1153                                debug_ = log_nodebug;
1154                } catch (SettingsException e) {
1155                        return true;
1156                }
1157        } else if (debug_ == log_looking)
1158                return true;
1159        return (debug_ == log_debug);
1160}
1161
1162void log_broken_message(std::wstring msg) {
1163#ifdef WIN32
1164        OutputDebugString(msg.c_str());
1165#else
1166        std::wcout << _T("--BROKEN MESSAGE: ") << msg << _T("--") << std::endl;
1167#endif
1168}
1169/**
1170 * Report a message to all logging enabled modules.
1171 *
1172 * @param msgType Message type
1173 * @param file Filename generally __FILE__
1174 * @param line  Line number, generally __LINE__
1175 * @param message The message as a human readable string.
1176 */
1177void NSClientT::reportMessage(int msgType, const wchar_t* file, const int line, std::wstring message) {
1178        try {
1179                strEx::replace(message, _T("\n"), _T(" "));
1180                strEx::replace(message, _T("\r"), _T(" "));
1181                if ((msgType == NSCAPI::debug)&&(!logDebug())) {
1182                        return;
1183                }
1184//              if (shared_server_.get() != NULL && shared_server_->hasClients()) {
1185//                      try {
1186//                              shared_server_->sendLogMessageToClients(msgType, file, line, message);
1187//                      } catch (nsclient_session::session_exception e) {
1188//                              log_broken_message(_T("Failed to send message to clients: ") + e.what());
1189//                      }
1190//              }
1191                std::wstring file_stl = file;
1192                std::wstring::size_type pos = file_stl.find_last_of(_T("\\"));
1193                if (pos != std::wstring::npos)
1194                        file_stl = file_stl.substr(pos);
1195                {
1196                        boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
1197                        if (!readLock.owns_lock()) {
1198                                log_broken_message(_T("Message was lost as the (mutexRW) core was locked: ") + message);
1199                                return;
1200                        }
1201                        boost::unique_lock<boost::timed_mutex> lock(messageMutex, boost::get_system_time() + boost::posix_time::seconds(5));
1202                        if (!lock.owns_lock()) {
1203                                log_broken_message(_T("Message was lost as the core was locked: ") + message);
1204                                return;
1205                        }
1206                        if (g_bConsoleLog) {
1207                                std::string k = "?";
1208                                switch (msgType) {
1209                                case NSCAPI::critical:
1210                                        k ="c";
1211                                        break;
1212                                case NSCAPI::warning:
1213                                        k ="w";
1214                                        break;
1215                                case NSCAPI::error:
1216                                        k ="e";
1217                                        break;
1218                                case NSCAPI::log:
1219                                        k ="l";
1220                                        break;
1221                                case NSCAPI::debug:
1222                                        k ="d";
1223                                        break;
1224                                }       
1225                                std::cout << k << " " << strEx::wstring_to_string(file_stl) << "(" << line << ") " << strEx::wstring_to_string(message) << std::endl;
1226                        }
1227                        if (!plugins_loaded_) {
1228                                log_broken_message(message);
1229                                cached_log_entry entry(msgType, file, line, message);
1230                                log_cache_.push_back(entry);
1231                        } else {
1232                                if (log_cache_.size() > 0) {
1233                                        for (log_cache_type::const_iterator cit=log_cache_.begin();cit!=log_cache_.end();++cit) {
1234                                                for (pluginList::size_type i = 0; i< messageHandlers_.size(); i++) {
1235                                                        try {
1236                                                                messageHandlers_[i]->handleMessage((*cit).msgType, (_T("CACHE") + (*cit).file).c_str(), (*cit).line, (*cit).message.c_str());
1237                                                        } catch(const NSPluginException& e) {
1238                                                                log_broken_message(_T("Caught: ") + e.error_ + _T(" when trying to log a message..."));
1239                                                                return;
1240                                                        } catch(...) {
1241                                                                log_broken_message(_T("Caught: Unknown Exception when trying to log a message..."));
1242                                                                return;
1243                                                        }
1244                                                }
1245                                        }
1246                                        log_cache_.clear();
1247                                }
1248                                for (pluginList::size_type i = 0; i< messageHandlers_.size(); i++) {
1249                                        try {
1250                                                messageHandlers_[i]->handleMessage(msgType, file, line, message.c_str());
1251                                        } catch(const NSPluginException& e) {
1252                                                log_broken_message(_T("Caught: ") + e.error_ + _T(" when trying to log a message..."));
1253                                                return;
1254                                        } catch(...) {
1255                                                log_broken_message(_T("Caught: Unknown Exception when trying to log a message..."));
1256                                                return;
1257                                        }
1258                                }
1259                        }
1260                }
1261        } catch (...) {
1262                log_broken_message(_T("Caught UNKNOWN Exception when trying to log a message: ") + message);
1263        }
1264}
1265boost::filesystem::wpath NSClientT::getBasePath(void) {
1266        boost::unique_lock<boost::timed_mutex> lock(internalVariables, boost::get_system_time() + boost::posix_time::seconds(5));
1267        if (!lock.owns_lock()) {
1268                LOG_ERROR_CORE(_T("FATAL ERROR: Could not get mutex."));
1269                return _T("FATAL ERROR");
1270        }
1271        if (!basePath.empty())
1272                return basePath;
1273        unsigned int buf_len = 4096;
1274#ifdef WIN32
1275        wchar_t* buffer = new wchar_t[buf_len+1];
1276        GetModuleFileName(NULL, buffer, buf_len);
1277        std::wstring path = buffer;
1278        std::wstring::size_type pos = path.rfind('\\');
1279        basePath = path.substr(0, pos) + _T("\\");
1280        delete [] buffer;
1281#else
1282        basePath = to_wstring(boost::filesystem::initial_path().string());
1283#endif
1284        try {
1285                settings_manager::get_core()->set_base(basePath);
1286        } catch (SettingsException e) {
1287                LOG_ERROR_CORE_STD(_T("Failed to set settings file: ") + e.getMessage());
1288        } catch (...) {
1289                LOG_ERROR_CORE_STD(_T("Failed to set settings file"));
1290        }
1291        return basePath;
1292}
1293
1294
1295std::wstring Encrypt(std::wstring str, unsigned int algorithm) {
1296        unsigned int len = 0;
1297        NSAPIEncrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), NULL, &len);
1298        len+=2;
1299        wchar_t *buf = new wchar_t[len+1];
1300        NSCAPI::errorReturn ret = NSAPIEncrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), buf, &len);
1301        if (ret == NSCAPI::isSuccess) {
1302                std::wstring ret = buf;
1303                delete [] buf;
1304                return ret;
1305        }
1306        return _T("");
1307}
1308std::wstring Decrypt(std::wstring str, unsigned int algorithm) {
1309        unsigned int len = 0;
1310        NSAPIDecrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), NULL, &len);
1311        len+=2;
1312        wchar_t *buf = new wchar_t[len+1];
1313        NSCAPI::errorReturn ret = NSAPIDecrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), buf, &len);
1314        if (ret == NSCAPI::isSuccess) {
1315                std::wstring ret = buf;
1316                delete [] buf;
1317                return ret;
1318        }
1319        return _T("");
1320}
1321
1322void NSClientT::nsclient_log_error(std::wstring file, int line, std::wstring error) {
1323        reportMessage(NSCAPI::error, file.c_str(), line, error);
1324}
1325
1326
1327
1328// Service API
1329NSClient* NSClientT::get_global_instance() {
1330        return &mainClient;
1331}
1332void NSClientT::handle_startup() {
1333        initCore(true);
1334/*
1335        DWORD dwSessionId = remote_processes::getActiveSessionId();
1336        if (dwSessionId != 0xFFFFFFFF)
1337                tray_starter::start(dwSessionId);
1338        else
1339                LOG_ERROR_STD(_T("Failed to start tray helper:" ) + error::lookup::last_error());
1340                */
1341}
1342void NSClientT::handle_shutdown() {
1343        exitCore(true);
1344}
1345#ifdef _WIN32
1346void NSClientT::handle_session_change(unsigned long dwSessionId, bool logon) {
1347
1348}
1349#endif
Note: See TracBrowser for help on using the repository browser.