From c7274d56274fa1a38837510b1cbde447e73e9b63 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 10 Sep 2025 13:40:21 +0200 Subject: netutils.h: clang-format --- plugins/netutils.h | 131 ++++++++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 66 deletions(-) (limited to 'plugins/netutils.h') diff --git a/plugins/netutils.h b/plugins/netutils.h index a95057e0..0ca524f2 100644 --- a/plugins/netutils.h +++ b/plugins/netutils.h @@ -1,63 +1,64 @@ /***************************************************************************** -* -* Monitoring Plugins net utilities include file -* -* License: GPL -* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org) -* Copyright (c) 2003-2007 Monitoring Plugins Development Team -* -* Description: -* -* This file contains common include files and function definitions -* used in many of the plugins. -* -* -* 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 . -* -* -*****************************************************************************/ + * + * Monitoring Plugins net utilities include file + * + * License: GPL + * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org) + * Copyright (c) 2003-2007 Monitoring Plugins Development Team + * + * Description: + * + * This file contains common include files and function definitions + * used in many of the plugins. + * + * + * 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 . + * + * + *****************************************************************************/ #ifndef _NETUTILS_H_ #define _NETUTILS_H_ #include "common.h" +#include "states.h" #include "utils.h" #include #include #include #ifdef HAVE_SYS_UN_H -# include -# ifndef UNIX_PATH_MAX - /* linux uses this, on sun it's hard-coded at 108 without a define, on BSD at 104 */ -# define UNIX_PATH_MAX 104 -# endif /* UNIX_PATH_MAX */ -#endif /* HAVE_SYS_UN_H */ +# include +# ifndef UNIX_PATH_MAX +/* linux uses this, on sun it's hard-coded at 108 without a define, on BSD at 104 */ +# define UNIX_PATH_MAX 104 +# endif /* UNIX_PATH_MAX */ +#endif /* HAVE_SYS_UN_H */ #ifndef HOST_MAX_BYTES -# define HOST_MAX_BYTES 255 +# define HOST_MAX_BYTES 255 #endif /* process_request and wrapper macros */ -#define process_tcp_request(addr, port, sbuf, rbuf, rsize) \ +#define process_tcp_request(addr, port, sbuf, rbuf, rsize) \ process_request(addr, port, IPPROTO_TCP, sbuf, rbuf, rsize) -#define process_udp_request(addr, port, sbuf, rbuf, rsize) \ +#define process_udp_request(addr, port, sbuf, rbuf, rsize) \ process_request(addr, port, IPPROTO_UDP, sbuf, rbuf, rsize) -int process_tcp_request2 (const char *address, int port, - const char *sbuffer, char *rbuffer, int rsize); -int process_request (const char *address, int port, int proto, - const char *sbuffer, char *rbuffer, int rsize); +int process_tcp_request2(const char *address, int port, const char *sbuffer, char *rbuffer, + int rsize); +int process_request(const char *address, int port, int proto, const char *sbuffer, char *rbuffer, + int rsize); /* my_connect and wrapper macros */ #define my_tcp_connect(addr, port, s) np_net_connect(addr, port, s, IPPROTO_TCP) @@ -65,25 +66,22 @@ int process_request (const char *address, int port, int proto, int np_net_connect(const char *address, int port, int *sd, int proto); /* send_request and wrapper macros */ -#define send_tcp_request(s, sbuf, rbuf, rsize) \ - send_request(s, IPPROTO_TCP, sbuf, rbuf, rsize) -#define send_udp_request(s, sbuf, rbuf, rsize) \ - send_request(s, IPPROTO_UDP, sbuf, rbuf, rsize) -int send_request (int sd, int proto, const char *send_buffer, char *recv_buffer, int recv_size); - +#define send_tcp_request(s, sbuf, rbuf, rsize) send_request(s, IPPROTO_TCP, sbuf, rbuf, rsize) +#define send_udp_request(s, sbuf, rbuf, rsize) send_request(s, IPPROTO_UDP, sbuf, rbuf, rsize) +int send_request(int sd, int proto, const char *send_buffer, char *recv_buffer, int recv_size); /* "is_*" wrapper macros and functions */ -bool is_host (const char *); -bool is_addr (const char *); -int dns_lookup (const char *, struct sockaddr_storage *, int); +bool is_host(const char *); +bool is_addr(const char *); +int dns_lookup(const char *, struct sockaddr_storage *, int); void host_or_die(const char *str); #define resolve_host_or_addr(addr, family) dns_lookup(addr, NULL, family) -#define is_inet_addr(addr) resolve_host_or_addr(addr, AF_INET) +#define is_inet_addr(addr) resolve_host_or_addr(addr, AF_INET) #ifdef USE_IPV6 -# define is_inet6_addr(addr) resolve_host_or_addr(addr, AF_INET6) -# define is_hostname(addr) resolve_host_or_addr(addr, address_family) +# define is_inet6_addr(addr) resolve_host_or_addr(addr, AF_INET6) +# define is_hostname(addr) resolve_host_or_addr(addr, address_family) #else -# define is_hostname(addr) resolve_host_or_addr(addr, AF_INET) +# define is_hostname(addr) resolve_host_or_addr(addr, AF_INET) #endif extern unsigned int socket_timeout; @@ -92,25 +90,26 @@ extern int econn_refuse_state; extern bool was_refused; extern int address_family; -void socket_timeout_alarm_handler (int) __attribute__((noreturn)); +void 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 +# 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); int np_net_ssl_init_with_hostname_and_version(int sd, char *host_name, int version); -int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int version, char *cert, char *privkey); +int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int version, char *cert, + char *privkey); void np_net_ssl_cleanup(); int np_net_ssl_write(const void *buf, int num); int np_net_ssl_read(void *buf, int num); -- cgit v1.2.3-74-g34f1 From 572ad994b136c443c5d59509a28b8343c3e40ab3 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 10 Sep 2025 13:41:22 +0200 Subject: plugins-netutils: return proper state from test functions --- plugins/netutils.h | 2 +- plugins/sslutils.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'plugins/netutils.h') diff --git a/plugins/netutils.h b/plugins/netutils.h index 0ca524f2..c53b3cef 100644 --- a/plugins/netutils.h +++ b/plugins/netutils.h @@ -113,7 +113,7 @@ int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int void np_net_ssl_cleanup(); int np_net_ssl_write(const void *buf, int num); 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); +mp_state_enum np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit); #endif /* HAVE_SSL */ #endif /* _NETUTILS_H_ */ diff --git a/plugins/sslutils.c b/plugins/sslutils.c index 92e0cc84..b20a2b2c 100644 --- a/plugins/sslutils.c +++ b/plugins/sslutils.c @@ -30,6 +30,7 @@ #include "common.h" #include "netutils.h" #include "../lib/monitoringplug.h" +#include "states.h" #ifdef HAVE_SSL static SSL_CTX *ctx = NULL; @@ -318,7 +319,7 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, # endif /* USE_OPENSSL */ } -int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit) { +mp_state_enum np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit) { # ifdef USE_OPENSSL X509 *certificate = NULL; certificate = SSL_get_peer_certificate(s); -- cgit v1.2.3-74-g34f1 From f5f4a021a2760d553e3e4cdedd291eb815750369 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 15 Sep 2025 01:57:40 +0200 Subject: Add new cert check function --- plugins/check_curl.c | 3 +- plugins/netutils.h | 3 +- plugins/sslutils.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 2 deletions(-) (limited to 'plugins/netutils.h') diff --git a/plugins/check_curl.c b/plugins/check_curl.c index 680ecef7..b1021045 100644 --- a/plugins/check_curl.c +++ b/plugins/check_curl.c @@ -569,8 +569,9 @@ mp_subcheck check_http(const check_curl_config config, check_curl_working_state sc_body_regex = mp_set_subcheck_state(sc_body_regex, STATE_OK); } } else if (errcode == REG_NOMATCH) { - xasprintf(&sc_body_regex.output, "%s not", sc_body_regex.output); // got no match + xasprintf(&sc_body_regex.output, "%s not", sc_body_regex.output); + if (config.invert_regex) { sc_body_regex = mp_set_subcheck_state(sc_body_regex, STATE_OK); } else { diff --git a/plugins/netutils.h b/plugins/netutils.h index c53b3cef..6adb8e01 100644 --- a/plugins/netutils.h +++ b/plugins/netutils.h @@ -32,6 +32,7 @@ #define _NETUTILS_H_ #include "common.h" +#include "output.h" #include "states.h" #include "utils.h" #include @@ -114,6 +115,6 @@ void np_net_ssl_cleanup(); int np_net_ssl_write(const void *buf, int num); int np_net_ssl_read(void *buf, int num); mp_state_enum np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit); +mp_subcheck mp_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit); #endif /* HAVE_SSL */ - #endif /* _NETUTILS_H_ */ diff --git a/plugins/sslutils.c b/plugins/sslutils.c index bea1307f..3ce6afed 100644 --- a/plugins/sslutils.c +++ b/plugins/sslutils.c @@ -26,6 +26,7 @@ * *****************************************************************************/ +#include "output.h" #define MAX_CN_LENGTH 256 #include "common.h" #include "netutils.h" @@ -322,4 +323,138 @@ mp_state_enum np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_cr # endif /* USE_OPENSSL */ } +mp_subcheck mp_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, + int days_till_exp_crit) { + mp_subcheck sc_cert = mp_subcheck_init(); +# ifdef USE_OPENSSL + if (!certificate) { + xasprintf(&sc_cert.output, _("No server certificate present to inspect")); + sc_cert = mp_set_subcheck_state(sc_cert, STATE_CRITICAL); + return sc_cert; + } + + /* Extract CN from certificate subject */ + X509_NAME *subj = X509_get_subject_name(certificate); + + if (!subj) { + xasprintf(&sc_cert.output, _("Cannot retrieve certificate subject")); + sc_cert = mp_set_subcheck_state(sc_cert, STATE_CRITICAL); + return sc_cert; + } + + char commonName[MAX_CN_LENGTH] = ""; + int cnlen = X509_NAME_get_text_by_NID(subj, NID_commonName, commonName, sizeof(commonName)); + if (cnlen == -1) { + strcpy(commonName, _("Unknown CN")); + } + + /* Retrieve timestamp of certificate */ + ASN1_STRING *expiry_timestamp = X509_get_notAfter(certificate); + + int offset = 0; + struct tm stamp = {}; + /* Generate tm structure to process timestamp */ + if (expiry_timestamp->type == V_ASN1_UTCTIME) { + if (expiry_timestamp->length < 10) { + xasprintf(&sc_cert.output, _("Wrong time format in certificate")); + sc_cert = mp_set_subcheck_state(sc_cert, STATE_CRITICAL); + return sc_cert; + } + + stamp.tm_year = (expiry_timestamp->data[0] - '0') * 10 + (expiry_timestamp->data[1] - '0'); + if (stamp.tm_year < 50) { + stamp.tm_year += 100; + } + + offset = 0; + } else { + if (expiry_timestamp->length < 12) { + xasprintf(&sc_cert.output, _("Wrong time format in certificate")); + sc_cert = mp_set_subcheck_state(sc_cert, STATE_CRITICAL); + return sc_cert; + } + stamp.tm_year = (expiry_timestamp->data[0] - '0') * 1000 + + (expiry_timestamp->data[1] - '0') * 100 + + (expiry_timestamp->data[2] - '0') * 10 + (expiry_timestamp->data[3] - '0'); + stamp.tm_year -= 1900; + offset = 2; + } + + stamp.tm_mon = (expiry_timestamp->data[2 + offset] - '0') * 10 + + (expiry_timestamp->data[3 + offset] - '0') - 1; + stamp.tm_mday = (expiry_timestamp->data[4 + offset] - '0') * 10 + + (expiry_timestamp->data[5 + offset] - '0'); + stamp.tm_hour = (expiry_timestamp->data[6 + offset] - '0') * 10 + + (expiry_timestamp->data[7 + offset] - '0'); + stamp.tm_min = (expiry_timestamp->data[8 + offset] - '0') * 10 + + (expiry_timestamp->data[9 + offset] - '0'); + stamp.tm_sec = (expiry_timestamp->data[10 + offset] - '0') * 10 + + (expiry_timestamp->data[11 + offset] - '0'); + stamp.tm_isdst = -1; + + time_t tm_t = timegm(&stamp); + double time_left = difftime(tm_t, time(NULL)); + int days_left = (int)(time_left / 86400); + char *timeZone = getenv("TZ"); + setenv("TZ", "GMT", 1); + tzset(); + + char timestamp[50] = ""; + strftime(timestamp, 50, "%c %z", localtime(&tm_t)); + if (timeZone) { + setenv("TZ", timeZone, 1); + } else { + unsetenv("TZ"); + } + + tzset(); + + int time_remaining; + if (days_left > 0 && days_left <= days_till_exp_warn) { + xasprintf(&sc_cert.output, _("Certificate '%s' expires in %d day(s) (%s)"), commonName, + days_left, timestamp); + if (days_left > days_till_exp_crit) { + sc_cert = mp_set_subcheck_state(sc_cert, STATE_WARNING); + } else { + sc_cert = mp_set_subcheck_state(sc_cert, STATE_CRITICAL); + } + } else if (days_left == 0 && time_left > 0) { + if (time_left >= 3600) { + time_remaining = (int)time_left / 3600; + } else { + time_remaining = (int)time_left / 60; + } + + xasprintf(&sc_cert.output, _("Certificate '%s' expires in %u %s (%s)"), commonName, + time_remaining, time_left >= 3600 ? "hours" : "minutes", timestamp); + + if (days_left > days_till_exp_crit) { + sc_cert = mp_set_subcheck_state(sc_cert, STATE_WARNING); + } else { + sc_cert = mp_set_subcheck_state(sc_cert, STATE_CRITICAL); + } + } else if (time_left < 0) { + xasprintf(&sc_cert.output, _("Certificate '%s' expired on %s"), commonName, timestamp); + sc_cert = mp_set_subcheck_state(sc_cert, STATE_CRITICAL); + } else if (days_left == 0) { + xasprintf(&sc_cert.output, _("Certificate '%s' just expired (%s)"), commonName, + timestamp); + if (days_left > days_till_exp_crit) { + sc_cert = mp_set_subcheck_state(sc_cert, STATE_WARNING); + } else { + sc_cert = mp_set_subcheck_state(sc_cert, STATE_CRITICAL); + } + } else { + xasprintf(&sc_cert.output, _("Certificate '%s' will expire on %s"), commonName, + timestamp); + sc_cert = mp_set_subcheck_state(sc_cert, STATE_OK); + } + X509_free(certificate); + return sc_cert; +# else /* ifndef USE_OPENSSL */ + xasprintf(&sc_cert.output, _("Plugin does not support checking certificates")); + sc_cert = mp_set_subcheck_state(sc_cert, STATE_WARNING); + return sc_cert; +# endif /* USE_OPENSSL */ +} #endif /* HAVE_SSL */ -- cgit v1.2.3-74-g34f1