check_nrpe.c 50 KB

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