check_nrpe.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530
  1. /********************************************************************************************
  2. *
  3. * CHECK_NRPE.C - NRPE Plugin For Nagios
  4. * Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)
  5. * License: GPL
  6. *
  7. * Last Modified: 09-08-2016
  8. *
  9. * Command line: CHECK_NRPE -H <host_address> [-p port] [-c command] [-to to_sec]
  10. *
  11. * Description:
  12. *
  13. * This plugin will attempt to connect to the NRPE daemon on the specified server and port.
  14. * The daemon will attempt to run the command defined as [command]. Program output and
  15. * return code are sent back from the daemon and displayed as this plugin's own output and
  16. * return code.
  17. *
  18. ********************************************************************************************/
  19. #include "config.h"
  20. #include "common.h"
  21. #include "utils.h"
  22. #define DEFAULT_NRPE_COMMAND "_NRPE_CHECK" /* check version of NRPE daemon */
  23. u_short server_port = 0;
  24. char *server_name = NULL;
  25. char *bind_address = NULL;
  26. char *config_file = NULL;
  27. #ifdef HAVE_STRUCT_SOCKADDR_STORAGE
  28. struct sockaddr_storage hostaddr;
  29. #else
  30. struct sockaddr hostaddr;
  31. #endif
  32. int address_family = AF_UNSPEC;
  33. char *command_name = NULL;
  34. int socket_timeout = DEFAULT_SOCKET_TIMEOUT;
  35. char timeout_txt[10];
  36. int timeout_return_code = -1;
  37. int sd;
  38. char rem_host[MAX_HOST_ADDRESS_LENGTH];
  39. char query[MAX_INPUT_BUFFER] = "";
  40. int show_help = FALSE;
  41. int show_license = FALSE;
  42. int show_version = FALSE;
  43. int packet_ver = NRPE_PACKET_VERSION_3;
  44. int force_v2_packet = 0;
  45. int payload_size = 0;
  46. extern char *log_file;
  47. #ifdef HAVE_SSL
  48. # if (defined(__sun) && defined(SOLARIS_10)) || defined(_AIX) || defined(__hpux)
  49. SSL_METHOD *meth;
  50. # else
  51. const SSL_METHOD *meth;
  52. # endif
  53. SSL_CTX *ctx;
  54. SSL *ssl;
  55. int use_ssl = TRUE;
  56. unsigned long ssl_opts = SSL_OP_ALL;
  57. #else
  58. int use_ssl = FALSE;
  59. #endif
  60. /* SSL/TLS parameters */
  61. typedef enum _SSL_VER {
  62. SSL_Ver_Invalid = 0, SSLv2 = 1, SSLv2_plus, SSLv3, SSLv3_plus,
  63. TLSv1, TLSv1_plus, TLSv1_1, TLSv1_1_plus, TLSv1_2, TLSv1_2_plus
  64. } SslVer;
  65. typedef enum _CLNT_CERTS { Ask_For_Cert = 1, Require_Cert = 2 } ClntCerts;
  66. typedef enum _SSL_LOGGING {
  67. SSL_NoLogging = 0, SSL_LogStartup = 1, SSL_LogIpAddr = 2,
  68. SSL_LogVersion = 4, SSL_LogCipher = 8, SSL_LogIfClientCert = 16,
  69. SSL_LogCertDetails = 32,
  70. } SslLogging;
  71. struct _SSL_PARMS {
  72. char *cert_file;
  73. char *cacert_file;
  74. char *privatekey_file;
  75. char cipher_list[MAX_FILENAME_LENGTH];
  76. SslVer ssl_min_ver;
  77. int allowDH;
  78. ClntCerts client_certs;
  79. SslLogging log_opts;
  80. } sslprm = {
  81. NULL, NULL, NULL, "", SSL_Ver_Invalid, -1, 0, SSL_NoLogging};
  82. int have_log_opts = FALSE;
  83. int process_arguments(int, char **, int);
  84. int read_config_file(char *);
  85. const char *state_text (int result);
  86. int translate_state (char *state_text);
  87. void set_timeout_state (char *state);
  88. int parse_timeout_string (char *timeout_str);
  89. void usage(int result);
  90. void setup_ssl();
  91. void set_sig_handlers();
  92. int connect_to_remote();
  93. int send_request();
  94. int read_response();
  95. int read_packet(int sock, void *ssl_ptr, v2_packet ** v2_pkt, v3_packet ** v3_pkt);
  96. #ifdef HAVE_SSL
  97. static int verify_callback(int ok, X509_STORE_CTX * ctx);
  98. #endif
  99. void alarm_handler(int);
  100. int graceful_close(int, int);
  101. int main(int argc, char **argv)
  102. {
  103. int16_t result;
  104. result = process_arguments(argc, argv, 0);
  105. open_log_file();
  106. if (result != OK || show_help == TRUE || show_license == TRUE || show_version == TRUE)
  107. usage(result); /* usage() will call exit() */
  108. snprintf(timeout_txt, sizeof(timeout_txt), "%d", socket_timeout);
  109. if (server_port == 0)
  110. server_port = DEFAULT_SERVER_PORT;
  111. if (socket_timeout == -1)
  112. socket_timeout = DEFAULT_SOCKET_TIMEOUT;
  113. if (timeout_return_code == -1)
  114. timeout_return_code = STATE_CRITICAL;
  115. if (sslprm.cipher_list[0] == '\0')
  116. strncpy(sslprm.cipher_list, "ALL:!MD5:@STRENGTH", MAX_FILENAME_LENGTH - 1);
  117. if (sslprm.ssl_min_ver == SSL_Ver_Invalid)
  118. sslprm.ssl_min_ver = TLSv1_plus;
  119. if (sslprm.allowDH == -1)
  120. sslprm.allowDH = TRUE;
  121. generate_crc32_table(); /* generate the CRC 32 table */
  122. setup_ssl(); /* Do all the SSL/TLS set up */
  123. set_sig_handlers(); /* initialize alarm signal handling */
  124. result = connect_to_remote(); /* Make the connection */
  125. if (result != STATE_OK) {
  126. alarm(0);
  127. return result;
  128. }
  129. result = send_request(); /* Send the request */
  130. if (result != STATE_OK)
  131. return result;
  132. result = read_response(); /* Get the response */
  133. if (result == -1) {
  134. /* Failure reading from remote, so try version 2 packet */
  135. logit(LOG_INFO, "Remote %s does not support Version 3 Packets", rem_host);
  136. packet_ver = NRPE_PACKET_VERSION_2;
  137. /* Rerun the setup */
  138. setup_ssl();
  139. set_sig_handlers();
  140. result = connect_to_remote(); /* Connect */
  141. if (result != STATE_OK) {
  142. alarm(0);
  143. close_log_file(); /* close the log file */
  144. return result;
  145. }
  146. result = send_request(); /* Send the request */
  147. if (result != STATE_OK) {
  148. close_log_file(); /* close the log file */
  149. return result;
  150. }
  151. result = read_response(); /* Get the response */
  152. }
  153. if (result != -1 && force_v2_packet == 0 && packet_ver == NRPE_PACKET_VERSION_2)
  154. logit(LOG_DEBUG, "Remote %s accepted a Version %d Packet", rem_host, packet_ver);
  155. close_log_file(); /* close the log file */
  156. return result;
  157. }
  158. /* process command line arguments */
  159. int process_arguments(int argc, char **argv, int from_config_file)
  160. {
  161. char optchars[MAX_INPUT_BUFFER];
  162. int argindex = 0;
  163. int c = 1;
  164. int i = 1;
  165. int has_cert = 0, has_priv_key = 0, rc;
  166. #ifdef HAVE_GETOPT_LONG
  167. int option_index = 0;
  168. static struct option long_options[] = {
  169. {"host", required_argument, 0, 'H'},
  170. {"config-file", required_argument, 0, 'f'},
  171. {"bind", required_argument, 0, 'b'},
  172. {"command", required_argument, 0, 'c'},
  173. {"args", required_argument, 0, 'a'},
  174. {"no-ssl", no_argument, 0, 'n'},
  175. {"unknown-timeout", no_argument, 0, 'u'},
  176. {"v2-packets-only", no_argument, 0, '2'},
  177. {"ipv4", no_argument, 0, '4'},
  178. {"ipv6", no_argument, 0, '6'},
  179. {"use-adh", required_argument, 0, 'd'},
  180. {"ssl-version", required_argument, 0, 'S'},
  181. {"cipher-list", required_argument, 0, 'L'},
  182. {"client-cert", required_argument, 0, 'C'},
  183. {"key-file", required_argument, 0, 'K'},
  184. {"ca-cert-file", required_argument, 0, 'A'},
  185. {"ssl-logging", required_argument, 0, 's'},
  186. {"timeout", required_argument, 0, 't'},
  187. {"port", required_argument, 0, 'p'},
  188. {"payload-size", required_argument, 0, 'P'},
  189. {"log-file", required_argument, 0, 'g'},
  190. {"help", no_argument, 0, 'h'},
  191. {"license", no_argument, 0, 'l'},
  192. {0, 0, 0, 0}
  193. };
  194. #endif
  195. /* no options were supplied */
  196. if (argc < 2)
  197. return ERROR;
  198. optind = 0;
  199. snprintf(optchars, MAX_INPUT_BUFFER, "H:f:b:c:a:t:p:S:L:C:K:A:d:s:P:g:246hlnuV");
  200. while (1) {
  201. if (argindex > 0)
  202. break;
  203. #ifdef HAVE_GETOPT_LONG
  204. c = getopt_long(argc, argv, optchars, long_options, &option_index);
  205. #else
  206. c = getopt(argc, argv, optchars);
  207. #endif
  208. if (c == -1 || c == EOF)
  209. break;
  210. /* process all arguments */
  211. switch (c) {
  212. case '?':
  213. case 'h':
  214. show_help = TRUE;
  215. break;
  216. case 'b':
  217. bind_address = strdup(optarg);
  218. break;
  219. case 'f':
  220. if (from_config_file) {
  221. printf("Error: The config file should not have a config-file (-f) option.\n");
  222. break;
  223. }
  224. config_file = strdup(optarg);
  225. break;
  226. case 'V':
  227. show_version = TRUE;
  228. break;
  229. case 'l':
  230. show_license = TRUE;
  231. break;
  232. case 't':
  233. if (from_config_file && socket_timeout != -1) {
  234. logit(LOG_WARNING, "WARNING: Command-line socket timeout overrides "
  235. "the config file option.");
  236. break;
  237. }
  238. socket_timeout=parse_timeout_string(optarg);
  239. if (socket_timeout <= 0)
  240. return ERROR;
  241. break;
  242. case 'p':
  243. if (from_config_file && server_port != 0) {
  244. logit(LOG_WARNING, "WARNING: Command-line server port overrides "
  245. "the config file option.");
  246. break;
  247. }
  248. server_port = atoi(optarg);
  249. if (server_port <= 0)
  250. return ERROR;
  251. break;
  252. case 'P':
  253. if (from_config_file && payload_size > 0) {
  254. logit(LOG_WARNING, "WARNING: Command-line payload-size (-P) overrides "
  255. "the config file option.");
  256. break;
  257. }
  258. payload_size = atoi(optarg);
  259. if (payload_size < 0)
  260. return ERROR;
  261. break;
  262. case 'H':
  263. if (from_config_file && server_name != NULL) {
  264. logit(LOG_WARNING, "WARNING: Command-line server name overrides "
  265. "the config file option.");
  266. break;
  267. }
  268. server_name = strdup(optarg);
  269. break;
  270. case 'c':
  271. if (from_config_file) {
  272. printf("Error: The config file should not have a command (-c) option.\n");
  273. return ERROR;
  274. }
  275. command_name = strdup(optarg);
  276. break;
  277. case 'a':
  278. if (from_config_file) {
  279. printf("Error: The config file should not have args (-a) arguments.\n");
  280. return ERROR;
  281. }
  282. argindex = optind;
  283. break;
  284. case 'n':
  285. use_ssl = FALSE;
  286. break;
  287. case 'u':
  288. if (from_config_file && timeout_return_code != -1) {
  289. logit(LOG_WARNING, "WARNING: Command-line unknown-timeout (-u) "
  290. "overrides the config file option.");
  291. break;
  292. }
  293. timeout_return_code = STATE_UNKNOWN;
  294. break;
  295. case '2':
  296. if (from_config_file && packet_ver != NRPE_PACKET_VERSION_3) {
  297. logit(LOG_WARNING, "WARNING: Command-line v2-packets-only (-2) "
  298. "overrides the config file option.");
  299. break;
  300. }
  301. packet_ver = NRPE_PACKET_VERSION_2;
  302. force_v2_packet = 1;
  303. break;
  304. case '4':
  305. if (from_config_file && address_family != AF_UNSPEC) {
  306. logit(LOG_WARNING, "WARNING: Command-line ipv4 (-4) "
  307. "or ipv6 (-6) overrides the config file option.");
  308. break;
  309. }
  310. address_family = AF_INET;
  311. break;
  312. case '6':
  313. if (from_config_file && address_family != AF_UNSPEC) {
  314. logit(LOG_WARNING, "WARNING: Command-line ipv4 (-4) "
  315. "or ipv6 (-6) overrides the config file option.");
  316. break;
  317. }
  318. address_family = AF_INET6;
  319. break;
  320. case 'd':
  321. if (from_config_file && sslprm.allowDH != -1) {
  322. logit(LOG_WARNING, "WARNING: Command-line use-adh (-d) "
  323. "overrides the config file option.");
  324. break;
  325. }
  326. if (!optarg || optarg[0] < '0' || optarg[0] > '2')
  327. return ERROR;
  328. sslprm.allowDH = atoi(optarg);
  329. break;
  330. case 'A':
  331. if (from_config_file && sslprm.cacert_file != NULL) {
  332. logit(LOG_WARNING, "WARNING: Command-line ca-cert-file (-A) "
  333. "overrides the config file option.");
  334. break;
  335. }
  336. sslprm.cacert_file = strdup(optarg);
  337. break;
  338. case 'C':
  339. if (from_config_file && sslprm.cert_file != NULL) {
  340. logit(LOG_WARNING, "WARNING: Command-line client-cert (-C) "
  341. "overrides the config file option.");
  342. break;
  343. }
  344. sslprm.cert_file = strdup(optarg);
  345. has_cert = 1;
  346. break;
  347. case 'K':
  348. if (from_config_file && sslprm.privatekey_file != NULL) {
  349. logit(LOG_WARNING, "WARNING: Command-line key-file (-K) "
  350. "overrides the config file option.");
  351. break;
  352. }
  353. sslprm.privatekey_file = strdup(optarg);
  354. has_priv_key = 1;
  355. break;
  356. case 'S':
  357. if (from_config_file && sslprm.ssl_min_ver != SSL_Ver_Invalid) {
  358. logit(LOG_WARNING, "WARNING: Command-line ssl-version (-S) "
  359. "overrides the config file option.");
  360. break;
  361. }
  362. if (!strcmp(optarg, "SSLv2"))
  363. sslprm.ssl_min_ver = SSLv2;
  364. else if (!strcmp(optarg, "SSLv2+"))
  365. sslprm.ssl_min_ver = SSLv2_plus;
  366. else if (!strcmp(optarg, "SSLv3"))
  367. sslprm.ssl_min_ver = SSLv3;
  368. else if (!strcmp(optarg, "SSLv3+"))
  369. sslprm.ssl_min_ver = SSLv3_plus;
  370. else if (!strcmp(optarg, "TLSv1"))
  371. sslprm.ssl_min_ver = TLSv1;
  372. else if (!strcmp(optarg, "TLSv1+"))
  373. sslprm.ssl_min_ver = TLSv1_plus;
  374. else if (!strcmp(optarg, "TLSv1.1"))
  375. sslprm.ssl_min_ver = TLSv1_1;
  376. else if (!strcmp(optarg, "TLSv1.1+"))
  377. sslprm.ssl_min_ver = TLSv1_1_plus;
  378. else if (!strcmp(optarg, "TLSv1.2"))
  379. sslprm.ssl_min_ver = TLSv1_2;
  380. else if (!strcmp(optarg, "TLSv1.2+"))
  381. sslprm.ssl_min_ver = TLSv1_2_plus;
  382. else
  383. return ERROR;
  384. break;
  385. case 'L':
  386. if (from_config_file && sslprm.cipher_list[0] != '\0') {
  387. logit(LOG_WARNING, "WARNING: Command-line cipher-list (-L) "
  388. "overrides the config file option.");
  389. break;
  390. }
  391. strncpy(sslprm.cipher_list, optarg, sizeof(sslprm.cipher_list) - 1);
  392. sslprm.cipher_list[sizeof(sslprm.cipher_list) - 1] = '\0';
  393. break;
  394. case 's':
  395. if (from_config_file && have_log_opts == TRUE) {
  396. logit(LOG_WARNING, "WARNING: Command-line ssl-logging (-s) "
  397. "overrides the config file option.");
  398. break;
  399. }
  400. sslprm.log_opts = strtoul(optarg, NULL, 0);
  401. have_log_opts = TRUE;
  402. break;
  403. case 'g':
  404. if (from_config_file && log_file != NULL) {
  405. logit(LOG_WARNING, "WARNING: Command-line log-file (-g) "
  406. "overrides the config file option.");
  407. break;
  408. }
  409. log_file = strdup(optarg);
  410. break;
  411. default:
  412. return ERROR;
  413. }
  414. }
  415. /* determine (base) command query */
  416. if (!from_config_file) {
  417. snprintf(query, sizeof(query), "%s",
  418. (command_name == NULL) ? DEFAULT_NRPE_COMMAND : command_name);
  419. query[sizeof(query) - 1] = '\x0';
  420. }
  421. /* get the command args */
  422. if (!from_config_file && argindex > 0) {
  423. for (c = argindex - 1; c < argc; c++) {
  424. i = sizeof(query) - strlen(query) - 2;
  425. if (i <= 0)
  426. break;
  427. strcat(query, "!");
  428. strncat(query, argv[c], i);
  429. query[sizeof(query) - 1] = '\x0';
  430. }
  431. }
  432. if (!from_config_file && config_file != NULL) {
  433. if ((rc = read_config_file(config_file)) != OK)
  434. return rc;
  435. }
  436. if ((has_cert && !has_priv_key) || (!has_cert && has_priv_key)) {
  437. printf("Error: the client certificate and the private key "
  438. "must both be given or neither\n");
  439. return ERROR;
  440. }
  441. if (payload_size > 0 && packet_ver != NRPE_PACKET_VERSION_2) {
  442. printf("Error: if a fixed payload size is specified, "
  443. "'-2' must also be specified\n");
  444. return ERROR;
  445. }
  446. /* make sure required args were supplied */
  447. if (server_name == NULL && show_help == FALSE && show_version == FALSE
  448. && show_license == FALSE)
  449. return ERROR;
  450. return OK;
  451. }
  452. int read_config_file(char *fname)
  453. {
  454. int rc, argc = 0;
  455. FILE *f;
  456. char *buf, *bufp, **argv;
  457. char *delims = " \t\r\n";
  458. struct stat st;
  459. size_t sz;
  460. if (stat(fname, &st)) {
  461. logit(LOG_ERR, "Error: Could not stat config file %s", fname);
  462. return ERROR;
  463. }
  464. if ((f = fopen(fname, "r")) == NULL) {
  465. logit(LOG_ERR, "Error: Could not open config file %s", fname);
  466. return ERROR;
  467. }
  468. if ((buf = (char*)calloc(1, st.st_size + 2)) == NULL) {
  469. fclose(f);
  470. logit(LOG_ERR, "Error: read_config_file fail to allocate memory");
  471. return ERROR;
  472. }
  473. if ((sz = fread(buf, 1, st.st_size, f)) != st.st_size) {
  474. fclose(f);
  475. free(buf);
  476. logit(LOG_ERR, "Error: Failed to completely read config file %s", fname);
  477. return ERROR;
  478. }
  479. if ((argv = calloc(50, sizeof(char*))) == NULL) {
  480. fclose(f);
  481. free(buf);
  482. logit(LOG_ERR, "Error: read_config_file fail to allocate memory");
  483. return ERROR;
  484. }
  485. argv[argc++] = "check_nrpe";
  486. bufp = buf;
  487. while (argc < 50) {
  488. if (*bufp == '\0')
  489. break;
  490. while (strchr(delims, *bufp))
  491. ++bufp;
  492. argv[argc] = my_strsep(&bufp, delims);
  493. if (!argv[argc++])
  494. break;
  495. }
  496. fclose(f);
  497. if (argc == 50) {
  498. free(buf);
  499. free(argv);
  500. logit(LOG_ERR, "Error: too many parameters in config file %s", fname);
  501. return ERROR;
  502. }
  503. rc = process_arguments(argc, argv, 1);
  504. free(buf);
  505. free(argv);
  506. return rc;
  507. }
  508. const char *state_text (int result)
  509. {
  510. switch (result) {
  511. case STATE_OK:
  512. return "OK";
  513. case STATE_WARNING:
  514. return "WARNING";
  515. case STATE_CRITICAL:
  516. return "CRITICAL";
  517. default:
  518. return "UNKNOWN";
  519. }
  520. }
  521. int translate_state (char *state_text) {
  522. if (!strcasecmp(state_text,"OK") || !strcmp(state_text,"0"))
  523. return STATE_OK;
  524. if (!strcasecmp(state_text,"WARNING") || !strcmp(state_text,"1"))
  525. return STATE_WARNING;
  526. if (!strcasecmp(state_text,"CRITICAL") || !strcmp(state_text,"2"))
  527. return STATE_CRITICAL;
  528. if (!strcasecmp(state_text,"UNKNOWN") || !strcmp(state_text,"3"))
  529. return STATE_UNKNOWN;
  530. return ERROR;
  531. }
  532. void set_timeout_state (char *state) {
  533. if ((timeout_return_code = translate_state(state)) == ERROR)
  534. printf("Timeout state must be a valid state name (OK, "
  535. "WARNING, CRITICAL, UNKNOWN) or integer (0-3).\n");
  536. }
  537. int parse_timeout_string (char *timeout_str)
  538. {
  539. char *separated_str;
  540. char *timeout_val = NULL;
  541. char *timeout_sta = NULL;
  542. if (strstr(timeout_str, ":") == NULL)
  543. timeout_val = timeout_str;
  544. else if (strncmp(timeout_str, ":", 1) == 0) {
  545. separated_str = strtok(timeout_str, ":");
  546. if (separated_str != NULL)
  547. timeout_sta = separated_str;
  548. } else {
  549. separated_str = strtok(timeout_str, ":");
  550. timeout_val = separated_str;
  551. separated_str = strtok(NULL, ":");
  552. if (separated_str != NULL) {
  553. timeout_sta = separated_str;
  554. }
  555. }
  556. if ( timeout_sta != NULL )
  557. set_timeout_state(timeout_sta);
  558. if ((timeout_val == NULL) || (timeout_val[0] == '\0'))
  559. return socket_timeout;
  560. else if (atoi(timeout_val) > 0)
  561. return atoi(timeout_val);
  562. else {
  563. printf("Timeout value must be a positive integer\n");
  564. exit (STATE_UNKNOWN);
  565. }
  566. }
  567. void usage(int result)
  568. {
  569. if (result != OK)
  570. printf("Incorrect command line arguments supplied\n");
  571. printf("\n");
  572. printf("NRPE Plugin for Nagios\n");
  573. printf("Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)\n");
  574. printf("Version: %s\n", PROGRAM_VERSION);
  575. printf("Last Modified: %s\n", MODIFICATION_DATE);
  576. printf("License: GPL v2 with exemptions (-l for more info)\n");
  577. #ifdef HAVE_SSL
  578. printf("SSL/TLS Available: OpenSSL 0.9.6 or higher required\n");
  579. #endif
  580. printf("\n");
  581. if (result != OK || show_help == TRUE) {
  582. printf("Usage: check_nrpe -H <host> [-2] [-4] [-6] [-n] [-u] [-V] [-l] [-d <dhopt>]\n"
  583. " [-P <size>] [-S <ssl version>] [-L <cipherlist>] [-C <clientcert>]\n"
  584. " [-K <key>] [-A <ca-certificate>] [-s <logopts>] [-b <bindaddr>]\n"
  585. " [-f <cfg-file>] [-p <port>] [-t <interval>:<state>]\n"
  586. " [-c <command>] [-a <arglist...>]\n");
  587. printf("\n");
  588. printf("Options:\n");
  589. printf(" <host> = The address of the host running the NRPE daemon\n");
  590. printf(" -2 = Only use Version 2 packets, not Version 3\n");
  591. printf(" -4 = bind to ipv4 only\n");
  592. printf(" -6 = bind to ipv6 only\n");
  593. printf(" -n = Do no use SSL\n");
  594. printf
  595. (" -u = (DEPRECATED) Make timeouts return UNKNOWN instead of CRITICAL\n");
  596. printf(" -V = Show version\n");
  597. printf(" -l = Show license\n");
  598. printf(" <dhopt> = Anonymous Diffie Hellman use:\n");
  599. printf(" 0 = Don't use Anonymous Diffie Hellman\n");
  600. printf(" (This will be the default in a future release.)\n");
  601. printf(" 1 = Allow Anonymous Diffie Hellman (default)\n");
  602. printf(" 2 = Force Anonymous Diffie Hellman\n");
  603. printf(" <size> = Specify non-default payload size for NSClient++\n");
  604. printf
  605. (" <ssl ver> = The SSL/TLS version to use. Can be any one of: SSLv2 (only),\n");
  606. printf(" SSLv2+ (or above), SSLv3 (only), SSLv3+ (or above),\n");
  607. printf(" TLSv1 (only), TLSv1+ (or above DEFAULT), TLSv1.1 (only),\n");
  608. printf(" TLSv1.1+ (or above), TLSv1.2 (only), TLSv1.2+ (or above)\n");
  609. printf(" <cipherlist> = The list of SSL ciphers to use (currently defaults\n");
  610. printf
  611. (" to \"ALL:!MD5:@STRENGTH\". WILL change in a future release.)\n");
  612. printf(" <clientcert> = The client certificate to use for PKI\n");
  613. printf(" <key> = The private key to use with the client certificate\n");
  614. printf(" <ca-cert> = The CA certificate to use for PKI\n");
  615. printf(" <logopts> = SSL Logging Options\n");
  616. printf(" <bindaddr> = bind to local address\n");
  617. printf(" <cfg-file> = configuration file to use\n");
  618. printf(" [port] = The port on which the daemon is running (default=%d)\n",
  619. DEFAULT_SERVER_PORT);
  620. printf(" [command] = The name of the command that the remote daemon should run\n");
  621. printf(" [arglist] = Optional arguments that should be passed to the command,\n");
  622. printf(" separated by a space. If provided, this must be the last\n");
  623. printf(" option supplied on the command line.\n");
  624. printf("\n");
  625. printf(" NEW TIMEOUT SYNTAX\n");
  626. printf(" -t <interval>:<state>\n");
  627. printf(" <interval> = Number of seconds before connection times out (default=%d)\n",DEFAULT_SOCKET_TIMEOUT);
  628. printf(" <state> = Check state to exit with in the event of a timeout (default=CRITICAL)\n");
  629. printf(" Timeout state must be a valid state name (case-insensitive) or integer:\n");
  630. printf(" (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)\n");
  631. printf("\n");
  632. printf("Note:\n");
  633. printf
  634. ("This plugin requires that you have the NRPE daemon running on the remote host.\n");
  635. printf
  636. ("You must also have configured the daemon to associate a specific plugin command\n");
  637. printf("with the [command] option you are specifying here. Upon receipt of the\n");
  638. printf
  639. ("[command] argument, the NRPE daemon will run the appropriate plugin command and\n");
  640. printf
  641. ("send the plugin output and return code back to *this* plugin. This allows you\n");
  642. printf
  643. ("to execute plugins on remote hosts and 'fake' the results to make Nagios think\n");
  644. printf("the plugin is being run locally.\n");
  645. printf("\n");
  646. }
  647. if (show_license == TRUE)
  648. display_license();
  649. exit(STATE_UNKNOWN);
  650. }
  651. void setup_ssl()
  652. {
  653. #ifdef HAVE_SSL
  654. int vrfy;
  655. if (sslprm.log_opts & SSL_LogStartup) {
  656. char *val;
  657. logit(LOG_INFO, "SSL Certificate File: %s",
  658. sslprm.cert_file ? sslprm.cert_file : "None");
  659. logit(LOG_INFO, "SSL Private Key File: %s",
  660. sslprm.privatekey_file ? sslprm.privatekey_file : "None");
  661. logit(LOG_INFO, "SSL CA Certificate File: %s",
  662. sslprm.cacert_file ? sslprm.cacert_file : "None");
  663. if (sslprm.allowDH < 2)
  664. logit(LOG_INFO, "SSL Cipher List: %s", sslprm.cipher_list);
  665. else
  666. logit(LOG_INFO, "SSL Cipher List: ADH");
  667. logit(LOG_INFO, "SSL Allow ADH: %s",
  668. sslprm.allowDH == 0 ? "No" : (sslprm.allowDH == 1 ? "Allow" : "Require"));
  669. logit(LOG_INFO, "SSL Log Options: 0x%02x", sslprm.log_opts);
  670. switch (sslprm.ssl_min_ver) {
  671. case SSLv2:
  672. val = "SSLv2";
  673. break;
  674. case SSLv2_plus:
  675. val = "SSLv2 And Above";
  676. break;
  677. case SSLv3:
  678. val = "SSLv3";
  679. break;
  680. case SSLv3_plus:
  681. val = "SSLv3_plus And Above";
  682. break;
  683. case TLSv1:
  684. val = "TLSv1";
  685. break;
  686. case TLSv1_plus:
  687. val = "TLSv1_plus And Above";
  688. break;
  689. case TLSv1_1:
  690. val = "TLSv1_1";
  691. break;
  692. case TLSv1_1_plus:
  693. val = "TLSv1_1_plus And Above";
  694. break;
  695. case TLSv1_2:
  696. val = "TLSv1_2";
  697. break;
  698. case TLSv1_2_plus:
  699. val = "TLSv1_2_plus And Above";
  700. break;
  701. default:
  702. val = "INVALID VALUE!";
  703. break;
  704. }
  705. logit(LOG_INFO, "SSL Version: %s", val);
  706. }
  707. /* initialize SSL */
  708. if (use_ssl == TRUE) {
  709. SSL_load_error_strings();
  710. SSL_library_init();
  711. meth = SSLv23_client_method();
  712. # ifndef OPENSSL_NO_SSL2
  713. if (sslprm.ssl_min_ver == SSLv2)
  714. meth = SSLv2_client_method();
  715. # endif
  716. # ifndef OPENSSL_NO_SSL3
  717. if (sslprm.ssl_min_ver == SSLv3)
  718. meth = SSLv3_client_method();
  719. # endif
  720. if (sslprm.ssl_min_ver == TLSv1)
  721. meth = TLSv1_client_method();
  722. # ifdef SSL_TXT_TLSV1_1
  723. if (sslprm.ssl_min_ver == TLSv1_1)
  724. meth = TLSv1_1_client_method();
  725. # ifdef SSL_TXT_TLSV1_2
  726. if (sslprm.ssl_min_ver == TLSv1_2)
  727. meth = TLSv1_2_client_method();
  728. # endif
  729. # endif
  730. if ((ctx = SSL_CTX_new(meth)) == NULL) {
  731. printf("CHECK_NRPE: Error - could not create SSL context.\n");
  732. exit(STATE_CRITICAL);
  733. }
  734. switch(sslprm.ssl_min_ver) {
  735. case SSLv2:
  736. case SSLv2_plus:
  737. break;
  738. case TLSv1_2:
  739. case TLSv1_2_plus:
  740. ssl_opts |= SSL_OP_NO_TLSv1_1;
  741. case TLSv1_1:
  742. case TLSv1_1_plus:
  743. ssl_opts |= SSL_OP_NO_TLSv1;
  744. case TLSv1:
  745. case TLSv1_plus:
  746. ssl_opts |= SSL_OP_NO_SSLv3;
  747. case SSLv3:
  748. case SSLv3_plus:
  749. ssl_opts |= SSL_OP_NO_SSLv2;
  750. break;
  751. }
  752. SSL_CTX_set_options(ctx, ssl_opts);
  753. if (sslprm.cert_file != NULL && sslprm.privatekey_file != NULL) {
  754. if (!SSL_CTX_use_certificate_file(ctx, sslprm.cert_file, SSL_FILETYPE_PEM)) {
  755. SSL_CTX_free(ctx);
  756. printf("Error: could not use certificate file '%s'.\n", sslprm.cert_file);
  757. exit(STATE_CRITICAL);
  758. }
  759. if (!SSL_CTX_use_PrivateKey_file(ctx, sslprm.privatekey_file, SSL_FILETYPE_PEM)) {
  760. SSL_CTX_free(ctx);
  761. printf("Error: could not use private key file '%s'.\n",
  762. sslprm.privatekey_file);
  763. exit(STATE_CRITICAL);
  764. }
  765. }
  766. if (sslprm.cacert_file != NULL) {
  767. vrfy = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
  768. SSL_CTX_set_verify(ctx, vrfy, verify_callback);
  769. if (!SSL_CTX_load_verify_locations(ctx, sslprm.cacert_file, NULL)) {
  770. SSL_CTX_free(ctx);
  771. printf("Error: could not use CA certificate '%s'.\n", sslprm.cacert_file);
  772. exit(STATE_CRITICAL);
  773. }
  774. }
  775. if (!sslprm.allowDH) {
  776. if (strlen(sslprm.cipher_list) < sizeof(sslprm.cipher_list) - 6) {
  777. strcat(sslprm.cipher_list, ":!ADH");
  778. if (sslprm.log_opts & SSL_LogStartup)
  779. logit(LOG_INFO, "New SSL Cipher List: %s", sslprm.cipher_list);
  780. }
  781. } else {
  782. /* use anonymous DH ciphers */
  783. if (sslprm.allowDH == 2)
  784. strcpy(sslprm.cipher_list, "ADH");
  785. }
  786. if (SSL_CTX_set_cipher_list(ctx, sslprm.cipher_list) == 0) {
  787. SSL_CTX_free(ctx);
  788. printf("Error: Could not set SSL/TLS cipher list: %s\n", sslprm.cipher_list);
  789. exit(STATE_CRITICAL);
  790. }
  791. }
  792. #endif
  793. }
  794. void set_sig_handlers()
  795. {
  796. #ifdef HAVE_SIGACTION
  797. struct sigaction sig_action;
  798. #endif
  799. #ifdef HAVE_SIGACTION
  800. sig_action.sa_sigaction = NULL;
  801. sig_action.sa_handler = alarm_handler;
  802. sigfillset(&sig_action.sa_mask);
  803. sig_action.sa_flags = SA_NODEFER | SA_RESTART;
  804. sigaction(SIGALRM, &sig_action, NULL);
  805. #else
  806. signal(SIGALRM, alarm_handler);
  807. #endif /* HAVE_SIGACTION */
  808. /* set socket timeout */
  809. alarm(socket_timeout);
  810. }
  811. int connect_to_remote()
  812. {
  813. struct sockaddr addr;
  814. struct in_addr *inaddr;
  815. socklen_t addrlen;
  816. int result, rc, ssl_err, ern;
  817. /* try to connect to the host at the given port number */
  818. if ((sd =
  819. my_connect(server_name, &hostaddr, server_port, address_family, bind_address)) < 0)
  820. exit(STATE_CRITICAL);
  821. result = STATE_OK;
  822. addrlen = sizeof(addr);
  823. rc = getpeername(sd, (struct sockaddr *)&addr, &addrlen);
  824. if (addr.sa_family == AF_INET) {
  825. struct sockaddr_in *addrin = (struct sockaddr_in *)&addr;
  826. inaddr = &addrin->sin_addr;
  827. } else {
  828. struct sockaddr_in6 *addrin = (struct sockaddr_in6 *)&addr;
  829. inaddr = (struct in_addr *)&addrin->sin6_addr;
  830. }
  831. if (inet_ntop(addr.sa_family, inaddr, rem_host, sizeof(rem_host)) == NULL)
  832. strncpy(rem_host, "Unknown", sizeof(rem_host));
  833. rem_host[MAX_HOST_ADDRESS_LENGTH - 1] = '\0';
  834. if ((sslprm.log_opts & SSL_LogIpAddr) != 0)
  835. logit(LOG_DEBUG, "Connected to %s", rem_host);
  836. #ifdef HAVE_SSL
  837. if (use_ssl == FALSE)
  838. return result;
  839. /* do SSL handshake */
  840. if ((ssl = SSL_new(ctx)) == NULL) {
  841. printf("CHECK_NRPE: Error - Could not create SSL connection structure.\n");
  842. return STATE_CRITICAL;
  843. }
  844. SSL_set_fd(ssl, sd);
  845. if ((rc = SSL_connect(ssl)) != 1) {
  846. ern = errno;
  847. ssl_err = SSL_get_error(ssl, rc);
  848. if (sslprm.log_opts & (SSL_LogCertDetails | SSL_LogIfClientCert)) {
  849. int x, nerrs = 0;
  850. rc = 0;
  851. while ((x = ERR_get_error_line_data(NULL, NULL, NULL, NULL)) != 0) {
  852. logit(LOG_ERR, "Error: Could not complete SSL handshake with %s: %s",
  853. rem_host, ERR_reason_error_string(x));
  854. ++nerrs;
  855. }
  856. if (nerrs == 0)
  857. logit(LOG_ERR, "Error: Could not complete SSL handshake with %s: rc=%d SSL-error=%d",
  858. rem_host, rc, ssl_err);
  859. } else
  860. logit(LOG_ERR, "Error: Could not complete SSL handshake with %s: rc=%d SSL-error=%d",
  861. rem_host, rc, ssl_err);
  862. if (ssl_err == 5) {
  863. /* Often, errno will be zero, so print a generic message here */
  864. if (ern == 0)
  865. printf("CHECK_NRPE: Error - Could not connect to %s. Check system logs on %s\n",
  866. rem_host, rem_host);
  867. else
  868. printf("CHECK_NRPE: Error - Could not connect to %s: %s\n",
  869. rem_host, strerror(ern));
  870. } else
  871. printf("CHECK_NRPE: Error - Could not complete SSL handshake with %s: %d\n",
  872. rem_host, ssl_err);
  873. # ifdef DEBUG
  874. printf("SSL_connect=%d\n", rc);
  875. /*
  876. rc = SSL_get_error(ssl, rc);
  877. printf("SSL_get_error=%d\n", rc);
  878. printf("ERR_get_error=%lu\n", ERR_get_error());
  879. printf("%s\n",ERR_error_string(rc, NULL));
  880. */
  881. ERR_print_errors_fp(stdout);
  882. # endif
  883. result = STATE_CRITICAL;
  884. } else {
  885. if (sslprm.log_opts & SSL_LogVersion)
  886. logit(LOG_NOTICE, "Remote %s - SSL Version: %s", rem_host, SSL_get_version(ssl));
  887. if (sslprm.log_opts & SSL_LogCipher) {
  888. # if (defined(__sun) && defined(SOLARIS_10)) || defined(_AIX) || defined(__hpux)
  889. SSL_CIPHER *c = SSL_get_current_cipher(ssl);
  890. # else
  891. const SSL_CIPHER *c = SSL_get_current_cipher(ssl);
  892. # endif
  893. logit(LOG_NOTICE, "Remote %s - %s, Cipher is %s", rem_host,
  894. SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
  895. }
  896. if ((sslprm.log_opts & SSL_LogIfClientCert) || (sslprm.log_opts & SSL_LogCertDetails)) {
  897. char peer_cn[256], buffer[2048];
  898. X509 *peer = SSL_get_peer_certificate(ssl);
  899. if (peer) {
  900. if (sslprm.log_opts & SSL_LogIfClientCert)
  901. logit(LOG_NOTICE, "SSL %s has %s certificate",
  902. rem_host, peer->valid ? "a valid" : "an invalid");
  903. if (sslprm.log_opts & SSL_LogCertDetails) {
  904. logit(LOG_NOTICE, "SSL %s Cert Name: %s", rem_host, peer->name);
  905. X509_NAME_oneline(X509_get_issuer_name(peer), buffer, sizeof(buffer));
  906. logit(LOG_NOTICE, "SSL %s Cert Issuer: %s", rem_host, buffer);
  907. }
  908. } else
  909. logit(LOG_NOTICE, "SSL Did not get certificate from %s", rem_host);
  910. }
  911. }
  912. /* bail if we had errors */
  913. if (result != STATE_OK) {
  914. SSL_CTX_free(ctx);
  915. close(sd);
  916. exit(result);
  917. }
  918. #endif
  919. return result;
  920. }
  921. int send_request()
  922. {
  923. v2_packet *v2_send_packet = NULL;
  924. v3_packet *v3_send_packet = NULL;
  925. u_int32_t calculated_crc32;
  926. int rc, bytes_to_send, pkt_size;
  927. char *send_pkt;
  928. if (packet_ver == NRPE_PACKET_VERSION_2) {
  929. pkt_size = sizeof(v2_packet);
  930. if (payload_size > 0)
  931. pkt_size = sizeof(v2_packet) - MAX_PACKETBUFFER_LENGTH + payload_size;
  932. v2_send_packet = (v2_packet*)calloc(1, pkt_size);
  933. send_pkt = (char *)v2_send_packet;
  934. /* fill the packet with semi-random data */
  935. randomize_buffer((char *)v2_send_packet, pkt_size);
  936. /* initialize response packet data */
  937. v2_send_packet->packet_version = htons(packet_ver);
  938. v2_send_packet->packet_type = htons(QUERY_PACKET);
  939. if (payload_size > 0) {
  940. strncpy(&v2_send_packet->buffer[0], query, payload_size);
  941. v2_send_packet->buffer[payload_size - 1] = '\x0';
  942. } else {
  943. strncpy(&v2_send_packet->buffer[0], query, MAX_PACKETBUFFER_LENGTH);
  944. v2_send_packet->buffer[MAX_PACKETBUFFER_LENGTH - 1] = '\x0';
  945. }
  946. /* calculate the crc 32 value of the packet */
  947. v2_send_packet->crc32_value = 0;
  948. calculated_crc32 = calculate_crc32(send_pkt, pkt_size);
  949. v2_send_packet->crc32_value = htonl(calculated_crc32);
  950. } else {
  951. pkt_size = (sizeof(v3_packet) - 1) + strlen(query) + 1;
  952. if (pkt_size < sizeof(v2_packet))
  953. pkt_size = sizeof(v2_packet);
  954. v3_send_packet = calloc(1, pkt_size);
  955. send_pkt = (char *)v3_send_packet;
  956. /* initialize response packet data */
  957. v3_send_packet->packet_version = htons(packet_ver);
  958. v3_send_packet->packet_type = htons(QUERY_PACKET);
  959. v3_send_packet->alignment = 0;
  960. v3_send_packet->buffer_length = htonl(pkt_size - sizeof(v3_packet) + 1);
  961. strcpy(&v3_send_packet->buffer[0], query);
  962. /* calculate the crc 32 value of the packet */
  963. v3_send_packet->crc32_value = 0;
  964. calculated_crc32 = calculate_crc32((char *)v3_send_packet, pkt_size);
  965. v3_send_packet->crc32_value = htonl(calculated_crc32);
  966. }
  967. /* send the request to the remote */
  968. bytes_to_send = pkt_size;
  969. if (use_ssl == FALSE)
  970. rc = sendall(sd, (char *)send_pkt, &bytes_to_send);
  971. #ifdef HAVE_SSL
  972. else {
  973. rc = SSL_write(ssl, send_pkt, bytes_to_send);
  974. if (rc < 0)
  975. rc = -1;
  976. }
  977. #endif
  978. if (v3_send_packet)
  979. free(v3_send_packet);
  980. if (v2_send_packet)
  981. free(v2_send_packet);
  982. if (rc == -1) {
  983. printf("CHECK_NRPE: Error sending query to host.\n");
  984. close(sd);
  985. return STATE_UNKNOWN;
  986. }
  987. return STATE_OK;
  988. }
  989. int read_response()
  990. {
  991. v2_packet *v2_receive_packet = NULL;
  992. v3_packet *v3_receive_packet = NULL;
  993. u_int32_t packet_crc32;
  994. u_int32_t calculated_crc32;
  995. int32_t pkt_size;
  996. int rc, result;
  997. alarm(0);
  998. set_sig_handlers();
  999. #ifdef HAVE_SSL
  1000. rc = read_packet(sd, ssl, &v2_receive_packet, &v3_receive_packet);
  1001. #else
  1002. rc = read_packet(sd, NULL, &v2_receive_packet, &v3_receive_packet);
  1003. #endif
  1004. alarm(0);
  1005. /* close the connection */
  1006. #ifdef HAVE_SSL
  1007. if (use_ssl == TRUE) {
  1008. SSL_shutdown(ssl);
  1009. SSL_free(ssl);
  1010. SSL_CTX_free(ctx);
  1011. }
  1012. #endif
  1013. graceful_close(sd, 1000);
  1014. /* recv() error */
  1015. if (rc < 0) {
  1016. if (packet_ver == NRPE_PACKET_VERSION_3) {
  1017. if (v3_receive_packet)
  1018. free(v3_receive_packet);
  1019. return -1;
  1020. }
  1021. if (v2_receive_packet)
  1022. free(v2_receive_packet);
  1023. return STATE_UNKNOWN;
  1024. } else if (rc == 0) {
  1025. /* server disconnected */
  1026. printf("CHECK_NRPE: Received 0 bytes from daemon. Check "
  1027. "the remote server logs for error messages.\n");
  1028. if (packet_ver == NRPE_PACKET_VERSION_3) {
  1029. if (v3_receive_packet)
  1030. free(v3_receive_packet);
  1031. } else if (v2_receive_packet)
  1032. free(v2_receive_packet);
  1033. return STATE_UNKNOWN;
  1034. }
  1035. /* check the crc 32 value */
  1036. if (packet_ver == NRPE_PACKET_VERSION_3) {
  1037. pkt_size = (sizeof(v3_packet) - 1) + ntohl(v3_receive_packet->buffer_length);
  1038. packet_crc32 = ntohl(v3_receive_packet->crc32_value);
  1039. v3_receive_packet->crc32_value = 0L;
  1040. v3_receive_packet->alignment = 0;
  1041. calculated_crc32 = calculate_crc32((char *)v3_receive_packet, pkt_size);
  1042. } else {
  1043. pkt_size = sizeof(v2_packet);
  1044. if (payload_size > 0)
  1045. pkt_size = sizeof(v2_packet) - MAX_PACKETBUFFER_LENGTH + payload_size;
  1046. packet_crc32 = ntohl(v2_receive_packet->crc32_value);
  1047. v2_receive_packet->crc32_value = 0L;
  1048. calculated_crc32 = calculate_crc32((char *)v2_receive_packet, pkt_size);
  1049. }
  1050. if (packet_crc32 != calculated_crc32) {
  1051. printf("CHECK_NRPE: Response packet had invalid CRC32.\n");
  1052. close(sd);
  1053. if (packet_ver == NRPE_PACKET_VERSION_3) {
  1054. if (v3_receive_packet)
  1055. free(v3_receive_packet);
  1056. } else if (v2_receive_packet)
  1057. free(v2_receive_packet);
  1058. return STATE_UNKNOWN;
  1059. }
  1060. /* get the return code from the remote plugin */
  1061. /* and print the output returned by the daemon */
  1062. if (packet_ver == NRPE_PACKET_VERSION_3) {
  1063. result = ntohs(v3_receive_packet->result_code);
  1064. if (v3_receive_packet->buffer_length == 0)
  1065. printf("CHECK_NRPE: No output returned from daemon.\n");
  1066. else
  1067. printf("%s\n", v3_receive_packet->buffer);
  1068. } else {
  1069. result = ntohs(v2_receive_packet->result_code);
  1070. if (payload_size > 0)
  1071. v2_receive_packet->buffer[payload_size - 1] = '\x0';
  1072. else
  1073. v2_receive_packet->buffer[MAX_PACKETBUFFER_LENGTH - 1] = '\x0';
  1074. if (!strcmp(v2_receive_packet->buffer, ""))
  1075. printf("CHECK_NRPE: No output returned from daemon.\n");
  1076. else if (strstr(v2_receive_packet->buffer, "Invalid packet version.3") != NULL)
  1077. /* NSClient++ doesn't recognize it */
  1078. return -1;
  1079. else
  1080. printf("%s\n", v2_receive_packet->buffer);
  1081. }
  1082. if (packet_ver == NRPE_PACKET_VERSION_3) {
  1083. if (v3_receive_packet)
  1084. free(v3_receive_packet);
  1085. } else if (v2_receive_packet)
  1086. free(v2_receive_packet);
  1087. return result;
  1088. }
  1089. int read_packet(int sock, void *ssl_ptr, v2_packet ** v2_pkt, v3_packet ** v3_pkt)
  1090. {
  1091. v2_packet packet;
  1092. int32_t pkt_size, common_size, tot_bytes, bytes_to_recv, buffer_size, bytes_read = 0;
  1093. int rc;
  1094. char *buff_ptr;
  1095. /* Read only the part that's common between versions 2 & 3 */
  1096. common_size = tot_bytes = bytes_to_recv = (char *)packet.buffer - (char *)&packet;
  1097. if (use_ssl == FALSE) {
  1098. rc = recvall(sock, (char *)&packet, &tot_bytes, socket_timeout);
  1099. if (rc <= 0 || rc != bytes_to_recv) {
  1100. if (rc < bytes_to_recv) {
  1101. if (packet_ver != NRPE_PACKET_VERSION_3)
  1102. printf("CHECK_NRPE: Receive header underflow - "
  1103. "only %d bytes received (%ld expected).\n",
  1104. rc, sizeof(bytes_to_recv));
  1105. }
  1106. return -1;
  1107. }
  1108. packet_ver = ntohs(packet.packet_version);
  1109. if (packet_ver != NRPE_PACKET_VERSION_2 && packet_ver != NRPE_PACKET_VERSION_3) {
  1110. printf("CHECK_NRPE: Invalid packet version received from server.\n");
  1111. return -1;
  1112. }
  1113. if (ntohs(packet.packet_type) != RESPONSE_PACKET) {
  1114. printf("CHECK_NRPE: Invalid packet type received from server.\n");
  1115. return -1;
  1116. }
  1117. if (packet_ver == NRPE_PACKET_VERSION_2) {
  1118. pkt_size = sizeof(v2_packet);
  1119. if (payload_size > 0) {
  1120. pkt_size = common_size + payload_size;
  1121. buffer_size = payload_size;
  1122. } else
  1123. buffer_size = pkt_size - common_size;
  1124. if ((*v2_pkt = calloc(1, pkt_size)) == NULL) {
  1125. logit(LOG_ERR, "Error: Could not allocate memory for packet");
  1126. return -1;
  1127. }
  1128. memcpy(*v2_pkt, &packet, common_size);
  1129. buff_ptr = (*v2_pkt)->buffer;
  1130. memset(buff_ptr, 0, buffer_size);
  1131. } else {
  1132. pkt_size = sizeof(v3_packet) - 1;
  1133. /* Read the alignment filler */
  1134. bytes_to_recv = sizeof(int16_t);
  1135. rc = recvall(sock, (char *)&buffer_size, &bytes_to_recv, socket_timeout);
  1136. if (rc <= 0 || bytes_to_recv != sizeof(int16_t))
  1137. return -1;
  1138. tot_bytes += rc;
  1139. /* Read the buffer size */
  1140. bytes_to_recv = sizeof(buffer_size);
  1141. rc = recvall(sock, (char *)&buffer_size, &bytes_to_recv, socket_timeout);
  1142. if (rc <= 0 || bytes_to_recv != sizeof(buffer_size))
  1143. return -1;
  1144. tot_bytes += rc;
  1145. buffer_size = ntohl(buffer_size);
  1146. pkt_size += buffer_size;
  1147. if ((*v3_pkt = calloc(1, pkt_size)) == NULL) {
  1148. logit(LOG_ERR, "Error: Could not allocate memory for packet");
  1149. return -1;
  1150. }
  1151. memcpy(*v3_pkt, &packet, common_size);
  1152. (*v3_pkt)->buffer_length = htonl(buffer_size);
  1153. buff_ptr = (*v3_pkt)->buffer;
  1154. }
  1155. bytes_to_recv = buffer_size;
  1156. rc = recvall(sock, buff_ptr, &bytes_to_recv, socket_timeout);
  1157. if (rc <= 0 || rc != buffer_size) {
  1158. if (packet_ver == NRPE_PACKET_VERSION_3) {
  1159. free(*v3_pkt);
  1160. *v3_pkt = NULL;
  1161. } else {
  1162. free(*v2_pkt);
  1163. *v2_pkt = NULL;
  1164. }
  1165. if (rc < buffer_size)
  1166. printf("CHECK_NRPE: Receive underflow - only %d bytes received "
  1167. "(%ld expected).\n", rc, sizeof(buffer_size));
  1168. return -1;
  1169. } else
  1170. tot_bytes += rc;
  1171. }
  1172. #ifdef HAVE_SSL
  1173. else {
  1174. SSL *ssl = (SSL *) ssl_ptr;
  1175. while (((rc = SSL_read(ssl, &packet, bytes_to_recv)) <= 0)
  1176. && (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)) {
  1177. }
  1178. if (rc <= 0 || rc != bytes_to_recv) {
  1179. if (rc < bytes_to_recv) {
  1180. if (packet_ver != NRPE_PACKET_VERSION_3)
  1181. printf("CHECK_NRPE: Receive header underflow - only %d bytes "
  1182. "received (%ld expected).\n", rc, sizeof(bytes_to_recv));
  1183. }
  1184. return -1;
  1185. }
  1186. packet_ver = ntohs(packet.packet_version);
  1187. if (packet_ver != NRPE_PACKET_VERSION_2 && packet_ver != NRPE_PACKET_VERSION_3) {
  1188. printf("CHECK_NRPE: Invalid packet version received from server.\n");
  1189. return -1;
  1190. }
  1191. if (ntohs(packet.packet_type) != RESPONSE_PACKET) {
  1192. printf("CHECK_NRPE: Invalid packet type received from server.\n");
  1193. return -1;
  1194. }
  1195. if (packet_ver == NRPE_PACKET_VERSION_2) {
  1196. pkt_size = sizeof(v2_packet);
  1197. if (payload_size > 0) {
  1198. pkt_size = common_size + payload_size;
  1199. buffer_size = payload_size;
  1200. } else
  1201. buffer_size = pkt_size - common_size;
  1202. if ((*v2_pkt = calloc(1, pkt_size)) == NULL) {
  1203. logit(LOG_ERR, "Error: Could not allocate memory for packet");
  1204. return -1;
  1205. }
  1206. memcpy(*v2_pkt, &packet, common_size);
  1207. buff_ptr = (*v2_pkt)->buffer;
  1208. memset(buff_ptr, 0, buffer_size);
  1209. } else {
  1210. pkt_size = sizeof(v3_packet) - 1;
  1211. /* Read the alignment filler */
  1212. bytes_to_recv = sizeof(int16_t);
  1213. while (((rc = SSL_read(ssl, &buffer_size, bytes_to_recv)) <= 0)
  1214. && (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)) {
  1215. }
  1216. if (rc <= 0 || bytes_to_recv != sizeof(int16_t))
  1217. return -1;
  1218. tot_bytes += rc;
  1219. /* Read the buffer size */
  1220. bytes_to_recv = sizeof(buffer_size);
  1221. while (((rc = SSL_read(ssl, &buffer_size, bytes_to_recv)) <= 0)
  1222. && (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)) {
  1223. }
  1224. if (rc <= 0 || bytes_to_recv != sizeof(buffer_size))
  1225. return -1;
  1226. tot_bytes += rc;
  1227. buffer_size = ntohl(buffer_size);
  1228. pkt_size += buffer_size;
  1229. if ((*v3_pkt = calloc(1, pkt_size)) == NULL) {
  1230. logit(LOG_ERR, "Error: Could not allocate memory for packet");
  1231. return -1;
  1232. }
  1233. memcpy(*v3_pkt, &packet, common_size);
  1234. (*v3_pkt)->buffer_length = htonl(buffer_size);
  1235. buff_ptr = (*v3_pkt)->buffer;
  1236. }
  1237. bytes_to_recv = buffer_size;
  1238. for (;;) {
  1239. while (((rc = SSL_read(ssl, &buff_ptr[bytes_read], bytes_to_recv)) <= 0)
  1240. && (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)) {
  1241. }
  1242. if (rc <= 0)
  1243. break;
  1244. bytes_read += rc;
  1245. bytes_to_recv -= rc;
  1246. }
  1247. buff_ptr[bytes_read] = 0;
  1248. if (rc < 0 || bytes_read != buffer_size) {
  1249. if (packet_ver == NRPE_PACKET_VERSION_3) {
  1250. free(*v3_pkt);
  1251. *v3_pkt = NULL;
  1252. } else {
  1253. free(*v2_pkt);
  1254. *v2_pkt = NULL;
  1255. }
  1256. if (bytes_read != buffer_size) {
  1257. if (packet_ver == NRPE_PACKET_VERSION_3)
  1258. printf("CHECK_NRPE: Receive buffer size - %ld bytes received "
  1259. "(%ld expected).\n", (long)bytes_read, sizeof(buffer_size));
  1260. else
  1261. printf("CHECK_NRPE: Receive underflow - only %ld bytes received "
  1262. "(%ld expected).\n", (long)bytes_read, sizeof(buffer_size));
  1263. }
  1264. return -1;
  1265. } else
  1266. tot_bytes += rc;
  1267. }
  1268. #endif
  1269. return tot_bytes;
  1270. }
  1271. #ifdef HAVE_SSL
  1272. int verify_callback(int preverify_ok, X509_STORE_CTX * ctx)
  1273. {
  1274. char name[256], issuer[256];
  1275. X509 *err_cert;
  1276. int err;
  1277. SSL *ssl;
  1278. if (preverify_ok || ((sslprm.log_opts & SSL_LogCertDetails) == 0))
  1279. return preverify_ok;
  1280. err_cert = X509_STORE_CTX_get_current_cert(ctx);
  1281. err = X509_STORE_CTX_get_error(ctx);
  1282. /* Get the pointer to the SSL of the current connection */
  1283. ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
  1284. X509_NAME_oneline(X509_get_subject_name(err_cert), name, 256);
  1285. X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), issuer, 256);
  1286. if (!preverify_ok && sslprm.client_certs >= Ask_For_Cert
  1287. && (sslprm.log_opts & SSL_LogCertDetails)) {
  1288. logit(LOG_ERR, "SSL Client has an invalid certificate: %s (issuer=%s) err=%d:%s",
  1289. name, issuer, err, X509_verify_cert_error_string(err));
  1290. }
  1291. return preverify_ok;
  1292. }
  1293. #endif
  1294. void alarm_handler(int sig)
  1295. {
  1296. const char msg1[] = "CHECK_NRPE STATE ";
  1297. const char msg2[] = ": Socket timeout after ";
  1298. const char msg3[] = " seconds.\n";
  1299. const char *text = state_text(timeout_return_code);
  1300. size_t lth1 = 0, lth2 = 0;
  1301. for (lth1 = 0; lth1 < 10; ++lth1)
  1302. if (text[lth1] == 0)
  1303. break;
  1304. for (lth2 = 0; lth2 < 10; ++lth2)
  1305. if (timeout_txt[lth2] == 0)
  1306. break;
  1307. write(STDOUT_FILENO, msg1, sizeof(msg1) - 1);
  1308. write(STDOUT_FILENO, text, lth1);
  1309. write(STDOUT_FILENO, msg2, sizeof(msg2) - 1);
  1310. write(STDOUT_FILENO, timeout_txt, lth2);
  1311. write(STDOUT_FILENO, msg3, sizeof(msg3) - 1);
  1312. exit(timeout_return_code);
  1313. }
  1314. /* submitted by Mark Plaksin 08/31/2006 */
  1315. int graceful_close(int sd, int timeout)
  1316. {
  1317. fd_set in;
  1318. struct timeval tv;
  1319. char buf[1000];
  1320. /* send FIN packet */
  1321. shutdown(sd, SHUT_WR);
  1322. for (;;) {
  1323. FD_ZERO(&in);
  1324. FD_SET(sd, &in);
  1325. tv.tv_sec = timeout / 1000;
  1326. tv.tv_usec = (timeout % 1000) * 1000;
  1327. /* timeout or error */
  1328. if (1 != select(sd + 1, &in, NULL, NULL, &tv))
  1329. break;
  1330. /* no more data (FIN or RST) */
  1331. if (0 >= recv(sd, buf, sizeof(buf), 0))
  1332. break;
  1333. }
  1334. #ifdef HAVE_CLOSESOCKET
  1335. closesocket(sd);
  1336. #else
  1337. close(sd);
  1338. #endif
  1339. return OK;
  1340. }