Changeset 1a5449e in nscp for modules/NRPEListener


Ignore:
Timestamp:
03/26/05 23:29:52 (8 years ago)
Author:
Michael Medin <michael@…>
Branches:
master, 0.4.0, 0.4.1, 0.4.2, stable
Children:
452fd41
Parents:
c4f6204
Message:

+ NRPE Support (very basic, no encryption, and nothing fancy)

  • Socket classes rewritten + Added NSCModuleHelper::getSettingsSection to the API
Location:
modules/NRPEListener
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • modules/NRPEListener/NRPEListener.cpp

    r1eef1ee r1a5449e  
    2020} 
    2121 
     22#define DEFAULT_NRPE_PORT 5666 
     23 
    2224 
    2325bool NRPEListener::loadModule() { 
    24   socketThreadManager.createThread(NULL); 
     26  timeout = NSCModuleHelper::getSettingsInt("NRPE", "commandTimeout", 60); 
     27  std::list<std::string> commands = NSCModuleHelper::getSettingsSection("NRPE Handlers"); 
     28  std::list<std::string>::iterator it; 
     29  for (it = commands.begin(); it != commands.end(); it++) { 
     30    strEx::token t = strEx::getToken(*it, '='); 
     31    if (t.first.substr(0,7) == "command") { 
     32      strEx::token t2 = strEx::getToken(t.first, '['); 
     33      t2 = strEx::getToken(t2.second, ']'); 
     34      t.first = t2.first; 
     35    } 
     36    if (t.first.empty() || t.second.empty()) { 
     37      NSC_LOG_ERROR_STD("Invalid command definition: " + (*it)); 
     38    } else 
     39      addCommand(t.first, t.second); 
     40  } 
     41 
     42  simpleSocket::Socket::WSAStartup(); 
     43  socket.StartListen(NSCModuleHelper::getSettingsInt("NRPE", "port", DEFAULT_NRPE_PORT)); 
    2544  return true; 
    2645} 
    2746bool NRPEListener::unloadModule() { 
    28   socketThreadManager.exitThread(); 
     47  socket.close(); 
     48  simpleSocket::Socket::WSACleanup(); 
    2949  return true; 
    3050} 
    3151 
    3252std::string NRPEListener::getModuleName() { 
    33   return "CheckDisk Various Disk related checks."; 
     53  return "NRPE module."; 
    3454} 
    3555NSCModuleWrapper::module_version NRPEListener::getModuleVersion() { 
     
    4767 
    4868NSCAPI::nagiosReturn NRPEListener::handleCommand(const std::string command, const unsigned int argLen, char **char_args, std::string &message, std::string &perf) { 
    49   return NSCAPI::returnIgnored; 
     69  commandList::iterator it = commands.find(command); 
     70  if (it == commands.end()) 
     71    return NSCAPI::returnIgnored; 
     72 
     73  std::string str = (*it).second; 
     74  if (NSCModuleHelper::getSettingsInt("NRPE", "AllowArguments", 0) == 0) { 
     75    arrayBuffer::arrayList arr = arrayBuffer::arrayBuffer2list(argLen, char_args); 
     76    arrayBuffer::arrayList::const_iterator cit = arr.begin(); 
     77    int i=0; 
     78 
     79    for (;cit!=arr.end();it++,i++) { 
     80      strEx::replace(str, "ARG" + strEx::itos(i), (*cit)); 
     81    } 
     82  } 
     83 
     84  if (NSCModuleHelper::getSettingsInt("NRPE", "AllowNastyMetaChars", 0) == 0) { 
     85    if (str.find_first_of(NASTY_METACHARS) != std::string::npos) { 
     86      NSC_LOG_ERROR("Request command contained illegal metachars!"); 
     87      return NSCAPI::returnIgnored; 
     88    } 
     89  } 
     90 
     91  return executeNRPECommand(str, message, perf); 
     92} 
     93#define MAX_INPUT_BUFFER 1024 
     94 
     95int NRPEListener::executeNRPECommand(std::string command, std::string &msg, std::string &perf) 
     96{ 
     97  NSCAPI::nagiosReturn result; 
     98  PROCESS_INFORMATION pi; 
     99  STARTUPINFO si; 
     100  HANDLE hChildOutR, hChildOutW, hChildInR, hChildInW; 
     101  SECURITY_ATTRIBUTES sec; 
     102  DWORD dwstate, dwexitcode; 
     103  int retval; 
     104 
     105 
     106  // Set up members of SECURITY_ATTRIBUTES structure.  
     107 
     108  sec.nLength = sizeof(SECURITY_ATTRIBUTES); 
     109  sec.bInheritHandle = TRUE; 
     110  sec.lpSecurityDescriptor = NULL; 
     111 
     112  // Create Pipes 
     113  CreatePipe(&hChildInR, &hChildInW, &sec, 0); 
     114  CreatePipe(&hChildOutR, &hChildOutW, &sec, 0); 
     115 
     116  // Set up members of STARTUPINFO structure.  
     117 
     118  ZeroMemory(&si, sizeof(STARTUPINFO)); 
     119  si.cb = sizeof(STARTUPINFO); 
     120  si.dwFlags = STARTF_USESTDHANDLES; 
     121  si.hStdInput = hChildInR; 
     122  si.hStdOutput = hChildOutW; 
     123  si.hStdError = hChildOutW; 
     124 
     125 
     126  // CreateProcess doesn't work with a const command 
     127  char *cmd = new char[command.length()+1]; 
     128  strncpy(cmd, command.c_str(), command.length()); 
     129  cmd[command.length()] = 0; 
     130 
     131  // Create the child process.  
     132  BOOL processOK = CreateProcess(NULL, cmd,        // command line  
     133    NULL, // process security attributes  
     134    NULL, // primary thread security attributes  
     135    TRUE, // handles are inherited  
     136    0,    // creation flags  
     137    NULL, // use parent's environment  
     138    NULL, // use parent's current directory  
     139    &si,  // STARTUPINFO pointer  
     140    &pi); // receives PROCESS_INFORMATION  
     141  delete [] cmd; 
     142 
     143  if (processOK) { 
     144    dwstate = WaitForSingleObject(pi.hProcess, 1000*timeout); 
     145    CloseHandle(hChildInR); 
     146    CloseHandle(hChildInW); 
     147    CloseHandle(hChildOutW); 
     148 
     149    if (dwstate == WAIT_TIMEOUT) { 
     150      TerminateProcess(pi.hProcess, 5); 
     151      msg = "The check didn't respond within the timeout period!"; 
     152      result = NSCAPI::returnUNKNOWN; 
     153    } else { 
     154      DWORD dwread; 
     155      char *buf = new char[MAX_INPUT_BUFFER+1]; 
     156      retval = ReadFile(hChildOutR, buf, MAX_INPUT_BUFFER, &dwread, NULL); 
     157      if (!retval || dwread == 0) { 
     158        msg = "No output available from command..."; 
     159      } else { 
     160        buf[dwread] = 0; 
     161        msg = buf; 
     162        strEx::token t = strEx::getToken(msg, '\n'); 
     163        t = strEx::getToken(t.first, '|'); 
     164        msg = t.first; 
     165        perf = t.second; 
     166      } 
     167      delete [] buf; 
     168      result = NSCHelper::int2nagios(GetExitCodeProcess(pi.hProcess, &dwexitcode)); 
     169    } 
     170    CloseHandle(pi.hThread); 
     171    CloseHandle(pi.hProcess); 
     172    CloseHandle(hChildOutR); 
     173  } 
     174  else { 
     175    msg = "NRPE_NT failed to create process, exiting..."; 
     176    result = NSCAPI::returnUNKNOWN; 
     177    CloseHandle(hChildInR); 
     178    CloseHandle(hChildInW); 
     179    CloseHandle(hChildOutW); 
     180    CloseHandle(pi.hThread); 
     181    CloseHandle(pi.hProcess); 
     182    CloseHandle(hChildOutR); 
     183  } 
     184  return result; 
    50185} 
    51186 
  • modules/NRPEListener/NRPEListener.h

    r1eef1ee r1a5449e  
    44#include "NRPESocket.h" 
    55#include <Socket.h> 
     6#include <map> 
    67 
    78class NRPEListener { 
    89private: 
    9   NRPESocketThread socketThreadManager; 
     10  NRPESocket socket; 
     11  typedef std::map<std::string, std::string> commandList; 
     12  commandList commands; 
     13  unsigned int timeout; 
    1014 
    1115public: 
     
    2024  bool hasMessageHandler(); 
    2125  NSCAPI::nagiosReturn handleCommand(const std::string command, const unsigned int argLen, char **char_args, std::string &message, std::string &perf); 
     26 
     27private: 
     28  int executeNRPECommand(std::string command, std::string &msg, std::string &perf); 
     29  void addCommand(std::string key, std::string args) { 
     30    commands[key] = args; 
     31  } 
    2232}; 
    2333 
  • modules/NRPEListener/NRPEListener.vcproj

    r1eef1ee r1a5449e  
    122122      UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> 
    123123      <File 
     124        RelativePath="..\..\include\arrayBuffer.cpp"> 
     125      </File> 
     126      <File 
    124127        RelativePath=".\NRPEListener.cpp"> 
    125128      </File> 
  • modules/NRPEListener/NRPESocket.cpp

    rd4f294a r1a5449e  
    66 * Default c-tor 
    77 */ 
    8 NRPESocket::NRPESocket(): SimpleSocketListsner(DEFAULT_NRPE_PORT) { 
     8NRPESocket::NRPESocket() { 
    99} 
    1010 
     
    1212} 
    1313 
     14 
     15 
    1416typedef short int16_t; 
    1517typedef unsigned long u_int32_t; 
    1618 
    17 typedef struct packet_struct{ 
    18   int16_t   packet_version; 
    19   int16_t   packet_type; 
    20   u_int32_t crc32_value; 
    21   int16_t   result_code; 
    22   char      buffer[1024]; 
    23 }packet; 
    24  
    2519static unsigned long crc32_table[256]; 
    26  
    27 /* build the crc table - must be called before calculating the crc value */ 
     20static bool hascrc32 = false; 
    2821void generate_crc32_table(void){ 
    2922  unsigned long crc, poly; 
    3023  int i, j; 
    31  
    3224  poly=0xEDB88320L; 
    3325  for(i=0;i<256;i++){ 
     
    4133    crc32_table[i]=crc; 
    4234  } 
    43  
    44   return; 
     35  hascrc32 = true; 
    4536} 
    46  
    47 /* calculates the CRC 32 value for a buffer */ 
    48 unsigned long calculate_crc32(char *buffer, int buffer_size){ 
     37unsigned long calculate_crc32(const char *buffer, int buffer_size){ 
     38  if (!hascrc32) 
     39    generate_crc32_table(); 
    4940  register unsigned long crc; 
    5041  int this_char; 
     
    6152} 
    6253 
    63 void NRPESocket::onAccept(SOCKET client) { 
    64   NSC_DEBUG_MSG("Accepting connection from remote host"); 
    6554 
    66   SimpleSocketListsner::readAllDataBlock block = SimpleSocketListsner::readAll(client); 
    67   packet *p = reinterpret_cast<packet*>(block.first); 
    68   // @todo Verify versions and stuff, and ofcource add SSL (but thats in the future :) 
    69   NSC_DEBUG_MSG_STD("Incoming data: " + p->buffer); 
     55class NRPEPacket { 
     56public: 
     57  static const short queryPacket = 1; 
     58  static const short responsePacket = 2; 
     59  static const short version2 = 2; 
     60private: 
     61  typedef struct packet { 
     62    int16_t   packet_version; 
     63    int16_t   packet_type; 
     64    u_int32_t crc32_value; 
     65    int16_t   result_code; 
     66    char      buffer[1024]; 
     67  } packet; 
     68  std::string payload_; 
     69  short type_; 
     70  short version_; 
     71  NSCAPI::nagiosReturn result_; 
     72  unsigned int crc32_; 
     73  unsigned int calculatedCRC32_; 
     74  char *tmpBuffer; 
     75public: 
     76  NRPEPacket(const char *buffer) : tmpBuffer(NULL) { 
     77    const packet *p = reinterpret_cast<const packet*>(buffer); 
     78    type_ = ntohs(p->packet_type); 
     79    assert( (type_ == queryPacket)||(type_ == responsePacket)); 
     80    version_ = ntohs(p->packet_version); 
     81    assert(version_ == version2); 
     82    crc32_ = ntohl(p->crc32_value); 
     83    // Verify CRC32 
     84    // @todo Fix this, currently we need a const buffer so we cannot change the crc to 0. 
     85    char * tb = new char[getBufferLength()]; 
     86    memcpy(tb, buffer, getBufferLength()); 
     87    packet *p2 = reinterpret_cast<packet*>(tb); 
     88    p2->crc32_value = 0; 
     89    calculatedCRC32_ = calculate_crc32(tb, getBufferLength()); 
     90    delete [] tb; 
     91    // Verify CRC32 end 
     92    result_ = NSCHelper::int2nagios(ntohs(p->result_code)); 
     93    payload_ = std::string(p->buffer); 
     94  } 
     95  NRPEPacket(short type, short version, NSCAPI::nagiosReturn result, std::string payLoad)  
     96    : tmpBuffer(NULL)  
     97    ,type_(type) 
     98    ,version_(version) 
     99    ,result_(result) 
     100    ,payload_(payLoad) 
     101  { 
     102  } 
     103  ~NRPEPacket() { 
     104    delete [] tmpBuffer; 
     105  } 
     106  unsigned short getVersion() const { return version_; } 
     107  unsigned short getType() const { return type_; } 
     108  unsigned short getResult() const { return result_; } 
     109  std::string getPayload() const { return payload_; } 
     110  const char* getBuffer() { 
     111    delete [] tmpBuffer; 
     112    tmpBuffer = new char[getBufferLength()]; 
     113    packet *p = reinterpret_cast<packet*>(tmpBuffer); 
     114    p->result_code = htons(NSCHelper::nagios2int(result_)); 
     115    p->packet_type = htons(type_); 
     116    p->packet_version = htons(version_); 
     117    p->crc32_value = 0; 
     118    strncpy(p->buffer, payload_.c_str(), 1023); 
     119    p->buffer[1024] = 0; 
     120    p->crc32_value = htonl(calculate_crc32(tmpBuffer, getBufferLength())); 
     121    return tmpBuffer; 
     122  } 
     123  bool verifyCRC() { 
     124    return calculatedCRC32_ == crc32_; 
     125  } 
     126  const unsigned int getBufferLength() const { 
     127    return sizeof(packet); 
     128  } 
     129}; 
    70130 
    71   charEx::token cmd = charEx::getToken(p->buffer, '!'); 
     131void NRPESocket::onAccept(simpleSocket::Socket client) { 
     132  simpleSocket::DataBuffer block; 
     133  client.readAll(block); 
     134  NRPEPacket p(block.getBuffer()); 
     135  if (p.getType() != NRPEPacket::queryPacket) { 
     136    NSC_LOG_ERROR("Request is not a query."); 
     137    client.close(); 
     138    return; 
     139  } 
     140  if (p.getVersion() != NRPEPacket::version2) { 
     141    NSC_LOG_ERROR("Request had unsupported version."); 
     142    client.close(); 
     143    return; 
     144  } 
     145  if (!p.verifyCRC()) { 
     146    NSC_LOG_ERROR("Request had invalid checksum."); 
     147    client.close(); 
     148    return; 
     149  } 
     150  strEx::token cmd = strEx::getToken(p.getPayload(), '!'); 
    72151  std::string msg, perf; 
    73   NSCAPI::nagiosReturn ret = NSCModuleHelper::InjectSplitAndCommand(cmd.first.c_str(), cmd.second, '!', msg, perf); 
    74 //QUERY_PACKET 
    75   packet p2; 
    76   strncpy(p2.buffer, (msg+"|"+perf).c_str(), 1023); 
    77   p2.buffer[1023] = 0; 
    78   p2.packet_type = htons(2); 
    79   p2.packet_version = htons(2); 
    80   p2.result_code = htons(static_cast<int>(ret)); 
     152  NSC_DEBUG_MSG_STD("Command: " + cmd.first); 
     153  NSC_DEBUG_MSG_STD("Arguments: " + cmd.second); 
    81154 
    82   generate_crc32_table(); 
    83   p2.crc32_value = 0; 
    84   p2.crc32_value = htonl(calculate_crc32(reinterpret_cast<char*>(&p2),sizeof(p2))); 
    85   send(client, reinterpret_cast<char*>(&p2), sizeof(p2), 0); 
     155  if (NSCModuleHelper::getSettingsInt("NRPE", "AllowArguments", 0) == 0) { 
     156    if (!cmd.second.empty()) { 
     157      NSC_LOG_ERROR("Request contained arguments (not currently allowed)."); 
     158      client.close(); 
     159      return; 
     160    } 
     161  } 
     162  if (NSCModuleHelper::getSettingsInt("NRPE", "AllowNastyMetaChars", 0) == 0) { 
     163    if (cmd.first.find_first_of(NASTY_METACHARS) != std::string::npos) { 
     164      NSC_LOG_ERROR("Request command contained illegal metachars!"); 
     165      client.close(); 
     166      return; 
     167    } 
     168    if (cmd.second.find_first_of(NASTY_METACHARS) != std::string::npos) { 
     169      NSC_LOG_ERROR("Request arguments contained illegal metachars!"); 
     170      client.close(); 
     171      return; 
     172    } 
     173  } 
    86174 
    87   delete [] block.first; 
    88   closesocket(client); 
     175  NSCAPI::nagiosReturn ret = NSCModuleHelper::InjectSplitAndCommand(cmd.first, cmd.second, '!', msg, perf); 
     176  if (perf.empty()) { 
     177    NRPEPacket p2(NRPEPacket::responsePacket, NRPEPacket::version2, ret, msg); 
     178    client.send(p2.getBuffer(), p2.getBufferLength(), 0); 
     179  } else { 
     180    NRPEPacket p2(NRPEPacket::responsePacket, NRPEPacket::version2, ret, msg + "|" + perf); 
     181    client.send(p2.getBuffer(), p2.getBufferLength(), 0); 
     182  } 
     183  client.close(); 
    89184} 
    90185 
  • modules/NRPEListener/NRPESocket.h

    r1eef1ee r1a5449e  
    55#include <WinSock2.h> 
    66#include <Socket.h> 
     7#include <string.h> 
    78/** 
    89 * @ingroup NSClient++ 
     
    3031 */ 
    3132 
    32 #define DEFAULT_NRPE_PORT 5666 
    3333 
     34#define NASTY_METACHARS         "|`&><'\"\\[]{}"        /* This may need to be modified for windows directory seperator */ 
    3435 
    35 class NRPESocket : public SimpleSocketListsner { 
     36class NRPESocket : public simpleSocket::Listener { 
    3637private: 
    3738 
     
    4142 
    4243private: 
    43   virtual void onAccept(SOCKET client); 
     44  virtual void onAccept(simpleSocket::Socket client); 
    4445}; 
    4546 
    4647 
    47 typedef Thread<NRPESocket> NRPESocketThread; // Thread manager 
    4848 
    4949 
Note: See TracChangeset for help on using the changeset viewer.