diff options
Diffstat (limited to 'plugins/check_smtp.c')
-rw-r--r-- | plugins/check_smtp.c | 218 |
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 | |||
50 | int check_cert = FALSE; | 31 | int check_cert = FALSE; |
51 | int days_till_exp; | 32 | int days_till_exp; |
52 | SSL_CTX *ctx; | 33 | # define my_recv(buf, len) ((use_ssl && ssl_established) ? np_net_ssl_read(buf, len) : read(sd, buf, len)) |
53 | SSL *ssl; | 34 | # define my_send(buf, len) ((use_ssl && ssl_established) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0)) |
54 | X509 *server_cert; | 35 | #else /* ifndef HAVE_SSL */ |
55 | int 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) |
57 | int check_certificate (X509 **); | ||
58 | # endif | ||
59 | #endif | 38 | #endif |
60 | 39 | ||
61 | enum { | 40 | enum { |
@@ -77,7 +56,6 @@ int process_arguments (int, char **); | |||
77 | int validate_arguments (void); | 56 | int validate_arguments (void); |
78 | void print_help (void); | 57 | void print_help (void); |
79 | void print_usage (void); | 58 | void print_usage (void); |
80 | int myrecv(void); | ||
81 | int my_close(void); | 59 | int my_close(void); |
82 | 60 | ||
83 | #ifdef HAVE_REGEX_H | 61 | #ifdef HAVE_REGEX_H |
@@ -111,7 +89,7 @@ int check_critical_time = FALSE; | |||
111 | int verbose = 0; | 89 | int verbose = 0; |
112 | int use_ssl = FALSE; | 90 | int use_ssl = FALSE; |
113 | short use_ehlo = FALSE; | 91 | short use_ehlo = FALSE; |
114 | short ssl_established = TRUE; | 92 | short ssl_established = 0; |
115 | char *localhostname = NULL; | 93 | char *localhostname = NULL; |
116 | int sd; | 94 | int sd; |
117 | char buffer[MAX_INPUT_BUFFER]; | 95 | char 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 | ||
630 | int | ||
631 | connect_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 | ||
666 | int | ||
667 | check_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 | |||
741 | int | ||
742 | myrecv (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 | |||
759 | int | 590 | int |
760 | my_close (void) | 591 | my_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 | } |