check_nrpe.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. /********************************************************************************************
  2. *
  3. * CHECK_NRPE.C - NRPE Plugin For Nagios
  4. * Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)
  5. * License: GPL
  6. *
  7. * Last Modified: 11-09-2015
  8. *
  9. * Command line: CHECK_NRPE -H <host_address> [-p port] [-c command] [-to to_sec]
  10. *
  11. * Description:
  12. *
  13. * This plugin will attempt to connect to the NRPE daemon on the specified server and port.
  14. * The daemon will attempt to run the command defined as [command]. Program output and
  15. * return code are sent back from the daemon and displayed as this plugin's own output and
  16. * return code.
  17. *
  18. ********************************************************************************************/
  19. #include "config.h"
  20. #include "common.h"
  21. #include "utils.h"
  22. #define DEFAULT_NRPE_COMMAND "_NRPE_CHECK" /* check version of NRPE daemon */
  23. u_short server_port = DEFAULT_SERVER_PORT;
  24. char *server_name = NULL;
  25. char *bind_address = NULL;
  26. struct sockaddr_storage hostaddr;
  27. int address_family = AF_UNSPEC;
  28. char *command_name = NULL;
  29. int socket_timeout = DEFAULT_SOCKET_TIMEOUT;
  30. int timeout_return_code = STATE_CRITICAL;
  31. int sd;
  32. char rem_host[MAX_HOST_ADDRESS_LENGTH];
  33. char query[MAX_INPUT_BUFFER] = "";
  34. int show_help = FALSE;
  35. int show_license = FALSE;
  36. int show_version = FALSE;
  37. int packet_ver = NRPE_PACKET_VERSION_3;
  38. #ifdef HAVE_SSL
  39. # ifdef __sun
  40. SSL_METHOD *meth;
  41. # else
  42. const SSL_METHOD *meth;
  43. # endif
  44. SSL_CTX *ctx;
  45. SSL *ssl;
  46. int use_ssl = TRUE;
  47. int ssl_opts = SSL_OP_ALL;
  48. #else
  49. int use_ssl = FALSE;
  50. #endif
  51. /* SSL/TLS parameters */
  52. typedef enum _SSL_VER {
  53. SSLv2 = 1, SSLv2_plus, SSLv3, SSLv3_plus, TLSv1,
  54. TLSv1_plus, TLSv1_1, TLSv1_1_plus, TLSv1_2, TLSv1_2_plus
  55. } SslVer;
  56. typedef enum _CLNT_CERTS { Ask_For_Cert = 1, Require_Cert = 2 } ClntCerts;
  57. typedef enum _SSL_LOGGING {
  58. SSL_NoLogging = 0, SSL_LogStartup = 1, SSL_LogIpAddr = 2,
  59. SSL_LogVersion = 4, SSL_LogCipher = 8, SSL_LogIfClientCert = 16,
  60. SSL_LogCertDetails = 32
  61. } SslLogging;
  62. struct _SSL_PARMS {
  63. char *cert_file;
  64. char *cacert_file;
  65. char *privatekey_file;
  66. char cipher_list[MAX_FILENAME_LENGTH];
  67. SslVer ssl_min_ver;
  68. int allowDH;
  69. ClntCerts client_certs;
  70. SslLogging log_opts;
  71. } sslprm = {
  72. NULL, NULL, NULL, "ALL:!MD5:@STRENGTH", TLSv1_plus, TRUE, 0, SSL_NoLogging};
  73. int process_arguments(int, char **);
  74. void usage(int result);
  75. void setup_ssl();
  76. void set_sig_hadlers();
  77. int connect_to_remote();
  78. int send_request();
  79. int read_response();
  80. int read_packet(int sock, void *ssl_ptr, v2_packet * v2_pkt, v3_packet ** v3_pkt);
  81. #ifdef HAVE_SSL
  82. static int verify_callback(int ok, X509_STORE_CTX * ctx);
  83. #endif
  84. void alarm_handler(int);
  85. int graceful_close(int, int);
  86. int main(int argc, char **argv)
  87. {
  88. int16_t result;
  89. result = process_arguments(argc, argv);
  90. if (result != OK || show_help == TRUE || show_license == TRUE || show_version == TRUE)
  91. usage(result); /* usage() will call exit() */
  92. generate_crc32_table(); /* generate the CRC 32 table */
  93. setup_ssl(); /* Do all the SSL/TLS set up */
  94. set_sig_hadlers(); /* initialize alarm signal handling */
  95. result = connect_to_remote(); /* Make the connection */
  96. if (result != STATE_OK) {
  97. alarm(0);
  98. return result;
  99. }
  100. result = send_request(); /* Send the request */
  101. if (result != STATE_OK)
  102. return result;
  103. result = read_response(); /* Get the response */
  104. if (result == -1) {
  105. /* Failure reading from remote, so try version 2 packet */
  106. syslog(LOG_NOTICE, "Remote %s does not support Version 3 Packets", rem_host);
  107. packet_ver = NRPE_PACKET_VERSION_2;
  108. /* Rerun the setup */
  109. setup_ssl();
  110. set_sig_hadlers();
  111. result = connect_to_remote(); /* Connect */
  112. if (result != STATE_OK) {
  113. alarm(0);
  114. return result;
  115. }
  116. result = send_request(); /* Send the request */
  117. if (result != STATE_OK)
  118. return result;
  119. result = read_response(); /* Get the response */
  120. }
  121. if (result != -1)
  122. syslog(LOG_NOTICE, "Remote %s accepted a Version %d Packet", rem_host, packet_ver);
  123. return result;
  124. }
  125. /* process command line arguments */
  126. int process_arguments(int argc, char **argv)
  127. {
  128. char optchars[MAX_INPUT_BUFFER];
  129. int argindex = 0;
  130. int c = 1;
  131. int i = 1;
  132. #ifdef HAVE_GETOPT_LONG
  133. int option_index = 0;
  134. static struct option long_options[] = {
  135. {"host", required_argument, 0, 'H'},
  136. {"bind", required_argument, 0, 'b'},
  137. {"command", required_argument, 0, 'c'},
  138. {"args", required_argument, 0, 'a'},
  139. {"no-ssl", no_argument, 0, 'n'},
  140. {"unknown-timeout", no_argument, 0, 'u'},
  141. {"v2-packets-only", no_argument, 0, '2'},
  142. {"ipv4", no_argument, 0, '4'},
  143. {"ipv6", no_argument, 0, '6'},
  144. {"no-adh", no_argument, 0, 'd'},
  145. {"use-adh", optional_argument, 0, 'd'},
  146. {"ssl-version", required_argument, 0, 'S'},
  147. {"cipher-list", required_argument, 0, 'L'},
  148. {"client-cert", required_argument, 0, 'C'},
  149. {"key-file", required_argument, 0, 'K'},
  150. {"ca-cert-file", required_argument, 0, 'A'},
  151. {"ssl-logging", required_argument, 0, 's'},
  152. {"timeout", required_argument, 0, 't'},
  153. {"port", required_argument, 0, 'p'},
  154. {"help", no_argument, 0, 'h'},
  155. {"license", no_argument, 0, 'l'},
  156. {0, 0, 0, 0}
  157. };
  158. #endif
  159. /* no options were supplied */
  160. if (argc < 2)
  161. return ERROR;
  162. snprintf(optchars, MAX_INPUT_BUFFER, "H:b:c:a:t:p:S:L:C:K:A:d::s:46hlnuV");
  163. while (1) {
  164. #ifdef HAVE_GETOPT_LONG
  165. c = getopt_long(argc, argv, optchars, long_options, &option_index);
  166. #else
  167. c = getopt(argc, argv, optchars);
  168. #endif
  169. if (c == -1 || c == EOF || argindex > 0)
  170. break;
  171. /* process all arguments */
  172. switch (c) {
  173. case '?':
  174. case 'h':
  175. show_help = TRUE;
  176. break;
  177. case 'b':
  178. bind_address = strdup(optarg);
  179. break;
  180. case 'V':
  181. show_version = TRUE;
  182. break;
  183. case 'l':
  184. show_license = TRUE;
  185. break;
  186. case 't':
  187. socket_timeout = atoi(optarg);
  188. if (socket_timeout <= 0)
  189. return ERROR;
  190. break;
  191. case 'p':
  192. server_port = atoi(optarg);
  193. if (server_port <= 0)
  194. return ERROR;
  195. break;
  196. case 'H':
  197. server_name = strdup(optarg);
  198. break;
  199. case 'c':
  200. command_name = strdup(optarg);
  201. break;
  202. case 'a':
  203. argindex = optind;
  204. break;
  205. case 'n':
  206. use_ssl = FALSE;
  207. break;
  208. case 'u':
  209. timeout_return_code = STATE_UNKNOWN;
  210. break;
  211. case '2':
  212. packet_ver = NRPE_PACKET_VERSION_2;
  213. break;
  214. case '4':
  215. address_family = AF_INET;
  216. break;
  217. case '6':
  218. address_family = AF_INET6;
  219. break;
  220. case 'd':
  221. if (optarg)
  222. sslprm.allowDH = atoi(optarg);
  223. else
  224. sslprm.allowDH = 0;
  225. if (sslprm.allowDH < 0 || sslprm.allowDH > 2)
  226. return ERROR;
  227. break;
  228. case 'A':
  229. sslprm.cacert_file = strdup(optarg);
  230. break;
  231. case 'C':
  232. sslprm.cert_file = strdup(optarg);
  233. break;
  234. case 'K':
  235. sslprm.privatekey_file = strdup(optarg);
  236. break;
  237. case 'S':
  238. if (!strcmp(optarg, "SSLv2"))
  239. sslprm.ssl_min_ver = SSLv2;
  240. else if (!strcmp(optarg, "SSLv2+"))
  241. sslprm.ssl_min_ver = SSLv2_plus;
  242. else if (!strcmp(optarg, "SSLv3"))
  243. sslprm.ssl_min_ver = SSLv3;
  244. else if (!strcmp(optarg, "SSLv3+"))
  245. sslprm.ssl_min_ver = SSLv3_plus;
  246. else if (!strcmp(optarg, "TLSv1"))
  247. sslprm.ssl_min_ver = TLSv1;
  248. else if (!strcmp(optarg, "TLSv1+"))
  249. sslprm.ssl_min_ver = TLSv1_plus;
  250. else if (!strcmp(optarg, "TLSv1.1"))
  251. sslprm.ssl_min_ver = TLSv1_1;
  252. else if (!strcmp(optarg, "TLSv1.1+"))
  253. sslprm.ssl_min_ver = TLSv1_1_plus;
  254. else if (!strcmp(optarg, "TLSv1.2"))
  255. sslprm.ssl_min_ver = TLSv1_2;
  256. else if (!strcmp(optarg, "TLSv1.2+"))
  257. sslprm.ssl_min_ver = TLSv1_2_plus;
  258. else
  259. return ERROR;
  260. break;
  261. case 'L':
  262. strncpy(sslprm.cipher_list, optarg, sizeof(sslprm.cipher_list) - 1);
  263. sslprm.cipher_list[sizeof(sslprm.cipher_list) - 1] = '\0';
  264. break;
  265. case 's':
  266. sslprm.log_opts = strtoul(optarg, NULL, 0);
  267. break;
  268. default:
  269. return ERROR;
  270. break;
  271. }
  272. }
  273. /* determine (base) command query */
  274. snprintf(query, sizeof(query), "%s",
  275. (command_name == NULL) ? DEFAULT_NRPE_COMMAND : command_name);
  276. query[sizeof(query) - 1] = '\x0';
  277. /* get the command args */
  278. if (argindex > 0) {
  279. for (c = argindex - 1; c < argc; c++) {
  280. i = sizeof(query) - strlen(query) - 2;
  281. if (i <= 0)
  282. break;
  283. strcat(query, "!");
  284. strncat(query, argv[c], i);
  285. query[sizeof(query) - 1] = '\x0';
  286. }
  287. }
  288. /* make sure required args were supplied */
  289. if (server_name == NULL && show_help == FALSE && show_version == FALSE
  290. && show_license == FALSE)
  291. return ERROR;
  292. return OK;
  293. }
  294. void usage(int result)
  295. {
  296. if (result != OK)
  297. printf("Incorrect command line arguments supplied\n");
  298. printf("\n");
  299. printf("NRPE Plugin for Nagios\n");
  300. printf("Copyright (c) 1999-2008 Ethan Galstad (nagios@nagios.org)\n");
  301. printf("Version: %s\n", PROGRAM_VERSION);
  302. printf("Last Modified: %s\n", MODIFICATION_DATE);
  303. printf("License: GPL v2 with exemptions (-l for more info)\n");
  304. #ifdef HAVE_SSL
  305. printf("SSL/TLS Available: OpenSSL 0.9.6 or higher required\n");
  306. #endif
  307. printf("\n");
  308. if (result != OK || show_help == TRUE) {
  309. printf("Usage: check_nrpe -H <host> [-2] [-4] [-6] [-n] [-u] [-V] [-l] [-d <num>]\n"
  310. " [-S <ssl version> [-L <cipherlist>] [-C <clientcert>]\n"
  311. " [-K <key>] [-A <ca-certificate>] [-s <logopts>] [-b <bindaddr>]\n"
  312. " [-p <port>] [-t <timeout>] [-c <command>] [-a <arglist...>]\n");
  313. printf("\n");
  314. printf("Options:\n");
  315. printf(" <host> = The address of the host running the NRPE daemon\n");
  316. printf(" -2 = Only use Version 2 packets, not Version 3\n");
  317. printf(" -4 = bind to ipv4 only\n");
  318. printf(" -6 = bind to ipv6 only\n");
  319. printf(" -n = Do no use SSL\n");
  320. printf
  321. (" -u = Make socket timeouts return UNKNOWN state instead of CRITICAL\n");
  322. printf(" -V = Show version\n");
  323. printf(" -l = Show license\n");
  324. printf(" -d = Don't use Anonymous Diffie Hellman\n");
  325. printf(" -<num> = Anonymous Diffie Hellman use:\n");
  326. printf(" 0 = Don't use Anonymous Diffie Hellman\n");
  327. printf(" (This will be the default in a future release.)\n");
  328. printf(" 1 = Allow Anonymous Diffie Hellman\n");
  329. printf(" 2 = Force Anonymous Diffie Hellman\n");
  330. printf(" <bindaddr> = bind to local address\n");
  331. printf
  332. (" <ssl ver> = The SSL/TLS version to use. Can be any one of: SSLv2 (only),\n");
  333. printf(" SSLv2+ (or above), SSLv3 (only), SSLv3+ (or above),\n");
  334. printf(" TLSv1 (only), TLSv1+ (or above DEFAULT), TLSv1.1 (only),\n");
  335. printf(" TLSv1.1+ (or above), TLSv1.2 (only), TLSv1.2+ (or above)\n");
  336. printf(" <cipherlist> = The list of SSL ciphers to use (currently defaults\n");
  337. printf
  338. (" to \"ALL:!MD5:@STRENGTH\". WILL change in a future release.)\n");
  339. printf(" <clientcert> = The client certificate to use for PKI\n");
  340. printf(" <key> = The private key to use with the client certificate\n");
  341. printf(" <ca-cert> = The CA certificate to use for PKI\n");
  342. printf(" <logopts> = SSL Logging Options\n");
  343. printf(" [port] = The port on which the daemon is running (default=%d)\n",
  344. DEFAULT_SERVER_PORT);
  345. printf(" [timeout] = Number of seconds before connection times out (default=%d)\n",
  346. DEFAULT_SOCKET_TIMEOUT);
  347. printf(" [command] = The name of the command that the remote daemon should run\n");
  348. printf(" [arglist] = Optional arguments that should be passed to the command,\n");
  349. printf(" separated by a space. If provided, this must be the last\n");
  350. printf(" option supplied on the command line.\n");
  351. printf("\n");
  352. printf("Note:\n");
  353. printf
  354. ("This plugin requires that you have the NRPE daemon running on the remote host.\n");
  355. printf
  356. ("You must also have configured the daemon to associate a specific plugin command\n");
  357. printf("with the [command] option you are specifying here. Upon receipt of the\n");
  358. printf
  359. ("[command] argument, the NRPE daemon will run the appropriate plugin command and\n");
  360. printf
  361. ("send the plugin output and return code back to *this* plugin. This allows you\n");
  362. printf
  363. ("to execute plugins on remote hosts and 'fake' the results to make Nagios think\n");
  364. printf("the plugin is being run locally.\n");
  365. printf("\n");
  366. }
  367. if (show_license == TRUE)
  368. display_license();
  369. exit(STATE_UNKNOWN);
  370. }
  371. void setup_ssl()
  372. {
  373. #ifdef HAVE_SSL
  374. int vrfy;
  375. if (sslprm.log_opts & SSL_LogStartup) {
  376. char *val;
  377. syslog(LOG_INFO, "SSL Certificate File: %s",
  378. sslprm.cert_file ? sslprm.cert_file : "None");
  379. syslog(LOG_INFO, "SSL Private Key File: %s",
  380. sslprm.privatekey_file ? sslprm.privatekey_file : "None");
  381. syslog(LOG_INFO, "SSL CA Certificate File: %s",
  382. sslprm.cacert_file ? sslprm.cacert_file : "None");
  383. if (sslprm.allowDH < 2)
  384. syslog(LOG_INFO, "SSL Cipher List: %s", sslprm.cipher_list);
  385. else
  386. syslog(LOG_INFO, "SSL Cipher List: ADH");
  387. syslog(LOG_INFO, "SSL Allow ADH: %s",
  388. sslprm.allowDH == 0 ? "No" : (sslprm.allowDH == 1 ? "Allow" : "Require"));
  389. syslog(LOG_INFO, "SSL Log Options: 0x%02x", sslprm.log_opts);
  390. switch (sslprm.ssl_min_ver) {
  391. case SSLv2:
  392. val = "SSLv2";
  393. break;
  394. case SSLv2_plus:
  395. val = "SSLv2 And Above";
  396. break;
  397. case SSLv3:
  398. val = "SSLv3";
  399. break;
  400. case SSLv3_plus:
  401. val = "SSLv3_plus And Above";
  402. break;
  403. case TLSv1:
  404. val = "TLSv1";
  405. break;
  406. case TLSv1_plus:
  407. val = "TLSv1_plus And Above";
  408. break;
  409. case TLSv1_1:
  410. val = "TLSv1_1";
  411. break;
  412. case TLSv1_1_plus:
  413. val = "TLSv1_1_plus And Above";
  414. break;
  415. case TLSv1_2:
  416. val = "TLSv1_2";
  417. break;
  418. case TLSv1_2_plus:
  419. val = "TLSv1_2_plus And Above";
  420. break;
  421. default:
  422. val = "INVALID VALUE!";
  423. break;
  424. }
  425. syslog(LOG_INFO, "SSL Version: %s", val);
  426. }
  427. /* initialize SSL */
  428. if (use_ssl == TRUE) {
  429. SSL_load_error_strings();
  430. SSL_library_init();
  431. meth = SSLv23_client_method();
  432. # ifndef OPENSSL_NO_SSL2
  433. if (sslprm.ssl_min_ver == SSLv2)
  434. meth = SSLv2_client_method();
  435. # endif
  436. # ifndef OPENSSL_NO_SSL3
  437. if (sslprm.ssl_min_ver == SSLv3)
  438. meth = SSLv3_client_method();
  439. # endif
  440. if (sslprm.ssl_min_ver == TLSv1)
  441. meth = TLSv1_client_method();
  442. if (sslprm.ssl_min_ver == TLSv1_1)
  443. meth = TLSv1_1_client_method();
  444. if (sslprm.ssl_min_ver == TLSv1_2)
  445. meth = TLSv1_2_client_method();
  446. if ((ctx = SSL_CTX_new(meth)) == NULL) {
  447. printf("CHECK_NRPE: Error - could not create SSL context.\n");
  448. exit(STATE_CRITICAL);
  449. }
  450. if (sslprm.ssl_min_ver >= SSLv3) {
  451. ssl_opts |= SSL_OP_NO_SSLv2;
  452. if (sslprm.ssl_min_ver >= TLSv1)
  453. ssl_opts |= SSL_OP_NO_SSLv3;
  454. }
  455. SSL_CTX_set_options(ctx, ssl_opts);
  456. if (sslprm.cert_file != NULL && sslprm.privatekey_file != NULL) {
  457. if (!SSL_CTX_use_certificate_file(ctx, sslprm.cert_file, SSL_FILETYPE_PEM)) {
  458. SSL_CTX_free(ctx);
  459. printf("Error: could not use certificate file '%s'.\n", sslprm.cert_file);
  460. exit(STATE_CRITICAL);
  461. }
  462. if (!SSL_CTX_use_PrivateKey_file(ctx, sslprm.privatekey_file, SSL_FILETYPE_PEM)) {
  463. SSL_CTX_free(ctx);
  464. printf("Error: could not use private key file '%s'.\n",
  465. sslprm.privatekey_file);
  466. exit(STATE_CRITICAL);
  467. }
  468. }
  469. if (sslprm.cacert_file != NULL) {
  470. vrfy = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
  471. SSL_CTX_set_verify(ctx, vrfy, verify_callback);
  472. if (!SSL_CTX_load_verify_locations(ctx, sslprm.cacert_file, NULL)) {
  473. SSL_CTX_free(ctx);
  474. printf("Error: could not use CA certificate '%s'.\n", sslprm.cacert_file);
  475. exit(STATE_CRITICAL);
  476. }
  477. }
  478. if (!sslprm.allowDH) {
  479. if (strlen(sslprm.cipher_list) < sizeof(sslprm.cipher_list) - 6)
  480. strcat(sslprm.cipher_list, ":!ADH");
  481. } else {
  482. /* use anonymous DH ciphers */
  483. if (sslprm.allowDH == 2)
  484. strcpy(sslprm.cipher_list, "ADH");
  485. }
  486. if (SSL_CTX_set_cipher_list(ctx, sslprm.cipher_list) == 0) {
  487. SSL_CTX_free(ctx);
  488. printf("Error: Could not set SSL/TLS cipher list: %s", sslprm.cipher_list);
  489. exit(STATE_CRITICAL);
  490. }
  491. }
  492. #endif
  493. }
  494. void set_sig_hadlers()
  495. {
  496. #ifdef HAVE_SIGACTION
  497. struct sigaction sig_action;
  498. #endif
  499. #ifdef HAVE_SIGACTION
  500. sig_action.sa_sigaction = NULL;
  501. sig_action.sa_handler = alarm_handler;
  502. sigfillset(&sig_action.sa_mask);
  503. sig_action.sa_flags = SA_NODEFER | SA_RESTART;
  504. sigaction(SIGALRM, &sig_action, NULL);
  505. #else
  506. signal(SIGALRM, alarm_handler);
  507. #endif /* HAVE_SIGACTION */
  508. /* set socket timeout */
  509. alarm(socket_timeout);
  510. }
  511. int connect_to_remote()
  512. {
  513. struct sockaddr addr;
  514. struct in_addr *inaddr;
  515. socklen_t addrlen;
  516. int result, rc;
  517. /* try to connect to the host at the given port number */
  518. if ((sd =
  519. my_connect(server_name, &hostaddr, server_port, address_family, bind_address)) < 0)
  520. exit(STATE_CRITICAL);
  521. result = STATE_OK;
  522. addrlen = sizeof(addr);
  523. rc = getpeername(sd, (struct sockaddr *)&addr, &addrlen);
  524. if (addr.sa_family == AF_INET) {
  525. struct sockaddr_in *addrin = (struct sockaddr_in *)&addr;
  526. inaddr = &addrin->sin_addr;
  527. } else {
  528. struct sockaddr_in6 *addrin = (struct sockaddr_in6 *)&addr;
  529. inaddr = (struct in_addr *)&addrin->sin6_addr;
  530. }
  531. if (inet_ntop(addr.sa_family, inaddr, rem_host, sizeof(rem_host)) == NULL)
  532. strncpy(rem_host, "Unknown", sizeof(rem_host));
  533. rem_host[MAX_HOST_ADDRESS_LENGTH - 1] = '\0';
  534. if ((sslprm.log_opts & SSL_LogIpAddr) != 0)
  535. syslog(LOG_DEBUG, "Connected to %s", rem_host);
  536. #ifdef HAVE_SSL
  537. if (use_ssl == FALSE)
  538. return result;
  539. /* do SSL handshake */
  540. if ((ssl = SSL_new(ctx)) == NULL) {
  541. printf("CHECK_NRPE: Error - Could not create SSL connection structure.\n");
  542. return STATE_CRITICAL;
  543. }
  544. SSL_set_fd(ssl, sd);
  545. if ((rc = SSL_connect(ssl)) != 1) {
  546. if (sslprm.log_opts & (SSL_LogCertDetails | SSL_LogIfClientCert)) {
  547. int x, nerrs = 0;
  548. rc = 0;
  549. while ((x = ERR_get_error_line_data(NULL, NULL, NULL, NULL)) != 0) {
  550. syslog(LOG_ERR, "Error: Could not complete SSL handshake with %s: %s",
  551. rem_host, ERR_reason_error_string(x));
  552. ++nerrs;
  553. }
  554. if (nerrs == 0)
  555. syslog(LOG_ERR, "Error: Could not complete SSL handshake with %s: %d",
  556. rem_host, SSL_get_error(ssl, rc));
  557. } else
  558. syslog(LOG_ERR, "Error: Could not complete SSL handshake with %s: %d",
  559. rem_host, SSL_get_error(ssl, rc));
  560. printf("CHECK_NRPE: Error - Could not complete SSL handshake with %s: %d\n",
  561. rem_host, SSL_get_error(ssl, rc));
  562. # ifdef DEBUG
  563. printf("SSL_connect=%d\n", rc);
  564. /*
  565. rc = SSL_get_error(ssl, rc);
  566. printf("SSL_get_error=%d\n", rc);
  567. printf("ERR_get_error=%lu\n", ERR_get_error());
  568. printf("%s\n",ERR_error_string(rc, NULL));
  569. */
  570. ERR_print_errors_fp(stdout);
  571. # endif
  572. result = STATE_CRITICAL;
  573. } else {
  574. if (sslprm.log_opts & SSL_LogVersion)
  575. syslog(LOG_NOTICE, "Remote %s - SSL Version: %s", rem_host, SSL_get_version(ssl));
  576. if (sslprm.log_opts & SSL_LogCipher) {
  577. const SSL_CIPHER *c = SSL_get_current_cipher(ssl);
  578. syslog(LOG_NOTICE, "Remote %s - %s, Cipher is %s", rem_host,
  579. SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
  580. }
  581. if ((sslprm.log_opts & SSL_LogIfClientCert) || (sslprm.log_opts & SSL_LogCertDetails)) {
  582. char peer_cn[256], buffer[2048];
  583. X509 *peer = SSL_get_peer_certificate(ssl);
  584. if (peer) {
  585. if (sslprm.log_opts & SSL_LogIfClientCert)
  586. syslog(LOG_NOTICE, "SSL %s has %s certificate",
  587. rem_host, peer->valid ? "a valid" : "an invalid");
  588. if (sslprm.log_opts & SSL_LogCertDetails) {
  589. syslog(LOG_NOTICE, "SSL %s Cert Name: %s", rem_host, peer->name);
  590. X509_NAME_oneline(X509_get_issuer_name(peer), buffer, sizeof(buffer));
  591. syslog(LOG_NOTICE, "SSL %s Cert Issuer: %s", rem_host, buffer);
  592. }
  593. } else
  594. syslog(LOG_NOTICE, "SSL Did not get certificate from %s", rem_host);
  595. }
  596. }
  597. /* bail if we had errors */
  598. if (result != STATE_OK) {
  599. SSL_CTX_free(ctx);
  600. close(sd);
  601. exit(result);
  602. }
  603. #endif
  604. return result;
  605. }
  606. int send_request()
  607. {
  608. v2_packet send_packet;
  609. v3_packet *v3_send_packet = NULL;
  610. u_int32_t calculated_crc32;
  611. int rc, bytes_to_send, pkt_size;
  612. char *send_pkt;
  613. if (packet_ver == NRPE_PACKET_VERSION_2) {
  614. pkt_size = sizeof(v2_packet);
  615. send_pkt = (char *)&send_packet;
  616. /* clear the response packet buffer */
  617. memset(&send_packet, 0, sizeof(send_packet));
  618. /* fill the packet with semi-random data */
  619. randomize_buffer((char *)&send_packet, sizeof(send_packet));
  620. /* initialize response packet data */
  621. send_packet.packet_version = htons(packet_ver);
  622. send_packet.packet_type = htons(QUERY_PACKET);
  623. strncpy(&send_packet.buffer[0], query, MAX_PACKETBUFFER_LENGTH);
  624. send_packet.buffer[MAX_PACKETBUFFER_LENGTH - 1] = '\x0';
  625. /* calculate the crc 32 value of the packet */
  626. send_packet.crc32_value = 0;
  627. calculated_crc32 = calculate_crc32((char *)&send_packet, sizeof(send_packet));
  628. send_packet.crc32_value = htonl(calculated_crc32);
  629. } else {
  630. pkt_size = (sizeof(v3_packet) - 1) + strlen(query) + 1;
  631. v3_send_packet = calloc(1, pkt_size);
  632. send_pkt = (char *)v3_send_packet;
  633. /* initialize response packet data */
  634. v3_send_packet->packet_version = htons(packet_ver);
  635. v3_send_packet->packet_type = htons(QUERY_PACKET);
  636. v3_send_packet->alignment = 0;
  637. v3_send_packet->buffer_length = htonl(strlen(query) + 1);
  638. strcpy(&v3_send_packet->buffer[0], query);
  639. /* calculate the crc 32 value of the packet */
  640. v3_send_packet->crc32_value = 0;
  641. calculated_crc32 = calculate_crc32((char *)v3_send_packet, pkt_size);
  642. v3_send_packet->crc32_value = htonl(calculated_crc32);
  643. }
  644. /* send the request to the remote */
  645. bytes_to_send = pkt_size;
  646. if (use_ssl == FALSE)
  647. rc = sendall(sd, (char *)send_pkt, &bytes_to_send);
  648. #ifdef HAVE_SSL
  649. else {
  650. rc = SSL_write(ssl, send_pkt, bytes_to_send);
  651. if (rc < 0)
  652. rc = -1;
  653. }
  654. #endif
  655. if (v3_send_packet)
  656. free(v3_send_packet);
  657. if (rc == -1) {
  658. printf("CHECK_NRPE: Error sending query to host.\n");
  659. close(sd);
  660. return STATE_UNKNOWN;
  661. }
  662. return STATE_OK;
  663. }
  664. int read_response()
  665. {
  666. v2_packet receive_packet;
  667. v3_packet *v3_receive_packet = NULL;
  668. u_int32_t packet_crc32;
  669. u_int32_t calculated_crc32;
  670. int32_t pkt_size;
  671. int rc, result;
  672. alarm(0);
  673. set_sig_hadlers();
  674. #ifdef HAVE_SSL
  675. rc = read_packet(sd, ssl, &receive_packet, &v3_receive_packet);
  676. #else
  677. rc = read_packet(sd, NULL, &receive_packet, &v3_receive_packet);
  678. #endif
  679. alarm(0);
  680. /* close the connection */
  681. #ifdef HAVE_SSL
  682. if (use_ssl == TRUE) {
  683. SSL_shutdown(ssl);
  684. SSL_free(ssl);
  685. SSL_CTX_free(ctx);
  686. }
  687. #endif
  688. graceful_close(sd, 1000);
  689. /* recv() error */
  690. if (rc < 0) {
  691. if (packet_ver == NRPE_PACKET_VERSION_3) {
  692. free(v3_receive_packet);
  693. return -1;
  694. }
  695. return STATE_UNKNOWN;
  696. } else if (rc == 0) {
  697. /* server disconnected */
  698. printf
  699. ("CHECK_NRPE: Received 0 bytes from daemon. Check the remote server logs for error messages.\n");
  700. if (packet_ver == NRPE_PACKET_VERSION_3)
  701. free(v3_receive_packet);
  702. return STATE_UNKNOWN;
  703. }
  704. /* check the crc 32 value */
  705. if (packet_ver == NRPE_PACKET_VERSION_3) {
  706. pkt_size = (sizeof(v3_packet) - 1) + ntohl(v3_receive_packet->buffer_length);
  707. packet_crc32 = ntohl(v3_receive_packet->crc32_value);
  708. v3_receive_packet->crc32_value = 0L;
  709. v3_receive_packet->alignment = 0;
  710. calculated_crc32 = calculate_crc32((char *)v3_receive_packet, pkt_size);
  711. } else {
  712. packet_crc32 = ntohl(receive_packet.crc32_value);
  713. receive_packet.crc32_value = 0L;
  714. calculated_crc32 = calculate_crc32((char *)&receive_packet, sizeof(receive_packet));
  715. }
  716. if (packet_crc32 != calculated_crc32) {
  717. printf("CHECK_NRPE: Response packet had invalid CRC32.\n");
  718. close(sd);
  719. if (packet_ver == NRPE_PACKET_VERSION_3)
  720. free(v3_receive_packet);
  721. return STATE_UNKNOWN;
  722. }
  723. /* get the return code from the remote plugin */
  724. /* and print the output returned by the daemon */
  725. if (packet_ver == NRPE_PACKET_VERSION_3) {
  726. result = ntohs(v3_receive_packet->result_code);
  727. if (v3_receive_packet->buffer_length == 0)
  728. printf("CHECK_NRPE: No output returned from daemon.\n");
  729. else
  730. printf("%s\n", v3_receive_packet->buffer);
  731. } else {
  732. result = ntohs(receive_packet.result_code);
  733. receive_packet.buffer[MAX_PACKETBUFFER_LENGTH - 1] = '\x0';
  734. if (!strcmp(receive_packet.buffer, ""))
  735. printf("CHECK_NRPE: No output returned from daemon.\n");
  736. else
  737. printf("%s\n", receive_packet.buffer);
  738. }
  739. if (packet_ver == NRPE_PACKET_VERSION_3)
  740. free(v3_receive_packet);
  741. return result;
  742. }
  743. int read_packet(int sock, void *ssl_ptr, v2_packet * v2_pkt, v3_packet ** v3_pkt)
  744. {
  745. int32_t common_size, tot_bytes, bytes_to_recv, buffer_size, bytes_read = 0;
  746. int rc;
  747. char *buff_ptr;
  748. /* Read only the part that's common between versions 2 & 3 */
  749. common_size = tot_bytes = bytes_to_recv = (char *)&v2_pkt->buffer - (char *)v2_pkt;
  750. if (use_ssl == FALSE) {
  751. rc = recvall(sock, (char *)v2_pkt, &tot_bytes, socket_timeout);
  752. if (rc <= 0 || rc != bytes_to_recv) {
  753. if (rc < bytes_to_recv) {
  754. if (packet_ver != NRPE_PACKET_VERSION_3)
  755. printf
  756. ("CHECK_NRPE: Receive header underflow - only %d bytes received (%ld expected).\n",
  757. rc, sizeof(bytes_to_recv));
  758. }
  759. return -1;
  760. }
  761. packet_ver = ntohs(v2_pkt->packet_version);
  762. if (packet_ver != NRPE_PACKET_VERSION_2 && packet_ver != NRPE_PACKET_VERSION_3) {
  763. printf("CHECK_NRPE: Invalid packet version received from server.\n");
  764. return -1;
  765. }
  766. if (ntohs(v2_pkt->packet_type) != RESPONSE_PACKET) {
  767. printf("CHECK_NRPE: Invalid packet type received from server.\n");
  768. return -1;
  769. }
  770. if (packet_ver == NRPE_PACKET_VERSION_2) {
  771. buffer_size = sizeof(v2_packet) - common_size;
  772. buff_ptr = (char *)v2_pkt + common_size;
  773. } else {
  774. int32_t pkt_size = sizeof(v3_packet) - 1;
  775. /* Read the alignment filler */
  776. bytes_to_recv = sizeof(int16_t);
  777. rc = recvall(sock, (char *)&buffer_size, &bytes_to_recv, socket_timeout);
  778. if (rc <= 0 || bytes_to_recv != sizeof(int16_t))
  779. return -1;
  780. tot_bytes += rc;
  781. /* Read the buffer size */
  782. bytes_to_recv = sizeof(buffer_size);
  783. rc = recvall(sock, (char *)&buffer_size, &bytes_to_recv, socket_timeout);
  784. if (rc <= 0 || bytes_to_recv != sizeof(buffer_size))
  785. return -1;
  786. tot_bytes += rc;
  787. buffer_size = ntohl(buffer_size);
  788. pkt_size += buffer_size;
  789. if ((*v3_pkt = calloc(1, pkt_size)) == NULL) {
  790. syslog(LOG_ERR, "Error: Could not allocate memory for packet");
  791. return -1;
  792. }
  793. memcpy(*v3_pkt, v2_pkt, common_size);
  794. (*v3_pkt)->buffer_length = htonl(buffer_size);
  795. buff_ptr = (*v3_pkt)->buffer;
  796. }
  797. bytes_to_recv = buffer_size;
  798. rc = recvall(sock, buff_ptr, &bytes_to_recv, socket_timeout);
  799. if (rc <= 0 || rc != buffer_size) {
  800. if (packet_ver == NRPE_PACKET_VERSION_3) {
  801. free(*v3_pkt);
  802. *v3_pkt = NULL;
  803. }
  804. if (rc < buffer_size)
  805. printf
  806. ("CHECK_NRPE: Receive underflow - only %d bytes received (%ld expected).\n",
  807. rc, sizeof(buffer_size));
  808. return -1;
  809. } else
  810. tot_bytes += rc;
  811. }
  812. #ifdef HAVE_SSL
  813. else {
  814. SSL *ssl = (SSL *) ssl_ptr;
  815. int32_t pkt_size;
  816. while (((rc = SSL_read(ssl, v2_pkt, bytes_to_recv)) <= 0)
  817. && (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)) {
  818. }
  819. if (rc <= 0 || rc != bytes_to_recv) {
  820. if (rc < bytes_to_recv) {
  821. if (packet_ver != NRPE_PACKET_VERSION_3)
  822. printf
  823. ("CHECK_NRPE: Receive header underflow - only %d bytes received (%ld expected).\n",
  824. rc, sizeof(bytes_to_recv));
  825. }
  826. return -1;
  827. }
  828. packet_ver = ntohs(v2_pkt->packet_version);
  829. if (packet_ver != NRPE_PACKET_VERSION_2 && packet_ver != NRPE_PACKET_VERSION_3) {
  830. printf("CHECK_NRPE: Invalid packet version received from server.\n");
  831. return -1;
  832. }
  833. if (ntohs(v2_pkt->packet_type) != RESPONSE_PACKET) {
  834. printf("CHECK_NRPE: Invalid packet type received from server.\n");
  835. return -1;
  836. }
  837. if (packet_ver == NRPE_PACKET_VERSION_2) {
  838. buffer_size = sizeof(v2_packet) - common_size;
  839. buff_ptr = (char *)v2_pkt + common_size;
  840. } else {
  841. pkt_size = sizeof(v3_packet) - 1;
  842. /* Read the alignment filler */
  843. bytes_to_recv = sizeof(int16_t);
  844. while (((rc = SSL_read(ssl, &buffer_size, bytes_to_recv)) <= 0)
  845. && (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)) {
  846. }
  847. if (rc <= 0 || bytes_to_recv != sizeof(int16_t))
  848. return -1;
  849. tot_bytes += rc;
  850. /* Read the buffer size */
  851. bytes_to_recv = sizeof(buffer_size);
  852. while (((rc = SSL_read(ssl, &buffer_size, bytes_to_recv)) <= 0)
  853. && (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)) {
  854. }
  855. if (rc <= 0 || bytes_to_recv != sizeof(buffer_size))
  856. return -1;
  857. tot_bytes += rc;
  858. buffer_size = ntohl(buffer_size);
  859. pkt_size += buffer_size;
  860. if ((*v3_pkt = calloc(1, pkt_size)) == NULL) {
  861. syslog(LOG_ERR, "Error: Could not allocate memory for packet");
  862. return -1;
  863. }
  864. memcpy(*v3_pkt, v2_pkt, common_size);
  865. (*v3_pkt)->buffer_length = htonl(buffer_size);
  866. buff_ptr = (*v3_pkt)->buffer;
  867. }
  868. bytes_to_recv = buffer_size;
  869. for (;;) {
  870. while (((rc = SSL_read(ssl, &buff_ptr[bytes_read], bytes_to_recv)) <= 0)
  871. && (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)) {
  872. }
  873. if (rc <= 0)
  874. break;
  875. bytes_read += rc;
  876. bytes_to_recv -= rc;
  877. }
  878. if (rc < 0 || bytes_read != buffer_size) {
  879. if (packet_ver == NRPE_PACKET_VERSION_3) {
  880. free(*v3_pkt);
  881. *v3_pkt = NULL;
  882. }
  883. if (bytes_read != buffer_size) {
  884. if (packet_ver == NRPE_PACKET_VERSION_3)
  885. printf("CHECK_NRPE: Receive buffer size - %ld bytes received "
  886. "(%ld expected).\n", bytes_read, sizeof(buffer_size));
  887. else
  888. printf("CHECK_NRPE: Receive underflow - only %ld bytes received "
  889. "(%ld expected).\n", bytes_read, sizeof(buffer_size));
  890. }
  891. return -1;
  892. } else
  893. tot_bytes += rc;
  894. }
  895. #endif
  896. return tot_bytes;
  897. }
  898. int verify_callback(int preverify_ok, X509_STORE_CTX * ctx)
  899. {
  900. char name[256], issuer[256];
  901. X509 *err_cert;
  902. int err;
  903. SSL *ssl;
  904. if (preverify_ok || (sslprm.log_opts & SSL_LogCertDetails == 0))
  905. return preverify_ok;
  906. err_cert = X509_STORE_CTX_get_current_cert(ctx);
  907. err = X509_STORE_CTX_get_error(ctx);
  908. /* Get the pointer to the SSL of the current connection */
  909. ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
  910. X509_NAME_oneline(X509_get_subject_name(err_cert), name, 256);
  911. X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), issuer, 256);
  912. if (!preverify_ok && sslprm.client_certs >= Ask_For_Cert
  913. && (sslprm.log_opts & SSL_LogCertDetails)) {
  914. syslog(LOG_ERR, "SSL Client has an invalid certificate: %s (issuer=%s) err=%d:%s",
  915. name, issuer, err, X509_verify_cert_error_string(err));
  916. }
  917. return preverify_ok;
  918. }
  919. void alarm_handler(int sig)
  920. {
  921. const char msg[] = "CHECK_NRPE: Socket timeout";
  922. write(STDOUT_FILENO, msg, sizeof(msg) - 1);
  923. exit(timeout_return_code);
  924. }
  925. /* submitted by Mark Plaksin 08/31/2006 */
  926. int graceful_close(int sd, int timeout)
  927. {
  928. fd_set in;
  929. struct timeval tv;
  930. char buf[1000];
  931. /* send FIN packet */
  932. shutdown(sd, SHUT_WR);
  933. for (;;) {
  934. FD_ZERO(&in);
  935. FD_SET(sd, &in);
  936. tv.tv_sec = timeout / 1000;
  937. tv.tv_usec = (timeout % 1000) * 1000;
  938. /* timeout or error */
  939. if (1 != select(sd + 1, &in, NULL, NULL, &tv))
  940. break;
  941. /* no more data (FIN or RST) */
  942. if (0 >= recv(sd, buf, sizeof(buf), 0))
  943. break;
  944. }
  945. #ifdef HAVE_CLOSESOCKET
  946. closesocket(sd);
  947. #else
  948. close(sd);
  949. #endif
  950. return OK;
  951. }