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

0.4.00.4.10.4.2stable
Last change on this file since 7f596ce was 7f596ce, checked in by Michael Medin <michael@…>, 5 years ago
  • Changed so log is now in unicode format

Hopefully this will make it simpler to diagnose PDH issues in "strange locales".
If anyone hates this let me know and I will add an option to use "old ansi log".

  • Fixed so the console is logged as ANSI (properly) and all unicodes are discarded. This means "strangness" in unicode and non-us-ascii chars on the console,

so for details refer to the log-file which is proper unicode.

+ Since log module is loaded "after" the client has booted I added a "hello" message that prints the current version

(if you find this annoying let me know, I will make it optional :)

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