source: nscp/trunk/modules/NRPEClient/NRPEClient.cpp @ 83d61f0

Last change on this file since 83d61f0 was 83d61f0, checked in by Michael Medin <michael@…>, 5 years ago
  • Fixed a bug in NSCA module (now it works again :) + Added a command wrapper for the NRPECLient module so now it can act as a check command.

(No argument handling yet though), For a sample check out the [NRPE Client Handlers] section in NSC.ini

  • Property mode set to 100644
File size: 11.2 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2004-2007 by Michael Medin <michael@medin.name>         *
3*                                                                         *
4*   This code is part of NSClient++ - http://trac.nakednuns.org/nscp      *
5*                                                                         *
6*   This program is free software; you can redistribute it and/or modify  *
7*   it under the terms of the GNU General Public License as published by  *
8*   the Free Software Foundation; either version 2 of the License, or     *
9*   (at your option) any later version.                                   *
10*                                                                         *
11*   This program is distributed in the hope that it will be useful,       *
12*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14*   GNU General Public License for more details.                          *
15*                                                                         *
16*   You should have received a copy of the GNU General Public License     *
17*   along with this program; if not, write to the                         *
18*   Free Software Foundation, Inc.,                                       *
19*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20***************************************************************************/
21#include "stdafx.h"
22#include "NRPEClient.h"
23#include <strEx.h>
24#include <time.h>
25#include <config.h>
26#include <msvc_wrappers.h>
27#include <execute_process.hpp>
28#include <program_options_ex.hpp>
29
30NRPEClient gNRPEClient;
31
32BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
33{
34        NSCModuleWrapper::wrapDllMain(hModule, ul_reason_for_call);
35        return TRUE;
36}
37
38NRPEClient::NRPEClient() : buffer_length_(0) {
39}
40
41NRPEClient::~NRPEClient() {
42}
43
44bool NRPEClient::loadModule() {
45        buffer_length_ = NSCModuleHelper::getSettingsInt(NRPE_SECTION_TITLE, NRPE_SETTINGS_STRLEN, NRPE_SETTINGS_STRLEN_DEFAULT);
46
47        std::list<std::wstring> commands = NSCModuleHelper::getSettingsSection(NRPE_CLIENT_HANDLER_SECTION_TITLE);
48        NSC_DEBUG_MSG_STD(_T("humm..."));
49        for (std::list<std::wstring>::const_iterator it = commands.begin(); it != commands.end(); ++it) {
50                NSC_DEBUG_MSG_STD(*it);
51                std::wstring s = NSCModuleHelper::getSettingsString(NRPE_CLIENT_HANDLER_SECTION_TITLE, (*it), _T(""));
52                if (s.empty()) {
53                        NSC_LOG_ERROR_STD(_T("Invalid NRPE-client entry: ") + (*it));
54                } else {
55                        addCommand((*it).c_str(), s);
56                }
57        }
58        return true;
59}
60
61void NRPEClient::addCommand(strEx::blindstr key, std::wstring args) {
62        NSC_LOG_ERROR_STD(_T("Parsing: ") + args);
63        try {
64                boost::program_options::options_description desc = get_optionDesc();
65                boost::program_options::positional_options_description p = get_optionsPositional();
66
67                boost::program_options::variables_map vm;
68                boost::program_options::store(
69                        basic_command_line_parser_ex<TCHAR>(args).options(desc).positional(p).run()
70                        , vm);
71                boost::program_options::notify(vm);
72                nrpe_connection_data cd = get_ConectionData(vm);
73                NSC_DEBUG_MSG_STD(_T("Parsed CLI for: ") + key.c_str() + _T(" = ") + cd.toString());
74                commands[key] = cd;
75        } catch (boost::program_options::validation_error &e) {
76                NSC_LOG_ERROR_STD(_T("Could not parse: ") + key.c_str() + strEx::string_to_wstring(e.what()));
77        } catch (...) {
78                NSC_LOG_ERROR_STD(_T("Could not parse: ") + key.c_str());
79        }
80}
81
82bool NRPEClient::unloadModule() {
83        return true;
84}
85
86bool NRPEClient::hasCommandHandler() {
87        return true;
88}
89bool NRPEClient::hasMessageHandler() {
90        return false;
91}
92NSCAPI::nagiosReturn NRPEClient::handleCommand(const strEx::blindstr command, const unsigned int argLen, TCHAR **char_args, std::wstring &message, std::wstring &perf)
93{
94        command_list::const_iterator cit = commands.find(command);
95        if (cit == commands.end())
96                return NSCAPI::returnIgnored;
97        nrpe_result_data r = execute_nrpe_command((*cit).second);
98        message = r.text;
99        return r.result;
100}
101
102
103boost::program_options::options_description NRPEClient::get_optionDesc() {
104        boost::program_options::options_description desc("Allowed options");
105        buffer_length_ = NSCModuleHelper::getSettingsInt(NRPE_SECTION_TITLE, NRPE_SETTINGS_STRLEN, NRPE_SETTINGS_STRLEN_DEFAULT);
106        desc.add_options()
107                ("help,h", "Show this help message.")
108                ("host,H", boost::program_options::wvalue<std::wstring>(), "The address of the host running the NRPE daemon")
109                ("port,p", boost::program_options::value<int>(), "The port on which the daemon is running (default=5666)")
110                ("command,c", boost::program_options::wvalue<std::wstring>(), "The name of the command that the remote daemon should run")
111                ("timeout,t", boost::program_options::value<int>(), "Number of seconds before connection times out (default=10)")
112                ("buffer-length,l", boost::program_options::value<int>(), std::string("Length of payload (has to be same as on the server (default=" + strEx::s::itos(buffer_length_) + ")").c_str())
113                ("no-ssl,n", "Do not initial an ssl handshake with the server, talk in plaintext.")
114                ("arguments,a", boost::program_options::wvalue<std::vector<std::wstring>>(), "list of arguments")
115                ;
116        return desc;
117}
118boost::program_options::positional_options_description NRPEClient::get_optionsPositional() {
119        boost::program_options::positional_options_description p;
120        p.add("arguments", -1);
121        return p;
122}
123NRPEClient::nrpe_connection_data NRPEClient::get_ConectionData(boost::program_options::variables_map &vm) {
124        nrpe_connection_data ret(buffer_length_);
125        if (vm.count("host"))
126                ret.host = vm["host"].as<std::wstring>();
127        if (vm.count("port"))
128                ret.port = vm["port"].as<int>();
129        if (vm.count("timeout"))
130                ret.timeout = vm["timeout"].as<int>();
131        if (vm.count("buffer-length"))
132                ret.buffer_length = vm["buffer-length"].as<int>();
133        if (vm.count("command"))
134                ret.command = vm["command"].as<std::wstring>();
135        if (vm.count("arguments")) {
136                std::vector<std::wstring> v = vm["arguments"].as<std::vector<std::wstring>>();
137                for (std::vector<std::wstring>::const_iterator cit = v.begin(); cit != v.end(); ++cit) {
138                        if (!ret.arguments.empty())
139                                ret.arguments += _T("!");
140                        ret.arguments += *cit;
141                }
142        }
143        if (vm.count("no-ssl"))
144                ret.ssl = false;
145        return ret;
146}
147int NRPEClient::commandLineExec(const TCHAR* command, const unsigned int argLen, TCHAR** args) {
148        try {
149                boost::program_options::options_description desc = get_optionDesc();
150                boost::program_options::positional_options_description p = get_optionsPositional();
151               
152                boost::program_options::variables_map vm;
153                boost::program_options::store(
154                        basic_command_line_parser_ex<TCHAR>(command, argLen, args).options(desc).positional(p).run()
155                        , vm);
156                boost::program_options::notify(vm);   
157
158                if (vm.count("help")) {
159                        std::cout << desc << "\n";
160                        return 1;
161                }
162
163                nrpe_result_data result = execute_nrpe_command(get_ConectionData(vm));
164                std::wcout << result.text << std::endl;
165                return result.result;
166        } catch (boost::program_options::validation_error &e) {
167                std::cout << e.what() << std::endl;
168        } catch (...) {
169                std::cout << "Unknown exception parsing command line" << std::endl;
170        }
171        return NSCAPI::returnUNKNOWN;
172}
173NRPEClient::nrpe_result_data NRPEClient::execute_nrpe_command(nrpe_connection_data con) {
174        try {
175                NRPEPacket packet;
176                if (con.ssl)
177                        packet = send_ssl(con.host, con.port, con.timeout, NRPEPacket::make_request(con.get_cli(), con.buffer_length));
178                else
179                        packet = send_nossl(con.host, con.port, con.timeout, NRPEPacket::make_request(con.get_cli(), con.buffer_length));
180                return nrpe_result_data(packet.getResult(), packet.getPayload());
181        } catch (simpleSocket::SocketException &e) {
182                return nrpe_result_data(NSCAPI::returnUNKNOWN, _T("Socket error: ") + e.getMessage());
183        } catch (simpleSSL::SSLException &e) {
184                return nrpe_result_data(NSCAPI::returnUNKNOWN, _T("SSL Socket error: ") + e.getMessage());
185        } catch (...) {
186                return nrpe_result_data(NSCAPI::returnUNKNOWN, _T("Unknown error"));
187        }
188}
189NRPEPacket NRPEClient::send_ssl(std::wstring host, int port, int timeout, NRPEPacket packet)
190{
191        simpleSSL::Socket socket(true);
192        socket.connect(host, port);
193        socket.sendAll(packet.getBuffer(), packet.getBufferLength());
194        simpleSocket::DataBuffer buffer;
195        socket.readAll(buffer);
196        packet.readFrom(buffer.getBuffer(), buffer.getLength());
197        return packet;
198}
199NRPEPacket NRPEClient::send_nossl(std::wstring host, int port, int timeout, NRPEPacket packet)
200{
201        simpleSocket::Socket socket(true);
202        socket.connect(host, port);
203        socket.sendAll(packet.getBuffer(), packet.getBufferLength());
204        simpleSocket::DataBuffer buffer;
205        socket.readAll(buffer);
206        packet.readFrom(buffer.getBuffer(), buffer.getLength());
207        return packet;
208}
209
210
211
212
213
214
215NSC_WRAPPERS_MAIN_DEF(gNRPEClient);
216NSC_WRAPPERS_IGNORE_MSG_DEF();
217NSC_WRAPPERS_HANDLE_CMD_DEF(gNRPEClient);
218NSC_WRAPPERS_HANDLE_CONFIGURATION(gNRPEClient);
219NSC_WRAPPERS_CLI_DEF(gNRPEClient);
220
221
222MODULE_SETTINGS_START(NRPEClient, _T("NRPE Listener configuration"), _T("..."))
223
224PAGE(_T("NRPE Listsner configuration"))
225
226ITEM_EDIT_TEXT(_T("port"), _T("This is the port the NRPEClient.dll will listen to."))
227ITEM_MAP_TO(_T("basic_ini_text_mapper"))
228OPTION(_T("section"), _T("NRPE"))
229OPTION(_T("key"), _T("port"))
230OPTION(_T("default"), _T("5666"))
231ITEM_END()
232
233ITEM_CHECK_BOOL(_T("allow_arguments"), _T("This option determines whether or not the NRPE daemon will allow clients to specify arguments to commands that are executed."))
234ITEM_MAP_TO(_T("basic_ini_bool_mapper"))
235OPTION(_T("section"), _T("NRPE"))
236OPTION(_T("key"), _T("allow_arguments"))
237OPTION(_T("default"), _T("false"))
238OPTION(_T("true_value"), _T("1"))
239OPTION(_T("false_value"), _T("0"))
240ITEM_END()
241
242ITEM_CHECK_BOOL(_T("allow_nasty_meta_chars"), _T("This might have security implications (depending on what you do with the options)"))
243ITEM_MAP_TO(_T("basic_ini_bool_mapper"))
244OPTION(_T("section"), _T("NRPE"))
245OPTION(_T("key"), _T("allow_nasty_meta_chars"))
246OPTION(_T("default"), _T("false"))
247OPTION(_T("true_value"), _T("1"))
248OPTION(_T("false_value"), _T("0"))
249ITEM_END()
250
251ITEM_CHECK_BOOL(_T("use_ssl"), _T("This option will enable SSL encryption on the NRPE data socket (this increases security somwhat."))
252ITEM_MAP_TO(_T("basic_ini_bool_mapper"))
253OPTION(_T("section"), _T("NRPE"))
254OPTION(_T("key"), _T("use_ssl"))
255OPTION(_T("default"), _T("true"))
256OPTION(_T("true_value"), _T("1"))
257OPTION(_T("false_value"), _T("0"))
258ITEM_END()
259
260PAGE_END()
261ADVANCED_PAGE(_T("Access configuration"))
262
263ITEM_EDIT_OPTIONAL_LIST(_T("Allow connection from:"), _T("This is the hosts that will be allowed to poll performance data from the NRPE server."))
264OPTION(_T("disabledCaption"), _T("Use global settings (defined previously)"))
265OPTION(_T("enabledCaption"), _T("Specify hosts for NRPE server"))
266OPTION(_T("listCaption"), _T("Add all IP addresses (not hosts) which should be able to connect:"))
267OPTION(_T("separator"), _T(","))
268OPTION(_T("disabled"), _T(""))
269ITEM_MAP_TO(_T("basic_ini_text_mapper"))
270OPTION(_T("section"), _T("NRPE"))
271OPTION(_T("key"), _T("allowed_hosts"))
272OPTION(_T("default"), _T(""))
273ITEM_END()
274
275PAGE_END()
276MODULE_SETTINGS_END()
Note: See TracBrowser for help on using the repository browser.