1 /******************************************************************************
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 ******************************************************************************/
19 const char *progname = "check_radius";
20 const char *revision = "$Revision$";
21 const char *copyright = "2000-2003";
22 const char *email = "nagiosplug-devel@lists.sourceforge.net";
24 #include "config.h"
25 #include "common.h"
26 #include "utils.h"
27 #include <radiusclient.h>
29 void
30 print_usage (void)
31 {
32 printf ("\
33 Usage: %s -H host -F config_file -u username -p password [-P port]\n\
34 [-t timeout] [-r retries] [-e expect]\n", progname);
35 printf (_(UT_HLP_VRS), progname, progname);
36 }
38 void
39 print_help (void)
40 {
41 char *myport;
42 asprintf (&myport, "%d", PW_AUTH_UDP_PORT);
44 print_revision (progname, revision);
46 printf (_("Copyright (c) 1999 Robert August Vincent II\n"));
47 printf (_(COPYRIGHT), copyright, email);
49 printf(_("Tests to see if a radius server is accepting connections.\n\n"));
51 print_usage ();
53 printf (_(UT_HELP_VRSN));
55 printf (_(UT_HOST_PORT), 'P', myport);
57 printf (_("\
58 -u, --username=STRING\n\
59 The user to authenticate\n\
60 -p, --password=STRING\n\
61 Password for autentication (SECURITY RISK)\n\
62 -F, --filename=STRING\n\
63 Configuration file\n\
64 -e, --expect=STRING\n\
65 Response string to expect from the server\n\
66 -r, --retries=INTEGER\n\
67 Number of times to retry a failed connection\n"));
69 printf (_(UT_TIMEOUT), timeout_interval);
71 printf (_("\n\
72 This plugin tests a radius server to see if it is accepting connections.\n\
73 \n\
74 The server to test must be specified in the invocation, as well as a user\n\
75 name and password. A configuration file may also be present. The format of\n\
76 the configuration file is described in the radiusclient library sources.\n\n"));
78 printf (_("\
79 The password option presents a substantial security issue because the\n\
80 password can be determined by careful watching of the command line in\n\
81 a process listing. This risk is exacerbated because nagios will\n\
82 run the plugin at regular prdictable intervals. Please be sure that\n\
83 the password used does not allow access to sensitive system resources,\n\
84 otherwise compormise could occur.\n"));
86 printf (_(UT_SUPPORT));
87 }
88 \f
89 int process_arguments (int, char **);
91 char *server = NULL;
92 char *username = NULL;
93 char *password = NULL;
94 char *expect = NULL;
95 char *config_file = NULL;
96 int port = PW_AUTH_UDP_PORT;
97 int retries = 1;
98 int verbose = FALSE;
99 ENV *env = NULL;
101 /******************************************************************************
103 The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@
104 tags in the comments. With in the tags, the XML is assembled sequentially.
105 You can define entities in tags. You also have all the #defines available as
106 entities.
108 Please note that all tags must be lowercase to use the DocBook XML DTD.
110 @@-<article>
112 <sect1>
113 <title>Quick Reference</title>
114 <!-- The refentry forms a manpage -->
115 <refentry>
116 <refmeta>
117 <manvolnum>5<manvolnum>
118 </refmeta>
119 <refnamdiv>
120 <refname>&progname;</refname>
121 <refpurpose>&SUMMARY;</refpurpose>
122 </refnamdiv>
123 </refentry>
124 </sect1>
126 <sect1>
127 <title>FAQ</title>
128 </sect1>
130 <sect1>
131 <title>Theory, Installation, and Operation</title>
133 <sect2>
134 <title>General Description</title>
135 <para>
136 &DESCRIPTION;
137 </para>
138 </sect2>
140 <sect2>
141 <title>Future Enhancements</title>
142 <para>Todo List</para>
143 <itemizedlist>
144 <listitem>Add option to get password from a secured file rather than the command line</listitem>
145 </itemizedlist>
146 </sect2>
149 <sect2>
150 <title>Functions</title>
151 -@@
152 ******************************************************************************/
154 int
155 main (int argc, char **argv)
156 {
157 UINT4 service;
158 char msg[BUFFER_LEN];
159 SEND_DATA data;
160 int result;
161 UINT4 client_id;
163 if (process_arguments (argc, argv) == ERROR)
164 usage (_("Could not parse arguments\n"));
166 if ((config_file && rc_read_config (config_file)) ||
167 rc_read_dictionary (rc_conf_str ("dictionary")))
168 die (STATE_UNKNOWN, _("Config file error"));
170 service = PW_AUTHENTICATE_ONLY;
172 if (!(rc_avpair_add (&data.send_pairs, PW_SERVICE_TYPE, &service, 0) &&
173 rc_avpair_add (&data.send_pairs, PW_USER_NAME, username, 0) &&
174 rc_avpair_add (&data.send_pairs, PW_USER_PASSWORD, password, 0)))
175 die (STATE_UNKNOWN, _("Out of Memory?"));
177 /*
178 * Fill in NAS-IP-Address
179 */
181 if ((client_id = rc_own_ipaddress ()) == 0)
182 return (ERROR_RC);
184 if (rc_avpair_add (&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) ==
185 NULL) return (ERROR_RC);
187 rc_buildreq (&data, PW_ACCESS_REQUEST, server, port, timeout_interval,
188 retries);
190 result = rc_send_server (&data, msg);
191 rc_avpair_free (data.send_pairs);
192 if (data.receive_pairs)
193 rc_avpair_free (data.receive_pairs);
195 if (result == TIMEOUT_RC)
196 die (STATE_CRITICAL, _("Timeout"));
197 if (result == ERROR_RC)
198 die (STATE_CRITICAL, _("Auth Error"));
199 if (result == BADRESP_RC)
200 die (STATE_WARNING, _("Auth Failed"));
201 if (expect && !strstr (msg, expect))
202 die (STATE_WARNING, msg);
203 if (result == OK_RC)
204 die (STATE_OK, _("Auth OK"));
205 return (0);
206 }
210 /* process command-line arguments */
211 int
212 process_arguments (int argc, char **argv)
213 {
214 int c;
216 int option_index = 0;
217 static struct option long_options[] = {
218 {"hostname", required_argument, 0, 'H'},
219 {"port", required_argument, 0, 'P'},
220 {"username", required_argument, 0, 'u'},
221 {"password", required_argument, 0, 'p'},
222 {"filename", required_argument, 0, 'F'},
223 {"expect", required_argument, 0, 'e'},
224 {"retries", required_argument, 0, 'r'},
225 {"timeout", required_argument, 0, 't'},
226 {"verbose", no_argument, 0, 'v'},
227 {"version", no_argument, 0, 'V'},
228 {"help", no_argument, 0, 'h'},
229 {0, 0, 0, 0}
230 };
232 if (argc < 2)
233 return ERROR;
235 if (argc == 9) {
236 config_file = argv[1];
237 username = argv[2];
238 password = argv[3];
239 if (is_intpos (argv[4]))
240 timeout_interval = atoi (argv[4]);
241 else
242 usage (_("Timeout interval must be a positive integer"));
243 if (is_intpos (argv[5]))
244 retries = atoi (argv[5]);
245 else
246 usage (_("Number of retries must be a positive integer"));
247 server = argv[6];
248 if (is_intpos (argv[7]))
249 port = atoi (argv[7]);
250 else
251 usage (_("Server port must be a positive integer"));
252 expect = argv[8];
253 return OK;
254 }
256 while (1) {
257 c = getopt_long (argc, argv, "+hVvH:P:F:u:p:t:r:e:", long_options,
258 &option_index);
260 if (c == -1 || c == EOF || c == 1)
261 break;
263 switch (c) {
264 case '?': /* print short usage statement if args not parsable */
265 printf (_("%s: Unknown argument: %s\n\n"), progname, optarg);
266 print_usage ();
267 exit (STATE_UNKNOWN);
268 case 'h': /* help */
269 print_help ();
270 exit (OK);
271 case 'V': /* version */
272 print_revision (progname, revision);
273 exit (OK);
274 case 'v': /* verbose mode */
275 verbose = TRUE;
276 break;
277 case 'H': /* hostname */
278 if (is_host (optarg) == FALSE) {
279 printf (_("Invalid host name/address\n\n"));
280 print_usage ();
281 exit (STATE_UNKNOWN);
282 }
283 server = optarg;
284 break;
285 case 'P': /* port */
286 if (is_intnonneg (optarg))
287 port = atoi (optarg);
288 else
289 usage (_("Server port must be a positive integer"));
290 break;
291 case 'u': /* username */
292 username = optarg;
293 break;
294 case 'p': /* password */
295 password = optarg;
296 break;
297 case 'F': /* configuration file */
298 config_file = optarg;
299 break;
300 case 'e': /* expect */
301 expect = optarg;
302 break;
303 case 'r': /* retries */
304 if (is_intpos (optarg))
305 retries = atoi (optarg);
306 else
307 usage (_("Number of retries must be a positive integer"));
308 break;
309 case 't': /* timeout */
310 if (is_intpos (optarg))
311 timeout_interval = atoi (optarg);
312 else
313 usage (_("Timeout interval must be a positive integer"));
314 break;
315 }
316 }
317 return OK;
318 }