check_smtp.c 19 KB

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