source: nscp/NSClient++.cpp @ 394f7a1

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

+ Added propper output handling to process subsystem (now you can execute programs tat return "much" data.

+ Added select support for SSL_write (now you can send "any amount of data" to the (SSL) socket.

Since check_nrpe doesn't do this it wont work in that end, but still...

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