source: nscp/NSClient++.cpp @ 4c8d44d

0.4.00.4.10.4.2stable
Last change on this file since 4c8d44d was 2f01f93, checked in by Michael Medin <michael@…>, 5 years ago

+ Added new module NRPEClient that can act as a NRPE client, might be useful for testing things and

eventually for relaying events.
Usage: nsclient++ -noboot NRPEClient -H 192.168.0.1 -p 5666 -c check_something -a foo bar
This is an early concept so don't expect much...

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