[monitoring-plugins] check_curl: implement certificate checks

Sven Nierlein git at monitoring-plugins.org
Wed Mar 15 09:20:14 CET 2017


 Module: monitoring-plugins
 Branch: feature_check_curl
 Commit: 1684deb8f7cc64270edcdff7c9bf40981bff20e3
 Author: Sven Nierlein <sven at nierlein.de>
   Date: Tue Mar 14 22:52:04 2017 +0100
    URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=1684deb

check_curl: implement certificate checks

Signed-off-by: Sven Nierlein <sven at nierlein.de>

---

 plugins/Makefile.am  |  4 ++--
 plugins/check_curl.c | 66 ++++++++++++++++++++++++++++++++++++++++++++--------
 plugins/sslutils.c   | 33 ++++++++++++++++----------
 3 files changed, 79 insertions(+), 24 deletions(-)

diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 2c87b4e..ffd8baf 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -71,7 +71,7 @@ check_apt_LDADD = $(BASEOBJS)
 check_cluster_LDADD = $(BASEOBJS)
 check_curl_CFLAGS = $(AM_CFLAGS) $(LIBCURLCFLAGS)
 check_curl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBCURLINCLUDE)
-check_curl_LDADD = $(NETLIBS) $(LIBCURLLIBS)
+check_curl_LDADD = $(NETLIBS) $(LIBCURLLIBS) $(SSLOBJS)
 check_dbi_LDADD = $(NETLIBS) $(DBILIBS)
 check_dig_LDADD = $(NETLIBS)
 check_disk_LDADD = $(BASEOBJS)
@@ -92,7 +92,7 @@ check_mysql_query_CFLAGS = $(AM_CFLAGS) $(MYSQLCFLAGS)
 check_mysql_query_CPPFLAGS = $(AM_CPPFLAGS) $(MYSQLINCLUDE)
 check_mysql_query_LDADD = $(NETLIBS) $(MYSQLLIBS)
 check_nagios_LDADD = $(BASEOBJS)
-check_nt_LDADD = $(NETLIBS) 
+check_nt_LDADD = $(NETLIBS)
 check_ntp_LDADD = $(NETLIBS) $(MATHLIBS)
 check_ntp_peer_LDADD = $(NETLIBS) $(MATHLIBS)
 check_nwstat_LDADD = $(NETLIBS)
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index c6a7ab8..e14fb19 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -93,6 +93,7 @@ unsigned short server_port = HTTP_PORT;
 char output_string_search[30] = "";
 char *warning_thresholds = NULL;
 char *critical_thresholds = NULL;
+int days_till_exp_warn, days_till_exp_crit;
 thresholds *thlds;
 char user_agent[DEFAULT_BUFFER_SIZE];
 int verbose = 0;
@@ -122,6 +123,7 @@ int ssl_version = CURL_SSLVERSION_DEFAULT;
 char *client_cert = NULL;
 char *client_privkey = NULL;
 char *ca_cert = NULL;
+X509 *cert = NULL;
 
 int process_arguments (int, char**);
 int check_http (void);
@@ -162,6 +164,19 @@ main (int argc, char **argv)
   return result;
 }
 
+int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
+{
+  cert = X509_STORE_CTX_get_current_cert(x509_ctx);
+  return 1;
+}
+
+CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm)
+{
+  SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback);
+
+  return CURLE_OK;
+}
+
 int
 check_http (void)
 {
@@ -177,6 +192,9 @@ check_http (void)
   if (verbose >= 3)
     curl_easy_setopt (curl, CURLOPT_VERBOSE, TRUE);
 
+  /* print everything on stdout like check_http would do */
+  curl_easy_setopt(curl, CURLOPT_STDERR, stdout);
+
   /* initialize buffer for body of the answer */
   if (curlhelp_initbuffer(&body_buf) < 0)
     die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n");
@@ -242,14 +260,16 @@ check_http (void)
   curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 2);
   curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2);
 
