From 3008d521c1284f6f182d9cc10d56afdaa3978a04 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Wed, 12 Mar 2025 16:51:02 +0100
Subject: Refactor check_radius

---
 plugins/Makefile.am             |   1 +
 plugins/check_radius.c          | 126 +++++++++++++++++++++++-----------------
 plugins/check_radius.d/config.h |  42 ++++++++++++++
 3 files changed, 115 insertions(+), 54 deletions(-)
 create mode 100644 plugins/check_radius.d/config.h

(limited to 'plugins')

diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 6c582a15..dacd36e8 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -53,6 +53,7 @@ EXTRA_DIST = t \
 			 check_ldap.d \
 			 check_hpjd.d \
 			 check_game.d \
+			 check_radius.d \
 			 check_nagios.d \
 			 check_dbi.d \
 			 check_ssh.d \
diff --git a/plugins/check_radius.c b/plugins/check_radius.c
index ab7c6519..6a27e113 100644
--- a/plugins/check_radius.c
+++ b/plugins/check_radius.c
@@ -36,6 +36,7 @@ const char *email = "devel@monitoring-plugins.org";
 #include "utils.h"
 #include "netutils.h"
 #include "states.h"
+#include "check_radius.d/config.h"
 
 #if defined(HAVE_LIBRADCLI)
 #	include <radcli/radcli.h>
@@ -47,7 +48,11 @@ const char *email = "devel@monitoring-plugins.org";
 #	include <radiusclient.h>
 #endif
 
-static int process_arguments(int /*argc*/, char ** /*argv*/);
+typedef struct {
+	int errorcode;
+	check_radius_config config;
+} check_radius_config_wrapper;
+static check_radius_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
 static void print_help(void);
 void print_usage(void);
 
@@ -79,21 +84,8 @@ void print_usage(void);
 #	define REJECT_RC BADRESP_RC
 #endif
 
-static int my_rc_read_config(char * /*a*/);
+static int my_rc_read_config(char * /*a*/, rc_handle ** /*rch*/);
 
-#if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || defined(HAVE_LIBRADCLI)
-static rc_handle *rch = NULL;
-#endif
-
-static char *server = NULL;
-static char *username = NULL;
-static char *password = NULL;
-static char *nasid = NULL;
-static char *nasipaddress = NULL;
-static char *expect = NULL;
-static char *config_file = NULL;
-static unsigned short port = PW_AUTH_UDP_PORT;
-static int retries = 1;
 static bool verbose = false;
 
 /******************************************************************************
@@ -157,12 +149,20 @@ int main(int argc, char **argv) {
 	/* Parse extra opts if any */
 	argv = np_extra_opts(&argc, argv, progname);
 
