source: nscp/NSClient++.cpp @ 846bbe4

0.4.00.4.10.4.2stable
Last change on this file since 846bbe4 was 846bbe4, checked in by Michael Medin <michael@…>, 5 years ago

2008-08-09 MickeM

+ Added ChangeWindowMessageFilter? so systray should not work on vista and beyond!

2008-07-28 MickeM

  • Improved the error handling for the check proc state.
  • Removed all (I think) asserts replacing them with exceptions (should I hope reduce crashes and instead leave some form of errors)
  • Property mode set to 100644
File size: 33.2 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 <winsvc.h>
17#include "NSClient++.h"
18#include <Settings.h>
19#include <charEx.h>
20#include <Socket.h>
21#include <b64/b64.h>
22#include <config.h>
23#include <msvc_wrappers.h>
24
25
26NSClient mainClient;    // Global core instance.
27bool g_bConsoleLog = false;
28
29/**
30 * Application startup point
31 *
32 * @param argc Argument count
33 * @param argv[] Argument array
34 * @param envp[] Environment array
35 * @return exit status
36 */
37int wmain(int argc, TCHAR* argv[], TCHAR* envp[])
38{
39        srand( (unsigned)time( NULL ) );
40        int nRetCode = 0;
41        if ( (argc > 1) && ((*argv[1] == '-') || (*argv[1] == '/')) ) {
42                if ( _wcsicmp( _T("install"), argv[1]+1 ) == 0 ) {
43                        g_bConsoleLog = true;
44                        try {
45                                serviceControll::Install(SZSERVICENAME, SZSERVICEDISPLAYNAME, SZDEPENDENCIES);
46                        } catch (const serviceControll::SCException& e) {
47                                LOG_MESSAGE_STD(_T("Service installation failed: ") + e.error_);
48                                return -1;
49                        }
50                        try {
51                                serviceControll::SetDescription(SZSERVICENAME, SZSERVICEDESCRIPTION);
52                        } catch (const serviceControll::SCException& e) {
53                                LOG_MESSAGE_STD(_T("Couldn't set service description: ") + e.error_);
54                        }
55                        LOG_MESSAGE(_T("Service installed!"));
56                } else if ( _wcsicmp( _T("uninstall"), argv[1]+1 ) == 0 ) {
57                        g_bConsoleLog = true;
58                        try {
59                                serviceControll::Uninstall(SZSERVICENAME);
60                        } catch (const serviceControll::SCException& e) {
61                                LOG_MESSAGE_STD(_T("Service deinstallation failed; ") + e.error_);
62                                return -1;
63                        }
64                } else if ( _wcsicmp( _T("encrypt"), argv[1]+1 ) == 0 ) {
65                        g_bConsoleLog = true;
66                        std::wstring password;
67                        try {
68                                Settings::getInstance()->setFile(mainClient.getBasePath(), _T("NSC.ini"));
69                        } catch (SettingsException e) {
70                                std::wcout << _T("Could not find settings: ") << e.getMessage() << std::endl;;
71                                return 1;
72                        }
73                        std::wcout << _T("Enter password to encrypt (has to be a single word): ");
74                        std::wcin >> password;
75                        std::wstring xor_pwd = Encrypt(password);
76                        std::wcout << _T("obfuscated_password=") << xor_pwd << std::endl;
77                        std::wstring outPasswd = Decrypt(xor_pwd);
78                        if (password != outPasswd)
79                                std::wcout << _T("ERROR: Password did not match: ") << outPasswd<< std::endl;
80                        Settings::destroyInstance();
81                        return 0;
82                } else if ( _wcsicmp( _T("start"), argv[1]+1 ) == 0 ) {
83                        g_bConsoleLog = true;
84                        try {
85                                serviceControll::Start(SZSERVICENAME);
86                        } catch (const serviceControll::SCException& e) {
87                                LOG_MESSAGE_STD(_T("Service failed to start: ") + e.error_);
88                                return -1;
89                        }
90                } else if ( _wcsicmp( _T("stop"), argv[1]+1 ) == 0 ) {
91                        g_bConsoleLog = true;
92                        try {
93                                serviceControll::Stop(SZSERVICENAME);
94                        } catch (const serviceControll::SCException& e) {
95                                LOG_MESSAGE_STD(_T("Service failed to stop: ") + e.error_);
96                                return -1;
97                        }
98                } else if ( _wcsicmp( _T("about"), argv[1]+1 ) == 0 ) {
99                        g_bConsoleLog = true;
100                        LOG_MESSAGE(SZAPPNAME _T(" (C) Michael Medin"));
101                        LOG_MESSAGE(_T("Version ") SZVERSION);
102                } else if ( _wcsicmp( _T("version"), argv[1]+1 ) == 0 ) {
103                        g_bConsoleLog = true;
104                        LOG_MESSAGE(SZAPPNAME _T(" Version: ") SZVERSION _T(", Plattform: ") SZARCH);
105                } else if ( _wcsicmp( _T("noboot"), argv[1]+1 ) == 0 ) {
106                        mainClient.setBoot(false);
107                        g_bConsoleLog = false;
108                        mainClient.enableDebug(true);
109                        mainClient.InitiateService();
110                        int nRetCode = -1;
111                        if (argc>=4)
112                                nRetCode = mainClient.commandLineExec(argv[2], argv[3], argc-4, &argv[4]);
113                        else if (argc>=3)
114                                nRetCode = mainClient.commandLineExec(argv[2], argv[3], 0, NULL);
115                        mainClient.TerminateService();
116                        return nRetCode;
117                } else if ( _wcsicmp( _T("test"), argv[1]+1 ) == 0 ) {
118                        std::wcout << "Launching test mode..." << std::endl;
119                        LOG_MESSAGE_STD(_T("Booting: " SZSERVICEDISPLAYNAME ));
120                        try {
121                                if (serviceControll::isStarted(SZSERVICENAME)) {
122                                        std::wcerr << "Service seems to be started, this is probably not a good idea..." << std::endl;
123                                }
124                        } catch (const serviceControll::SCException& e) {
125                                // Empty by design
126                        }
127                        g_bConsoleLog = true;
128                        mainClient.enableDebug(true);
129                        if (!mainClient.InitiateService()) {
130                                LOG_ERROR_STD(_T("Service *NOT* started!"));
131                                return -1;
132                        }
133                        LOG_MESSAGE_STD(_T("Using settings from: ") + Settings::getInstance()->getActiveType());
134                        LOG_MESSAGE(_T("Enter command to inject or exit to terminate..."));
135
136                        std::wstring s = _T("");
137                        std::wstring buff = _T("");
138                        while (true) {
139                                std::wcin >> s;
140                                if (s == _T("exit")) {
141                                        std::wcout << _T("Exiting...") << std::endl;
142                                        break;
143                                } else if (s == _T("off") && buff == _T("debug ")) {
144                                        std::wcout << _T("Setting debug log off...") << std::endl;
145                                        mainClient.enableDebug(false);
146                                } else if (s == _T("on") && buff == _T("debug ")) {
147                                        std::wcout << _T("Setting debug log on...") << std::endl;
148                                        mainClient.enableDebug(true);
149                                } else if (std::cin.peek() < 15) {
150                                        buff += s;
151                                        strEx::token t = strEx::getToken(buff, ' ');
152                                        std::wstring msg, perf;
153                                        NSCAPI::nagiosReturn ret = mainClient.inject(t.first, t.second, ' ', true, msg, perf);
154                                        if (ret == NSCAPI::returnIgnored) {
155                                                std::wcout << _T("No handler for command: ") << t.first << std::endl;
156                                        } else {
157                                                std::wcout << NSCHelper::translateReturn(ret) << _T(":");
158                                                std::cout << strEx::wstring_to_string(msg);
159                                                if (!perf.empty())
160                                                        std::cout << "|" << strEx::wstring_to_string(perf);
161                                                std::wcout << std::endl;
162                                        }
163                                        buff = _T("");
164                                } else {
165                                        buff += s + _T(" ");
166                                }
167                        }
168                        mainClient.TerminateService();
169                        return 0;
170                } else {
171                        std::wcerr << _T("Usage: -version, -about, -install, -uninstall, -start, -stop, -encrypt") << std::endl;
172                        std::wcerr << _T("Usage: [-noboot] <ModuleName> <commnd> [arguments]") << std::endl;
173                        return -1;
174                }
175                return nRetCode;
176        } else if (argc > 2) {
177                g_bConsoleLog = true;
178                mainClient.InitiateService();
179                if (argc>=3)
180                        nRetCode = mainClient.commandLineExec(argv[1], argv[2], argc-3, &argv[3]);
181                else
182                        nRetCode = mainClient.commandLineExec(argv[1], argv[2], 0, NULL);
183                mainClient.TerminateService();
184                return nRetCode;
185        } else if (argc > 1) {
186                g_bConsoleLog = true;
187                mainClient.enableDebug(true);
188                std::wcerr << _T("Invalid command line argument: ") << argv[1] << std::endl;
189                std::wcerr << _T("Usage: -version, -about, -install, -uninstall, -start, -stop, -encrypt") << std::endl;
190                std::wcerr << _T("Usage: [-noboot] <ModuleName> <commnd> [arguments]") << std::endl;
191                return -1;
192        }
193        std::wcout << _T("Running as service...") << std::endl;
194        if (!mainClient.StartServiceCtrlDispatcher()) {
195                LOG_MESSAGE(_T("We failed to start the service"));
196        }
197        return nRetCode;
198}
199
200//////////////////////////////////////////////////////////////////////////
201// Service functions
202
203/**
204 * Service control handler startup point.
205 * When the program is started as a service this will be the entry point.
206 */
207bool NSClientT::InitiateService() {
208        try {
209                Settings::getInstance()->setFile(getBasePath(), _T("NSC.ini"));
210                if (debug_) {
211                        Settings::getInstance()->setInt(_T("log"), _T("debug"), 1);
212                }
213        } catch (SettingsException e) {
214                LOG_ERROR_STD(_T("Could not find settings: ") + e.getMessage());
215                return false;
216        } catch (...) {
217                LOG_ERROR_STD(_T("Unknown exception reading settings..."));
218                return false;
219        }
220
221        try {
222                simpleSocket::WSAStartup();
223        } catch (simpleSocket::SocketException e) {
224                LOG_ERROR_STD(_T("Socket exception: ") + e.getMessage());
225                return false;
226        } catch (...) {
227                LOG_ERROR_STD(_T("Unknown exception iniating socket..."));
228                return false;
229        }
230
231        try {
232                com_helper_.initialize();
233        } catch (com_helper::com_exception e) {
234                LOG_ERROR_STD(_T("COM exception: ") + e.getMessage());
235                return false;
236        } catch (...) {
237                LOG_ERROR_STD(_T("Unknown exception iniating COM..."));
238                return false;
239        }
240        if (boot_) {
241                try {
242                        SettingsT::sectionList list = Settings::getInstance()->getSection(_T("modules"));
243                        for (SettingsT::sectionList::iterator it = list.begin(); it != list.end(); it++) {
244                                try {
245                                        loadPlugin(getBasePath() + _T("modules\\") + (*it));
246                                } catch(const NSPluginException& e) {
247                                        LOG_ERROR_STD(_T("Exception raised: ") + e.error_ + _T(" in module: ") + e.file_);
248                                        //return false;
249                                } catch (std::exception e) {
250                                        LOG_ERROR_STD(_T("exception loading plugin: ") + (*it) + strEx::string_to_wstring(e.what()));
251                                        return false;
252                                } catch (...) {
253                                        LOG_ERROR_STD(_T("Unknown exception loading plugin: ") + (*it));
254                                        return false;
255                                }
256                        }
257                } catch (SettingsException e) {
258                        NSC_LOG_ERROR_STD(_T("Failed to set settings file") + e.getMessage());
259                } catch (...) {
260                        LOG_ERROR_STD(_T("Unknown exception when loading settings"));
261                        return false;
262                }
263                try {
264                        loadPlugins();
265                } catch (...) {
266                        LOG_ERROR_STD(_T("Unknown exception loading plugins"));
267                        return false;
268                }
269        }
270        return true;
271}
272/**
273 * Service control handler termination point.
274 * When the program is stopped as a service this will be the "exit point".
275 */
276void NSClientT::TerminateService(void) {
277        if (boot_) {
278                try {
279                        mainClient.unloadPlugins();
280                } catch(NSPluginException e) {
281                        std::wcout << _T("Exception raised: ") << e.error_ << _T(" in module: ") << e.file_ << std::endl;;
282                } catch(...) {
283                        std::wcout << _T("UNknown exception raised: ") << std::endl;;
284                }
285        }
286        try {
287                com_helper_.unInitialize();
288        } catch (com_helper::com_exception e) {
289                LOG_ERROR_STD(_T("COM exception: ") + e.getMessage());
290        } catch (...) {
291                LOG_ERROR_STD(_T("Unknown exception uniniating COM..."));
292        }
293        try {
294                simpleSocket::WSACleanup();
295        } catch (simpleSocket::SocketException e) {
296                LOG_ERROR_STD(_T("Socket exception: ") + e.getMessage());
297        } catch (...) {
298                LOG_ERROR_STD(_T("Unknown exception uniniating socket..."));
299        }
300        Settings::destroyInstance();
301}
302
303/**
304 * Forward this to the main service dispatcher helper class
305 * @param dwArgc
306 * @param *lpszArgv
307 */
308void WINAPI NSClientT::service_main_dispatch(DWORD dwArgc, LPTSTR *lpszArgv) {
309        mainClient.service_main(dwArgc, lpszArgv);
310}
311/**
312 * Forward this to the main service dispatcher helper class
313 * @param dwCtrlCode
314 */
315void WINAPI NSClientT::service_ctrl_dispatch(DWORD dwCtrlCode) {
316        mainClient.service_ctrl(dwCtrlCode);
317}
318
319//////////////////////////////////////////////////////////////////////////
320// Member functions
321
322int NSClientT::commandLineExec(const TCHAR* module, const TCHAR* command, const unsigned int argLen, TCHAR** args) {
323        std::wstring sModule = module;
324        std::wstring moduleList = _T("");
325        {
326                ReadLock readLock(&m_mutexRW, true, 10000);
327                if (!readLock.IsLocked()) {
328                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
329                        return -1;
330                }
331                for (pluginList::size_type i=0;i<plugins_.size();++i) {
332                        NSCPlugin *p = plugins_[i];
333                        if (!moduleList.empty())
334                                moduleList += _T(", ");
335                        moduleList += p->getModule();
336                        if (p->getModule() == sModule) {
337                                LOG_DEBUG_STD(_T("Found module: ") + p->getName() + _T("..."));
338                                try {
339                                        return p->commandLineExec(command, argLen, args);
340                                } catch (NSPluginException e) {
341                                        LOG_ERROR_STD(_T("Could not execute command: ") + e.error_ + _T(" in ") + e.file_);
342                                        return -1;
343                                }
344                        }
345                }
346        }
347        try {
348                plugin_type plugin = loadPlugin(getBasePath() + _T("modules\\") + module);
349                LOG_DEBUG_STD(_T("Loading plugin: ") + plugin->getName() + _T("..."));
350                plugin->load_plugin();
351                return plugin->commandLineExec(command, argLen, args);
352        } catch (NSPluginException e) {
353                LOG_MESSAGE_STD(_T("Module (") + e.file_ + _T(") was not found: ") + e.error_);
354        }
355        try {
356                plugin_type plugin = loadPlugin(getBasePath() + _T("modules\\") + module + _T(".dll"));
357                LOG_DEBUG_STD(_T("Loading plugin: ") + plugin->getName() + _T("..."));
358                plugin->load_plugin();
359                return plugin->commandLineExec(command, argLen, args);
360        } catch (NSPluginException e) {
361                LOG_MESSAGE_STD(_T("Module (") + e.file_ + _T(") was not found: ") + e.error_);
362        }
363        LOG_ERROR_STD(_T("Module not found: ") + module + _T(" available modules are: ") + moduleList);
364        return 0;
365}
366
367/**
368 * Load a list of plug-ins
369 * @param plugins A list with plug-ins (DLL files) to load
370 */
371void NSClientT::addPlugins(const std::list<std::wstring> plugins) {
372        ReadLock readLock(&m_mutexRW, true, 10000);
373        if (!readLock.IsLocked()) {
374                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
375                return;
376        }
377        std::list<std::wstring>::const_iterator it;
378        for (it = plugins.begin(); it != plugins.end(); ++it) {
379                loadPlugin(*it);
380        }
381}
382/**
383 * Unload all plug-ins (in reversed order)
384 */
385void NSClientT::unloadPlugins() {
386        {
387                WriteLock writeLock(&m_mutexRW, true, 10000);
388                if (!writeLock.IsLocked()) {
389                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
390                        return;
391                }
392                commandHandlers_.clear();
393                messageHandlers_.clear();
394        }
395        {
396                ReadLock readLock(&m_mutexRW, true, 10000);
397                if (!readLock.IsLocked()) {
398                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
399                        return;
400                }
401                for (pluginList::size_type i=plugins_.size();i>0;i--) {
402                        NSCPlugin *p = plugins_[i-1];
403                        LOG_DEBUG_STD(_T("Unloading plugin: ") + p->getName() + _T("..."));
404                        p->unload();
405                }
406        }
407        {
408                WriteLock writeLock(&m_mutexRW, true, 10000);
409                if (!writeLock.IsLocked()) {
410                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
411                        return;
412                }
413                for (pluginList::size_type i=plugins_.size();i>0;i--) {
414                        NSCPlugin *p = plugins_[i-1];
415                        plugins_[i-1] = NULL;
416                        delete p;
417                }
418                plugins_.clear();
419        }
420}
421
422void NSClientT::loadPlugins() {
423        ReadLock readLock(&m_mutexRW, true, 10000);
424        if (!readLock.IsLocked()) {
425                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
426                return;
427        }
428        for (pluginList::iterator it=plugins_.begin(); it != plugins_.end(); ++it) {
429                LOG_DEBUG_STD(_T("Loading plugin: ") + (*it)->getName() + _T("..."));
430                (*it)->load_plugin();
431        }
432}
433/**
434 * Load a single plug-in using a DLL filename
435 * @param file The DLL file
436 */
437NSClientT::plugin_type NSClientT::loadPlugin(const std::wstring file) {
438        return addPlugin(new NSCPlugin(file));
439}
440/**
441 * Load and add a plugin to various internal structures
442 * @param *plugin The plug-ininstance to load. The pointer is managed by the
443 */
444NSClientT::plugin_type NSClientT::addPlugin(plugin_type plugin) {
445        plugin->load_dll();
446        {
447                WriteLock writeLock(&m_mutexRW, true, 10000);
448                if (!writeLock.IsLocked()) {
449                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
450                        return plugin;
451                }
452                plugins_.insert(plugins_.end(), plugin);
453                if (plugin->hasCommandHandler())
454                        commandHandlers_.insert(commandHandlers_.end(), plugin);
455                if (plugin->hasMessageHandler())
456                        messageHandlers_.insert(messageHandlers_.end(), plugin);
457        }
458        return plugin;
459}
460
461
462std::wstring NSClientT::describeCommand(std::wstring command) {
463        ReadLock readLock(&m_mutexRWcmdDescriptions, true, 5000);
464        if (!readLock.IsLocked()) {
465                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex when trying to get command list."));
466                return _T("Failed to get mutex when describing command: ") + command;
467        }
468        cmdMap::const_iterator cit = cmdDescriptions_.find(command);
469        if (cit == cmdDescriptions_.end())
470                return _T("Command not found: ") + command + _T(", maybe it has not been register?");
471        return (*cit).second;
472}
473std::list<std::wstring> NSClientT::getAllCommandNames() {
474        std::list<std::wstring> lst;
475        ReadLock readLock(&m_mutexRWcmdDescriptions, true, 5000);
476        if (!readLock.IsLocked()) {
477                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex when trying to get command list."));
478                return lst;
479        }
480        for (cmdMap::const_iterator cit = cmdDescriptions_.begin(); cit != cmdDescriptions_.end(); ++cit) {
481                lst.push_back((*cit).first);
482        }
483        return lst;
484}
485void NSClientT::registerCommand(std::wstring cmd, std::wstring desc) {
486        WriteLock writeLock(&m_mutexRWcmdDescriptions, true, 10000);
487        if (!writeLock.IsLocked()) {
488                LOG_ERROR_STD(_T("FATAL ERROR: Failed to describe command:") + cmd);
489                return;
490        }
491        cmdDescriptions_[cmd] = desc;
492}
493
494unsigned int NSClientT::getBufferLength() {
495        static unsigned int len = 0;
496        if (len == 0) {
497                try {
498                        len = Settings::getInstance()->getInt(MAIN_SECTION_TITLE, MAIN_STRING_LENGTH, MAIN_STRING_LENGTH_DEFAULT);
499                } catch (SettingsException &e) {
500                        NSC_DEBUG_MSG(_T("Failed to get length: ") + e.getMessage());
501                        return MAIN_STRING_LENGTH_DEFAULT;
502                } catch (...) {
503                        NSC_LOG_ERROR(_T("Failed to get length: :("));
504                        return MAIN_STRING_LENGTH_DEFAULT;
505                }
506        }
507        return len;
508}
509
510NSCAPI::nagiosReturn NSClientT::inject(std::wstring command, std::wstring arguments, TCHAR splitter, bool escape, std::wstring &msg, std::wstring & perf) {
511        unsigned int aLen = 0;
512        TCHAR ** aBuf = arrayBuffer::split2arrayBuffer(arguments, splitter, aLen, escape);
513        unsigned int buf_len = getBufferLength();
514        TCHAR * mBuf = new TCHAR[buf_len+1]; mBuf[0] = '\0';
515        TCHAR * pBuf = new TCHAR[buf_len+1]; pBuf[0] = '\0';
516        NSCAPI::nagiosReturn ret = injectRAW(command.c_str(), aLen, aBuf, mBuf, buf_len, pBuf, buf_len);
517        arrayBuffer::destroyArrayBuffer(aBuf, aLen);
518        if ( (ret == NSCAPI::returnInvalidBufferLen) || (ret == NSCAPI::returnIgnored) ) {
519                delete [] mBuf;
520                delete [] pBuf;
521                return ret;
522        }
523        msg = mBuf;
524        perf = pBuf;
525        delete [] mBuf;
526        delete [] pBuf;
527        return ret;
528}
529
530/**
531 * Inject a command into the plug-in stack.
532 *
533 * @param command Command to inject
534 * @param argLen Length of argument buffer
535 * @param **argument Argument buffer
536 * @param *returnMessageBuffer Message buffer
537 * @param returnMessageBufferLen Length of returnMessageBuffer
538 * @param *returnPerfBuffer Performance data buffer
539 * @param returnPerfBufferLen Length of returnPerfBuffer
540 * @return The command status
541 */
542NSCAPI::nagiosReturn NSClientT::injectRAW(const TCHAR* command, const unsigned int argLen, TCHAR **argument, TCHAR *returnMessageBuffer, unsigned int returnMessageBufferLen, TCHAR *returnPerfBuffer, unsigned int returnPerfBufferLen) {
543        if (logDebug()) {
544                LOG_DEBUG_STD(_T("Injecting: ") + (std::wstring) command + _T(": ") + arrayBuffer::arrayBuffer2string(argument, argLen, _T(", ")));
545        }
546        ReadLock readLock(&m_mutexRW, true, 5000);
547        if (!readLock.IsLocked()) {
548                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
549                return NSCAPI::returnUNKNOWN;
550        }
551        for (pluginList::size_type i = 0; i < commandHandlers_.size(); i++) {
552                try {
553                        NSCAPI::nagiosReturn c = commandHandlers_[i]->handleCommand(command, argLen, argument, returnMessageBuffer, returnMessageBufferLen, returnPerfBuffer, returnPerfBufferLen);
554                        switch (c) {
555                                case NSCAPI::returnInvalidBufferLen:
556                                        LOG_ERROR(_T("UNKNOWN: Return buffer to small to handle this command."));
557                                        return c;
558                                case NSCAPI::returnIgnored:
559                                        break;
560                                case NSCAPI::returnOK:
561                                case NSCAPI::returnWARN:
562                                case NSCAPI::returnCRIT:
563                                case NSCAPI::returnUNKNOWN:
564                                        LOG_DEBUG_STD(_T("Injected Result: ") + NSCHelper::translateReturn(c) + _T(" '") + (std::wstring)(returnMessageBuffer) + _T("'"));
565                                        LOG_DEBUG_STD(_T("Injected Performance Result: '") +(std::wstring)(returnPerfBuffer) + _T("'"));
566                                        return c;
567                                default:
568                                        LOG_ERROR_STD(_T("Unknown error from handleCommand: ") + strEx::itos(c) + _T(" the injected command was: ") + (std::wstring)command);
569                                        return c;
570                        }
571                } catch(const NSPluginException& e) {
572                        LOG_ERROR_STD(_T("Exception raised: ") + e.error_ + _T(" in module: ") + e.file_);
573                        return NSCAPI::returnCRIT;
574                } catch(...) {
575                        LOG_ERROR_STD(_T("Unknown exception raised in module"));
576                        return NSCAPI::returnCRIT;
577                }
578        }
579        LOG_MESSAGE_STD(_T("No handler for command: '") + command + _T("'"));
580        return NSCAPI::returnIgnored;
581}
582
583bool NSClientT::logDebug() {
584        if (debug_ == log_unknown) {
585                try {
586                        if (Settings::getInstance()->getInt(_T("log"), _T("debug"), 0) == 1)
587                                debug_ = log_debug;
588                        else
589                                debug_ = log_nodebug;
590                } catch (SettingsException e) {
591                        debug_ = log_debug;
592                }
593        }
594        return (debug_ == log_debug);
595}
596
597/**
598 * Report a message to all logging enabled modules.
599 *
600 * @param msgType Message type
601 * @param file Filename generally __FILE__
602 * @param line  Line number, generally __LINE__
603 * @param message The message as a human readable string.
604 */
605void NSClientT::reportMessage(int msgType, const TCHAR* file, const int line, std::wstring message) {
606        if ((msgType == NSCAPI::debug)&&(!logDebug())) {
607                return;
608        }
609        std::wstring file_stl = file;
610        std::wstring::size_type pos = file_stl.find_last_of(_T("\\"));
611        if (pos != std::wstring::npos)
612                file_stl = file_stl.substr(pos);
613        {
614                ReadLock readLock(&m_mutexRW, true, 5000);
615                if (!readLock.IsLocked()) {
616                        std::wcout << _T("Message was lost as the core was locked...") << std::endl;
617                        return;
618                }
619                MutexLock lock(messageMutex);
620                if (!lock.hasMutex()) {
621                        std::wcout << _T("Message was lost as the core was locked...") << std::endl;
622                        std::wcout << message << std::endl;
623                        return;
624                }
625                if (g_bConsoleLog) {
626                        std::string k = "?";
627                        switch (msgType) {
628                        case NSCAPI::critical:
629                                k ="c";
630                                break;
631                        case NSCAPI::warning:
632                                k ="w";
633                                break;
634                        case NSCAPI::error:
635                                k ="e";
636                                break;
637                        case NSCAPI::log:
638                                k ="l";
639                                break;
640                        case NSCAPI::debug:
641                                k ="d";
642                                break;
643                        }       
644                        std::cout << k << " " << strEx::wstring_to_string(file_stl) << "(" << line << ") " << strEx::wstring_to_string(message) << std::endl;
645                }
646                for (pluginList::size_type i = 0; i< messageHandlers_.size(); i++) {
647                        try {
648                                messageHandlers_[i]->handleMessage(msgType, file, line, message.c_str());
649                        } catch(const NSPluginException& e) {
650                                // Here we are pretty much fucked! (as logging this might cause a loop :)
651                                std::wcout << _T("Caught: ") << e.error_ << _T(" when trying to log a message...") << std::endl;
652                                std::wcout << _T("This is *really really* bad, now the world is about to end...") << std::endl;
653                        }
654                }
655        }
656}
657std::wstring NSClientT::getBasePath(void) {
658        MutexLock lock(internalVariables);
659        if (!lock.hasMutex()) {
660                LOG_ERROR(_T("FATAL ERROR: Could not get mutex."));
661                return _T("FATAL ERROR");
662        }
663        if (!basePath.empty())
664                return basePath;
665        unsigned int buf_len = 4096;
666        TCHAR* buffer = new TCHAR[buf_len+1];
667        GetModuleFileName(NULL, buffer, buf_len);
668        std::wstring path = buffer;
669        std::wstring::size_type pos = path.rfind('\\');
670        basePath = path.substr(0, pos) + _T("\\");
671        delete [] buffer;
672        try {
673                Settings::getInstance()->setFile(basePath, _T("NSC.ini"));
674        } catch (SettingsException e) {
675                NSC_LOG_ERROR_STD(_T("Failed to set settings file") + e.getMessage());
676        }
677        return basePath;
678}
679
680
681NSCAPI::errorReturn NSAPIGetSettingsString(const TCHAR* section, const TCHAR* key, const TCHAR* defaultValue, TCHAR* buffer, unsigned int bufLen) {
682        try {
683                return NSCHelper::wrapReturnString(buffer, bufLen, Settings::getInstance()->getString(section, key, defaultValue), NSCAPI::isSuccess);
684        } catch (...) {
685                NSC_LOG_ERROR_STD(_T("Failed to getString: ") + key);
686                return NSCAPI::hasFailed;
687        }
688}
689int NSAPIGetSettingsInt(const TCHAR* section, const TCHAR* key, int defaultValue) {
690        try {
691                return Settings::getInstance()->getInt(section, key, defaultValue);
692        } catch (SettingsException e) {
693                NSC_LOG_ERROR_STD(_T("Failed to set settings file") + e.getMessage());
694                return defaultValue;
695        }
696}
697NSCAPI::errorReturn NSAPIGetBasePath(TCHAR*buffer, unsigned int bufLen) {
698        return NSCHelper::wrapReturnString(buffer, bufLen, mainClient.getBasePath(), NSCAPI::isSuccess);
699}
700NSCAPI::errorReturn NSAPIGetApplicationName(TCHAR*buffer, unsigned int bufLen) {
701        return NSCHelper::wrapReturnString(buffer, bufLen, SZAPPNAME, NSCAPI::isSuccess);
702}
703NSCAPI::errorReturn NSAPIGetApplicationVersionStr(TCHAR*buffer, unsigned int bufLen) {
704        return NSCHelper::wrapReturnString(buffer, bufLen, SZVERSION, NSCAPI::isSuccess);
705}
706void NSAPIMessage(int msgType, const TCHAR* file, const int line, const TCHAR* message) {
707        mainClient.reportMessage(msgType, file, line, message);
708}
709void NSAPIStopServer(void) {
710        serviceControll::StopNoWait(SZSERVICENAME);
711}
712NSCAPI::nagiosReturn NSAPIInject(const TCHAR* command, const unsigned int argLen, TCHAR **argument, TCHAR *returnMessageBuffer, unsigned int returnMessageBufferLen, TCHAR *returnPerfBuffer, unsigned int returnPerfBufferLen) {
713        return mainClient.injectRAW(command, argLen, argument, returnMessageBuffer, returnMessageBufferLen, returnPerfBuffer, returnPerfBufferLen);
714}
715NSCAPI::errorReturn NSAPIGetSettingsSection(const TCHAR* section, TCHAR*** aBuffer, unsigned int * bufLen) {
716        try {
717                unsigned int len = 0;
718                *aBuffer = arrayBuffer::list2arrayBuffer(Settings::getInstance()->getSection(section), len);
719                *bufLen = len;
720                return NSCAPI::isSuccess;
721        } catch (...) {
722                NSC_LOG_ERROR_STD(_T("Failed to getSection: ") + section);
723                return NSCAPI::hasFailed;
724        }
725}
726NSCAPI::errorReturn NSAPIReleaseSettingsSectionBuffer(TCHAR*** aBuffer, unsigned int * bufLen) {
727        arrayBuffer::destroyArrayBuffer(*aBuffer, *bufLen);
728        *bufLen = 0;
729        *aBuffer = NULL;
730        return NSCAPI::isSuccess;
731}
732
733NSCAPI::boolReturn NSAPICheckLogMessages(int messageType) {
734        if (mainClient.logDebug())
735                return NSCAPI::istrue;
736        return NSCAPI::isfalse;
737}
738
739std::wstring Encrypt(std::wstring str, unsigned int algorithm) {
740        unsigned int len = 0;
741        NSAPIEncrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), NULL, &len);
742        len+=2;
743        TCHAR *buf = new TCHAR[len+1];
744        NSCAPI::errorReturn ret = NSAPIEncrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), buf, &len);
745        if (ret == NSCAPI::isSuccess) {
746                std::wstring ret = buf;
747                delete [] buf;
748                return ret;
749        }
750        return _T("");
751}
752std::wstring Decrypt(std::wstring str, unsigned int algorithm) {
753        unsigned int len = 0;
754        NSAPIDecrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), NULL, &len);
755        len+=2;
756        TCHAR *buf = new TCHAR[len+1];
757        NSCAPI::errorReturn ret = NSAPIDecrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), buf, &len);
758        if (ret == NSCAPI::isSuccess) {
759                std::wstring ret = buf;
760                delete [] buf;
761                return ret;
762        }
763        return _T("");
764}
765
766NSCAPI::errorReturn NSAPIEncrypt(unsigned int algorithm, const TCHAR* inBuffer, unsigned int inBufLen, TCHAR* outBuf, unsigned int *outBufLen) {
767        if (algorithm != NSCAPI::xor) {
768                LOG_ERROR(_T("Unknown algortihm requested."));
769                return NSCAPI::hasFailed;
770        }
771        std::wstring key = Settings::getInstance()->getString(MAIN_SECTION_TITLE, MAIN_MASTERKEY, MAIN_MASTERKEY_DEFAULT);
772        int tcharInBufLen = 0;
773        char *c = charEx::tchar_to_char(inBuffer, inBufLen, tcharInBufLen);
774        std::wstring::size_type j=0;
775        for (int i=0;i<tcharInBufLen;i++,j++) {
776                if (j > key.size())
777                        j = 0;
778                c[i] ^= key[j];
779        }
780        size_t cOutBufLen = b64::b64_encode(reinterpret_cast<void*>(c), tcharInBufLen, NULL, NULL);
781        if (!outBuf) {
782                *outBufLen = static_cast<unsigned int>(cOutBufLen*2); // TODO: Guessing wildly here but no proper way to tell without a lot of extra work
783                return NSCAPI::isSuccess;
784        }
785        char *cOutBuf = new char[cOutBufLen+1];
786        size_t len = b64::b64_encode(reinterpret_cast<void*>(c), tcharInBufLen, cOutBuf, cOutBufLen);
787        delete [] c;
788        if (len == 0) {
789                LOG_ERROR(_T("Invalid out buffer length."));
790                return NSCAPI::isInvalidBufferLen;
791        }
792        int realOutLen;
793        TCHAR *realOut = charEx::char_to_tchar(cOutBuf, cOutBufLen, realOutLen);
794        if (static_cast<unsigned int>(realOutLen) >= *outBufLen) {
795                LOG_ERROR_STD(_T("Invalid out buffer length: ") + strEx::itos(realOutLen) + _T(" was needed but only ") + strEx::itos(*outBufLen) + _T(" was allocated."));
796                return NSCAPI::isInvalidBufferLen;
797        }
798        wcsncpy_s(outBuf, *outBufLen, realOut, realOutLen);
799        delete [] realOut;
800        outBuf[realOutLen] = 0;
801        *outBufLen = static_cast<unsigned int>(realOutLen);
802        return NSCAPI::isSuccess;
803}
804
805NSCAPI::errorReturn NSAPIDecrypt(unsigned int algorithm, const TCHAR* inBuffer, unsigned int inBufLen, TCHAR* outBuf, unsigned int *outBufLen) {
806        if (algorithm != NSCAPI::xor) {
807                LOG_ERROR(_T("Unknown algortihm requested."));
808                return NSCAPI::hasFailed;
809        }
810        int inBufLenC = 0;
811        char *inBufferC = charEx::tchar_to_char(inBuffer, inBufLen, inBufLenC);
812        size_t cOutLen =  b64::b64_decode(inBufferC, inBufLenC, NULL, NULL);
813        if (!outBuf) {
814                *outBufLen = static_cast<unsigned int>(cOutLen*2); // TODO: Guessing wildly here but no proper way to tell without a lot of extra work
815                return NSCAPI::isSuccess;
816        }
817        char *cOutBuf = new char[cOutLen+1];
818        size_t len = b64::b64_decode(inBufferC, inBufLenC, reinterpret_cast<void*>(cOutBuf), cOutLen);
819        delete [] inBufferC;
820        if (len == 0) {
821                LOG_ERROR(_T("Invalid out buffer length."));
822                return NSCAPI::isInvalidBufferLen;
823        }
824        int realOutLen;
825
826        std::wstring key = Settings::getInstance()->getString(MAIN_SECTION_TITLE, MAIN_MASTERKEY, MAIN_MASTERKEY_DEFAULT);
827        std::wstring::size_type j=0;
828        for (int i=0;i<cOutLen;i++,j++) {
829                if (j > key.size())
830                        j = 0;
831                cOutBuf[i] ^= key[j];
832        }
833
834        TCHAR *realOut = charEx::char_to_tchar(cOutBuf, cOutLen, realOutLen);
835        if (static_cast<unsigned int>(realOutLen) >= *outBufLen) {
836                LOG_ERROR_STD(_T("Invalid out buffer length: ") + strEx::itos(realOutLen) + _T(" was needed but only ") + strEx::itos(*outBufLen) + _T(" was allocated."));
837                return NSCAPI::isInvalidBufferLen;
838        }
839        wcsncpy_s(outBuf, *outBufLen, realOut, realOutLen);
840        delete [] realOut;
841        outBuf[realOutLen] = 0;
842        *outBufLen = static_cast<unsigned int>(realOutLen);
843        return NSCAPI::isSuccess;
844}
845
846NSCAPI::errorReturn NSAPISetSettingsString(const TCHAR* section, const TCHAR* key, const TCHAR* value) {
847        try {
848                Settings::getInstance()->setString(section, key, value);
849        } catch (...) {
850                NSC_LOG_ERROR_STD(_T("Failed to setString: ") + key);
851                return NSCAPI::hasFailed;
852        }
853        return NSCAPI::isSuccess;
854}
855NSCAPI::errorReturn NSAPISetSettingsInt(const TCHAR* section, const TCHAR* key, int value) {
856        try {
857                Settings::getInstance()->setInt(section, key, value);
858        } catch (...) {
859                NSC_LOG_ERROR_STD(_T("Failed to setInt: ") + key);
860                return NSCAPI::hasFailed;
861        }
862        return NSCAPI::isSuccess;
863}
864NSCAPI::errorReturn NSAPIWriteSettings(int type) {
865        try {
866                if (type == NSCAPI::settings_registry)
867                        Settings::getInstance()->write(REGSettings::getType());
868                else if (type == NSCAPI::settings_inifile)
869                        Settings::getInstance()->write(INISettings::getType());
870                else
871                        Settings::getInstance()->write();
872        } catch (SettingsException e) {
873                LOG_ERROR_STD(_T("Failed to write settings: ") + e.getMessage());
874                return NSCAPI::hasFailed;
875        } catch (...) {
876                NSC_LOG_ERROR_STD(_T("Failed to write settings"));
877                return NSCAPI::hasFailed;
878        }
879        return NSCAPI::isSuccess;
880}
881NSCAPI::errorReturn NSAPIReadSettings(int type) {
882        try {
883                if (type == NSCAPI::settings_registry)
884                        Settings::getInstance()->read(REGSettings::getType());
885                else if (type == NSCAPI::settings_inifile)
886                        Settings::getInstance()->read(INISettings::getType());
887                else
888                        Settings::getInstance()->read();
889        } catch (SettingsException e) {
890                LOG_ERROR_STD(_T("Failed to read settings: ") + e.getMessage());
891                return NSCAPI::hasFailed;
892        } catch (...) {
893                NSC_LOG_ERROR_STD(_T("Failed to read settings"));
894                return NSCAPI::hasFailed;
895        }
896        return NSCAPI::isSuccess;
897}
898NSCAPI::errorReturn NSAPIRehash(int flag) {
899        return NSCAPI::hasFailed;
900}
901NSCAPI::errorReturn NSAPIDescribeCommand(const TCHAR* command, TCHAR* buffer, unsigned int bufLen) {
902        return NSCHelper::wrapReturnString(buffer, bufLen, mainClient.describeCommand(command), NSCAPI::isSuccess);
903}
904NSCAPI::errorReturn NSAPIGetAllCommandNames(arrayBuffer::arrayBuffer* aBuffer, unsigned int *bufLen) {
905        unsigned int len = 0;
906        *aBuffer = arrayBuffer::list2arrayBuffer(mainClient.getAllCommandNames(), len);
907        *bufLen = len;
908        return NSCAPI::isSuccess;
909}
910NSCAPI::errorReturn NSAPIReleaseAllCommandNamessBuffer(TCHAR*** aBuffer, unsigned int * bufLen) {
911        arrayBuffer::destroyArrayBuffer(*aBuffer, *bufLen);
912        *bufLen = 0;
913        *aBuffer = NULL;
914        return NSCAPI::isSuccess;
915}
916NSCAPI::errorReturn NSAPIRegisterCommand(const TCHAR* cmd,const TCHAR* desc) {
917        mainClient.registerCommand(cmd, desc);
918        return NSCAPI::isSuccess;
919}
920
921
922LPVOID NSAPILoader(TCHAR*buffer) {
923        if (_wcsicmp(buffer, _T("NSAPIGetApplicationName")) == 0)
924                return &NSAPIGetApplicationName;
925        if (_wcsicmp(buffer, _T("NSAPIGetApplicationVersionStr")) == 0)
926                return &NSAPIGetApplicationVersionStr;
927        if (_wcsicmp(buffer, _T("NSAPIGetSettingsString")) == 0)
928                return &NSAPIGetSettingsString;
929        if (_wcsicmp(buffer, _T("NSAPIGetSettingsSection")) == 0)
930                return &NSAPIGetSettingsSection;
931        if (_wcsicmp(buffer, _T("NSAPIReleaseSettingsSectionBuffer")) == 0)
932                return &NSAPIReleaseSettingsSectionBuffer;
933        if (_wcsicmp(buffer, _T("NSAPIGetSettingsInt")) == 0)
934                return &NSAPIGetSettingsInt;
935        if (_wcsicmp(buffer, _T("NSAPIMessage")) == 0)
936                return &NSAPIMessage;
937        if (_wcsicmp(buffer, _T("NSAPIStopServer")) == 0)
938                return &NSAPIStopServer;
939        if (_wcsicmp(buffer, _T("NSAPIInject")) == 0)
940                return &NSAPIInject;
941        if (_wcsicmp(buffer, _T("NSAPIGetBasePath")) == 0)
942                return &NSAPIGetBasePath;
943        if (_wcsicmp(buffer, _T("NSAPICheckLogMessages")) == 0)
944                return &NSAPICheckLogMessages;
945        if (_wcsicmp(buffer, _T("NSAPIEncrypt")) == 0)
946                return &NSAPIEncrypt;
947        if (_wcsicmp(buffer, _T("NSAPIDecrypt")) == 0)
948                return &NSAPIDecrypt;
949        if (_wcsicmp(buffer, _T("NSAPISetSettingsString")) == 0)
950                return &NSAPISetSettingsString;
951        if (_wcsicmp(buffer, _T("NSAPISetSettingsInt")) == 0)
952                return &NSAPISetSettingsInt;
953        if (_wcsicmp(buffer, _T("NSAPIWriteSettings")) == 0)
954                return &NSAPIWriteSettings;
955        if (_wcsicmp(buffer, _T("NSAPIReadSettings")) == 0)
956                return &NSAPIReadSettings;
957        if (_wcsicmp(buffer, _T("NSAPIRehash")) == 0)
958                return &NSAPIRehash;
959        if (_wcsicmp(buffer, _T("NSAPIDescribeCommand")) == 0)
960                return &NSAPIDescribeCommand;
961        if (_wcsicmp(buffer, _T("NSAPIGetAllCommandNames")) == 0)
962                return &NSAPIGetAllCommandNames;
963        if (_wcsicmp(buffer, _T("NSAPIReleaseAllCommandNamessBuffer")) == 0)
964                return &NSAPIReleaseAllCommandNamessBuffer;
965        if (_wcsicmp(buffer, _T("NSAPIRegisterCommand")) == 0)
966                return &NSAPIRegisterCommand;
967
968        return NULL;
969}
Note: See TracBrowser for help on using the repository browser.