source: nscp/trunk/modules/NRPEListener/NRPEListener.cpp @ ae192e3

Last change on this file since ae192e3 was ae192e3, checked in by Michael Medin <michael@…>, 8 years ago

+ Added multitasking to socket listsner (it can now handle multiple connections)

  • Fixed bug in NSClientListener now "seqv" in check_nt shouldn't happen. + Added COUNTER support to NSClient and CheckSystem
  • Property mode set to 100644
File size: 9.6 KB
Line 
1// CheckEventLog.cpp : Defines the entry point for the DLL application.
2//
3
4#include "stdafx.h"
5#include "NRPEListener.h"
6#include <strEx.h>
7#include <time.h>
8#include <config.h>
9#include "NRPEPacket.h"
10
11NRPEListener gNRPEListener;
12
13BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
14{
15        NSCModuleWrapper::wrapDllMain(hModule, ul_reason_for_call);
16        return TRUE;
17}
18
19NRPEListener::NRPEListener() {
20}
21NRPEListener::~NRPEListener() {
22}
23
24
25
26bool NRPEListener::loadModule() {
27        bUseSSL_ = NSCModuleHelper::getSettingsInt(NRPE_SECTION_TITLE, NRPE_SETTINGS_USE_SSL ,NRPE_SETTINGS_USE_SSL_DEFAULT)==1;
28        timeout = NSCModuleHelper::getSettingsInt(NRPE_SECTION_TITLE, NRPE_SETTINGS_TIMEOUT ,NRPE_SETTINGS_TIMEOUT_DEFAULT);
29        std::list<std::string> commands = NSCModuleHelper::getSettingsSection(NRPE_HANDLER_SECTION_TITLE);
30        std::list<std::string>::iterator it;
31        for (it = commands.begin(); it != commands.end(); it++) {
32                strEx::token t = strEx::getToken(*it, '=');
33                if (t.first.substr(0,7) == "command") {
34                        strEx::token t2 = strEx::getToken(t.first, '[');
35                        t2 = strEx::getToken(t2.second, ']');
36                        t.first = t2.first;
37                }
38                if (t.first.empty() || t.second.empty()) {
39                        NSC_LOG_ERROR_STD("Invalid command definition: " + (*it));
40                } else
41                        addCommand(t.first, t.second);
42        }
43
44        allowedHosts.setAllowedHosts(strEx::splitEx(NSCModuleHelper::getSettingsString(NRPE_SECTION_TITLE, NRPE_SETTINGS_ALLOWED, NRPE_SETTINGS_ALLOWED_DEFAULT), ","));
45        try {
46                if (bUseSSL_) {
47                        socket_ssl_.setHandler(this);
48                        socket_ssl_.StartListener(NSCModuleHelper::getSettingsInt(NRPE_SECTION_TITLE, NRPE_SETTINGS_PORT, NRPE_SETTINGS_PORT_DEFAULT));
49                } else {
50                        socket_.setHandler(this);
51                        socket_.StartListener(NSCModuleHelper::getSettingsInt(NRPE_SECTION_TITLE, NRPE_SETTINGS_PORT, NRPE_SETTINGS_PORT_DEFAULT));
52                }
53        } catch (simpleSocket::SocketException e) {
54                NSC_LOG_ERROR_STD("Exception caught: " + e.getMessage());
55                return false;
56        } catch (simpleSSL::SSLException e) {
57                NSC_LOG_ERROR_STD("Exception caught: " + e.getMessage());
58                return false;
59        }
60
61        return true;
62}
63bool NRPEListener::unloadModule() {
64        try {
65                if (bUseSSL_) {
66                        socket_ssl_.removeHandler(this);
67                        socket_ssl_.StopListener();
68                } else {
69                        socket_.removeHandler(this);
70                        socket_.StopListener();
71                }
72        } catch (simpleSocket::SocketException e) {
73                NSC_LOG_ERROR_STD("Exception caught: " + e.getMessage());
74                return false;
75        } catch (simpleSSL::SSLException e) {
76                NSC_LOG_ERROR_STD("Exception caught: " + e.getMessage());
77                return false;
78        }
79        return true;
80}
81
82std::string NRPEListener::getModuleName() {
83        return "NRPE module.";
84}
85NSCModuleWrapper::module_version NRPEListener::getModuleVersion() {
86        NSCModuleWrapper::module_version version = {0, 0, 1 };
87        return version;
88}
89
90bool NRPEListener::hasCommandHandler() {
91        return true;
92}
93bool NRPEListener::hasMessageHandler() {
94        return false;
95}
96
97
98NSCAPI::nagiosReturn NRPEListener::handleCommand(const std::string command, const unsigned int argLen, char **char_args, std::string &message, std::string &perf) {
99        commandList::iterator it = commands.find(command);
100        if (it == commands.end())
101                return NSCAPI::returnIgnored;
102
103        std::string str = (*it).second;
104        if (NSCModuleHelper::getSettingsInt(NRPE_SECTION_TITLE, NRPE_SETTINGS_ALLOW_ARGUMENTS, NRPE_SETTINGS_ALLOW_ARGUMENTS_DEFAULT) == 1) {
105                arrayBuffer::arrayList arr = arrayBuffer::arrayBuffer2list(argLen, char_args);
106                arrayBuffer::arrayList::const_iterator cit = arr.begin();
107                int i=1;
108
109                for (;cit!=arr.end();cit++,i++) {
110                        if (NSCModuleHelper::getSettingsInt(NRPE_SECTION_TITLE, NRPE_SETTINGS_ALLOW_NASTY_META, NRPE_SETTINGS_ALLOW_NASTY_META_DEFAULT) == 0) {
111                                if ((*cit).find_first_of(NASTY_METACHARS) != std::string::npos) {
112                                        NSC_LOG_ERROR("Request string contained illegal metachars!");
113                                        return NSCAPI::returnIgnored;
114                                }
115                        }
116                        strEx::replace(str, "$ARG" + strEx::itos(i) + "$", (*cit));
117                }
118        }
119
120        if ((str.substr(0,6) == "inject")&&(str.length() > 7)) {
121                strEx::token t = strEx::getToken(str.substr(7), ' ');
122                return NSCModuleHelper::InjectSplitAndCommand(t.first, t.second, ' ', message, perf);
123        }
124
125        return executeNRPECommand(str, message, perf);
126}
127#define MAX_INPUT_BUFFER 1024
128
129int NRPEListener::executeNRPECommand(std::string command, std::string &msg, std::string &perf)
130{
131        NSCAPI::nagiosReturn result;
132        PROCESS_INFORMATION pi;
133        STARTUPINFO si;
134        HANDLE hChildOutR, hChildOutW, hChildInR, hChildInW;
135        SECURITY_ATTRIBUTES sec;
136        DWORD dwstate, dwexitcode;
137        int retval;
138
139
140        // Set up members of SECURITY_ATTRIBUTES structure.
141
142        sec.nLength = sizeof(SECURITY_ATTRIBUTES);
143        sec.bInheritHandle = TRUE;
144        sec.lpSecurityDescriptor = NULL;
145
146        // Create Pipes
147        CreatePipe(&hChildInR, &hChildInW, &sec, 0);
148        CreatePipe(&hChildOutR, &hChildOutW, &sec, 0);
149
150        // Set up members of STARTUPINFO structure.
151
152        ZeroMemory(&si, sizeof(STARTUPINFO));
153        si.cb = sizeof(STARTUPINFO);
154        si.dwFlags = STARTF_USESTDHANDLES;
155        si.hStdInput = hChildInR;
156        si.hStdOutput = hChildOutW;
157        si.hStdError = hChildOutW;
158
159
160        // CreateProcess doesn't work with a const command
161        char *cmd = new char[command.length()+1];
162        strncpy(cmd, command.c_str(), command.length());
163        cmd[command.length()] = 0;
164
165        // Create the child process.
166        BOOL processOK = CreateProcess(NULL, cmd,        // command line
167                NULL, // process security attributes
168                NULL, // primary thread security attributes
169                TRUE, // handles are inherited
170                0,    // creation flags
171                NULL, // use parent's environment
172                NULL, // use parent's current directory
173                &si,  // STARTUPINFO pointer
174                &pi); // receives PROCESS_INFORMATION
175        delete [] cmd;
176
177        if (processOK) {
178                dwstate = WaitForSingleObject(pi.hProcess, 1000*timeout);
179                CloseHandle(hChildInR);
180                CloseHandle(hChildInW);
181                CloseHandle(hChildOutW);
182
183                if (dwstate == WAIT_TIMEOUT) {
184                        TerminateProcess(pi.hProcess, 5);
185                        msg = "The check didn't respond within the timeout period!";
186                        result = NSCAPI::returnUNKNOWN;
187                } else {
188                        DWORD dwread;
189                        char *buf = new char[MAX_INPUT_BUFFER+1];
190                        retval = ReadFile(hChildOutR, buf, MAX_INPUT_BUFFER, &dwread, NULL);
191                        if (!retval || dwread == 0) {
192                                msg = "No output available from command...";
193                        } else {
194                                buf[dwread] = 0;
195                                msg = buf;
196                                strEx::token t = strEx::getToken(msg, '\n');
197                                t = strEx::getToken(t.first, '|');
198                                msg = t.first;
199                                perf = t.second;
200                        }
201                        delete [] buf;
202                        result = NSCHelper::int2nagios(GetExitCodeProcess(pi.hProcess, &dwexitcode));
203                }
204                CloseHandle(pi.hThread);
205                CloseHandle(pi.hProcess);
206                CloseHandle(hChildOutR);
207        }
208        else {
209                msg = "NRPE_NT failed to create process, exiting...";
210                result = NSCAPI::returnUNKNOWN;
211                CloseHandle(hChildInR);
212                CloseHandle(hChildInW);
213                CloseHandle(hChildOutW);
214                CloseHandle(pi.hThread);
215                CloseHandle(pi.hProcess);
216                CloseHandle(hChildOutR);
217        }
218        return result;
219}
220void NRPEListener::onClose()
221{}
222
223void NRPEListener::onAccept(simpleSocket::Socket *client)
224{
225        assert(client);
226        if (!allowedHosts.inAllowedHosts(client->getAddrString())) {
227                NSC_LOG_ERROR("Unothorized access from: " + client->getAddrString());
228                client->close();
229                return;
230        }
231        try {
232                simpleSocket::DataBuffer block;
233
234                for (int i=0;i<100;i++) {
235                        client->readAll(block);
236                        if (block.getLength() >= NRPEPacket::getBufferLength())
237                                break;
238                        Sleep(100);
239                }
240                if (i == 100) {
241                        NSC_LOG_ERROR_STD("Could not retrieve NRPE packet.");
242                        client->close();
243                        return;
244                }
245
246                if (block.getLength() == NRPEPacket::getBufferLength()) {
247                        try {
248                                NRPEPacket out = handlePacket(NRPEPacket(block.getBuffer(), block.getLength()));
249                                block.copyFrom(out.getBuffer(), out.getBufferLength());
250                        } catch (NRPEPacket::NRPEPacketException e) {
251                                NSC_LOG_ERROR_STD("NRPESocketException: " + e.getMessage());
252                                client->close();
253                                return;
254                        }
255                        client->send(block);
256                }
257        } catch (simpleSocket::SocketException e) {
258                NSC_LOG_ERROR_STD("SocketException: " + e.getMessage());
259        } catch (NRPEException e) {
260                NSC_LOG_ERROR_STD("NRPEException: " + e.getMessage());
261        }
262        client->close();
263}
264
265NRPEPacket NRPEListener::handlePacket(NRPEPacket p) {
266        if (p.getType() != NRPEPacket::queryPacket) {
267                NSC_LOG_ERROR("Request is not a query.");
268                throw NRPEException("Invalid query type");
269        }
270        if (p.getVersion() != NRPEPacket::version2) {
271                NSC_LOG_ERROR("Request had unsupported version.");
272                throw NRPEException("Invalid version");
273        }
274        if (!p.verifyCRC()) {
275                NSC_LOG_ERROR("Request had invalid checksum.");
276                throw NRPEException("Invalid checksum");
277        }
278        strEx::token cmd = strEx::getToken(p.getPayload(), '!');
279        std::string msg, perf;
280
281        if (NSCModuleHelper::getSettingsInt(NRPE_SECTION_TITLE, NRPE_SETTINGS_ALLOW_ARGUMENTS, NRPE_SETTINGS_ALLOW_ARGUMENTS_DEFAULT) == 0) {
282                if (!cmd.second.empty()) {
283                        NSC_LOG_ERROR("Request contained arguments (not currently allowed).");
284                        throw NRPEException("Request contained arguments (not currently allowed).");
285                }
286        }
287        if (NSCModuleHelper::getSettingsInt(NRPE_SECTION_TITLE, NRPE_SETTINGS_ALLOW_NASTY_META, NRPE_SETTINGS_ALLOW_NASTY_META_DEFAULT) == 0) {
288                if (cmd.first.find_first_of(NASTY_METACHARS) != std::string::npos) {
289                        NSC_LOG_ERROR("Request command contained illegal metachars!");
290                        throw NRPEException("Request command contained illegal metachars!");
291                }
292                if (cmd.second.find_first_of(NASTY_METACHARS) != std::string::npos) {
293                        NSC_LOG_ERROR("Request arguments contained illegal metachars!");
294                        throw NRPEException("Request command contained illegal metachars!");
295                }
296        }
297
298        NSCAPI::nagiosReturn ret = NSCModuleHelper::InjectSplitAndCommand(cmd.first, cmd.second, '!', msg, perf);
299        if (perf.empty()) {
300                return NRPEPacket(NRPEPacket::responsePacket, NRPEPacket::version2, ret, msg);
301        } else {
302                return NRPEPacket(NRPEPacket::responsePacket, NRPEPacket::version2, ret, msg + "|" + perf);
303        }
304}
305
306NSC_WRAPPERS_MAIN_DEF(gNRPEListener);
307NSC_WRAPPERS_IGNORE_MSG_DEF();
308NSC_WRAPPERS_HANDLE_CMD_DEF(gNRPEListener);
Note: See TracBrowser for help on using the repository browser.