Code

remove call_getopt and ssprintf
[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, --verbose\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 This plugin tests a radius server to see if it is accepting connections.\n\
64 \n\
65 The server to test must be specified in the invocation, as well as a user\n\
66 name and password. A configuration file may also be present. The format of\n\
67 the configuration file is described in the radiusclient library sources.\n\
68 \n\
69 The password option presents a substantial security issue because the\n\
70 password can be determined by careful watching of the command line in\n\
71 a process listing.  This risk is exacerbated because nagios will\n\
72 run the plugin at regular prdictable intervals.  Please be sure that\n\
73 the password used does not allow access to sensitive system resources,\n\
74 otherwise compormise could occur.\n"
76 #include "config.h"
77 #include "common.h"
78 #include "utils.h"
79 #include <radiusclient.h>
81 int process_arguments (int, char **);
82 void print_usage (void);
83 void print_help (void);
85 char *server = NULL;
86 int port = PW_AUTH_UDP_PORT;
87 char *username = NULL;
88 char *password = NULL;
89 char *expect = NULL;
90 char *config_file = NULL;
91 int retries = 1;
92 int verbose = FALSE;
94 ENV *env = NULL;
96 /******************************************************************************
98 The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@
99 tags in the comments. With in the tags, the XML is assembled sequentially.
100 You can define entities in tags. You also have all the #defines available as
101 entities.
103 Please note that all tags must be lowercase to use the DocBook XML DTD.
105 @@-<article>
107 <sect1>
108 <title>Quick Reference</title>
109 <!-- The refentry forms a manpage -->
110 <refentry>
111 <refmeta>
112 <manvolnum>5<manvolnum>
113 </refmeta>
114 <refnamdiv>
115 <refname>&PROGNAME;</refname>
116 <refpurpose>&SUMMARY;</refpurpose>
117 </refnamdiv>
118 </refentry>
119 </sect1>
121 <sect1>
122 <title>FAQ</title>
123 </sect1>
125 <sect1>
126 <title>Theory, Installation, and Operation</title>
128 <sect2>
129 <title>General Description</title>
130 <para>
131 &DESCRIPTION;
132 </para>
133 </sect2>
135 <sect2>
136 <title>Future Enhancements</title>
137 <para>Todo List</para>
138 <itemizedlist>
139 <listitem>Add option to get password from a secured file rather than the command line</listitem>
140 </itemizedlist>
141 </sect2>
144 <sect2>
145 <title>Functions</title>
146 -@@
147 ******************************************************************************/
149 int
150 main (int argc, char **argv)
152         UINT4 service;
153         char msg[BUFFER_LEN];
154         SEND_DATA data = { 0 };
155         int result;
156         UINT4 client_id;
158         if (process_arguments (argc, argv) == ERROR)
159                 usage ("Could not parse arguments\n");
161         if ((config_file && rc_read_config (config_file)) ||
162                         rc_read_dictionary (rc_conf_str ("dictionary")))
163                 terminate (STATE_UNKNOWN, "Config file error");
165         service = PW_AUTHENTICATE_ONLY;
167         if (!(rc_avpair_add (&data.send_pairs, PW_SERVICE_TYPE, &service, 0) &&
168                                 rc_avpair_add (&data.send_pairs, PW_USER_NAME, username, 0) &&
169                                 rc_avpair_add (&data.send_pairs, PW_USER_PASSWORD, password, 0)))
170                 terminate (STATE_UNKNOWN, "Out of Memory?");
172         /* 
173          * Fill in NAS-IP-Address 
174          */
176         if ((client_id = rc_own_ipaddress ()) == 0)
177                 return (ERROR_RC);
179         if (rc_avpair_add (&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) ==
180                         NULL) return (ERROR_RC);
182         rc_buildreq (&data, PW_ACCESS_REQUEST, server, port, timeout_interval,
183                                                          retries);
185         result = rc_send_server (&data, msg);
186         rc_avpair_free (data.send_pairs);
187         if (data.receive_pairs)
188                 rc_avpair_free (data.receive_pairs);
190         if (result == TIMEOUT_RC)
191                 terminate (STATE_CRITICAL, "Timeout");
192         if (result == ERROR_RC)
193                 terminate (STATE_CRITICAL, "Auth Error");
194         if (result == BADRESP_RC)
195                 terminate (STATE_WARNING, "Auth Failed");
196         if (expect && !strstr (msg, expect))
197                 terminate (STATE_WARNING, msg);
198         if (result == OK_RC)
199                 terminate (STATE_OK, "Auth OK");
200         return (0);
205 /* process command-line arguments */
206 int
207 process_arguments (int argc, char **argv)
209         int c;
211 #ifdef HAVE_GETOPT_H
212         int option_index = 0;
213         static struct option long_options[] = {
214                 {"hostname", required_argument, 0, 'H'},
215                 {"port", required_argument, 0, 'P'},
216                 {"username", required_argument, 0, 'u'},
217                 {"password", required_argument, 0, 'p'},
218                 {"filename", required_argument, 0, 'F'},
219                 {"expect", required_argument, 0, 'e'},
220                 {"retries", required_argument, 0, 'r'},
221                 {"timeout", required_argument, 0, 't'},
222                 {"verbose", no_argument, 0, 'v'},
223                 {"version", no_argument, 0, 'V'},
224                 {"help", no_argument, 0, 'h'},
225                 {0, 0, 0, 0}
226         };
227 #endif
229         if (argc < 2)
230                 return ERROR;
232         if (argc == 9) {
233                 config_file = argv[1];
234                 username = argv[2];
235                 password = argv[3];
236                 if (is_intpos (argv[4]))
237                         timeout_interval = atoi (argv[4]);
238                 else
239                         usage ("Timeout interval must be a positive integer");
240                 if (is_intpos (argv[5]))
241                         retries = atoi (argv[5]);
242                 else
243                         usage ("Number of retries must be a positive integer");
244                 server = argv[6];
245                 if (is_intpos (argv[7]))
246                         port = atoi (argv[7]);
247                 else
248                         usage ("Server port must be a positive integer");
249                 expect = argv[8];
250                 return OK;
251         }
253         while (1) {
254 #ifdef HAVE_GETOPT_H
255                 c =
256                         getopt_long (argc, argv, "+hVvH:P:F:u:p:t:r:e:", long_options,
257                                                                          &option_index);
258 #else
259                 c = getopt (argc, argv, "+hVvH:P:F:u:p:t:r:e:");
260 #endif
262                 if (c == -1 || c == EOF || c == 1)
263                         break;
265                 switch (c) {
266                 case '?':                                                                       /* print short usage statement if args not parsable */
267                         printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
268                         print_usage ();
269                         exit (STATE_UNKNOWN);
270                 case 'h':                                                                       /* help */
271                         print_help ();
272                         exit (OK);
273                 case 'V':                                                                       /* version */
274                         print_revision (my_basename (argv[0]), "$Revision$");
275                         exit (OK);
276                 case 'v':                                                                       /* verbose mode */
277                         verbose = TRUE;
278                         break;
279                 case 'H':                                                                       /* hostname */
280                         if (is_host (optarg) == FALSE) {
281                                 printf ("Invalid host name/address\n\n");
282                                 print_usage ();
283                                 exit (STATE_UNKNOWN);
284                         }
285                         server = optarg;
286                         break;
287                 case 'P':                                                                       /* port */
288                         if (is_intnonneg (optarg))
289                                 port = atoi (optarg);
290                         else
291                                 usage ("Server port must be a positive integer");
292                         break;
293                 case 'u':                                                                       /* username */
294                         username = optarg;
295                         break;
296                 case 'p':                                                                       /* password */
297                         password = optarg;
298                         break;
299                 case 'F':                                                                       /* configuration file */
300                         config_file = optarg;
301                         break;
302                 case 'e':                                                                       /* expect */
303                         expect = optarg;
304                         break;
305                 case 'r':                                                                       /* retries */
306                         if (is_intpos (optarg))
307                                 retries = atoi (optarg);
308                         else
309                                 usage ("Number of retries must be a positive integer");
310                         break;
311                 case 't':                                                                       /* timeout */
312                         if (is_intpos (optarg))
313                                 timeout_interval = atoi (optarg);
314                         else
315                                 usage ("Timeout interval must be a positive integer");
316                         break;
317                 }
318         }
319         return OK;
321 \f
324 void
325 print_help (void)
327         print_revision (PROGNAME, REVISION);
328         printf
329                 ("Copyright (c) %s %s <%s>\n\n%s\n",
330                  COPYRIGHT, AUTHORS, EMAIL, SUMMARY);
331         print_usage ();
332         printf
333                 ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n", 
334                  port, timeout_interval);
335         support ();
339 void
340 print_usage (void)
342         printf ("Usage:\n" " %s %s\n"
343 #ifdef HAVE_GETOPT_H
344                                         " %s (-h | --help) for detailed help\n"
345                                         " %s (-V | --version) for version information\n",
346 #else
347                                         " %s -h for detailed help\n"
348                                         " %s -V for version information\n",
349 #endif
350                                         PROGNAME, OPTIONS, PROGNAME, PROGNAME);