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

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

Major update with a new plugin glue that works better with *nix.
Everything should be the same but look tidier

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