source: nscp/NSClient++.cpp @ 7a156f4

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

2008-02-13 MickeM

+ Added string_length to [Settings] as well (used internally) for all "injected" buffers.

  • Fixed issue with scripts result truncated efter 1024 chars

(now they return "all" output and thus you can use the NRPE settings I adde yesterday :)

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