Back to index

nagios-plugins  1.4.16
check_radius.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002 * 
00003 * Nagios check_radius plugin
00004 * 
00005 * License: GPL
00006 * Copyright (c) 1999-2008 Nagios Plugins Development Team
00007 * 
00008 * Description:
00009 * 
00010 * This file contains the check_radius plugin
00011 * 
00012 * Tests to see if a radius server is accepting connections.
00013 * 
00014 * 
00015 * This program is free software: you can redistribute it and/or modify
00016 * it under the terms of the GNU General Public License as published by
00017 * the Free Software Foundation, either version 3 of the License, or
00018 * (at your option) any later version.
00019 * 
00020 * This program is distributed in the hope that it will be useful,
00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 * GNU General Public License for more details.
00024 * 
00025 * You should have received a copy of the GNU General Public License
00026 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00027 * 
00028 * 
00029 *****************************************************************************/
00030 
00031 const char *progname = "check_radius";
00032 const char *copyright = "2000-2008";
00033 const char *email = "nagiosplug-devel@lists.sourceforge.net";
00034 
00035 #include "common.h"
00036 #include "utils.h"
00037 #include "netutils.h"
00038 
00039 #ifdef HAVE_LIBRADIUSCLIENT_NG
00040 #include <radiusclient-ng.h>
00041 rc_handle *rch = NULL;
00042 #else
00043 #include <radiusclient.h>
00044 #endif
00045 
00046 int process_arguments (int, char **);
00047 void print_help (void);
00048 void print_usage (void);
00049 
00050 /* libradiusclient(-ng) wrapper functions */
00051 #ifdef HAVE_LIBRADIUSCLIENT_NG
00052 #define my_rc_conf_str(a) rc_conf_str(rch,a)
00053 #define my_rc_send_server(a,b) rc_send_server(rch,a,b)
00054 #define my_rc_buildreq(a,b,c,d,e,f) rc_buildreq(rch,a,b,c,d,e,f)
00055 #define my_rc_own_ipaddress() rc_own_ipaddress(rch)
00056 #define my_rc_avpair_add(a,b,c,d) rc_avpair_add(rch,a,b,c,-1,d)
00057 #define my_rc_read_dictionary(a) rc_read_dictionary(rch, a)
00058 #else
00059 #define my_rc_conf_str(a) rc_conf_str(a)
00060 #define my_rc_send_server(a,b) rc_send_server(a, b)
00061 #define my_rc_buildreq(a,b,c,d,e,f) rc_buildreq(a,b,c,d,e,f)
00062 #define my_rc_own_ipaddress() rc_own_ipaddress()
00063 #define my_rc_avpair_add(a,b,c,d) rc_avpair_add(a, b, c, d)
00064 #define my_rc_read_dictionary(a) rc_read_dictionary(a)
00065 #endif
00066 
00067 /* REJECT_RC is only defined in some version of radiusclient. It has
00068  * been reported from radiusclient-ng 0.5.6 on FreeBSD 7.2-RELEASE */
00069 #ifndef REJECT_RC
00070 #define REJECT_RC BADRESP_RC
00071 #endif
00072 
00073 int my_rc_read_config(char *);
00074 
00075 char *server = NULL;
00076 char *username = NULL;
00077 char *password = NULL;
00078 char *nasid = NULL;
00079 char *nasipaddress = NULL;
00080 char *expect = NULL;
00081 char *config_file = NULL;
00082 unsigned short port = PW_AUTH_UDP_PORT;
00083 int retries = 1;
00084 int verbose = FALSE;
00085 ENV *env = NULL;
00086 
00087 /******************************************************************************
00088 
00089 The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@
00090 tags in the comments. With in the tags, the XML is assembled sequentially.
00091 You can define entities in tags. You also have all the #defines available as
00092 entities.
00093 
00094 Please note that all tags must be lowercase to use the DocBook XML DTD.
00095 
00096 @@-<article>
00097 
00098 <sect1>
00099 <title>Quick Reference</title>
00100 <!-- The refentry forms a manpage -->
00101 <refentry>
00102 <refmeta>
00103 <manvolnum>5<manvolnum>
00104 </refmeta>
00105 <refnamdiv>
00106 <refname>&progname;</refname>
00107 <refpurpose>&SUMMARY;</refpurpose>
00108 </refnamdiv>
00109 </refentry>
00110 </sect1>
00111 
00112 <sect1>
00113 <title>FAQ</title>
00114 </sect1>
00115 
00116 <sect1>
00117 <title>Theory, Installation, and Operation</title>
00118 
00119 <sect2>
00120 <title>General Description</title>
00121 <para>
00122 &DESCRIPTION;
00123 </para>
00124 </sect2>
00125 
00126 <sect2>
00127 <title>Future Enhancements</title>
00128 <para>Todo List</para>
00129 <itemizedlist>
00130 <listitem>Add option to get password from a secured file rather than the command line</listitem>
00131 </itemizedlist>
00132 </sect2>
00133 
00134 
00135 <sect2>
00136 <title>Functions</title>
00137 -@@
00138 ******************************************************************************/
00139 
00140 
00141 
00142 int
00143 main (int argc, char **argv)
00144 {
00145        UINT4 service;
00146        char msg[BUFFER_LEN];
00147        SEND_DATA data;
00148        int result = STATE_UNKNOWN;
00149        UINT4 client_id;
00150        char *str;
00151 
00152        setlocale (LC_ALL, "");
00153        bindtextdomain (PACKAGE, LOCALEDIR);
00154        textdomain (PACKAGE);
00155 
00156        /* Parse extra opts if any */
00157        argv=np_extra_opts (&argc, argv, progname);
00158 
00159        if (process_arguments (argc, argv) == ERROR)
00160               usage4 (_("Could not parse arguments"));
00161 
00162        str = strdup ("dictionary");
00163        if ((config_file && my_rc_read_config (config_file)) ||
00164                      my_rc_read_dictionary (my_rc_conf_str (str)))
00165               die (STATE_UNKNOWN, _("Config file error"));
00166 
00167        service = PW_AUTHENTICATE_ONLY;
00168 
00169        memset (&data, 0, sizeof(data));
00170        if (!(my_rc_avpair_add (&data.send_pairs, PW_SERVICE_TYPE, &service, 0) &&
00171                             my_rc_avpair_add (&data.send_pairs, PW_USER_NAME, username, 0) &&
00172                             my_rc_avpair_add (&data.send_pairs, PW_USER_PASSWORD, password, 0)
00173                             ))
00174               die (STATE_UNKNOWN, _("Out of Memory?"));
00175 
00176        if (nasid != NULL) {
00177               if (!(my_rc_avpair_add (&data.send_pairs, PW_NAS_IDENTIFIER, nasid, 0)))
00178                      die (STATE_UNKNOWN, _("Invalid NAS-Identifier"));
00179        }
00180 
00181        if (nasipaddress != NULL) {
00182               if (rc_good_ipaddr (nasipaddress))
00183                      die (STATE_UNKNOWN, _("Invalid NAS-IP-Address"));
00184               if ((client_id = rc_get_ipaddr(nasipaddress)) == 0)
00185                      die (STATE_UNKNOWN, _("Invalid NAS-IP-Address"));
00186        } else {
00187               if ((client_id = my_rc_own_ipaddress ()) == 0)
00188                      die (STATE_UNKNOWN, _("Can't find local IP for NAS-IP-Address"));
00189        }
00190        if (my_rc_avpair_add (&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) == NULL)
00191               die (STATE_UNKNOWN, _("Invalid NAS-IP-Address"));
00192 
00193        my_rc_buildreq (&data, PW_ACCESS_REQUEST, server, port, (int)timeout_interval,
00194                     retries);
00195 
00196        result = my_rc_send_server (&data, msg);
00197        rc_avpair_free (data.send_pairs);
00198        if (data.receive_pairs)
00199               rc_avpair_free (data.receive_pairs);
00200 
00201        if (result == TIMEOUT_RC)
00202               die (STATE_CRITICAL, _("Timeout"));
00203        if (result == ERROR_RC)
00204               die (STATE_CRITICAL, _("Auth Error"));
00205        if (result == REJECT_RC)
00206               die (STATE_WARNING, _("Auth Failed"));
00207        if (result == BADRESP_RC)
00208               die (STATE_WARNING, _("Bad Response"));
00209        if (expect && !strstr (msg, expect))
00210               die (STATE_WARNING, "%s", msg);
00211        if (result == OK_RC)
00212               die (STATE_OK, _("Auth OK"));
00213        (void)snprintf(msg, sizeof(msg), _("Unexpected result code %d"), result);
00214        die (STATE_UNKNOWN, "%s", msg);
00215 }
00216 
00217 
00218 
00219 /* process command-line arguments */
00220 int
00221 process_arguments (int argc, char **argv)
00222 {
00223        int c;
00224 
00225        int option = 0;
00226        static struct option longopts[] = {
00227               {"hostname", required_argument, 0, 'H'},
00228               {"port", required_argument, 0, 'P'},
00229               {"username", required_argument, 0, 'u'},
00230               {"password", required_argument, 0, 'p'},
00231               {"nas-id", required_argument, 0, 'n'},
00232               {"nas-ip-address", required_argument, 0, 'N'},
00233               {"filename", required_argument, 0, 'F'},
00234               {"expect", required_argument, 0, 'e'},
00235               {"retries", required_argument, 0, 'r'},
00236               {"timeout", required_argument, 0, 't'},
00237               {"verbose", no_argument, 0, 'v'},
00238               {"version", no_argument, 0, 'V'},
00239               {"help", no_argument, 0, 'h'},
00240               {0, 0, 0, 0}
00241        };
00242 
00243        while (1) {
00244               c = getopt_long (argc, argv, "+hVvH:P:F:u:p:n:N:t:r:e:", longopts,
00245                                                                 &option);
00246 
00247               if (c == -1 || c == EOF || c == 1)
00248                      break;
00249 
00250               switch (c) {
00251               case '?':                                                             /* print short usage statement if args not parsable */
00252                      usage5 ();
00253               case 'h':                                                             /* help */
00254                      print_help ();
00255                      exit (OK);
00256               case 'V':                                                             /* version */
00257                      print_revision (progname, NP_VERSION);
00258                      exit (OK);
00259               case 'v':                                                             /* verbose mode */
00260                      verbose = TRUE;
00261                      break;
00262               case 'H':                                                             /* hostname */
00263                      if (is_host (optarg) == FALSE) {
00264                             usage2 (_("Invalid hostname/address"), optarg);
00265                      }
00266                      server = optarg;
00267                      break;
00268               case 'P':                                                             /* port */
00269                      if (is_intnonneg (optarg))
00270                             port = atoi (optarg);
00271                      else
00272                             usage4 (_("Port must be a positive integer"));
00273                      break;
00274               case 'u':                                                             /* username */
00275                      username = optarg;
00276                      break;
00277               case 'p':                                                             /* password */
00278                      password = strdup(optarg);
00279 
00280                      /* Delete the password from process list */
00281                      while (*optarg != '\0') {
00282                             *optarg = 'X';
00283                             optarg++;
00284                      }
00285                      break;
00286               case 'n':                                                             /* nas id */
00287                      nasid = optarg;
00288                      break;
00289               case 'N':                                                             /* nas ip address */
00290                      nasipaddress = optarg;
00291                      break;
00292               case 'F':                                                             /* configuration file */
00293                      config_file = optarg;
00294                      break;
00295               case 'e':                                                             /* expect */
00296                      expect = optarg;
00297                      break;
00298               case 'r':                                                             /* retries */
00299                      if (is_intpos (optarg))
00300                             retries = atoi (optarg);
00301                      else
00302                             usage4 (_("Number of retries must be a positive integer"));
00303                      break;
00304               case 't':                                                             /* timeout */
00305                      if (is_intpos (optarg))
00306                             timeout_interval = atoi (optarg);
00307                      else
00308                             usage2 (_("Timeout interval must be a positive integer"), optarg);
00309                      break;
00310               }
00311        }
00312 
00313        if (server == NULL)
00314               usage4 (_("Hostname was not supplied"));
00315        if (username == NULL)
00316               usage4 (_("User not specified"));
00317        if (password == NULL)
00318               usage4 (_("Password not specified"));
00319        if (config_file == NULL)
00320               usage4 (_("Configuration file not specified"));
00321 
00322        return OK;
00323 }
00324 
00325 
00326 
00327 void
00328 print_help (void)
00329 {
00330        char *myport;
00331        asprintf (&myport, "%d", PW_AUTH_UDP_PORT);
00332 
00333        print_revision (progname, NP_VERSION);
00334 
00335        printf ("Copyright (c) 1999 Robert August Vincent II\n");
00336        printf (COPYRIGHT, copyright, email);
00337 
00338        printf("%s\n", _("Tests to see if a RADIUS server is accepting connections."));
00339 
00340   printf ("\n\n");
00341 
00342        print_usage ();
00343 
00344        printf (UT_HELP_VRSN);
00345        printf (UT_EXTRA_OPTS);
00346 
00347        printf (UT_HOST_PORT, 'P', myport);
00348 
00349        printf (" %s\n", "-u, --username=STRING");
00350   printf ("    %s\n", _("The user to authenticate"));
00351   printf (" %s\n", "-p, --password=STRING");
00352   printf ("    %s\n", _("Password for autentication (SECURITY RISK)"));
00353   printf (" %s\n", "-n, --nas-id=STRING");
00354   printf ("    %s\n", _("NAS identifier"));
00355   printf (" %s\n", "-N, --nas-ip-address=STRING");
00356   printf ("    %s\n", _("NAS IP Address"));
00357   printf (" %s\n", "-F, --filename=STRING");
00358   printf ("    %s\n", _("Configuration file"));
00359   printf (" %s\n", "-e, --expect=STRING");
00360   printf ("    %s\n", _("Response string to expect from the server"));
00361   printf (" %s\n", "-r, --retries=INTEGER");
00362   printf ("    %s\n", _("Number of times to retry a failed connection"));
00363 
00364        printf (UT_TIMEOUT, timeout_interval);
00365 
00366   printf ("\n");
00367   printf ("%s\n", _("This plugin tests a RADIUS server to see if it is accepting connections."));
00368   printf ("%s\n", _("The server to test must be specified in the invocation, as well as a user"));
00369   printf ("%s\n", _("name and password. A configuration file may also be present. The format of"));
00370   printf ("%s\n", _("the configuration file is described in the radiusclient library sources."));
00371        printf ("%s\n", _("The password option presents a substantial security issue because the"));
00372   printf ("%s\n", _("password can possibly be determined by careful watching of the command line"));
00373   printf ("%s\n", _("in a process listing. This risk is exacerbated because nagios will"));
00374   printf ("%s\n", _("run the plugin at regular predictable intervals. Please be sure that"));
00375   printf ("%s\n", _("the password used does not allow access to sensitive system resources."));
00376 
00377        printf (UT_SUPPORT);
00378 }
00379 
00380 
00381 
00382 void
00383 print_usage (void)
00384 {
00385   printf ("%s\n", _("Usage:"));
00386        printf ("%s -H host -F config_file -u username -p password\n\
00387                      [-P port] [-t timeout] [-r retries] [-e expect]\n\
00388                      [-n nas-id] [-N nas-ip-addr]\n", progname);
00389 }
00390 
00391 
00392 
00393 int my_rc_read_config(char * a)
00394 {
00395 #ifdef HAVE_LIBRADIUSCLIENT_NG
00396        rch = rc_read_config(a);
00397        return (rch == NULL) ? 1 : 0;
00398 #else
00399        return rc_read_config(a);
00400 #endif
00401 }