From 16121a9b5526aa751f77a2d5ec3f15755f99b291 Mon Sep 17 00:00:00 2001 From: Sven Nierlein Date: Tue, 14 Mar 2017 22:52:04 +0100 Subject: check_curl: implement certificate checks Signed-off-by: Sven Nierlein --- 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 2c87b4e1..ffd8baf2 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 c6a7ab85..e14fb19b 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 e38947e3..14f6579d 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 . -* -* +* +* *****************************************************************************/ #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; -- cgit v1.2.3-74-g34f1