check_nrpe.c 42 KB

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