source: nscp/modules/NRPEListener/NRPEListener.cpp @ 1d9338a

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

2005-05-23 MickeM

+ Added obfuscated password support
+ Added some more debug info on commands (returncode, and input args)
+ Added some more comments ot the NSC.ini
+ Added central password "override"
+ Added central "host override"
+ Fixed bug with external commands always getting WARNING state

2005-05-22 MickeM

+ Added debug outout for command
+ Added timestamps for log-to-file (date_mask to configure format)
+ Added support for "no password" with check_nt
+ Added log of bad password on NSClient requests.

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