-  /* backward-compatible behaviour, be tolerant in checks */
-  if (!check_cert) {
-    /* TODO: depending on more options have aspects we want
-     * to be tolerant about
-     * curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1 );
-     */
-    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0);
-    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0);
+  /* backward-compatible behaviour, be tolerant in checks
+   * TODO: depending on more options have aspects we want
+   * to be less tolerant about ssl verfications
+   */
+  curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0);
+  curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0);
+
+  /* set callback to extract certificate */
+  if(check_cert) {
+    curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun);
   }
 
   /* set default or user-given user agent identification */
@@ -308,6 +328,16 @@ check_http (void)
     die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
   }
 
+  /* certificate checks */
+#ifdef HAVE_SSL
+  if (use_ssl == TRUE) {
+    if (check_cert == TRUE) {
+      result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
+      return(result);
+    }
+  }
+#endif /* HAVE_SSL */
+
   /* we got the data and we executed the request in a given time, so we can append
    * performance data to the answer always
    */
@@ -439,6 +469,7 @@ int
 process_arguments (int argc, char **argv)
 {
   int c = 1;
+  char *temp;
 
   enum {
     INVERT_REGEX = CHAR_MAX + 1,
@@ -537,8 +568,23 @@ process_arguments (int argc, char **argv)
       break;
     case 'C': /* Check SSL cert validity */
 #ifdef LIBCURL_FEATURE_SSL
-      /* TODO: C:, check age of certificate for backward compatible
-       * behaviour, but we would later add more check conditions */
+      if ((temp=strchr(optarg,','))!=NULL) {
+        *temp='\0';
+        if (!is_intnonneg (optarg))
+          usage2 (_("Invalid certificate expiration period"), optarg);
+        days_till_exp_warn = atoi(optarg);
+        *temp=',';
+        temp++;
+        if (!is_intnonneg (temp))
+          usage2 (_("Invalid certificate expiration period"), temp);
+        days_till_exp_crit = atoi (temp);
+      }
+      else {
+        days_till_exp_crit=0;
+        if (!is_intnonneg (optarg))
+          usage2 (_("Invalid certificate expiration period"), optarg);
+        days_till_exp_warn = atoi (optarg);
+      }
       check_cert = TRUE;
       goto enable_ssl;
 #endif
diff --git a/plugins/sslutils.c b/plugins/sslutils.c
index e38947e..14f6579 100644
--- a/plugins/sslutils.c
+++ b/plugins/sslutils.c
@@ -1,29 +1,29 @@
 /*****************************************************************************
-* 
+*
 * Monitoring Plugins SSL utilities
-* 
+*
 * License: GPL
 * Copyright (c) 2005-2010 Monitoring Plugins Development Team
-* 
+*
 * Description:
-* 
+*
 * This file contains common functions for plugins that require SSL.
-* 
+*
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
-* 
+*
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
-* 
+*
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
-* 
-* 
+*
+*
 *****************************************************************************/
 
 #define MAX_CN_LENGTH 256
@@ -193,12 +193,22 @@ int np_net_ssl_read(void *buf, int num) {
 
 int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){
 #  ifdef USE_OPENSSL
-	X509 *certificate=NULL;
+	X509 *certificate = NULL;
+	certificate=SSL_get_peer_certificate(s);
+	return(np_net_ssl_check_certificate(certificate, days_till_exp_warn, days_till_exp_crit));
+#  else /* ifndef USE_OPENSSL */
+	printf("%s\n", _("WARNING - Plugin does not support checking certificates."));
+	return STATE_WARNING;
+#  endif /* USE_OPENSSL */
+}
+
+int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit){
+#  ifdef USE_OPENSSL
 	X509_NAME *subj=NULL;
 	char timestamp[50] = "";
 	char cn[MAX_CN_LENGTH]= "";
 	char *tz;
-	
+
 	int cnlen =-1;
 	int status=STATE_UNKNOWN;
 
@@ -210,7 +220,6 @@ int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){
 	int time_remaining;
 	time_t tm_t;
 
-	certificate=SSL_get_peer_certificate(s);
 	if (!certificate) {
 		printf("%s\n",_("CRITICAL - Cannot retrieve server certificate."));
 		return STATE_CRITICAL;



More information about the Commits mailing list