check_nrpe.c 45 KB

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