-	if (process_arguments(argc, argv) == ERROR) {
+	check_radius_config_wrapper tmp_config = process_arguments(argc, argv);
+
+	if (tmp_config.errorcode == ERROR) {
 		usage4(_("Could not parse arguments"));
 	}
 
+	check_radius_config config = tmp_config.config;
+
+#if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || defined(HAVE_LIBRADCLI)
+	rc_handle *rch = NULL;
+#endif
+
 	char *str = strdup("dictionary");
-	if ((config_file && my_rc_read_config(config_file)) || my_rc_read_dictionary(my_rc_conf_str(str))) {
+	if ((config.config_file && my_rc_read_config(config.config_file, &rch)) || my_rc_read_dictionary(my_rc_conf_str(str))) {
 		die(STATE_UNKNOWN, _("Config file error\n"));
 	}
 
@@ -171,36 +171,36 @@ int main(int argc, char **argv) {
 	SEND_DATA data;
 	memset(&data, 0, sizeof(data));
 	if (!(my_rc_avpair_add(&data.send_pairs, PW_SERVICE_TYPE, &service, 0) &&
-		  my_rc_avpair_add(&data.send_pairs, PW_USER_NAME, username, 0) &&
-		  my_rc_avpair_add(&data.send_pairs, PW_USER_PASSWORD, password, 0))) {
+		  my_rc_avpair_add(&data.send_pairs, PW_USER_NAME, config.username, 0) &&
+		  my_rc_avpair_add(&data.send_pairs, PW_USER_PASSWORD, config.password, 0))) {
 		die(STATE_UNKNOWN, _("Out of Memory?\n"));
 	}
 
-	if (nasid != NULL) {
-		if (!(my_rc_avpair_add(&data.send_pairs, PW_NAS_IDENTIFIER, nasid, 0))) {
+	if (config.nas_id != NULL) {
+		if (!(my_rc_avpair_add(&data.send_pairs, PW_NAS_IDENTIFIER, config.nas_id, 0))) {
 			die(STATE_UNKNOWN, _("Invalid NAS-Identifier\n"));
 		}
 	}
 
 	char name[HOST_NAME_MAX];
-	if (nasipaddress == NULL) {
+	if (config.nas_ip_address == NULL) {
 		if (gethostname(name, sizeof(name)) != 0) {
 			die(STATE_UNKNOWN, _("gethostname() failed!\n"));
 		}
-		nasipaddress = name;
+		config.nas_ip_address = name;
 	}
 
-	struct sockaddr_storage ss;
-	if (!dns_lookup(nasipaddress, &ss, AF_INET)) { /* TODO: Support IPv6. */
+	struct sockaddr_storage radius_server_socket;
+	if (!dns_lookup(config.nas_ip_address, &radius_server_socket, AF_INET)) { /* TODO: Support IPv6. */
 		die(STATE_UNKNOWN, _("Invalid NAS-IP-Address\n"));
 	}
 
-	uint32_t client_id = ntohl(((struct sockaddr_in *)&ss)->sin_addr.s_addr);
+	uint32_t client_id = ntohl(((struct sockaddr_in *)&radius_server_socket)->sin_addr.s_addr);
 	if (my_rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) == NULL) {
 		die(STATE_UNKNOWN, _("Invalid NAS-IP-Address\n"));
 	}
 
-	my_rc_buildreq(&data, PW_ACCESS_REQUEST, server, port, (int)timeout_interval, retries);
+	my_rc_buildreq(&data, PW_ACCESS_REQUEST, config.server, config.port, (int)timeout_interval, config.retries);
 
 #ifdef RC_BUFFER_LEN
 	char msg[RC_BUFFER_LEN];
@@ -208,36 +208,49 @@ int main(int argc, char **argv) {
 	char msg[BUFFER_LEN];
 #endif
 
-	mp_state_enum result = my_rc_send_server(&data, msg);
+	int result = my_rc_send_server(&data, msg);
 	rc_avpair_free(data.send_pairs);
 	if (data.receive_pairs) {
 		rc_avpair_free(data.receive_pairs);
 	}
 
 	if (result == TIMEOUT_RC) {
-		die(STATE_CRITICAL, _("Timeout\n"));
+		printf("Timeout\n");
+		exit(STATE_CRITICAL);
 	}
+
 	if (result == ERROR_RC) {
-		die(STATE_CRITICAL, _("Auth Error\n"));
+		printf(_("Auth Error\n"));
+		exit(STATE_CRITICAL);
 	}
+
 	if (result == REJECT_RC) {
-		die(STATE_WARNING, _("Auth Failed\n"));
+		printf(_("Auth Failed\n"));
+		exit(STATE_WARNING);
 	}
+
 	if (result == BADRESP_RC) {
-		die(STATE_WARNING, _("Bad Response\n"));
+		printf(_("Bad Response\n"));
+		exit(STATE_WARNING);
 	}
-	if (expect && !strstr(msg, expect)) {
-		die(STATE_WARNING, "%s\n", msg);
+
+	if (config.expect && !strstr(msg, config.expect)) {
+		printf("%s\n", msg);
+		exit(STATE_WARNING);
 	}
+
 	if (result == OK_RC) {
-		die(STATE_OK, _("Auth OK\n"));
+		printf(_("Auth OK\n"));
+		exit(STATE_OK);
 	}
+
 	(void)snprintf(msg, sizeof(msg), _("Unexpected result code %d"), result);
-	die(STATE_UNKNOWN, "%s\n", msg);
+	printf("%s\n", msg);
+	exit(STATE_UNKNOWN);
 }
 
 /* process command-line arguments */
-int process_arguments(int argc, char **argv) {
+check_radius_config_wrapper process_arguments(int argc, char **argv) {
 	static struct option longopts[] = {{"hostname", required_argument, 0, 'H'}, {"port", required_argument, 0, 'P'},
 									   {"username", required_argument, 0, 'u'}, {"password", required_argument, 0, 'p'},
 									   {"nas-id", required_argument, 0, 'n'},   {"nas-ip-address", required_argument, 0, 'N'},
@@ -246,6 +259,11 @@ int process_arguments(int argc, char **argv) {
 									   {"verbose", no_argument, 0, 'v'},        {"version", no_argument, 0, 'V'},
 									   {"help", no_argument, 0, 'h'},           {0, 0, 0, 0}};
 
+	check_radius_config_wrapper result = {
+		.errorcode = OK,
+		.config = check_radius_config_init(),
+	};
+
 	while (true) {
 		int option = 0;
 		int option_index = getopt_long(argc, argv, "+hVvH:P:F:u:p:n:N:t:r:e:", longopts, &option);
@@ -270,20 +288,20 @@ int process_arguments(int argc, char **argv) {
 			if (!is_host(optarg)) {
 				usage2(_("Invalid hostname/address"), optarg);
 			}
-			server = optarg;
+			result.config.server = optarg;
 			break;
 		case 'P': /* port */
 			if (is_intnonneg(optarg)) {
-				port = (unsigned short)atoi(optarg);
+				result.config.port = (unsigned short)atoi(optarg);
 			} else {
 				usage4(_("Port must be a positive integer"));
 			}
 			break;
 		case 'u': /* username */
-			username = optarg;
+			result.config.username = optarg;
 			break;
 		case 'p': /* password */
-			password = strdup(optarg);
+			result.config.password = strdup(optarg);
 
 			/* Delete the password from process list */
 			while (*optarg != '\0') {
@@ -292,20 +310,20 @@ int process_arguments(int argc, char **argv) {
 			}
 			break;
 		case 'n': /* nas id */
-			nasid = optarg;
+			result.config.nas_id = optarg;
 			break;
 		case 'N': /* nas ip address */
-			nasipaddress = optarg;
+			result.config.nas_ip_address = optarg;
 			break;
 		case 'F': /* configuration file */
-			config_file = optarg;
+			result.config.config_file = optarg;
 			break;
 		case 'e': /* expect */
-			expect = optarg;
+			result.config.expect = optarg;
 			break;
 		case 'r': /* retries */
 			if (is_intpos(optarg)) {
-				retries = atoi(optarg);
+				result.config.retries = atoi(optarg);
 			} else {
 				usage4(_("Number of retries must be a positive integer"));
 			}
@@ -320,20 +338,20 @@ int process_arguments(int argc, char **argv) {
 		}
 	}
 
-	if (server == NULL) {
+	if (result.config.server == NULL) {
 		usage4(_("Hostname was not supplied"));
 	}
-	if (username == NULL) {
+	if (result.config.username == NULL) {
 		usage4(_("User not specified"));
 	}
-	if (password == NULL) {
+	if (result.config.password == NULL) {
 		usage4(_("Password not specified"));
 	}
-	if (config_file == NULL) {
+	if (result.config.config_file == NULL) {
 		usage4(_("Configuration file not specified"));
 	}
 
-	return OK;
+	return result;
 }
 
 void print_help(void) {
@@ -395,11 +413,11 @@ void print_usage(void) {
 		   progname);
 }
 
-int my_rc_read_config(char *a) {
+int my_rc_read_config(char *config_file_name, rc_handle **rch) {
 #if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || defined(HAVE_LIBRADCLI)
-	rch = rc_read_config(a);
+	*rch = rc_read_config(config_file_name);
 	return (rch == NULL) ? 1 : 0;
 #else
-	return rc_read_config(a);
+	return rc_read_config(config_file_name);
 #endif
 }
diff --git a/plugins/check_radius.d/config.h b/plugins/check_radius.d/config.h
new file mode 100644
index 00000000..b27d31e7
--- /dev/null
+++ b/plugins/check_radius.d/config.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "../../config.h"
+#include <stddef.h>
+#if defined(HAVE_LIBRADCLI)
+#	include <radcli/radcli.h>
+#elif defined(HAVE_LIBFREERADIUS_CLIENT)
+#	include <freeradius-client.h>
+#elif defined(HAVE_LIBRADIUSCLIENT_NG)
+#	include <radiusclient-ng.h>
+#else
+#	include <radiusclient.h>
+#endif
+
+typedef struct {
+	char *server;
+	char *username;
+	char *password;
+	char *config_file;
+	char *nas_id;
+	char *nas_ip_address;
+	int retries;
+	unsigned short port;
+
+	char *expect;
+} check_radius_config;
+
+check_radius_config check_radius_config_init() {
+	check_radius_config tmp = {
+		.server = NULL,
+		.username = NULL,
+		.password = NULL,
+		.config_file = NULL,
+		.nas_id = NULL,
+		.nas_ip_address = NULL,
+		.retries = 1,
+		.port = PW_AUTH_UDP_PORT,
+
+		.expect = NULL,
+	};
+	return tmp;
+}
-- 
cgit v1.2.3-74-g34f1