From 68ecdb70054dffaf0732016795e9735b19350b5d Mon Sep 17 00:00:00 2001 From: Stanley Hopcroft Date: Wed, 1 Dec 2004 08:26:59 +0000 Subject: [PATCH] 1041571 & 664615: check_tcp with cert check + nntps, simap, jabber git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@959 f882894a-f735-0410-b71e-b25c423dba1c --- plugins/check_tcp.c | 167 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 156 insertions(+), 11 deletions(-) diff --git a/plugins/check_tcp.c b/plugins/check_tcp.c index b78bf34..7cef8bb 100644 --- a/plugins/check_tcp.c +++ b/plugins/check_tcp.c @@ -45,9 +45,14 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; #endif #ifdef HAVE_SSL +int check_cert = FALSE; +int days_till_exp; +char *randbuff = ""; SSL_CTX *ctx; SSL *ssl; +X509 *server_cert; int connect_SSL (void); +int check_certificate (X509 **); #endif enum { @@ -68,6 +73,7 @@ char *QUIT = NULL; int PROTOCOL = 0; int PORT = 0; +char timestamp[17] = ""; int server_port = 0; char *server_address = NULL; char *server_send = NULL; @@ -184,6 +190,31 @@ main (int argc, char **argv) use_ssl=TRUE; PORT=995; } + else if (strstr(argv[0],"check_jabber")) { + progname = strdup("check_jabber"); + SERVICE = strdup("JABBER"); + SEND = strdup("\n"); + EXPECT = strdup("\n"); + PROTOCOL=TCP_PROTOCOL; + use_ssl=TRUE; + PORT = 5222; + } + else if (strstr (argv[0], "check_nntps")) { + progname = strdup("check_nntps"); + SERVICE = strdup("NNTPS"); + SEND = NULL; + EXPECT = NULL; + server_expect = realloc (server_expect, ++server_expect_count); + asprintf (&server_expect[server_expect_count - 1], "200"); + server_expect = realloc (server_expect, ++server_expect_count); + asprintf (&server_expect[server_expect_count - 1], "201"); + QUIT = strdup("QUIT\r\n"); + PROTOCOL = TCP_PROTOCOL; + use_ssl=TRUE; + PORT = 563; +} + #endif else if (strstr (argv[0], "check_nntp")) { progname = strdup ("check_nntp"); @@ -227,7 +258,24 @@ main (int argc, char **argv) /* try to connect to the host at the given port number */ gettimeofday (&tv, NULL); #ifdef HAVE_SSL - if (use_ssl) + if (use_ssl && check_cert == TRUE) { + if (connect_SSL () != OK) + die (STATE_CRITICAL,"TCP CRITICAL - Could not make SSL connection\n"); + if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) { + result = check_certificate (&server_cert); + X509_free(server_cert); + } + else { + printf("ERROR: Cannot retrieve server certificate.\n"); + result = STATE_CRITICAL; + } + SSL_shutdown (ssl); + SSL_free (ssl); + SSL_CTX_free (ctx); + close (sd); + return result; + } + else if (use_ssl) result = connect_SSL (); else #endif @@ -373,6 +421,10 @@ process_arguments (int argc, char **argv) {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, +#ifdef HAVE_SSL + {"ssl", no_argument, 0, 'S'}, + {"certificate", required_argument, 0, 'D'}, +#endif {0, 0, 0, 0} }; @@ -429,7 +481,7 @@ process_arguments (int argc, char **argv) break; case 'H': /* hostname */ if (is_host (optarg) == FALSE) - usage2 (_("Invalid host name/address"), optarg); + usage2 (_("invalid host name or address"), optarg); server_address = optarg; break; case 'c': /* critical */ @@ -459,7 +511,7 @@ process_arguments (int argc, char **argv) break; case 't': /* timeout */ if (!is_intpos (optarg)) - usage2 (_("Timeout interval must be a positive integer"), optarg); + usage (_("Timeout interval must be a positive integer\n")); else socket_timeout = atoi (optarg); break; @@ -504,12 +556,19 @@ process_arguments (int argc, char **argv) else usage (_("Delay must be a positive integer\n")); break; + case 'D': /* Check SSL cert validity - days 'til certificate expiration */ +#ifdef HAVE_SSL + if (!is_intnonneg (optarg)) + usage2 ("invalid certificate expiration period", optarg); + days_till_exp = atoi (optarg); + check_cert = TRUE; + use_ssl = TRUE; + break; case 'S': -#ifndef HAVE_SSL - die (STATE_UNKNOWN, - _("SSL support not available. Install OpenSSL and recompile.")); -#endif use_ssl = TRUE; +#else + die (STATE_UNKNOWN, "SSL support not available. Install OpenSSL and recompile."); +#endif break; } } @@ -556,7 +615,10 @@ connect_SSL (void) SSL_set_fd (ssl, sd); if (SSL_connect(ssl) == 1) return OK; - ERR_print_errors_fp (stderr); + /* ERR_print_errors_fp (stderr); */ + printf (_("ERROR: Cannot make SSL connection ")); + ERR_print_errors_fp (stdout); + /* printf("\n"); */ } else { @@ -572,7 +634,81 @@ connect_SSL (void) } #endif +#ifdef HAVE_SSL +int +check_certificate (X509 ** certificate) +{ + ASN1_STRING *tm; + int offset; + struct tm stamp; + int days_left; + + /* Retrieve timestamp of certificate */ + tm = X509_get_notAfter (*certificate); + + /* Generate tm structure to process timestamp */ + if (tm->type == V_ASN1_UTCTIME) { + if (tm->length < 10) { + printf ("ERROR: Wrong time format in certificate.\n"); + return STATE_CRITICAL; + } + else { + stamp.tm_year = (tm->data[0] - '0') * 10 + (tm->data[1] - '0'); + if (stamp.tm_year < 50) + stamp.tm_year += 100; + offset = 0; + } + } + else { + if (tm->length < 12) { + printf ("ERROR: Wrong time format in certificate.\n"); + return STATE_CRITICAL; + } + else { + stamp.tm_year = + (tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 + + (tm->data[2] - '0') * 10 + (tm->data[3] - '0'); + stamp.tm_year -= 1900; + offset = 2; + } + } + stamp.tm_mon = + (tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1; + stamp.tm_mday = + (tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0'); + stamp.tm_hour = + (tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0'); + stamp.tm_min = + (tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0'); + stamp.tm_sec = 0; + stamp.tm_isdst = -1; + + days_left = (mktime (&stamp) - time (NULL)) / 86400; + snprintf + (timestamp, 16, "%02d/%02d/%04d %02d:%02d", + stamp.tm_mon + 1, + stamp.tm_mday, stamp.tm_year + 1900, stamp.tm_hour, stamp.tm_min); + + if (days_left > 0 && days_left <= days_till_exp) { + printf ("Certificate expires in %d day(s) (%s).\n", days_left, timestamp); + return STATE_WARNING; + } + if (days_left < 0) { + printf ("Certificate expired on %s.\n", timestamp); + return STATE_CRITICAL; + } + + if (days_left == 0) { + printf ("Certificate expires today (%s).\n", timestamp); + return STATE_WARNING; + } + + printf ("Certificate will expire on %s.\n", timestamp); + + return STATE_OK; +} +#endif int my_recv (void) @@ -603,8 +739,8 @@ print_help (void) { print_revision (progname, revision); - printf ("Copyright (c) 1999 Ethan Galstad \n"); - printf (COPYRIGHT, copyright, email); + printf (_("Copyright (c) 1999 Ethan Galstad \n")); + printf (_(COPYRIGHT), copyright, email); printf (_("This plugin tests %s connections with the specified host.\n\n"), SERVICE); @@ -635,6 +771,14 @@ print_help (void) -d, --delay=INTEGER\n\ Seconds to wait between sending string and polling for response\n")); +#ifdef HAVE_SSL + printf (_("\ + -D, --certificate=INTEGER\n\ + Minimum number of days a certificate has to be valid.\n\ + -S, --ssl\n\ + Use SSL for the connection.\n")); +#endif + printf (_(UT_WARN_CRIT)); printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT); @@ -654,7 +798,8 @@ print_usage (void) Usage: %s -H host -p port [-w ] [-c ]\n\ [-s ] [-e ] [-q ]\n\ [-m ] [-d ] [-t ]\n\ - [-r ] [-v] [-4|-6] [-j]\n"), progname); + [-r ] [-v] [-4|-6] [-j] [-D ]\n\ + [-S ]\n"), progname); printf (" %s (-h|--help)\n", progname); printf (" %s (-V|--version)\n", progname); } -- 2.30.2