check_nrpe.c 44 KB

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