check_smtp.c 19 KB

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