check_smtp.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. /******************************************************************************
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; either version 2 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program; if not, write to the Free Software
  12. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  13. $Id$
  14. ******************************************************************************/
  15. const char *progname = "check_smtp";
  16. const char *revision = "$Revision$";
  17. const char *copyright = "2000-2004";
  18. const char *email = "nagiosplug-devel@lists.sourceforge.net";
  19. #include "common.h"
  20. #include "netutils.h"
  21. #include "utils.h"
  22. #ifdef HAVE_SSL_H
  23. # include <rsa.h>
  24. # include <crypto.h>
  25. # include <x509.h>
  26. # include <pem.h>
  27. # include <ssl.h>
  28. # include <err.h>
  29. #else
  30. # ifdef HAVE_OPENSSL_SSL_H
  31. # include <openssl/rsa.h>
  32. # include <openssl/crypto.h>
  33. # include <openssl/x509.h>
  34. # include <openssl/pem.h>
  35. # include <openssl/ssl.h>
  36. # include <openssl/err.h>
  37. # endif
  38. #endif
  39. #ifdef HAVE_SSL
  40. int check_cert = FALSE;
  41. int days_till_exp;
  42. SSL_CTX *ctx;
  43. SSL *ssl;
  44. X509 *server_cert;
  45. int connect_STARTTLS (void);
  46. int check_certificate (X509 **);
  47. #endif
  48. enum {
  49. SMTP_PORT = 25
  50. };
  51. const char *SMTP_EXPECT = "220";
  52. const char *SMTP_HELO = "HELO ";
  53. const char *SMTP_QUIT = "QUIT\r\n";
  54. const char *SMTP_STARTTLS = "STARTTLS\r\n";
  55. int process_arguments (int, char **);
  56. int validate_arguments (void);
  57. void print_help (void);
  58. void print_usage (void);
  59. int myrecv(void);
  60. int my_close(void);
  61. #ifdef HAVE_REGEX_H
  62. #include <regex.h>
  63. char regex_expect[MAX_INPUT_BUFFER] = "";
  64. regex_t preg;
  65. regmatch_t pmatch[10];
  66. char timestamp[10] = "";
  67. char errbuf[MAX_INPUT_BUFFER];
  68. int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
  69. int eflags = 0;
  70. int errcode, excode;
  71. #endif
  72. int server_port = SMTP_PORT;
  73. char *server_address = NULL;
  74. char *server_expect = NULL;
  75. int smtp_use_dummycmd = 0;
  76. char *mail_command = NULL;
  77. char *from_arg = NULL;
  78. int ncommands=0;
  79. int command_size=0;
  80. int nresponses=0;
  81. int response_size=0;
  82. char **commands = NULL;
  83. char **responses = NULL;
  84. int warning_time = 0;
  85. int check_warning_time = FALSE;
  86. int critical_time = 0;
  87. int check_critical_time = FALSE;
  88. int verbose = 0;
  89. int use_ssl = FALSE;
  90. int sd;
  91. char buffer[MAX_INPUT_BUFFER];
  92. enum {
  93. TCP_PROTOCOL = 1,
  94. UDP_PROTOCOL = 2,
  95. MAXBUF = 1024
  96. };
  97. int
  98. main (int argc, char **argv)
  99. {
  100. int n = 0;
  101. double elapsed_time;
  102. long microsec;
  103. int result = STATE_UNKNOWN;
  104. char *cmd_str = NULL;
  105. char *helocmd = NULL;
  106. struct timeval tv;
  107. setlocale (LC_ALL, "");
  108. bindtextdomain (PACKAGE, LOCALEDIR);
  109. textdomain (PACKAGE);
  110. if (process_arguments (argc, argv) == ERROR)
  111. usage4 (_("Could not parse arguments"));
  112. /* initialize the HELO command with the localhostname */
  113. #ifndef HOST_MAX_BYTES
  114. #define HOST_MAX_BYTES 255
  115. #endif
  116. helocmd = malloc (HOST_MAX_BYTES);
  117. gethostname(helocmd, HOST_MAX_BYTES);
  118. asprintf (&helocmd, "%s%s%s", SMTP_HELO, helocmd, "\r\n");
  119. /* initialize the MAIL command with optional FROM command */
  120. asprintf (&cmd_str, "%sFROM: %s%s", mail_command, from_arg, "\r\n");
  121. if (verbose && smtp_use_dummycmd)
  122. printf ("FROM CMD: %s", cmd_str);
  123. /* initialize alarm signal handling */
  124. (void) signal (SIGALRM, socket_timeout_alarm_handler);
  125. /* set socket timeout */
  126. (void) alarm (socket_timeout);
  127. /* start timer */
  128. gettimeofday (&tv, NULL);
  129. /* try to connect to the host at the given port number */
  130. result = my_tcp_connect (server_address, server_port, &sd);
  131. if (result == STATE_OK) { /* we connected */
  132. /* watch for the SMTP connection string and */
  133. /* return a WARNING status if we couldn't read any data */
  134. if (recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0) == -1) {
  135. printf (_("recv() failed\n"));
  136. result = STATE_WARNING;
  137. }
  138. else {
  139. if (verbose)
  140. printf ("%s", buffer);
  141. /* strip the buffer of carriage returns */
  142. strip (buffer);
  143. /* make sure we find the response we are looking for */
  144. if (!strstr (buffer, server_expect)) {
  145. if (server_port == SMTP_PORT)
  146. printf (_("Invalid SMTP response received from host\n"));
  147. else
  148. printf (_("Invalid SMTP response received from host on port %d\n"),
  149. server_port);
  150. result = STATE_WARNING;
  151. }
  152. }
  153. #ifdef HAVE_SSL
  154. if(use_ssl) {
  155. /* send the STARTTLS command */
  156. send(sd, SMTP_STARTTLS, strlen(SMTP_STARTTLS), 0);
  157. recv(sd,buffer, MAX_INPUT_BUFFER-1, 0); // wait for it
  158. if (!strstr (buffer, server_expect)) {
  159. printf (_("Server does not support STARTTLS\n"));
  160. return STATE_UNKNOWN;
  161. }
  162. if(connect_STARTTLS() != OK) {
  163. printf (_("CRITICAL - Cannot create SSL context.\n"));
  164. return STATE_CRITICAL;
  165. }
  166. if ( check_cert ) {
  167. if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) {
  168. result = check_certificate (&server_cert);
  169. X509_free(server_cert);
  170. }
  171. else {
  172. printf (_("CRITICAL - Cannot retrieve server certificate.\n"));
  173. result = STATE_CRITICAL;
  174. }
  175. my_close();
  176. return result;
  177. }
  178. }
  179. #endif
  180. /* send the HELO command */
  181. #ifdef HAVE_SSL
  182. if (use_ssl)
  183. SSL_write(ssl, helocmd, strlen(helocmd));
  184. else
  185. #endif
  186. send(sd, helocmd, strlen(helocmd), 0);
  187. /* allow for response to helo command to reach us */
  188. myrecv();
  189. /* sendmail will syslog a "NOQUEUE" error if session does not attempt
  190. * to do something useful. This can be prevented by giving a command
  191. * even if syntax is illegal (MAIL requires a FROM:<...> argument)
  192. *
  193. * According to rfc821 you can include a null reversepath in the from command
  194. * - but a log message is generated on the smtp server.
  195. *
  196. * You can disable sending mail_command with '--nocommand'
  197. * Use the -f option to provide a FROM address
  198. */
  199. if (smtp_use_dummycmd) {
  200. #ifdef HAVE_SSL
  201. if (use_ssl)
  202. SSL_write(ssl, cmd_str, strlen(cmd_str));
  203. else
  204. #endif
  205. send(sd, cmd_str, strlen(cmd_str), 0);
  206. myrecv();
  207. if (verbose)
  208. printf("%s", buffer);
  209. }
  210. while (n < ncommands) {
  211. asprintf (&cmd_str, "%s%s", commands[n], "\r\n");
  212. #ifdef HAVE_SSL
  213. if (use_ssl)
  214. SSL_write(ssl,cmd_str, strlen(cmd_str));
  215. else
  216. #endif
  217. send(sd, cmd_str, strlen(cmd_str), 0);
  218. myrecv();
  219. if (verbose)
  220. printf("%s", buffer);
  221. strip (buffer);
  222. if (n < nresponses) {
  223. #ifdef HAVE_REGEX_H
  224. cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
  225. //strncpy (regex_expect, responses[n], sizeof (regex_expect) - 1);
  226. //regex_expect[sizeof (regex_expect) - 1] = '\0';
  227. errcode = regcomp (&preg, responses[n], cflags);
  228. if (errcode != 0) {
  229. regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
  230. printf (_("Could Not Compile Regular Expression"));
  231. return ERROR;
  232. }
  233. excode = regexec (&preg, buffer, 10, pmatch, eflags);
  234. if (excode == 0) {
  235. result = STATE_OK;
  236. }
  237. else if (excode == REG_NOMATCH) {
  238. result = STATE_WARNING;
  239. printf (_("SMTP %s - Invalid response '%s' to command '%s'\n"), state_text (result), buffer, commands[n]);
  240. }
  241. else {
  242. regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
  243. printf (_("Execute Error: %s\n"), errbuf);
  244. result = STATE_UNKNOWN;
  245. }
  246. #else
  247. if (strstr(buffer, responses[n])!=buffer) {
  248. result = STATE_WARNING;
  249. printf (_("SMTP %s - Invalid response '%s' to command '%s'\n"), state_text (result), buffer, commands[n]);
  250. }
  251. #endif
  252. }
  253. n++;
  254. }
  255. /* tell the server we're done */
  256. #ifdef HAVE_SSL
  257. if (use_ssl)
  258. SSL_write(ssl,SMTP_QUIT, strlen (SMTP_QUIT));
  259. else
  260. #endif
  261. send (sd, SMTP_QUIT, strlen (SMTP_QUIT), 0);
  262. /* finally close the connection */
  263. close (sd);
  264. }
  265. /* reset the alarm */
  266. alarm (0);
  267. microsec = deltime (tv);
  268. elapsed_time = (double)microsec / 1.0e6;
  269. if (result == STATE_OK) {
  270. if (check_critical_time && elapsed_time > (double) critical_time)
  271. result = STATE_CRITICAL;
  272. else if (check_warning_time && elapsed_time > (double) warning_time)
  273. result = STATE_WARNING;
  274. }
  275. printf (_("SMTP %s - %.3f sec. response time%s%s|%s\n"),
  276. state_text (result), elapsed_time,
  277. verbose?", ":"", verbose?buffer:"",
  278. fperfdata ("time", elapsed_time, "s",
  279. (int)check_warning_time, warning_time,
  280. (int)check_critical_time, critical_time,
  281. TRUE, 0, FALSE, 0));
  282. return result;
  283. }
  284. /* process command-line arguments */
  285. int
  286. process_arguments (int argc, char **argv)
  287. {
  288. int c;
  289. int option = 0;
  290. static struct option longopts[] = {
  291. {"hostname", required_argument, 0, 'H'},
  292. {"expect", required_argument, 0, 'e'},
  293. {"critical", required_argument, 0, 'c'},
  294. {"warning", required_argument, 0, 'w'},
  295. {"timeout", required_argument, 0, 't'},
  296. {"port", required_argument, 0, 'p'},
  297. {"from", required_argument, 0, 'f'},
  298. {"command", required_argument, 0, 'C'},
  299. {"response", required_argument, 0, 'R'},
  300. {"nocommand", required_argument, 0, 'n'},
  301. {"verbose", no_argument, 0, 'v'},
  302. {"version", no_argument, 0, 'V'},
  303. {"use-ipv4", no_argument, 0, '4'},
  304. {"use-ipv6", no_argument, 0, '6'},
  305. {"help", no_argument, 0, 'h'},
  306. {"starttls",no_argument,0,'S'},
  307. {"certificate",required_argument,0,'D'},
  308. {0, 0, 0, 0}
  309. };
  310. if (argc < 2)
  311. return ERROR;
  312. for (c = 1; c < argc; c++) {
  313. if (strcmp ("-to", argv[c]) == 0)
  314. strcpy (argv[c], "-t");
  315. else if (strcmp ("-wt", argv[c]) == 0)
  316. strcpy (argv[c], "-w");
  317. else if (strcmp ("-ct", argv[c]) == 0)
  318. strcpy (argv[c], "-c");
  319. }
  320. while (1) {
  321. c = getopt_long (argc, argv, "+hVv46t:p:f:e:c:w:H:C:R:SD:",
  322. longopts, &option);
  323. if (c == -1 || c == EOF)
  324. break;
  325. switch (c) {
  326. case 'H': /* hostname */
  327. if (is_host (optarg)) {
  328. server_address = optarg;
  329. }
  330. else {
  331. usage2 (_("Invalid hostname/address"), optarg);
  332. }
  333. break;
  334. case 'p': /* port */
  335. if (is_intpos (optarg))
  336. server_port = atoi (optarg);
  337. else
  338. usage4 (_("Port must be a positive integer"));
  339. break;
  340. case 'f': /* from argument */
  341. from_arg = optarg;
  342. smtp_use_dummycmd = 1;
  343. break;
  344. case 'e': /* server expect string on 220 */
  345. server_expect = optarg;
  346. break;
  347. case 'C': /* commands */
  348. if (ncommands >= command_size) {
  349. commands = realloc (commands, command_size+8);
  350. if (commands == NULL)
  351. die (STATE_UNKNOWN,
  352. _("Could not realloc() units [%d]\n"), ncommands);
  353. }
  354. commands[ncommands] = optarg;
  355. ncommands++;
  356. break;
  357. case 'R': /* server responses */
  358. if (nresponses >= response_size) {
  359. responses = realloc (responses, response_size+8);
  360. if (responses == NULL)
  361. die (STATE_UNKNOWN,
  362. _("Could not realloc() units [%d]\n"), nresponses);
  363. }
  364. responses[nresponses] = optarg;
  365. nresponses++;
  366. break;
  367. case 'c': /* critical time threshold */
  368. if (is_intnonneg (optarg)) {
  369. critical_time = atoi (optarg);
  370. check_critical_time = TRUE;
  371. }
  372. else {
  373. usage4 (_("Critical time must be a positive integer"));
  374. }
  375. break;
  376. case 'w': /* warning time threshold */
  377. if (is_intnonneg (optarg)) {
  378. warning_time = atoi (optarg);
  379. check_warning_time = TRUE;
  380. }
  381. else {
  382. usage4 (_("Warning time must be a positive integer"));
  383. }
  384. break;
  385. case 'v': /* verbose */
  386. verbose++;
  387. break;
  388. case 't': /* timeout */
  389. if (is_intnonneg (optarg)) {
  390. socket_timeout = atoi (optarg);
  391. }
  392. else {
  393. usage4 (_("Timeout interval must be a positive integer"));
  394. }
  395. break;
  396. case 'S':
  397. /* starttls */
  398. use_ssl = TRUE;
  399. break;
  400. case 'D':
  401. /* Check SSL cert validity */
  402. #ifdef HAVE_SSL
  403. if (!is_intnonneg (optarg))
  404. usage2 ("Invalid certificate expiration period",optarg);
  405. days_till_exp = atoi (optarg);
  406. check_cert = TRUE;
  407. #else
  408. usage (_("SSL support not available - install OpenSSL and recompile"));
  409. #endif
  410. break;
  411. case '4':
  412. address_family = AF_INET;
  413. break;
  414. case '6':
  415. #ifdef USE_IPV6
  416. address_family = AF_INET6;
  417. #else
  418. usage4 (_("IPv6 support not available"));
  419. #endif
  420. break;
  421. case 'V': /* version */
  422. print_revision (progname, revision);
  423. exit (STATE_OK);
  424. case 'h': /* help */
  425. print_help ();
  426. exit (STATE_OK);
  427. case '?': /* help */
  428. usage2 (_("Unknown argument"), optarg);
  429. }
  430. }
  431. c = optind;
  432. if (server_address == NULL) {
  433. if (argv[c]) {
  434. if (is_host (argv[c]))
  435. server_address = argv[c];
  436. else
  437. usage2 (_("Invalid hostname/address"), argv[c]);
  438. }
  439. else {
  440. asprintf (&server_address, "127.0.0.1");
  441. }
  442. }
  443. if (server_expect == NULL)
  444. server_expect = strdup (SMTP_EXPECT);
  445. if (mail_command == NULL)
  446. mail_command = strdup("MAIL ");
  447. if (from_arg==NULL)
  448. from_arg = strdup(" ");
  449. return validate_arguments ();
  450. }
  451. int
  452. validate_arguments (void)
  453. {
  454. return OK;
  455. }
  456. void
  457. print_help (void)
  458. {
  459. char *myport;
  460. asprintf (&myport, "%d", SMTP_PORT);
  461. print_revision (progname, revision);
  462. printf ("Copyright (c) 1999-2001 Ethan Galstad <nagios@nagios.org>\n");
  463. printf (COPYRIGHT, copyright, email);
  464. printf(_("This plugin will attempt to open an SMTP connection with the host.\n\n"));
  465. print_usage ();
  466. printf (_(UT_HELP_VRSN));
  467. printf (_(UT_HOST_PORT), 'p', myport);
  468. printf (_(UT_IPv46));
  469. printf (_("\
  470. -e, --expect=STRING\n\
  471. String to expect in first line of server response (default: '%s')\n\
  472. -n, nocommand\n\
  473. Suppress SMTP command\n\
  474. -C, --command=STRING\n\
  475. SMTP command (may be used repeatedly)\n\
  476. -R, --command=STRING\n\
  477. Expected response to command (may be used repeatedly)\n\
  478. -f, --from=STRING\n\
  479. FROM-address to include in MAIL command, required by Exchange 2000\n"),
  480. SMTP_EXPECT);
  481. #ifdef HAVE_SSL
  482. printf (_("\
  483. -D, --certificate=INTEGER\n\
  484. Minimum number of days a certificate has to be valid.\n\
  485. -S, --starttls\n\
  486. Use STARTTLS for the connection.\n"));
  487. #endif
  488. printf (_(UT_WARN_CRIT));
  489. printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
  490. printf (_(UT_VERBOSE));
  491. printf(_("\n\
  492. Successul connects return STATE_OK, refusals and timeouts return\n\
  493. STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful\n\
  494. connects, but incorrect reponse messages from the host result in\n\
  495. STATE_WARNING return values.\n"));
  496. printf (_(UT_SUPPORT));
  497. }
  498. void
  499. print_usage (void)
  500. {
  501. printf ("\
  502. Usage: %s -H host [-p port] [-e expect] [-C command] [-f from addr]\n\
  503. [-w warn] [-c crit] [-t timeout] [-S] [-D days] [-n] [-v] [-4|-6]\n", progname);
  504. }
  505. #ifdef HAVE_SSL
  506. int
  507. connect_STARTTLS (void)
  508. {
  509. SSL_METHOD *meth;
  510. /* Initialize SSL context */
  511. SSLeay_add_ssl_algorithms ();
  512. meth = SSLv2_client_method ();
  513. SSL_load_error_strings ();
  514. if ((ctx = SSL_CTX_new (meth)) == NULL)
  515. {
  516. printf(_("CRITICAL - Cannot create SSL context.\n"));
  517. return STATE_CRITICAL;
  518. }
  519. /* do the SSL handshake */
  520. if ((ssl = SSL_new (ctx)) != NULL)
  521. {
  522. SSL_set_fd (ssl, sd);
  523. /* original version checked for -1
  524. I look for success instead (1) */
  525. if (SSL_connect (ssl) == 1)
  526. return OK;
  527. ERR_print_errors_fp (stderr);
  528. }
  529. else
  530. {
  531. printf (_("CRITICAL - Cannot initiate SSL handshake.\n"));
  532. }
  533. /* this causes a seg faul
  534. not sure why, being sloppy
  535. and commenting it out */
  536. // SSL_free (ssl);
  537. SSL_CTX_free(ctx);
  538. my_close();
  539. return STATE_CRITICAL;
  540. }
  541. int
  542. check_certificate (X509 ** certificate)
  543. {
  544. ASN1_STRING *tm;
  545. int offset;
  546. struct tm stamp;
  547. int days_left;
  548. /* Retrieve timestamp of certificate */
  549. tm = X509_get_notAfter (*certificate);
  550. /* Generate tm structure to process timestamp */
  551. if (tm->type == V_ASN1_UTCTIME) {
  552. if (tm->length < 10) {
  553. printf (_("CRITICAL - Wrong time format in certificate.\n"));
  554. return STATE_CRITICAL;
  555. }
  556. else {
  557. stamp.tm_year = (tm->data[0] - '0') * 10 + (tm->data[1] - '0');
  558. if (stamp.tm_year < 50)
  559. stamp.tm_year += 100;
  560. offset = 0;
  561. }
  562. }
  563. else {
  564. if (tm->length < 12) {
  565. printf (_("CRITICAL - Wrong time format in certificate.\n"));
  566. return STATE_CRITICAL;
  567. }
  568. else {
  569. stamp.tm_year =
  570. (tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 +
  571. (tm->data[2] - '0') * 10 + (tm->data[3] - '0');
  572. stamp.tm_year -= 1900;
  573. offset = 2;
  574. }
  575. }
  576. stamp.tm_mon =
  577. (tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1;
  578. stamp.tm_mday =
  579. (tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0');
  580. stamp.tm_hour =
  581. (tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0');
  582. stamp.tm_min =
  583. (tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0');
  584. stamp.tm_sec = 0;
  585. stamp.tm_isdst = -1;
  586. days_left = (mktime (&stamp) - time (NULL)) / 86400;
  587. snprintf
  588. (timestamp, 16, "%02d/%02d/%04d %02d:%02d",
  589. stamp.tm_mon + 1,
  590. stamp.tm_mday, stamp.tm_year + 1900, stamp.tm_hour, stamp.tm_min);
  591. if (days_left > 0 && days_left <= days_till_exp) {
  592. printf ("Certificate expires in %d day(s) (%s).\n", days_left, timestamp);
  593. return STATE_WARNING;
  594. }
  595. if (days_left < 0) {
  596. printf ("Certificate expired on %s.\n", timestamp);
  597. return STATE_CRITICAL;
  598. }
  599. if (days_left == 0) {
  600. printf ("Certificate expires today (%s).\n", timestamp);
  601. return STATE_WARNING;
  602. }
  603. printf ("Certificate will expire on %s.\n", timestamp);
  604. return STATE_OK;
  605. }
  606. #endif
  607. int
  608. myrecv (void)
  609. {
  610. int i;
  611. #ifdef HAVE_SSL
  612. if (use_ssl) {
  613. i = SSL_read (ssl, buffer, MAXBUF - 1);
  614. }
  615. else {
  616. #endif
  617. i = read (sd, buffer, MAXBUF - 1);
  618. #ifdef HAVE_SSL
  619. }
  620. #endif
  621. return i;
  622. }
  623. int
  624. my_close (void)
  625. {
  626. #ifdef HAVE_SSL
  627. if (use_ssl == TRUE) {
  628. SSL_shutdown (ssl);
  629. SSL_free (ssl);
  630. SSL_CTX_free (ctx);
  631. return 0;
  632. }
  633. else {
  634. #endif
  635. return close(sd);
  636. #ifdef HAVE_SSL
  637. }
  638. #endif
  639. }