Changeset 96c1461 in nscp for modules/NRPEClient


Ignore:
Timestamp:
11/27/11 22:04:35 (18 months ago)
Author:
Michael Medin <michael@…>
Branches:
master, 0.4.0, 0.4.1, 0.4.2
Children:
9853bc3
Parents:
16198e3
Message:
  • Major refactoring in the command line interface
  • Added support for alias to many common module (command line) so: nscp eventlog (is the same as nscp client --module CheckEventLog)
  • Fixed issue with CheckEventLog message rendering and eventid
  • Refactored all Client modules to all support command line, commands and submissions.
  • Added uniform handling of "everything" to all Client plugins
  • Fixed SyslogClient to work "as advertised" (ie. all hardcoded stuff is removed)
  • Fixed utf8 issue with text strings (now have a working concept which needs to be implementd "all over the place")
  • Many issues and fixes related to clients.
  • Fixed so CheckEvent? log (insert) works much better (added new options)
Location:
modules/NRPEClient
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • modules/NRPEClient/CMakeLists.txt

    r2b2e9b8 r96c1461  
    1010  ${NSCP_INCLUDEDIR}/nrpe/packet.cpp 
    1111  ${NSCP_INCLUDEDIR}/socket/socket_helpers.cpp 
     12  ${NSCP_INCLUDEDIR}/client/command_line_parser.cpp 
    1213 
    1314  ${NSCP_DEF_PLUGIN_CPP} 
     
    2829    ${NSCP_INCLUDEDIR}/swap_bytes.hpp 
    2930    ${NSCP_INCLUDEDIR}/socket/socket_helpers.hpp 
     31    ${NSCP_INCLUDEDIR}/client/command_line_parser.hpp 
    3032 
    3133    ${NSCP_DEF_PLUGIN_HPP} 
  • modules/NRPEClient/NRPEClient.cpp

    rf7a074d r96c1461  
    2121#include "stdafx.h" 
    2222#include "NRPEClient.h" 
     23 
     24#include <time.h> 
    2325#include <strEx.h> 
    24 #include <time.h> 
    25 //#include <config.h> 
     26 
    2627#include <strEx.h> 
    2728#include <nrpe/client/socket.hpp> 
     
    2930#include <settings/client/settings_client.hpp> 
    3031 
    31  
    32 namespace setting_keys { 
    33  
    34   // NSClient Setting headlines 
    35   namespace nrpe { 
    36     DEFINE_PATH(SECTION, NRPE_SECTION_PROTOCOL); 
    37     //DESCRIBE_SETTING(SECTION, "NRPE SECTION", "Section for NRPE (NRPEListener.dll) (check_nrpe) protocol options."); 
    38  
    39  
    40     DEFINE_PATH(CH_SECTION, NRPE_CLIENT_HANDLER_SECTION); 
    41     //DESCRIBE_SETTING(CH_SECTION, "CLIENT HANDLER SECTION", "..."); 
    42  
    43     DEFINE_SETTING_S(ALLOWED_HOSTS, NRPE_SECTION_PROTOCOL, GENERIC_KEY_ALLOWED_HOSTS, ""); 
    44     DESCRIBE_SETTING(ALLOWED_HOSTS, "ALLOWED HOST ADDRESSES", "This is a comma-delimited list of IP address of hosts that are allowed to talk to NSClient deamon. If you leave this blank the global version will be used instead."); 
    45  
    46     DEFINE_SETTING_I(PORT, NRPE_SECTION_PROTOCOL, "port", 5666); 
    47     //DESCRIBE_SETTING(PORT, "NSCLIENT PORT NUMBER", "This is the port the NSClientListener.dll will listen to."); 
    48  
    49     DEFINE_SETTING_S(BINDADDR, NRPE_SECTION_PROTOCOL, GENERIC_KEY_BIND_TO, ""); 
    50     //DESCRIBE_SETTING(BINDADDR, "BIND TO ADDRESS", "Allows you to bind server to a specific local address. This has to be a dotted ip adress not a hostname. Leaving this blank will bind to all avalible IP adresses."); 
    51  
    52     DEFINE_SETTING_I(READ_TIMEOUT, NRPE_SECTION_PROTOCOL, GENERIC_KEY_SOCK_READ_TIMEOUT, 30); 
    53     //DESCRIBE_SETTING(READ_TIMEOUT, "SOCKET TIMEOUT", "Timeout when reading packets on incoming sockets. If the data has not arrived withint this time we will bail out."); 
    54  
    55     DEFINE_SETTING_I(LISTENQUE, NRPE_SECTION_PROTOCOL, GENERIC_KEY_SOCK_LISTENQUE, 0); 
    56     //DESCRIBE_SETTING_ADVANCED(LISTENQUE, "LISTEN QUEUE", "Number of sockets to queue before starting to refuse new incoming connections. This can be used to tweak the amount of simultaneous sockets that the server accepts."); 
    57  
    58     DEFINE_SETTING_I(THREAD_POOL, NRPE_SECTION_PROTOCOL, "thread pool", 10); 
    59     //DESCRIBE_SETTING_ADVANCED(THREAD_POOL, "THREAD POOL", ""); 
    60  
    61  
    62  
    63     DEFINE_SETTING_B(CACHE_ALLOWED, NRPE_SECTION_PROTOCOL, GENERIC_KEY_SOCK_CACHE_ALLOWED, false); 
    64     DESCRIBE_SETTING_ADVANCED(CACHE_ALLOWED, "ALLOWED HOSTS CACHING", "Used to cache looked up hosts if you check dynamic/changing hosts set this to false."); 
    65  
    66     //DEFINE_SETTING_B(KEYUSE_SSL, NRPE_SECTION_PROTOCOL, GENERIC_KEY_USE_SSL, true); 
    67     //DESCRIBE_SETTING(KEYUSE_SSL, "USE SSL SOCKET", "This option controls if SSL should be used on the socket."); 
    68  
    69     DEFINE_SETTING_I(PAYLOAD_LENGTH, NRPE_SECTION_PROTOCOL, "payload length", 1024); 
    70     //DESCRIBE_SETTING_ADVANCED(PAYLOAD_LENGTH, "PAYLOAD LENGTH", "Length of payload to/from the NRPE agent. This is a hard specific value so you have to \"configure\" (read recompile) your NRPE agent to use the same value for it to work."); 
    71  
    72     //DEFINE_SETTING_B(ALLOW_PERFDATA, NRPE_SECTION, "performance data", true); 
    73     //DESCRIBE_SETTING_ADVANCED(ALLOW_PERFDATA, "PERFORMANCE DATA", "Send performance data back to nagios (set this to 0 to remove all performance data)."); 
    74  
    75     //DEFINE_SETTING_I(CMD_TIMEOUT, NRPE_SECTION, "command timeout", 60); 
    76     //DESCRIBE_SETTING(CMD_TIMEOUT, "COMMAND TIMEOUT", "This specifies the maximum number of seconds that the NRPE daemon will allow plug-ins to finish executing before killing them off."); 
    77  
    78     DEFINE_SETTING_B(ALLOW_ARGS, NRPE_SECTION, "allow arguments", false); 
    79     //DESCRIBE_SETTING(ALLOW_ARGS, "COMMAND ARGUMENT PROCESSING", "This option determines whether or not the NRPE daemon will allow clients to specify arguments to commands that are executed."); 
    80  
    81     DEFINE_SETTING_B(ALLOW_NASTY, NRPE_SECTION, "allow nasy characters", false); 
    82     //DESCRIBE_SETTING(ALLOW_NASTY, "COMMAND ALLOW NASTY META CHARS", "This option determines whether or not the NRPE daemon will allow clients to specify nasty (as in |`&><'\"\\[]{}) characters in arguments."); 
    83  
    84   } 
    85 } 
    8632namespace sh = nscapi::settings_helper; 
    8733 
    88 NRPEClient::NRPEClient() : buffer_length_(0) { 
    89 } 
    90  
    91 NRPEClient::~NRPEClient() { 
    92 } 
    93  
     34/** 
     35 * Default c-tor 
     36 * @return  
     37 */ 
     38NRPEClient::NRPEClient() {} 
     39 
     40/** 
     41 * Default d-tor 
     42 * @return  
     43 */ 
     44NRPEClient::~NRPEClient() {} 
     45 
     46/** 
     47 * Load (initiate) module. 
     48 * Start the background collector thread and let it run until unloadModule() is called. 
     49 * @return true 
     50 */ 
    9451bool NRPEClient::loadModule() { 
    9552  return false; 
     
    9956  std::map<std::wstring,std::wstring> commands; 
    10057 
    101   try { 
    102  
    103     //"/settings/NRPE/client/handlers" 
     58  std::wstring certificate; 
     59  unsigned int timeout = 30, buffer_length = 1024; 
     60  bool use_ssl = true; 
     61  try { 
     62 
    10463    sh::settings_registry settings(get_settings_proxy()); 
    10564    settings.set_alias(_T("NRPE"), alias, _T("client")); 
    10665 
     66    target_path = settings.alias().get_settings_path(_T("targets")); 
     67 
    10768    settings.alias().add_path_to_settings() 
     69      (_T("NRPE CLIENT SECTION"), _T("Section for NRPE active/passive check module.")) 
    10870 
    10971      (_T("handlers"), sh::fun_values_path(boost::bind(&NRPEClient::add_command, this, _1, _2)),  
    11072      _T("CLIENT HANDLER SECTION"), _T("")) 
    11173 
    112       (_T("servers"), sh::fun_values_path(boost::bind(&NRPEClient::add_server, this, _1, _2)),  
    113       _T("REMOTE SERVER DEFINITIONS"), _T("")) 
    114  
     74      (_T("targets"), sh::fun_values_path(boost::bind(&NRPEClient::add_target, this, _1, _2)),  
     75      _T("REMOTE TARGET DEFINITIONS"), _T("")) 
    11576      ; 
    11677 
    11778    settings.alias().add_key_to_settings() 
    118  
    119       (_T("payload length"),  sh::uint_key(&buffer_length_, 1024), 
     79      (_T("channel"), sh::wstring_key(&channel_, _T("NRPE")), 
     80      _T("CHANNEL"), _T("The channel to listen to.")) 
     81 
     82      ; 
     83 
     84    settings.alias(_T("/targets/default")).add_key_to_settings() 
     85 
     86      (_T("timeout"), sh::uint_key(&timeout, 30), 
     87      _T("TIMEOUT"), _T("Timeout when reading/writing packets to/from sockets.")) 
     88 
     89      (_T("use ssl"), sh::bool_key(&use_ssl, true), 
     90      _T("ENABLE SSL ENCRYPTION"), _T("This option controls if SSL should be enabled.")) 
     91 
     92      (_T("certificate"), sh::wpath_key(&certificate, _T("${certificate-path}/nrpe_dh_512.pem")), 
     93      _T("SSL CERTIFICATE"), _T("")) 
     94 
     95      (_T("payload length"),  sh::uint_key(&buffer_length, 1024), 
    12096      _T("PAYLOAD LENGTH"), _T("Length of payload to/from the NRPE agent. This is a hard specific value so you have to \"configure\" (read recompile) your NRPE agent to use the same value for it to work.")) 
    121  
    12297      ; 
    123  
    12498 
    12599    settings.register_all(); 
    126100    settings.notify(); 
    127101 
     102    get_core()->registerSubmissionListener(get_id(), channel_); 
     103 
     104    if (!targets.has_target(_T("default"))) { 
     105      add_target(_T("default"), _T("default")); 
     106      targets.rebuild(); 
     107    } 
     108    nscapi::target_handler::optarget t = targets.find_target(_T("default")); 
     109    if (t) { 
     110      if (!t->has_option("certificate")) 
     111        t->options[_T("certificate")] = certificate; 
     112      if (!t->has_option("timeout")) 
     113        t->options[_T("timeout")] = strEx::itos(timeout); 
     114      if (!t->has_option("payload length")) 
     115        t->options[_T("payload length")] = strEx::itos(buffer_length); 
     116      if (!t->has_option("ssl")) 
     117        t->options[_T("ssl")] = use_ssl?_T("true"):_T("false"); 
     118      targets.add(*t); 
     119    } else { 
     120      NSC_LOG_ERROR(_T("Default target not found!")); 
     121    } 
     122 
     123  } catch (nscapi::nscapi_exception &e) { 
     124    NSC_LOG_ERROR_STD(_T("NSClient API exception: ") + utf8::to_unicode(e.what())); 
     125    return false; 
     126  } catch (std::exception &e) { 
     127    NSC_LOG_ERROR_STD(_T("Exception caught: ") + utf8::to_unicode(e.what())); 
     128    return false; 
    128129  } catch (...) { 
    129130    NSC_LOG_ERROR_STD(_T("Exception caught: <UNKNOWN EXCEPTION>")); 
    130131    return false; 
    131132  } 
    132  
    133   boost::filesystem::wpath p = GET_CORE()->getBasePath() + std::wstring(_T("/security/nrpe_dh_512.pem")); 
    134   cert_ = p.string(); 
    135   if (boost::filesystem::is_regular(p)) { 
    136     NSC_DEBUG_MSG_STD(_T("Using certificate: ") + cert_); 
    137   } else { 
    138     NSC_LOG_ERROR_STD(_T("Certificate not found: ") + cert_); 
    139   } 
    140  
    141133  return true; 
    142134} 
    143  
    144 void NRPEClient::add_options(po::options_description &desc, nrpe_connection_data &command_data) { 
    145   desc.add_options() 
    146     ("host,H", po::wvalue<std::wstring>(&command_data.host), "The address of the host running the NRPE daemon") 
    147     ("port,p", po::value<int>(&command_data.port), "The port on which the daemon is running (default=5666)") 
    148     ("command,c", po::wvalue<std::wstring>(&command_data.command), "The name of the command that the remote daemon should run") 
    149     ("timeout,t", po::value<int>(&command_data.timeout), "Number of seconds before connection times out (default=10)") 
    150     ("buffer-length,l", po::value<unsigned int>(&command_data.buffer_length), std::string("Length of payload (has to be same as on the server (default=" + to_string(buffer_length_) + ")").c_str()) 
    151     ("no-ssl,n", po::value<bool>(&command_data.no_ssl)->zero_tokens()->default_value(false), "Do not initial an ssl handshake with the server, talk in plaintext.") 
    152     ("arguments,a", po::wvalue<std::vector<std::wstring> >(&command_data.argument_vector), "list of arguments") 
    153     ; 
    154 } 
    155  
    156 void NRPEClient::add_server(std::wstring key, std::wstring args) { 
    157 } 
    158  
    159 void NRPEClient::add_command(std::wstring key, std::wstring args) { 
    160   try { 
    161  
    162     NRPEClient::nrpe_connection_data command_data; 
    163     boost::program_options::variables_map vm; 
    164  
    165     po::options_description desc("Allowed options"); 
    166     buffer_length_ = SETTINGS_GET_INT(nrpe::PAYLOAD_LENGTH); 
    167     add_options(desc, command_data); 
    168  
    169     po::positional_options_description p; 
    170     p.add("arguments", -1); 
    171  
    172     std::vector<std::wstring> list; 
    173     //explicit escaped_list_separator(Char e = '\\', Char c = ',',Char q = '\"') 
    174     boost::escaped_list_separator<wchar_t> sep(L'\\', L' ', L'\"'); 
    175     typedef boost::tokenizer<boost::escaped_list_separator<wchar_t>,std::wstring::const_iterator, std::wstring > tokenizer_t; 
    176     tokenizer_t tok(args, sep); 
    177     for(tokenizer_t::iterator beg=tok.begin(); beg!=tok.end();++beg){ 
    178       list.push_back(*beg); 
    179     } 
    180  
    181     po::wparsed_options parsed = po::basic_command_line_parser<wchar_t>(list).options(desc).positional(p).run(); 
    182     po::store(parsed, vm); 
    183     po::notify(vm); 
    184     command_data.parse_arguments(); 
    185  
    186     NSC_DEBUG_MSG_STD(_T("Added NRPE Client: ") + key.c_str() + _T(" = ") + command_data.toString()); 
    187     commands[key.c_str()] = command_data; 
    188  
    189     register_command(key.c_str(), command_data.toString()); 
    190  
     135std::string get_command(std::string alias, std::string command = "") { 
     136  if (!alias.empty()) 
     137    return alias;  
     138  if (!command.empty()) 
     139    return command;  
     140  return "_NRPE_CHECK"; 
     141} 
     142 
     143////////////////////////////////////////////////////////////////////////// 
     144// Settings helpers 
     145// 
     146 
     147void NRPEClient::add_target(std::wstring key, std::wstring arg) { 
     148  try { 
     149    nscapi::target_handler::target t = targets.add(get_settings_proxy(), target_path , key, arg); 
     150    if (t.has_option(_T("certificate"))) { 
     151      boost::filesystem::wpath p = t.options[_T("certificate")]; 
     152      if (!boost::filesystem::is_regular(p)) { 
     153        p = get_core()->getBasePath() / p; 
     154        t.options[_T("certificate")] = utf8::cvt<std::wstring>(p.string()); 
     155        targets.add(t); 
     156      } 
     157      if (boost::filesystem::is_regular(p)) { 
     158        NSC_DEBUG_MSG_STD(_T("Using certificate: ") + p.string()); 
     159      } else { 
     160        NSC_LOG_ERROR_STD(_T("Certificate not found: ") + p.string()); 
     161      } 
     162    } 
     163  } catch (...) { 
     164    NSC_LOG_ERROR_STD(_T("Failed to add target: ") + key); 
     165  } 
     166} 
     167 
     168void NRPEClient::add_command(std::wstring name, std::wstring args) { 
     169  try { 
     170    std::wstring key = commands.add_command(name, args); 
     171    if (!key.empty()) 
     172      register_command(key.c_str(), _T("NRPE relay for: ") + name); 
    191173  } catch (boost::program_options::validation_error &e) { 
    192     NSC_LOG_ERROR_STD(_T("Could not parse: ") + key.c_str() + strEx::string_to_wstring(e.what())); 
     174    NSC_LOG_ERROR_STD(_T("Could not add command ") + name + _T(": ") + utf8::to_unicode(e.what())); 
    193175  } catch (...) { 
    194     NSC_LOG_ERROR_STD(_T("Could not parse: ") + key.c_str()); 
    195   } 
    196 } 
    197  
     176    NSC_LOG_ERROR_STD(_T("Could not add command ") + name); 
     177  } 
     178} 
     179 
     180/** 
     181 * Unload (terminate) module. 
     182 * Attempt to stop the background processing thread. 
     183 * @return true if successfully, false if not (if not things might be bad) 
     184 */ 
    198185bool NRPEClient::unloadModule() { 
    199186  return true; 
    200187} 
    201188 
    202 bool NRPEClient::hasCommandHandler() { 
    203   return true; 
    204 } 
    205 bool NRPEClient::hasMessageHandler() { 
    206   return false; 
    207 } 
    208189NSCAPI::nagiosReturn NRPEClient::handleCommand(const std::wstring &target, const std::wstring &command, std::list<std::wstring> &arguments, std::wstring &message, std::wstring &perf) { 
    209   command_list::const_iterator cit = commands.find(strEx::blindstr(command.c_str())); 
    210   if (cit == commands.end()) 
     190  std::wstring cmd = client::command_line_parser::parse_command(command, _T("nrpe")); 
     191 
     192  client::configuration config; 
     193  setup(config); 
     194  if (cmd == _T("query")) 
     195    return client::command_line_parser::query(config, cmd, arguments, message, perf); 
     196  if (cmd == _T("submit")) { 
     197    boost::tuple<int,std::wstring> result = client::command_line_parser::simple_submit(config, cmd, arguments); 
     198    message = result.get<1>(); 
     199    return result.get<0>(); 
     200  } 
     201  if (cmd == _T("exec")) { 
     202    return client::command_line_parser::exec(config, cmd, arguments, message); 
     203  } 
     204  return commands.exec_simple(config, target, command, arguments, message, perf); 
     205} 
     206 
     207int NRPEClient::commandLineExec(const std::wstring &command, std::list<std::wstring> &arguments, std::wstring &result) { 
     208  std::wstring cmd = client::command_line_parser::parse_command(command, _T("nrpe")); 
     209  if (!client::command_line_parser::is_command(cmd)) 
    211210    return NSCAPI::returnIgnored; 
    212211 
    213   std::wstring args = (*cit).second.arguments; 
    214   if (SETTINGS_GET_BOOL(nrpe::ALLOW_ARGS) == 1) { 
    215     int i=1; 
    216     BOOST_FOREACH(std::wstring arg, arguments) 
    217     { 
    218       if (SETTINGS_GET_INT(nrpe::ALLOW_NASTY) == 0) { 
    219         if (arg.find_first_of(NASTY_METACHARS_W) != std::wstring::npos) { 
    220           NSC_LOG_ERROR(_T("Request string contained illegal metachars!")); 
    221           return NSCAPI::returnIgnored; 
    222         } 
     212  client::configuration config; 
     213  setup(config); 
     214  return client::command_line_parser::commandLineExec(config, cmd, arguments, result); 
     215} 
     216 
     217NSCAPI::nagiosReturn NRPEClient::handleRAWNotification(const wchar_t* channel, std::string request, std::string &response) { 
     218  try { 
     219    client::configuration config; 
     220    setup(config); 
     221 
     222    if (!client::command_line_parser::relay_submit(config, request, response)) { 
     223      NSC_LOG_ERROR_STD(_T("Failed to submit message...")); 
     224      return NSCAPI::hasFailed; 
     225    } 
     226    return NSCAPI::isSuccess; 
     227  } catch (std::exception &e) { 
     228    NSC_LOG_ERROR_STD(_T("Failed to send data: ") + utf8::to_unicode(e.what())); 
     229    return NSCAPI::hasFailed; 
     230  } catch (...) { 
     231    NSC_LOG_ERROR_STD(_T("Failed to send data: UNKNOWN")); 
     232    return NSCAPI::hasFailed; 
     233  } 
     234} 
     235 
     236////////////////////////////////////////////////////////////////////////// 
     237// Parser setup/Helpers 
     238// 
     239 
     240void NRPEClient::add_local_options(po::options_description &desc, client::configuration::data_type data) { 
     241  desc.add_options() 
     242    ("certificate,c", po::value<std::string>()->notifier(boost::bind(&nscapi::functions::destination_container::set_string_data, &data->recipient, "certificate", _1)),  
     243      "Length of payload (has to be same as on the server)") 
     244 
     245    ("buffer-length,l", po::value<unsigned int>()->notifier(boost::bind(&nscapi::functions::destination_container::set_int_data, &data->recipient, "payload length", _1)),  
     246      "Length of payload (has to be same as on the server)") 
     247 
     248    ("no-ssl,n", po::value<bool>()->zero_tokens()->default_value(false)->notifier(boost::bind(&nscapi::functions::destination_container::set_bool_data, &data->recipient, "no ssl", _1)),  
     249      "Do not initial an ssl handshake with the server, talk in plaintext.") 
     250    ; 
     251} 
     252 
     253void NRPEClient::setup(client::configuration &config) { 
     254  boost::shared_ptr<clp_handler_impl> handler = boost::shared_ptr<clp_handler_impl>(new clp_handler_impl(this)); 
     255  add_local_options(config.local, config.data); 
     256 
     257  net::wurl url; 
     258  url.protocol = _T("nrpe"); 
     259  url.port = 5666; 
     260  nscapi::target_handler::optarget opt = targets.find_target(_T("default")); 
     261  if (opt) { 
     262    nscapi::target_handler::target t = *opt; 
     263    url.host = t.host; 
     264    if (t.has_option("port")) { 
     265      try { 
     266        url.port = strEx::stoi(t.options[_T("port")]); 
     267      } catch (...) {} 
     268    } 
     269    std::string keys[] = {"certificate", "timeout", "payload length", "ssl"}; 
     270    BOOST_FOREACH(std::string s, keys) { 
     271      config.data->recipient.data[s] = utf8::cvt<std::string>(t.options[utf8::cvt<std::wstring>(s)]); 
     272    } 
     273  } 
     274  config.data->recipient.id = "default"; 
     275  config.data->recipient.address = utf8::cvt<std::string>(url.to_string()); 
     276  config.data->host_self.id = "self"; 
     277  //config.data->host_self.host = hostname_; 
     278 
     279  config.target_lookup = handler; 
     280  config.handler = handler; 
     281} 
     282 
     283NRPEClient::connection_data NRPEClient::parse_header(const ::Plugin::Common_Header &header) { 
     284  nscapi::functions::destination_container recipient; 
     285  nscapi::functions::parse_destination(header, header.recipient_id(), recipient, true); 
     286  return connection_data(recipient); 
     287} 
     288 
     289////////////////////////////////////////////////////////////////////////// 
     290// Parser implementations 
     291// 
     292 
     293int NRPEClient::clp_handler_impl::query(client::configuration::data_type data, ::Plugin::Common_Header* header, const std::string &request, std::string &reply) { 
     294  NSCAPI::nagiosReturn ret = NSCAPI::returnOK; 
     295  try { 
     296    Plugin::QueryRequestMessage request_message; 
     297    request_message.ParseFromString(request); 
     298    connection_data con = parse_header(*header); 
     299 
     300    Plugin::QueryResponseMessage response_message; 
     301    nscapi::functions::create_simple_header(response_message.mutable_header()); // TODO copy request header (inverted) 
     302 
     303    for (int i=0;i<request_message.payload_size();i++) { 
     304      std::string command = get_command(request_message.payload(i).alias(), request_message.payload(i).command()); 
     305      std::string data = command; 
     306      for (int a=0;a<request_message.payload(i).arguments_size();a++) { 
     307        data += "!" + request_message.payload(i).arguments(a); 
    223308      } 
    224       strEx::replace(args, _T("$ARG") + strEx::itos(i++) + _T("$"), arg); 
    225     } 
    226   } 
    227  
    228   NSC_DEBUG_MSG_STD(_T("Rewrote command arguments: ") + args); 
    229   nrpe_result_data r = execute_nrpe_command((*cit).second, args); 
    230   message = r.text; 
    231   return r.result; 
    232 } 
    233  
    234 int NRPEClient::commandLineExec(const std::wstring &command, std::list<std::wstring> &arguments, std::wstring &result) { 
    235   if (command != _T("query_nrpe") && command != _T("help")) 
    236     return NSCAPI::returnIgnored; 
    237   try { 
    238     NRPEClient::nrpe_connection_data command_data; 
    239     boost::program_options::variables_map vm; 
    240  
    241     po::options_description desc("Allowed options"); 
    242     buffer_length_ = SETTINGS_GET_INT(nrpe::PAYLOAD_LENGTH); 
    243     add_options(desc, command_data); 
    244  
    245     std::vector<std::wstring> vargs(arguments.begin(), arguments.end()); 
    246     po::positional_options_description p; 
    247     p.add("arguments", -1); 
    248     po::wparsed_options parsed = po::basic_command_line_parser<wchar_t>(vargs).options(desc).positional(p).run(); 
    249     po::store(parsed, vm); 
    250     po::notify(vm); 
    251     command_data.parse_arguments(); 
    252     if (command == _T("help")) { 
    253       std::stringstream ss; 
    254       ss << "NRPEClient Command line syntax for command: query" << std::endl;; 
    255       ss << desc; 
    256       result = utf8::cvt<std::wstring>(ss.str()); 
    257       return NSCAPI::returnOK; 
    258     } 
    259  
    260     nrpe_result_data res = execute_nrpe_command(command_data, command_data.arguments); 
    261     result = res.text; 
    262     return res.result; 
    263   } catch (boost::program_options::validation_error &e) { 
    264     result = _T("Error: ") + utf8::cvt<std::wstring>(e.what()); 
     309      boost::tuple<int,std::wstring> ret = instance->send(con, data); 
     310      std::pair<std::wstring,std::wstring> rdata = strEx::split(ret.get<1>(), _T("|")); 
     311      nscapi::functions::append_simple_query_response_payload(response_message.add_payload(), utf8::cvt<std::wstring>(command), ret.get<0>(), rdata.first, rdata.second); 
     312    } 
     313    response_message.SerializeToString(&reply); 
     314    return NSCAPI::isSuccess; 
     315  } catch (std::exception &e) { 
     316    NSC_LOG_ERROR_STD(_T("Exception: ") + utf8::to_unicode(e.what())); 
     317    nscapi::functions::create_simple_query_response(_T("command"), NSCAPI::returnUNKNOWN, _T("Exception: ") + utf8::to_unicode(e.what()), _T(""), reply); 
    265318    return NSCAPI::returnUNKNOWN; 
    266   } catch (...) { 
    267     result = _T("Unknown exception parsing command line"); 
    268     return NSCAPI::returnUNKNOWN; 
    269   } 
    270   return NSCAPI::returnUNKNOWN; 
    271 } 
    272 NRPEClient::nrpe_result_data NRPEClient::execute_nrpe_command(nrpe_connection_data con, std::wstring arguments) { 
    273   try { 
     319  } 
     320} 
     321 
     322int NRPEClient::clp_handler_impl::submit(client::configuration::data_type data, ::Plugin::Common_Header* header, const std::string &request, std::string &reply) { 
     323  std::wstring channel; 
     324  try { 
     325    Plugin::SubmitRequestMessage message; 
     326    message.ParseFromString(request); 
     327    connection_data con = parse_header(*header); 
     328    channel = utf8::cvt<std::wstring>(message.channel()); 
     329     
     330    for (int i=0;i<message.payload_size();++i) { 
     331      std::string command = get_command(message.payload(i).alias(), message.payload(i).command()); 
     332      std::string data = command; 
     333      for (int a=0;a<message.payload(i).arguments_size();a++) { 
     334        data += "!" + message.payload(i).arguments(i); 
     335      } 
     336      boost::tuple<int,std::wstring> ret = instance->send(con, data); 
     337      // TODO: Change this to append! 
     338      nscapi::functions::create_simple_submit_response(channel, utf8::cvt<std::wstring>(command), ret.get<0>(), _T("Message submitted successfully: ") + ret.get<1>(), reply); 
     339      return NSCAPI::isSuccess; 
     340    } 
     341    nscapi::functions::create_simple_submit_response(channel, _T("UNKNOWN"), NSCAPI::returnUNKNOWN, _T("Empty message was submitted"), reply); 
     342    return NSCAPI::isSuccess; 
     343  } catch (std::exception &e) { 
     344    NSC_LOG_ERROR_STD(_T("Exception: ") + utf8::to_unicode(e.what())); 
     345    nscapi::functions::create_simple_submit_response(channel, _T("UNKNOWN"), NSCAPI::returnUNKNOWN, utf8::to_unicode(e.what()), reply); 
     346    return NSCAPI::hasFailed; 
     347  }  
     348} 
     349 
     350int NRPEClient::clp_handler_impl::exec(client::configuration::data_type data, ::Plugin::Common_Header* header, const std::string &request, std::string &reply) { 
     351  NSCAPI::nagiosReturn ret = NSCAPI::returnOK; 
     352  try { 
     353    Plugin::ExecuteRequestMessage request_message; 
     354    request_message.ParseFromString(request); 
     355    connection_data con = parse_header(*header); 
     356 
     357    for (int i=0;i<request_message.payload_size();i++) { 
     358      std::string command = get_command(request_message.payload(i).command()); 
     359      std::string data = command; 
     360      for (int a=0;a<request_message.payload(i).arguments_size();a++) { 
     361        data += "!" + request_message.payload(i).arguments(a); 
     362      } 
     363      boost::tuple<int,std::wstring> ret = instance->send(con, data); 
     364      nscapi::functions::create_simple_exec_response(utf8::cvt<std::wstring>(command), ret.get<0>(), ret.get<1>(), reply); 
     365    } 
     366    return NSCAPI::isSuccess; 
     367  } catch (std::exception &e) { 
     368    NSC_LOG_ERROR_STD(_T("Exception: ") + utf8::to_unicode(e.what())); 
     369    nscapi::functions::create_simple_exec_response(_T("command"), NSCAPI::returnUNKNOWN, _T("Exception: ") + utf8::to_unicode(e.what()), reply); 
     370    return NSCAPI::hasFailed; 
     371  } 
     372} 
     373 
     374////////////////////////////////////////////////////////////////////////// 
     375// Protocol implementations 
     376// 
     377 
     378boost::tuple<int,std::wstring> NRPEClient::send(connection_data con, const std::string data) { 
     379  try { 
     380    NSC_DEBUG_MSG_STD(_T("NRPE Connection details: ") + con.to_wstring()); 
     381    NSC_DEBUG_MSG_STD(_T("NRPE data: ") + utf8::cvt<std::wstring>(data)); 
    274382    nrpe::packet packet; 
    275     if (!con.no_ssl) { 
     383    if (con.use_ssl) { 
    276384#ifdef USE_SSL 
    277       packet = send_ssl(con.host, con.port, con.timeout, nrpe::packet::make_request(con.get_cli(arguments), con.buffer_length)); 
     385      packet = send_ssl(con.cert, con.host, con.port, con.timeout, nrpe::packet::make_request(utf8::cvt<std::wstring>(data), con.buffer_length)); 
    278386#else 
    279       NSC_LOG_ERROR_STD(_T("SSL not avalible (not compiled with USE_SSL)")); 
    280       return nrpe_result_data(NSCAPI::returnUNKNOWN, _T("SSL support not available (compiled without USE_SSL)!")); 
     387      NSC_LOG_ERROR_STD(_T("SSL not avalible (compiled without USE_SSL)")); 
     388      return boost::tie(NSCAPI::returnUNKNOWN, _T("SSL support not available (compiled without USE_SSL)")); 
    281389#endif 
    282390    } else 
    283       packet = send_nossl(con.host, con.port, con.timeout, nrpe::packet::make_request(con.get_cli(arguments), con.buffer_length)); 
    284     return nrpe_result_data(packet.getResult(), packet.getPayload()); 
     391      packet = send_nossl(con.host, con.port, con.timeout, nrpe::packet::make_request(utf8::cvt<std::wstring>(data), con.buffer_length)); 
     392    return boost::make_tuple(static_cast<int>(packet.getResult()), packet.getPayload()); 
    285393  } catch (nrpe::nrpe_packet_exception &e) { 
    286     return nrpe_result_data(NSCAPI::returnUNKNOWN, _T("NRPE Packet errro: ") + e.wwhat()); 
     394    return boost::tie(NSCAPI::returnUNKNOWN, _T("NRPE Packet errro: ") + e.wwhat()); 
    287395  } catch (std::runtime_error &e) { 
    288     NSC_LOG_ERROR_STD(_T("Socket error: ") + utf8::cvt<std::wstring>(e.what())); 
    289     return nrpe_result_data(NSCAPI::returnUNKNOWN, _T("Socket error: ") + utf8::cvt<std::wstring>(e.what())); 
     396    NSC_LOG_ERROR_STD(_T("Socket error: ") + utf8::to_unicode(e.what())); 
     397    return boost::tie(NSCAPI::returnUNKNOWN, _T("Socket error: ") + utf8::to_unicode(e.what())); 
     398  } catch (std::exception &e) { 
     399    NSC_LOG_ERROR_STD(_T("Error: ") + utf8::to_unicode(e.what())); 
     400    return boost::tie(NSCAPI::returnUNKNOWN, _T("Error: ") + utf8::to_unicode(e.what())); 
    290401  } catch (...) { 
    291     return nrpe_result_data(NSCAPI::returnUNKNOWN, _T("Unknown error -- REPORT THIS!")); 
     402    return boost::tie(NSCAPI::returnUNKNOWN, _T("Unknown error -- REPORT THIS!")); 
    292403  } 
    293404} 
     
    295406 
    296407#ifdef USE_SSL 
    297 nrpe::packet NRPEClient::send_ssl(std::wstring host, int port, int timeout, nrpe::packet packet) { 
     408nrpe::packet NRPEClient::send_ssl(std::string cert, std::string host, std::string port, int timeout, nrpe::packet packet) { 
    298409  boost::asio::io_service io_service; 
    299410  boost::asio::ssl::context ctx(io_service, boost::asio::ssl::context::sslv23); 
    300411  SSL_CTX_set_cipher_list(ctx.impl(), "ADH"); 
    301   ctx.use_tmp_dh_file(to_string(cert_)); 
     412  ctx.use_tmp_dh_file(to_string(cert)); 
    302413  ctx.set_verify_mode(boost::asio::ssl::context::verify_none); 
    303414  nrpe::client::ssl_socket socket(io_service, ctx, host, port); 
    304415  socket.send(packet, boost::posix_time::seconds(timeout)); 
    305   nrpe::packet ret = socket.recv(packet, boost::posix_time::seconds(timeout)); 
    306   return ret; 
     416  return socket.recv(packet, boost::posix_time::seconds(timeout)); 
    307417} 
    308418#endif 
    309419 
    310 nrpe::packet NRPEClient::send_nossl(std::wstring host, int port, int timeout, nrpe::packet packet) { 
     420nrpe::packet NRPEClient::send_nossl(std::string host, std::string port, int timeout, nrpe::packet packet) { 
    311421  boost::asio::io_service io_service; 
    312422  nrpe::client::socket socket(io_service, host, port); 
     
    320430NSC_WRAPPERS_HANDLE_CMD_DEF(); 
    321431NSC_WRAPPERS_CLI_DEF(); 
    322  
     432NSC_WRAPPERS_HANDLE_NOTIFICATION_DEF(); 
     433 
  • modules/NRPEClient/NRPEClient.def

    r291548e r96c1461  
    1515  NSCommandLineExec 
    1616  NSDeleteBuffer 
     17  NSHandleNotification 
     18  NSHasNotificationHandler 
  • modules/NRPEClient/NRPEClient.h

    ra78a985 r96c1461  
    1919*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             * 
    2020***************************************************************************/ 
     21#pragma once 
     22 
     23#include <boost/tuple/tuple.hpp> 
     24 
     25#include <client/command_line_parser.hpp> 
     26#include <nscapi/targets.hpp> 
     27 
     28#include <nrpe/packet.hpp> 
    2129 
    2230NSC_WRAPPERS_MAIN(); 
    2331NSC_WRAPPERS_CLI(); 
    24  
    25  
    26 #include <map> 
    27 #include <nrpe/packet.hpp> 
     32NSC_WRAPPERS_CHANNELS(); 
    2833 
    2934namespace po = boost::program_options; 
     
    3136class NRPEClient : public nscapi::impl::simple_command_handler, public nscapi::impl::simple_plugin, public nscapi::impl::simple_command_line_exec { 
    3237private: 
    33   typedef enum { 
    34     inject, script, script_dir, 
    35   } command_type; 
    36   struct nrpe_connection_data { 
    37     std::wstring host; 
    38     std::wstring command; 
    39     std::wstring arguments; 
    40     std::wstring command_line; 
    41     std::vector<std::wstring> argument_vector; 
    42     int port; 
     38 
     39  std::wstring channel_; 
     40  std::wstring target_path; 
     41 
     42  nscapi::target_handler targets; 
     43  client::command_manager commands; 
     44 
     45  struct connection_data { 
     46    std::string cert; 
     47    std::string host; 
     48    std::string port; 
    4349    int timeout; 
    44     unsigned int buffer_length; 
    45     bool no_ssl; 
    46     nrpe_connection_data(unsigned int buffer_length_ = 1024)  
    47       : host(_T("127.0.0.1")),  
    48       port(5666),  
    49       timeout(10),  
    50       no_ssl(false),  
    51       buffer_length(buffer_length_)  
    52     {} 
    53     void parse_arguments() { 
    54       for (std::vector<std::wstring>::const_iterator cit = argument_vector.begin(); cit != argument_vector.end(); ++cit) { 
    55         if (!arguments.empty()) 
    56           arguments += _T("!"); 
    57         arguments += *cit; 
    58       } 
     50    int buffer_length; 
     51    bool use_ssl; 
     52 
     53    connection_data(nscapi::functions::destination_container recipient) { 
     54      cert = recipient.get_string_data("certificate"); 
     55      timeout = recipient.get_int_data("timeout", 30); 
     56      buffer_length = recipient.get_int_data("payload length", 1024); 
     57      use_ssl = recipient.get_bool_data("ssl"); 
     58      if (recipient.has_data("no ssl")) 
     59        use_ssl = !recipient.get_bool_data("no ssl"); 
     60 
     61      net::url url = recipient.get_url(5666); 
     62      host = url.host; 
     63      port = url.get_port(); 
    5964    } 
    60     std::wstring get_cli(std::wstring arguments_) { 
    61       if (command_line.empty()) { 
    62         command_line = command; 
    63         if (command_line.empty()) 
    64           command_line = _T("_NRPE_CHECK"); 
    65         if (!arguments_.empty()) 
    66           command_line += _T("!") + arguments_; 
    67         else if (!arguments.empty()) 
    68           command_line += _T("!") + arguments; 
    69       } 
    70       return command_line; 
    71     } 
    72     std::wstring toString() { 
     65 
     66    std::wstring to_wstring() const { 
    7367      std::wstringstream ss; 
    74       ss << _T("host: ") << host; 
    75       ss << _T(", port: ") << port; 
     68      ss << _T("host: ") << utf8::cvt<std::wstring>(host); 
     69      ss << _T(", port: ") << utf8::cvt<std::wstring>(port); 
    7670      ss << _T(", timeout: ") << timeout; 
    77       ss << _T(", no_ssl: ") << no_ssl; 
    7871      ss << _T(", buffer_length: ") << buffer_length; 
    79       ss << _T(", command: ") << command; 
    80       ss << _T(", argument: ") << arguments; 
     72      ss << _T(", use_ssl: ") << use_ssl; 
     73      ss << _T(", certificate: ") << utf8::cvt<std::wstring>(cert); 
    8174      return ss.str(); 
    8275    } 
    8376  }; 
    84   struct nrpe_result_data { 
    85     nrpe_result_data() {} 
    86     nrpe_result_data(int result_, std::wstring text_) : result(result_), text(text_) {} 
    87     std::wstring text; 
    88     int result; 
     77 
     78  struct clp_handler_impl : public client::clp_handler, client::target_lookup_interface { 
     79 
     80    NRPEClient *instance; 
     81    clp_handler_impl(NRPEClient *instance) : instance(instance) {} 
     82 
     83    int query(client::configuration::data_type data, ::Plugin::Common_Header* header, const std::string &request, std::string &reply); 
     84    int submit(client::configuration::data_type data, ::Plugin::Common_Header* header, const std::string &request, std::string &reply); 
     85    int exec(client::configuration::data_type data, ::Plugin::Common_Header* header, const std::string &request, std::string &reply); 
     86 
     87    virtual nscapi::functions::destination_container lookup_target(std::wstring &id) { 
     88      nscapi::functions::destination_container ret; 
     89      nscapi::target_handler::optarget t = instance->targets.find_target(id); 
     90      if (t) { 
     91        if (!t->alias.empty()) 
     92          ret.id = utf8::cvt<std::string>(t->alias); 
     93        if (!t->host.empty()) 
     94          ret.host = utf8::cvt<std::string>(t->host); 
     95        if (t->has_option("address")) 
     96          ret.address = utf8::cvt<std::string>(t->options[_T("address")]); 
     97        else  
     98          ret.address = utf8::cvt<std::string>(t->host); 
     99        BOOST_FOREACH(const nscapi::target_handler::target::options_type::value_type &kvp, t->options) { 
     100          ret.data[utf8::cvt<std::string>(kvp.first)] = utf8::cvt<std::string>(kvp.second); 
     101        } 
     102      } 
     103      return ret; 
     104    } 
    89105  }; 
    90   typedef std::map<strEx::blindstr, nrpe_connection_data> command_list; 
    91   command_list commands; 
    92   unsigned int buffer_length_; 
    93   std::wstring cert_; 
     106 
    94107 
    95108public: 
     
    101114  bool unloadModule(); 
    102115 
    103  
     116  /** 
     117  * Return the module name. 
     118  * @return The module name 
     119  */ 
    104120  static std::wstring getModuleName() { 
    105121#ifdef USE_SSL 
     
    109125#endif 
    110126  } 
     127  /** 
     128  * Module version 
     129  * @return module version 
     130  */ 
    111131  static nscapi::plugin_wrapper::module_version getModuleVersion() { 
    112     nscapi::plugin_wrapper::module_version version = {0, 0, 1 }; 
     132    nscapi::plugin_wrapper::module_version version = {0, 4, 0 }; 
    113133    return version; 
    114134  } 
    115135  static std::wstring getModuleDescription() { 
    116136    return _T("A simple client for checking remote NRPE servers (think proxy).\n") 
    117 #ifndef USE_BOOST 
    118     _T("BOOST support is missing (this is probably very bad)!\n") 
    119 #endif 
    120137#ifndef USE_SSL 
    121138    _T("SSL support is missing (so you cant use encryption)!") 
     
    124141  } 
    125142 
    126   bool hasCommandHandler(); 
    127   bool hasMessageHandler(); 
     143  bool hasCommandHandler() { return true; }; 
     144  bool hasMessageHandler() { return true; }; 
     145  bool hasNotificationHandler() { return true; }; 
     146  NSCAPI::nagiosReturn handleRAWNotification(const wchar_t* channel, std::string request, std::string &response); 
    128147  NSCAPI::nagiosReturn handleCommand(const std::wstring &target, const std::wstring &command, std::list<std::wstring> &arguments, std::wstring &message, std::wstring &perf); 
    129148  int commandLineExec(const std::wstring &command, std::list<std::wstring> &arguments, std::wstring &result); 
    130   std::wstring getConfigurationMeta(); 
    131149 
    132150private: 
    133   nrpe_result_data  execute_nrpe_command(nrpe_connection_data con, std::wstring arguments); 
    134   nrpe::packet send_nossl(std::wstring host, int port, int timeout, nrpe::packet packet); 
    135   nrpe::packet send_ssl(std::wstring host, int port, int timeout, nrpe::packet packet); 
    136   void add_options(po::options_description &desc, nrpe_connection_data &command_data); 
     151  boost::tuple<int,std::wstring> send(connection_data con, std::string data); 
     152  static nrpe::packet send_nossl(std::string host, std::string port, int timeout, nrpe::packet packet); 
     153  static nrpe::packet send_ssl(std::string cert, std::string host, std::string port, int timeout, nrpe::packet packet); 
     154 
     155  static connection_data parse_header(const ::Plugin::Common_Header &header); 
    137156 
    138157private: 
     158  void add_local_options(po::options_description &desc, client::configuration::data_type data); 
     159  void setup(client::configuration &config); 
    139160  void add_command(std::wstring key, std::wstring args); 
    140   void add_server(std::wstring key, std::wstring args); 
     161  void add_target(std::wstring key, std::wstring args); 
    141162 
    142163}; 
Note: See TracChangeset for help on using the changeset viewer.