[monitoring-plugins] check_http: Allow for requesting TLSv1.1/TLSv1.2

Holger Weiss git at monitoring-plugins.org
Tue Oct 6 13:10:11 CEST 2015


 Module: monitoring-plugins
 Branch: master
 Commit: f43083c6a9d5d9e66d42e7cd0b698b7eb1ecf822
 Author: Holger Weiss <holger at zedat.fu-berlin.de>
   Date: Sun Oct  4 23:28:35 2015 +0200
    URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=f43083c

check_http: Allow for requesting TLSv1.1/TLSv1.2

check_http's -S/--ssl option now allows for requesting the TLSv1.1 and
TLSv1.2 protocols.  Apart from that, a '+' suffix can be appended in
oder to also accept newer protocols than the specified version.

Closes #1338, and closes #1354, and closes #1359.

---

 NEWS                 |  4 +++
 plugins/check_http.c | 22 ++++++++++----
 plugins/netutils.h   | 10 +++++++
 plugins/sslutils.c   | 81 ++++++++++++++++++++++++++++++++++++++++++----------
 4 files changed, 97 insertions(+), 20 deletions(-)

diff --git a/NEWS b/NEWS
index 1a4aead..4adc8f8 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,10 @@ This file documents the major additions and syntax changes between releases.
 	Make sure check_disk won't hang on hanging (network) file systems
 	New check_mailq -s option which tells the plugin to use sudo(8)
 	New -W/-C option for check_ldap to check number of entries (Gerhard Lausser)
+	The check_http -S/--ssl option now accepts the arguments "1.1" and "1.2"
+	  to force TLSv1.1 and TLSv1.2 connections, respectively
+	The check_http -S/--ssl option now allows for specifying the desired
+	  protocol with a "+" suffix to also accept newer versions
 
 	FIXES
 	Let check_real terminate lines with CRLF when talking to the server, as
diff --git a/plugins/check_http.c b/plugins/check_http.c
index 5167997..b1a69e5 100644
--- a/plugins/check_http.c
+++ b/plugins/check_http.c
@@ -343,9 +343,20 @@ process_arguments (int argc, char **argv)
          parameters, like -S and -C combinations */
       use_ssl = TRUE;
       if (c=='S' && optarg != NULL) {
-        ssl_version = atoi(optarg);
-        if (ssl_version < 1 || ssl_version > 3)
-            usage4 (_("Invalid option - Valid values for SSL Version are 1 (TLSv1), 2 (SSLv2) or 3 (SSLv3)"));
+        int got_plus = strchr(optarg, '+') != NULL;
+
+        if (!strncmp (optarg, "1.2", 3))
+          ssl_version = got_plus ? MP_TLSv1_2_OR_NEWER : MP_TLSv1_2;
+        else if (!strncmp (optarg, "1.1", 3))
+          ssl_version = got_plus ? MP_TLSv1_1_OR_NEWER : MP_TLSv1_1;
+        else if (optarg[0] == '1')
+          ssl_version = got_plus ? MP_TLSv1_OR_NEWER : MP_TLSv1;
+        else if (optarg[0] == '3')
+          ssl_version = got_plus ? MP_SSLv3_OR_NEWER : MP_SSLv3;
+        else if (optarg[0] == '2')
+          ssl_version = got_plus ? MP_SSLv2_OR_NEWER : MP_SSLv2;
+        else
+          usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2 (with optional '+' suffix)"));
       }
       if (specify_port == FALSE)
         server_port = HTTPS_PORT;
@@ -1467,9 +1478,10 @@ print_help (void)
   printf (UT_IPv46);
 
 #ifdef HAVE_SSL
-  printf (" %s\n", "-S, --ssl=VERSION");
+  printf (" %s\n", "-S, --ssl=VERSION[+]");
   printf ("    %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents"));
-  printf ("    %s\n", _("auto-negotiation (1 = TLSv1, 2 = SSLv2, 3 = SSLv3)."));
+  printf ("    %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,"));
+  printf ("    %s\n", _("1.2 = TLSv1.2). With a '+' suffix, newer versions are also accepted."));
   printf (" %s\n", "--sni");
   printf ("    %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
   printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]");
diff --git a/plugins/netutils.h b/plugins/netutils.h
index c6fce90..2766029 100644
--- a/plugins/netutils.h
+++ b/plugins/netutils.h
@@ -91,6 +91,16 @@ RETSIGTYPE socket_timeout_alarm_handler (int) __attribute__((noreturn));
 
 /* SSL-Related functionality */
 #ifdef HAVE_SSL
+#  define MP_SSLv2 1
+#  define MP_SSLv3 2
+#  define MP_TLSv1 3
+#  define MP_TLSv1_1 4
+#  define MP_TLSv1_2 5
+#  define MP_SSLv2_OR_NEWER 6
+#  define MP_SSLv3_OR_NEWER 7
+#  define MP_TLSv1_OR_NEWER 8
+#  define MP_TLSv1_1_OR_NEWER 9
+#  define MP_TLSv1_2_OR_NEWER 10
 /* maybe this could be merged with the above np_net_connect, via some flags */
 int np_net_ssl_init(int sd);
 int np_net_ssl_init_with_hostname(int sd, char *host_name);
