Code

Initial revision
[nagiosplug.git] / plugins / check_radius.c
1 /******************************************************************************
2  *
3  * Program: radius server check plugin for Nagios
4  * License: GPL
5  *
6  * License Information:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  * $Id$
23  *
24  *****************************************************************************/
26 #define PROGNAME "check_radius"
27 #define REVISION "$Revision$"
28 #define COPYRIGHT "1999-2001"
29 #define AUTHORS "Robert August Vincent II/Karl DeBisschop"
30 #define EMAIL "kdebisschop@users.sourceforge.net"
31 #define SUMMARY "Tests to see if a radius server is accepting connections.\n"
33 #define OPTIONS "\
34 -H host -F config_file -u username -p password\'\
35               [-P port] [-t timeout] [-r retries] [-e expect]"
37 #define LONGOPTIONS "\
38  -H, --hostname=HOST\n\
39     Host name argument for servers using host headers (use numeric\n\
40     address if possible to bypass DNS lookup).\n\
41  -P, --port=INTEGER\n\
42     Port number (default: %d)\n\
43  -u, --username=STRING\n\
44     The user to authenticate\n\
45  -p, --password=STRING\n\
46     Password for autentication (SECURITY RISK)\n\
47  -F, --filename=STRING\n\
48     Configuration file\n\
49  -e, --expect=STRING\n\
50     Response string to expect from the server\n\
51  -r, --retries=INTEGER\n\
52     Number of times to retry a failed connection\n\
53  -t, --timeout=INTEGER\n\
54     Seconds before connection times out (default: %d)\n\
55  -v\n\
56     Show details for command-line debugging (do not use with nagios server)\n\
57  -h, --help\n\
58     Print detailed help screen\n\
59  -V, --version\n\
60     Print version information\n"
62 #define DESCRIPTION "\
63 The password option presents a substantial security issue because the 
64 password can be determined by careful watching of the command line in
65 a process listing.  This risk is exacerbated because nagios will
66 run the plugin at regular prdictable intervals.  Please be sure that
67 the password used does not allow access to sensitive system resources,
68 otherwise compormise could occur.\n"
70 #include "config.h"
71 #include "common.h"
72 #include "utils.h"
73 #include <radiusclient.h>
75 int process_arguments (int, char **);
76 void print_usage (void);
77 void print_help (void);
79 char *server = NULL;
80 int port = PW_AUTH_UDP_PORT;
81 char *username = NULL;
82 char *password = NULL;
83 char *expect = NULL;
84 char *config_file = NULL;
85 int retries = 1;
86 int verbose = FALSE;
88 ENV *env = NULL;
90 /******************************************************************************
92 The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@
93 tags in the comments. With in the tags, the XML is assembled sequentially.
94 You can define entities in tags. You also have all the #defines available as
95 entities.
97 Please note that all tags must be lowercase to use the DocBook XML DTD.
99 @@-<article>
101 <sect1>
102 <title>Quick Reference</title>
103 <!-- The refentry forms a manpage -->
104 <refentry>
105 <refmeta>
106 <manvolnum>5<manvolnum>
107 </refmeta>
108 <refnamdiv>
109 <refname>&PROGNAME;</refname>
110 <refpurpose>&SUMMARY;</refpurpose>
111 </refnamdiv>
112 </refentry>
113 </sect1>
115 <sect1>
116 <title>FAQ</title>
117 </sect1>
119 <sect1>
120 <title>Theory, Installation, and Operation</title>
122 <sect2>
123 <title>General Description</title>
124 <para>
125 &DESCRIPTION;
126 </para>
127 </sect2>
129 <sect2>
130 <title>Future Enhancements</title>
131 <para>ToDo List</para>
132 <itemizedlist>
133 <listitem>Add option to get password from a secured file rather than the command line</listitem>
134 </itemizedlist>
135 </sect2>
138 <sect2>
139 <title>Functions</title>
140 -@@
141 ******************************************************************************/
143 int
144 main (int argc, char **argv)
146         UINT4 service;
147         char msg[BUFFER_LEN];
148         SEND_DATA data = { 0 };
149         int result;
150         UINT4 client_id;
152         if (process_arguments (argc, argv) == ERROR)
153                 usage ("Could not parse arguments\n");
155         if ((config_file && rc_read_config (config_file)) ||
156                         rc_read_dictionary (rc_conf_str ("dictionary")))
157                 terminate (STATE_UNKNOWN, "Config file error");
159         service = PW_AUTHENTICATE_ONLY;
161         if (!(rc_avpair_add (&data.send_pairs, PW_SERVICE_TYPE, &service, 0) &&
162                                 rc_avpair_add (&data.send_pairs, PW_USER_NAME, username, 0) &&
163                                 rc_avpair_add (&data.send_pairs, PW_USER_PASSWORD, password, 0)))
164                 terminate (STATE_UNKNOWN, "Out of Memory?");
166         /* 
167          * Fill in NAS-IP-Address 
168          */
170         if ((client_id = rc_own_ipaddress ()) == 0)
171                 return (ERROR_RC);
173         if (rc_avpair_add (&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) ==
174                         NULL) return (ERROR_RC);
176         rc_buildreq (&data, PW_ACCESS_REQUEST, server, port, timeout_interval,
177                                                          retries);
179         result = rc_send_server (&data, msg);
180         rc_avpair_free (data.send_pairs);
181         if (data.receive_pairs)
182                 rc_avpair_free (data.receive_pairs);
184         if (result == TIMEOUT_RC)
185                 terminate (STATE_CRITICAL, "Timeout");
186         if (result == ERROR_RC)
187                 terminate (STATE_CRITICAL, "Auth Error");
188         if (result == BADRESP_RC)
189                 terminate (STATE_WARNING, "Auth Failed");
190         if (expect && !strstr (msg, expect))
191                 terminate (STATE_WARNING, msg);
192         if (result == OK_RC)
193                 terminate (STATE_OK, "Auth OK");
194         return (0);
199 /* process command-line arguments */
200 int
201 process_arguments (int argc, char **argv)
203         int c;
205 #ifdef HAVE_GETOPT_H
206         int option_index = 0;
207         static struct option long_options[] = {
208                 {"hostname", required_argument, 0, 'H'},
209                 {"port", required_argument, 0, 'P'},
210                 {"username", required_argument, 0, 'u'},
211                 {"password", required_argument, 0, 'p'},
212                 {"filename", required_argument, 0, 'F'},
213                 {"expect", required_argument, 0, 'e'},
214                 {"retries", required_argument, 0, 'r'},
215                 {"timeout", required_argument, 0, 't'},
216                 {"verbose", no_argument, 0, 'v'},
217                 {"version", no_argument, 0, 'V'},
218                 {"help", no_argument, 0, 'h'},
219                 {0, 0, 0, 0}
220         };
221 #endif
223         if (argc < 2)
224                 return ERROR;
226         if (argc == 9) {
227                 config_file = argv[1];
228                 username = argv[2];
229                 password = argv[3];
230                 if (is_intpos (argv[4]))
231                         timeout_interval = atoi (argv[4]);
232                 else
233                         usage ("Timeout interval must be a positive integer");
234                 if (is_intpos (argv[5]))
235                         retries = atoi (argv[5]);
236                 else
237                         usage ("Number of retries must be a positive integer");
238                 server = argv[6];
239                 if (is_intpos (argv[7]))
240                         port = atoi (argv[7]);
241                 else
242                         usage ("Server port must be a positive integer");
243                 expect = argv[8];
244                 return OK;
245         }
247         while (1) {
248 #ifdef HAVE_GETOPT_H
249                 c =
250                         getopt_long (argc, argv, "+hVvH:P:F:u:p:t:r:e:", long_options,
251                                                                          &option_index);
252 #else
253                 c = getopt (argc, argv, "+hVvH:P:F:u:p:t:r:e:");
254 #endif
256                 if (c == -1 || c == EOF || c == 1)
257                         break;
259                 switch (c) {
260                 case '?':                                                                       /* print short usage statement if args not parsable */
261                         printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
262                         print_usage ();
263                         exit (STATE_UNKNOWN);
264                 case 'h':                                                                       /* help */
265                         print_help ();
266                         exit (OK);
267                 case 'V':                                                                       /* version */
268                         print_revision (my_basename (argv[0]), "$Revision$");
269                         exit (OK);
270                 case 'v':                                                                       /* verbose mode */
271                         verbose = TRUE;
272                         break;
273                 case 'H':                                                                       /* hostname */
274                         if (is_host (optarg) == FALSE) {
275                                 printf ("Invalid host name/address\n\n");
276                                 print_usage ();
277                                 exit (STATE_UNKNOWN);
278                         }
279                         server = optarg;
280                         break;
281                 case 'P':                                                                       /* port */
282                         if (is_intnonneg (optarg))
283                                 port = atoi (optarg);
284                         else
285                                 usage ("Server port must be a positive integer");
286                         break;
287                 case 'u':                                                                       /* username */
288                         username = optarg;
289                         break;
290                 case 'p':                                                                       /* password */
291                         password = optarg;
292                         break;
293                 case 'F':                                                                       /* configuration file */
294                         config_file = optarg;
295                         break;
296                 case 'e':                                                                       /* expect */
297                         expect = optarg;
298                         break;
299                 case 'r':                                                                       /* retries */
300                         if (is_intpos (optarg))
301                                 retries = atoi (optarg);
302                         else
303                                 usage ("Number of retries must be a positive integer");
304                         break;
305                 case 't':                                                                       /* timeout */
306                         if (is_intpos (optarg))
307                                 timeout_interval = atoi (optarg);
308                         else
309                                 usage ("Timeout interval must be a positive integer");
310                         break;
311                 }
312         }
313         return OK;
315 \f
318 void
319 print_help (void)
321         print_revision (PROGNAME, REVISION);
322         printf
323                 ("Copyright (c) %s %s <%s>\n\n%s\n",
324                  COPYRIGHT, AUTHORS, EMAIL, SUMMARY);
325         print_usage ();
326         printf
327                 ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n", 
328                  port, timeout_interval);
329         support ();
333 void
334 print_usage (void)
336         printf ("Usage:\n" " %s %s\n"
337 #ifdef HAVE_GETOPT_H
338                                         " %s (-h | --help) for detailed help\n"
339                                         " %s (-V | --version) for version information\n",
340 #else
341                                         " %s -h for detailed help\n"
342                                         " %s -V for version information\n",
343 #endif
344                                         PROGNAME, OPTIONS, PROGNAME, PROGNAME);