summaryrefslogtreecommitdiffstats
path: root/plugins/check_smtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_smtp.c')
-rw-r--r--plugins/check_smtp.c218
1 files changed, 20 insertions, 198 deletions
diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c
index 19e9aea8..ad85c7f6 100644
--- a/plugins/check_smtp.c
+++ b/plugins/check_smtp.c
@@ -27,35 +27,14 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net";
27#include "netutils.h" 27#include "netutils.h"
28#include "utils.h" 28#include "utils.h"
29 29
30#ifdef HAVE_SSL_H
31# include <rsa.h>
32# include <crypto.h>
33# include <x509.h>
34# include <pem.h>
35# include <ssl.h>
36# include <err.h>
37#else
38# ifdef HAVE_OPENSSL_SSL_H
39# include <openssl/rsa.h>
40# include <openssl/crypto.h>
41# include <openssl/x509.h>
42# include <openssl/pem.h>
43# include <openssl/ssl.h>
44# include <openssl/err.h>
45# endif
46#endif
47
48#ifdef HAVE_SSL 30#ifdef HAVE_SSL
49
50int check_cert = FALSE; 31int check_cert = FALSE;
51int days_till_exp; 32int days_till_exp;
52SSL_CTX *ctx; 33# define my_recv(buf, len) ((use_ssl && ssl_established) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
53SSL *ssl; 34# define my_send(buf, len) ((use_ssl && ssl_established) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
54X509 *server_cert; 35#else /* ifndef HAVE_SSL */
55int connect_STARTTLS (void); 36# define my_recv(buf, len) read(sd, buf, len)
56# ifdef USE_OPENSSL 37# define my_send(buf, len) send(sd, buf, len, 0)
57int check_certificate (X509 **);
58# endif
59#endif 38#endif
60 39
61enum { 40enum {
@@ -77,7 +56,6 @@ int process_arguments (int, char **);
77int validate_arguments (void); 56int validate_arguments (void);
78void print_help (void); 57void print_help (void);
79void print_usage (void); 58void print_usage (void);
80int myrecv(void);
81int my_close(void); 59int my_close(void);
82 60
83#ifdef HAVE_REGEX_H 61#ifdef HAVE_REGEX_H
@@ -111,7 +89,7 @@ int check_critical_time = FALSE;
111int verbose = 0; 89int verbose = 0;
112int use_ssl = FALSE; 90int use_ssl = FALSE;
113short use_ehlo = FALSE; 91short use_ehlo = FALSE;
114short ssl_established = TRUE; 92short ssl_established = 0;
115char *localhostname = NULL; 93char *localhostname = NULL;
116int sd; 94int sd;
117char buffer[MAX_INPUT_BUFFER]; 95char buffer[MAX_INPUT_BUFFER];
@@ -237,22 +215,20 @@ main (int argc, char **argv)
237 send (sd, SMTP_QUIT, strlen (SMTP_QUIT), 0); 215 send (sd, SMTP_QUIT, strlen (SMTP_QUIT), 0);
238 return STATE_UNKNOWN; 216 return STATE_UNKNOWN;
239 } 217 }
240 if(connect_STARTTLS() != OK) { 218 result = np_net_ssl_init(sd);
219 if(result != STATE_OK) {
241 printf (_("CRITICAL - Cannot create SSL context.\n")); 220 printf (_("CRITICAL - Cannot create SSL context.\n"));
221 np_net_ssl_cleanup();
222 close(sd);
242 return STATE_CRITICAL; 223 return STATE_CRITICAL;
243 } else { 224 } else {
244 ssl_established = TRUE; 225 ssl_established = 1;
245 } 226 }
246# ifdef USE_OPENSSL 227# ifdef USE_OPENSSL
247 if ( check_cert ) { 228 if ( check_cert ) {
248 if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) { 229 result = np_net_ssl_check_cert(days_till_exp);
249 result = check_certificate (&server_cert); 230 if(result != STATE_OK){
250 X509_free(server_cert);
251 }
252 else {
253 printf (_("CRITICAL - Cannot retrieve server certificate.\n")); 231 printf (_("CRITICAL - Cannot retrieve server certificate.\n"));
254 result = STATE_CRITICAL;
255
256 } 232 }
257 my_close(); 233 my_close();
258 return result; 234 return result;
@@ -272,26 +248,16 @@ main (int argc, char **argv)
272 * Use the -f option to provide a FROM address 248 * Use the -f option to provide a FROM address
273 */ 249 */
274 if (smtp_use_dummycmd) { 250 if (smtp_use_dummycmd) {
275#ifdef HAVE_SSL 251 my_send(cmd_str, strlen(cmd_str));
276 if (use_ssl) 252 my_recv(buffer, MAX_INPUT_BUFFER-1);
277 SSL_write(ssl, cmd_str, strlen(cmd_str));
278 else
279#endif
280 send(sd, cmd_str, strlen(cmd_str), 0);
281 myrecv();
282 if (verbose) 253 if (verbose)
283 printf("%s", buffer); 254 printf("%s", buffer);
284 } 255 }
285 256
286 while (n < ncommands) { 257 while (n < ncommands) {
287 asprintf (&cmd_str, "%s%s", commands[n], "\r\n"); 258 asprintf (&cmd_str, "%s%s", commands[n], "\r\n");
288#ifdef HAVE_SSL 259 my_send(cmd_str, strlen(cmd_str));
289 if (use_ssl) 260 my_recv(buffer, MAX_INPUT_BUFFER-1);
290 SSL_write(ssl,cmd_str, strlen(cmd_str));
291 else
292#endif
293 send(sd, cmd_str, strlen(cmd_str), 0);
294 myrecv();
295 if (verbose) 261 if (verbose)
296 printf("%s", buffer); 262 printf("%s", buffer);
297 strip (buffer); 263 strip (buffer);
@@ -328,12 +294,7 @@ main (int argc, char **argv)
328 } 294 }
329 295
330 /* tell the server we're done */ 296 /* tell the server we're done */
331#ifdef HAVE_SSL 297 my_send (SMTP_QUIT, strlen (SMTP_QUIT));
332 if (use_ssl)
333 SSL_write(ssl,SMTP_QUIT, strlen (SMTP_QUIT));
334 else
335#endif
336 send (sd, SMTP_QUIT, strlen (SMTP_QUIT), 0);
337 298
338 /* finally close the connection */ 299 /* finally close the connection */
339 close (sd); 300 close (sd);
@@ -626,150 +587,11 @@ Usage: %s -H host [-p port] [-e expect] [-C command] [-f from addr]\n\
626 [-w warn] [-c crit] [-t timeout] [-S] [-D days] [-n] [-v] [-4|-6]\n", progname); 587 [-w warn] [-c crit] [-t timeout] [-S] [-D days] [-n] [-v] [-4|-6]\n", progname);
627} 588}
628 589
629#ifdef HAVE_SSL
630int
631connect_STARTTLS (void)
632{
633 SSL_METHOD *meth;
634
635 /* Initialize SSL context */
636 SSLeay_add_ssl_algorithms ();
637 meth = SSLv23_client_method ();
638 SSL_load_error_strings ();
639 if ((ctx = SSL_CTX_new (meth)) == NULL)
640 {
641 printf(_("CRITICAL - Cannot create SSL context.\n"));
642 return STATE_CRITICAL;
643 }
644 /* do the SSL handshake */
645 if ((ssl = SSL_new (ctx)) != NULL)
646 {
647 SSL_set_fd (ssl, sd);
648 /* original version checked for -1
649 I look for success instead (1) */
650 if (SSL_connect (ssl) == 1)
651 return OK;
652# ifdef USE_OPENSSL
653 ERR_print_errors_fp (stderr);
654# endif
655 }
656 else
657 {
658 printf (_("CRITICAL - Cannot initiate SSL handshake.\n"));
659 }
660 my_close();
661
662 return STATE_CRITICAL;
663}
664
665# ifdef USE_OPENSSL
666int
667check_certificate (X509 ** certificate)
668{
669 ASN1_STRING *tm;
670 int offset;
671 struct tm stamp;
672 int days_left;
673
674 /* Retrieve timestamp of certificate */
675 tm = X509_get_notAfter (*certificate);
676
677 /* Generate tm structure to process timestamp */
678 if (tm->type == V_ASN1_UTCTIME) {
679 if (tm->length < 10) {
680 printf (_("CRITICAL - Wrong time format in certificate.\n"));
681 return STATE_CRITICAL;
682 }
683 else {
684 stamp.tm_year = (tm->data[0] - '0') * 10 + (tm->data[1] - '0');
685 if (stamp.tm_year < 50)
686 stamp.tm_year += 100;
687 offset = 0;
688 }
689 }
690 else {
691 if (tm->length < 12) {
692 printf (_("CRITICAL - Wrong time format in certificate.\n"));
693 return STATE_CRITICAL;
694 }
695 else {
696 stamp.tm_year =
697 (tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 +
698 (tm->data[2] - '0') * 10 + (tm->data[3] - '0');
699 stamp.tm_year -= 1900;
700 offset = 2;
701 }
702 }
703 stamp.tm_mon =
704 (tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1;
705 stamp.tm_mday =
706 (tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0');
707 stamp.tm_hour =
708 (tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0');
709 stamp.tm_min =
710 (tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0');
711 stamp.tm_sec = 0;
712 stamp.tm_isdst = -1;
713
714 days_left = (mktime (&stamp) - time (NULL)) / 86400;
715 snprintf
716 (timestamp, sizeof(timestamp), "%02d/%02d/%04d %02d:%02d",
717 stamp.tm_mon + 1,
718 stamp.tm_mday, stamp.tm_year + 1900, stamp.tm_hour, stamp.tm_min);
719
720 if (days_left > 0 && days_left <= days_till_exp) {
721 printf ("Certificate expires in %d day(s) (%s).\n", days_left, timestamp);
722 return STATE_WARNING;
723 }
724 if (days_left < 0) {
725 printf ("Certificate expired on %s.\n", timestamp);
726 return STATE_CRITICAL;
727 }
728
729 if (days_left == 0) {
730 printf ("Certificate expires today (%s).\n", timestamp);
731 return STATE_WARNING;
732 }
733
734 printf ("Certificate will expire on %s.\n", timestamp);
735
736 return STATE_OK;
737}
738# endif /* USE_OPENSSL */
739#endif
740
741int
742myrecv (void)
743{
744 int i;
745
746#ifdef HAVE_SSL
747 if (use_ssl) {
748 i = SSL_read (ssl, buffer, MAXBUF - 1);
749 }
750 else {
751#endif
752 i = read (sd, buffer, MAXBUF - 1);
753#ifdef HAVE_SSL
754 }
755#endif
756 return i;
757}
758
759int 590int
760my_close (void) 591my_close (void)
761{ 592{
762#ifdef HAVE_SSL 593#ifdef HAVE_SSL
763 if (use_ssl == TRUE && ssl_established == TRUE) { 594 np_net_ssl_cleanup();
764 SSL_shutdown (ssl);
765 SSL_free (ssl);
766 SSL_CTX_free (ctx);
767 return 0;
768 }
769 else {
770#endif
771 return close(sd);
772#ifdef HAVE_SSL
773 }
774#endif 595#endif
596 return close(sd);
775} 597}