diff --git a/plugins/sslutils.c b/plugins/sslutils.c
index d0ae474..43b1a5a 100644
--- a/plugins/sslutils.c
+++ b/plugins/sslutils.c
@@ -49,28 +49,78 @@ int np_net_ssl_init_with_hostname_and_version(int sd, char *host_name, int versi
 
 int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int version, char *cert, char *privkey) {
 	SSL_METHOD *method = NULL;
+	long options = 0;
 
 	switch (version) {
-	case 0: /* Deafult to auto negotiation */
-		method = SSLv23_client_method();
-		break;
-	case 1: /* TLSv1 protocol */
-		method = TLSv1_client_method();
-		break;
-	case 2: /* SSLv2 protocol */
+	case MP_SSLv2: /* SSLv2 protocol */
 #if defined(USE_GNUTLS) || defined(OPENSSL_NO_SSL2)
-		printf(("%s\n", _("CRITICAL - SSL protocol version 2 is not supported by your SSL library.")));
-		return STATE_CRITICAL;
+		printf("%s\n", _("UNKNOWN - SSL protocol version 2 is not supported by your SSL library."));
+		return STATE_UNKNOWN;
 #else
 		method = SSLv2_client_method();
-#endif
 		break;
-	case 3: /* SSLv3 protocol */
+#endif
+	case MP_SSLv3: /* SSLv3 protocol */
+#if defined(OPENSSL_NO_SSL3)
+		printf("%s\n", _("UNKNOWN - SSL protocol version 3 is not supported by your SSL library."));
+		return STATE_UNKNOWN;
+#else
 		method = SSLv3_client_method();
 		break;
-	default: /* Unsupported */
-		printf("%s\n", _("CRITICAL - Unsupported SSL protocol version."));
-		return STATE_CRITICAL;
+#endif
+	case MP_TLSv1: /* TLSv1 protocol */
+#if defined(OPENSSL_NO_TLS1)
+		printf("%s\n", _("UNKNOWN - TLS protocol version 1 is not supported by your SSL library."));
+		return STATE_UNKNOWN;
+#else
+		method = TLSv1_client_method();
+		break;
+#endif
+	case MP_TLSv1_1: /* TLSv1.1 protocol */
+#if !defined(SSL_OP_NO_TLSv1_1)
+		printf("%s\n", _("UNKNOWN - TLS protocol version 1.1 is not supported by your SSL library."));
+		return STATE_UNKNOWN;
+#else
+		method = TLSv1_1_client_method();
+		break;
+#endif
+	case MP_TLSv1_2: /* TLSv1.2 protocol */
+#if !defined(SSL_OP_NO_TLSv1_2)
+		printf("%s\n", _("UNKNOWN - TLS protocol version 1.2 is not supported by your SSL library."));
+		return STATE_UNKNOWN;
+#else
+		method = TLSv1_2_client_method();
+		break;
+#endif
+	case MP_TLSv1_2_OR_NEWER:
+#if !defined(SSL_OP_NO_TLSv1_1)
+		printf("%s\n", _("UNKNOWN - Disabling TLSv1.1 is not supported by your SSL library."));
+		return STATE_UNKNOWN;
+#else
+		options |= SSL_OP_NO_TLSv1_1;
+#endif
+		/* FALLTHROUGH */
+	case MP_TLSv1_1_OR_NEWER:
+#if !defined(SSL_OP_NO_TLSv1)
+		printf("%s\n", _("UNKNOWN - Disabling TLSv1 is not supported by your SSL library."));
+		return STATE_UNKNOWN;
+#else
+		options |= SSL_OP_NO_TLSv1;
+#endif
+		/* FALLTHROUGH */
+	case MP_TLSv1_OR_NEWER:
+#if defined(SSL_OP_NO_SSLv3)
+		options |= SSL_OP_NO_SSLv3;
+#endif
+		/* FALLTHROUGH */
+	case MP_SSLv3_OR_NEWER:
+#if defined(SSL_OP_NO_SSLv2)
+		options |= SSL_OP_NO_SSLv2;
+#endif
+	case MP_SSLv2_OR_NEWER:
+		/* FALLTHROUGH */
+	default: /* Default to auto negotiation */
+		method = SSLv23_client_method();
 	}
 	if (!initialized) {
 		/* Initialize SSL context */
@@ -94,8 +144,9 @@ int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int
 #endif
 	}
 #ifdef SSL_OP_NO_TICKET
-	SSL_CTX_set_options(c, SSL_OP_NO_TICKET);
+	options |= SSL_OP_NO_TICKET;
 #endif
+	SSL_CTX_set_options(c, options);
 	SSL_CTX_set_mode(c, SSL_MODE_AUTO_RETRY);
 	if ((s = SSL_new(c)) != NULL) {
 #ifdef SSL_set_tlsext_host_name



More information about the Commits mailing list