diff options
Diffstat (limited to 'plugins/check_radius.c')
| -rw-r--r-- | plugins/check_radius.c | 150 |
1 files changed, 115 insertions, 35 deletions
diff --git a/plugins/check_radius.c b/plugins/check_radius.c index cc846709..93352bcc 100644 --- a/plugins/check_radius.c +++ b/plugins/check_radius.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | * | 28 | * |
| 29 | *****************************************************************************/ | 29 | *****************************************************************************/ |
| 30 | 30 | ||
| 31 | #include "output.h" | ||
| 31 | const char *progname = "check_radius"; | 32 | const char *progname = "check_radius"; |
| 32 | const char *copyright = "2000-2024"; | 33 | const char *copyright = "2000-2024"; |
| 33 | const char *email = "devel@monitoring-plugins.org"; | 34 | const char *email = "devel@monitoring-plugins.org"; |
| @@ -56,7 +57,8 @@ static check_radius_config_wrapper process_arguments(int /*argc*/, char ** /*arg | |||
| 56 | static void print_help(void); | 57 | static void print_help(void); |
| 57 | void print_usage(void); | 58 | void print_usage(void); |
| 58 | 59 | ||
| 59 | #if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || defined(HAVE_LIBRADCLI) | 60 | #if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || \ |
| 61 | defined(HAVE_LIBRADCLI) | ||
| 60 | # define my_rc_conf_str(a) rc_conf_str(rch, a) | 62 | # define my_rc_conf_str(a) rc_conf_str(rch, a) |
| 61 | # if defined(HAVE_LIBRADCLI) | 63 | # if defined(HAVE_LIBRADCLI) |
| 62 | # define my_rc_send_server(a, b) rc_send_server(rch, a, b, AUTH) | 64 | # define my_rc_send_server(a, b) rc_send_server(rch, a, b, AUTH) |
| @@ -157,50 +159,84 @@ int main(int argc, char **argv) { | |||
| 157 | 159 | ||
| 158 | check_radius_config config = tmp_config.config; | 160 | check_radius_config config = tmp_config.config; |
| 159 | 161 | ||
| 160 | #if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || defined(HAVE_LIBRADCLI) | 162 | if (config.output_format_is_set) { |
| 163 | mp_set_format(config.output_format); | ||
| 164 | } | ||
| 165 | |||
| 166 | #if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || \ | ||
| 167 | defined(HAVE_LIBRADCLI) | ||
| 161 | rc_handle *rch = NULL; | 168 | rc_handle *rch = NULL; |
| 162 | #endif | 169 | #endif |
| 163 | 170 | ||
| 171 | mp_check overall = mp_check_init(); | ||
| 172 | mp_subcheck sc_read_config = mp_subcheck_init(); | ||
| 173 | |||
| 164 | char *str = strdup("dictionary"); | 174 | char *str = strdup("dictionary"); |
| 165 | if ((config.config_file && my_rc_read_config(config.config_file, &rch)) || my_rc_read_dictionary(my_rc_conf_str(str))) { | 175 | if ((config.config_file && my_rc_read_config(config.config_file, &rch)) || |
| 166 | die(STATE_UNKNOWN, _("Config file error\n")); | 176 | my_rc_read_dictionary(my_rc_conf_str(str))) { |
| 177 | sc_read_config = mp_set_subcheck_state(sc_read_config, STATE_UNKNOWN); | ||
| 178 | xasprintf(&sc_read_config.output, "failed to read config file"); | ||
| 179 | mp_add_subcheck_to_check(&overall, sc_read_config); | ||
| 180 | mp_exit(overall); | ||
| 167 | } | 181 | } |
| 168 | 182 | ||
| 183 | sc_read_config = mp_set_subcheck_state(sc_read_config, STATE_OK); | ||
| 184 | xasprintf(&sc_read_config.output, "read config file successfully"); | ||
| 185 | mp_add_subcheck_to_check(&overall, sc_read_config); | ||
| 186 | |||
| 169 | uint32_t service = PW_AUTHENTICATE_ONLY; | 187 | uint32_t service = PW_AUTHENTICATE_ONLY; |
| 170 | 188 | ||
| 189 | mp_subcheck sc_configuring = mp_subcheck_init(); | ||
| 171 | SEND_DATA data; | 190 | SEND_DATA data; |
| 172 | memset(&data, 0, sizeof(data)); | 191 | memset(&data, 0, sizeof(data)); |
| 173 | if (!(my_rc_avpair_add(&data.send_pairs, PW_SERVICE_TYPE, &service, 0) && | 192 | if (!(my_rc_avpair_add(&data.send_pairs, PW_SERVICE_TYPE, &service, 0) && |
| 174 | my_rc_avpair_add(&data.send_pairs, PW_USER_NAME, config.username, 0) && | 193 | my_rc_avpair_add(&data.send_pairs, PW_USER_NAME, config.username, 0) && |
| 175 | my_rc_avpair_add(&data.send_pairs, PW_USER_PASSWORD, config.password, 0))) { | 194 | my_rc_avpair_add(&data.send_pairs, PW_USER_PASSWORD, config.password, 0))) { |
| 176 | die(STATE_UNKNOWN, _("Out of Memory?\n")); | 195 | xasprintf(&sc_configuring.output, "Failed to the radius options: Out of Memory?"); |
| 196 | sc_configuring = mp_set_subcheck_state(sc_configuring, STATE_UNKNOWN); | ||
| 197 | mp_add_subcheck_to_check(&overall, sc_configuring); | ||
| 198 | mp_exit(overall); | ||
| 177 | } | 199 | } |
| 178 | 200 | ||
| 179 | if (config.nas_id != NULL) { | 201 | if (config.nas_id != NULL) { |
| 180 | if (!(my_rc_avpair_add(&data.send_pairs, PW_NAS_IDENTIFIER, config.nas_id, 0))) { | 202 | if (!(my_rc_avpair_add(&data.send_pairs, PW_NAS_IDENTIFIER, config.nas_id, 0))) { |
| 181 | die(STATE_UNKNOWN, _("Invalid NAS-Identifier\n")); | 203 | xasprintf(&sc_configuring.output, |
| 204 | "Failed to the radius options: invalid NAS identifier?"); | ||
| 205 | sc_configuring = mp_set_subcheck_state(sc_configuring, STATE_UNKNOWN); | ||
| 206 | mp_add_subcheck_to_check(&overall, sc_configuring); | ||
| 207 | mp_exit(overall); | ||
| 182 | } | 208 | } |
| 183 | } | 209 | } |
| 184 | 210 | ||
| 185 | char name[HOST_NAME_MAX]; | 211 | char name[HOST_NAME_MAX]; |
| 186 | if (config.nas_ip_address == NULL) { | 212 | if (config.nas_ip_address == NULL) { |
| 187 | if (gethostname(name, sizeof(name)) != 0) { | 213 | if (gethostname(name, sizeof(name)) != 0) { |
| 188 | die(STATE_UNKNOWN, _("gethostname() failed!\n")); | 214 | xasprintf(&sc_configuring.output, "gethostname() failed"); |
| 215 | sc_configuring = mp_set_subcheck_state(sc_configuring, STATE_UNKNOWN); | ||
| 216 | mp_add_subcheck_to_check(&overall, sc_configuring); | ||
| 217 | mp_exit(overall); | ||
| 189 | } | 218 | } |
| 190 | config.nas_ip_address = name; | 219 | config.nas_ip_address = name; |
| 191 | } | 220 | } |
| 192 | 221 | ||
| 193 | struct sockaddr_storage radius_server_socket; | 222 | struct sockaddr_storage radius_server_socket; |
| 194 | if (!dns_lookup(config.nas_ip_address, &radius_server_socket, AF_UNSPEC)) { | 223 | if (!dns_lookup(config.nas_ip_address, &radius_server_socket, AF_UNSPEC)) { |
| 195 | die(STATE_UNKNOWN, _("Invalid NAS-IP-Address\n")); | 224 | xasprintf(&sc_configuring.output, "invalid NAS IP address. Lookup failed"); |
| 225 | sc_configuring = mp_set_subcheck_state(sc_configuring, STATE_UNKNOWN); | ||
| 226 | mp_add_subcheck_to_check(&overall, sc_configuring); | ||
| 227 | mp_exit(overall); | ||
| 196 | } | 228 | } |
| 197 | 229 | ||
| 198 | uint32_t client_id = ntohl(((struct sockaddr_in *)&radius_server_socket)->sin_addr.s_addr); | 230 | uint32_t client_id = ntohl(((struct sockaddr_in *)&radius_server_socket)->sin_addr.s_addr); |
| 199 | if (my_rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) == NULL) { | 231 | if (my_rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) == NULL) { |
| 200 | die(STATE_UNKNOWN, _("Invalid NAS-IP-Address\n")); | 232 | xasprintf(&sc_configuring.output, "invalid NAS IP address. Setting option failed"); |
| 233 | sc_configuring = mp_set_subcheck_state(sc_configuring, STATE_UNKNOWN); | ||
| 234 | mp_add_subcheck_to_check(&overall, sc_configuring); | ||
| 235 | mp_exit(overall); | ||
| 201 | } | 236 | } |
| 202 | 237 | ||
| 203 | my_rc_buildreq(&data, PW_ACCESS_REQUEST, config.server, config.port, (int)timeout_interval, config.retries); | 238 | my_rc_buildreq(&data, PW_ACCESS_REQUEST, config.server, config.port, (int)timeout_interval, |
| 239 | config.retries); | ||
| 204 | 240 | ||
| 205 | #ifdef RC_BUFFER_LEN | 241 | #ifdef RC_BUFFER_LEN |
| 206 | char msg[RC_BUFFER_LEN]; | 242 | char msg[RC_BUFFER_LEN]; |
| @@ -214,50 +250,78 @@ int main(int argc, char **argv) { | |||
| 214 | rc_avpair_free(data.receive_pairs); | 250 | rc_avpair_free(data.receive_pairs); |
| 215 | } | 251 | } |
| 216 | 252 | ||
| 253 | mp_subcheck sc_eval = mp_subcheck_init(); | ||
| 254 | |||
| 217 | if (result == TIMEOUT_RC) { | 255 | if (result == TIMEOUT_RC) { |
| 218 | printf("Timeout\n"); | 256 | xasprintf(&sc_eval.output, "timeout"); |
| 219 | exit(STATE_CRITICAL); | 257 | sc_eval = mp_set_subcheck_state(sc_eval, STATE_CRITICAL); |
| 258 | mp_add_subcheck_to_check(&overall, sc_eval); | ||
| 259 | mp_exit(overall); | ||
| 220 | } | 260 | } |
| 221 | 261 | ||
| 222 | if (result == ERROR_RC) { | 262 | if (result == ERROR_RC) { |
| 223 | printf(_("Auth Error\n")); | 263 | xasprintf(&sc_eval.output, "auth error"); |
| 224 | exit(STATE_CRITICAL); | 264 | sc_eval = mp_set_subcheck_state(sc_eval, STATE_CRITICAL); |
| 265 | mp_add_subcheck_to_check(&overall, sc_eval); | ||
| 266 | mp_exit(overall); | ||
| 225 | } | 267 | } |
| 226 | 268 | ||
| 227 | if (result == REJECT_RC) { | 269 | if (result == REJECT_RC) { |
| 228 | printf(_("Auth Failed\n")); | 270 | xasprintf(&sc_eval.output, "auth failed"); |
| 229 | exit(STATE_WARNING); | 271 | sc_eval = mp_set_subcheck_state(sc_eval, STATE_WARNING); |
| 272 | mp_add_subcheck_to_check(&overall, sc_eval); | ||
| 273 | mp_exit(overall); | ||
| 230 | } | 274 | } |
| 231 | 275 | ||
| 232 | if (result == BADRESP_RC) { | 276 | if (result == BADRESP_RC) { |
| 233 | printf(_("Bad Response\n")); | 277 | xasprintf(&sc_eval.output, "bad response"); |
| 234 | exit(STATE_WARNING); | 278 | sc_eval = mp_set_subcheck_state(sc_eval, STATE_WARNING); |
| 279 | mp_add_subcheck_to_check(&overall, sc_eval); | ||
| 280 | mp_exit(overall); | ||
| 235 | } | 281 | } |
| 236 | 282 | ||
| 237 | if (config.expect && !strstr(msg, config.expect)) { | 283 | if (config.expect && !strstr(msg, config.expect)) { |
| 238 | printf("%s\n", msg); | 284 | xasprintf(&sc_eval.output, "%s", msg); |
| 239 | exit(STATE_WARNING); | 285 | sc_eval = mp_set_subcheck_state(sc_eval, STATE_WARNING); |
| 286 | mp_add_subcheck_to_check(&overall, sc_eval); | ||
| 287 | mp_exit(overall); | ||
| 240 | } | 288 | } |
| 241 | 289 | ||
| 242 | if (result == OK_RC) { | 290 | if (result == OK_RC) { |
| 243 | printf(_("Auth OK\n")); | 291 | xasprintf(&sc_eval.output, "auth OK"); |
| 244 | exit(STATE_OK); | 292 | sc_eval = mp_set_subcheck_state(sc_eval, STATE_OK); |
| 293 | mp_add_subcheck_to_check(&overall, sc_eval); | ||
| 294 | mp_exit(overall); | ||
| 245 | } | 295 | } |
| 246 | 296 | ||
| 247 | (void)snprintf(msg, sizeof(msg), _("Unexpected result code %d"), result); | 297 | xasprintf(&sc_eval.output, "unexpected result code: %d", result); |
| 248 | printf("%s\n", msg); | 298 | sc_eval = mp_set_subcheck_state(sc_eval, STATE_UNKNOWN); |
| 249 | exit(STATE_UNKNOWN); | 299 | mp_add_subcheck_to_check(&overall, sc_eval); |
| 300 | |||
| 301 | mp_exit(overall); | ||
| 250 | } | 302 | } |
| 251 | 303 | ||
| 252 | /* process command-line arguments */ | 304 | /* process command-line arguments */ |
| 253 | check_radius_config_wrapper process_arguments(int argc, char **argv) { | 305 | check_radius_config_wrapper process_arguments(int argc, char **argv) { |
| 254 | static struct option longopts[] = {{"hostname", required_argument, 0, 'H'}, {"port", required_argument, 0, 'P'}, | 306 | enum { |
| 255 | {"username", required_argument, 0, 'u'}, {"password", required_argument, 0, 'p'}, | 307 | output_format_index |
| 256 | {"nas-id", required_argument, 0, 'n'}, {"nas-ip-address", required_argument, 0, 'N'}, | 308 | }; |
| 257 | {"filename", required_argument, 0, 'F'}, {"expect", required_argument, 0, 'e'}, | 309 | |
| 258 | {"retries", required_argument, 0, 'r'}, {"timeout", required_argument, 0, 't'}, | 310 | static struct option longopts[] = {{"hostname", required_argument, 0, 'H'}, |
| 259 | {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, | 311 | {"port", required_argument, 0, 'P'}, |
| 260 | {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; | 312 | {"username", required_argument, 0, 'u'}, |
| 313 | {"password", required_argument, 0, 'p'}, | ||
| 314 | {"nas-id", required_argument, 0, 'n'}, | ||
| 315 | {"nas-ip-address", required_argument, 0, 'N'}, | ||
| 316 | {"filename", required_argument, 0, 'F'}, | ||
| 317 | {"expect", required_argument, 0, 'e'}, | ||
| 318 | {"retries", required_argument, 0, 'r'}, | ||
| 319 | {"timeout", required_argument, 0, 't'}, | ||
| 320 | {"verbose", no_argument, 0, 'v'}, | ||
| 321 | {"version", no_argument, 0, 'V'}, | ||
| 322 | {"help", no_argument, 0, 'h'}, | ||
| 323 | {"output-format", required_argument, 0, output_format_index}, | ||
| 324 | {0, 0, 0, 0}}; | ||
| 261 | 325 | ||
| 262 | check_radius_config_wrapper result = { | 326 | check_radius_config_wrapper result = { |
| 263 | .errorcode = OK, | 327 | .errorcode = OK, |
| @@ -335,6 +399,18 @@ check_radius_config_wrapper process_arguments(int argc, char **argv) { | |||
| 335 | usage2(_("Timeout interval must be a positive integer"), optarg); | 399 | usage2(_("Timeout interval must be a positive integer"), optarg); |
| 336 | } | 400 | } |
| 337 | break; | 401 | break; |
| 402 | case output_format_index: { | ||
| 403 | parsed_output_format parser = mp_parse_output_format(optarg); | ||
| 404 | if (!parser.parsing_success) { | ||
| 405 | // TODO List all available formats here, maybe add anothoer usage function | ||
| 406 | printf("Invalid output format: %s\n", optarg); | ||
| 407 | exit(STATE_UNKNOWN); | ||
| 408 | } | ||
| 409 | |||
| 410 | result.config.output_format_is_set = true; | ||
| 411 | result.config.output_format = parser.output_format; | ||
| 412 | break; | ||
| 413 | } | ||
| 338 | } | 414 | } |
| 339 | } | 415 | } |
| 340 | 416 | ||
| @@ -388,6 +464,7 @@ void print_help(void) { | |||
| 388 | printf(" %s\n", _("Response string to expect from the server")); | 464 | printf(" %s\n", _("Response string to expect from the server")); |
| 389 | printf(" %s\n", "-r, --retries=INTEGER"); | 465 | printf(" %s\n", "-r, --retries=INTEGER"); |
| 390 | printf(" %s\n", _("Number of times to retry a failed connection")); | 466 | printf(" %s\n", _("Number of times to retry a failed connection")); |
| 467 | printf(UT_OUTPUT_FORMAT); | ||
| 391 | 468 | ||
| 392 | printf(UT_CONN_TIMEOUT, timeout_interval); | 469 | printf(UT_CONN_TIMEOUT, timeout_interval); |
| 393 | 470 | ||
| @@ -397,9 +474,11 @@ void print_help(void) { | |||
| 397 | printf("%s\n", _("name and password. A configuration file must be present. The format of")); | 474 | printf("%s\n", _("name and password. A configuration file must be present. The format of")); |
| 398 | printf("%s\n", _("the configuration file is described in the radiusclient library sources.")); | 475 | printf("%s\n", _("the configuration file is described in the radiusclient library sources.")); |
| 399 | printf("%s\n", _("The password option presents a substantial security issue because the")); | 476 | printf("%s\n", _("The password option presents a substantial security issue because the")); |
| 400 | printf("%s\n", _("password can possibly be determined by careful watching of the command line")); | 477 | printf("%s\n", |
| 478 | _("password can possibly be determined by careful watching of the command line")); | ||
| 401 | printf("%s\n", _("in a process listing. This risk is exacerbated because the plugin will")); | 479 | printf("%s\n", _("in a process listing. This risk is exacerbated because the plugin will")); |
| 402 | printf("%s\n", _("typically be executed at regular predictable intervals. Please be sure that")); | 480 | printf("%s\n", |
| 481 | _("typically be executed at regular predictable intervals. Please be sure that")); | ||
| 403 | printf("%s\n", _("the password used does not allow access to sensitive system resources.")); | 482 | printf("%s\n", _("the password used does not allow access to sensitive system resources.")); |
| 404 | 483 | ||
| 405 | printf(UT_SUPPORT); | 484 | printf(UT_SUPPORT); |
| @@ -414,7 +493,8 @@ void print_usage(void) { | |||
| 414 | } | 493 | } |
| 415 | 494 | ||
| 416 | int my_rc_read_config(char *config_file_name, rc_handle **rch) { | 495 | int my_rc_read_config(char *config_file_name, rc_handle **rch) { |
| 417 | #if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || defined(HAVE_LIBRADCLI) | 496 | #if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || \ |
| 497 | defined(HAVE_LIBRADCLI) | ||
| 418 | *rch = rc_read_config(config_file_name); | 498 | *rch = rc_read_config(config_file_name); |
| 419 | return (rch == NULL) ? 1 : 0; | 499 | return (rch == NULL) ? 1 : 0; |
| 420 | #else | 500 | #else |
