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 "common.h"
25 #include "utils.h"
26 #include "netutils.h"
27 #include <radiusclient.h>
29 int process_arguments (int, char **);
30 void print_help (void);
31 void print_usage (void);
33 char *server = NULL;
34 char *username = NULL;
35 char *password = NULL;
36 char *expect = NULL;
37 char *config_file = NULL;
38 unsigned short port = PW_AUTH_UDP_PORT;
39 int retries = 1;
40 int verbose = FALSE;
41 ENV *env = NULL;
43 /******************************************************************************
45 The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@
46 tags in the comments. With in the tags, the XML is assembled sequentially.
47 You can define entities in tags. You also have all the #defines available as
48 entities.
50 Please note that all tags must be lowercase to use the DocBook XML DTD.
52 @@-<article>
54 <sect1>
55 <title>Quick Reference</title>
56 <!-- The refentry forms a manpage -->
57 <refentry>
58 <refmeta>
59 <manvolnum>5<manvolnum>
60 </refmeta>
61 <refnamdiv>
62 <refname>&progname;</refname>
63 <refpurpose>&SUMMARY;</refpurpose>
64 </refnamdiv>
65 </refentry>
66 </sect1>
68 <sect1>
69 <title>FAQ</title>
70 </sect1>
72 <sect1>
73 <title>Theory, Installation, and Operation</title>
75 <sect2>
76 <title>General Description</title>
77 <para>
78 &DESCRIPTION;
79 </para>
80 </sect2>
82 <sect2>
83 <title>Future Enhancements</title>
84 <para>Todo List</para>
85 <itemizedlist>
86 <listitem>Add option to get password from a secured file rather than the command line</listitem>
87 </itemizedlist>
88 </sect2>
91 <sect2>
92 <title>Functions</title>
93 -@@
94 ******************************************************************************/
96 int
97 main (int argc, char **argv)
98 {
99 UINT4 service;
100 char msg[BUFFER_LEN];
101 SEND_DATA data;
102 int result;
103 UINT4 client_id;
104 char *str;
106 setlocale (LC_ALL, "");
107 bindtextdomain (PACKAGE, LOCALEDIR);
108 textdomain (PACKAGE);
110 if (process_arguments (argc, argv) == ERROR)
111 usage (_("Could not parse arguments\n"));
113 str = strdup ("dictionary");
114 if ((config_file && rc_read_config (config_file)) ||
115 rc_read_dictionary (rc_conf_str (str)))
116 die (STATE_UNKNOWN, _("Config file error"));
118 service = PW_AUTHENTICATE_ONLY;
120 if (!(rc_avpair_add (&data.send_pairs, PW_SERVICE_TYPE, &service, 0) &&
121 rc_avpair_add (&data.send_pairs, PW_USER_NAME, username, 0) &&
122 rc_avpair_add (&data.send_pairs, PW_USER_PASSWORD, password, 0)))
123 die (STATE_UNKNOWN, _("Out of Memory?"));
125 /*
126 * Fill in NAS-IP-Address
127 */
129 if ((client_id = rc_own_ipaddress ()) == 0)
130 return (ERROR_RC);
132 if (rc_avpair_add (&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) ==
133 NULL) return (ERROR_RC);
135 rc_buildreq (&data, PW_ACCESS_REQUEST, server, port, (int)timeout_interval,
136 retries);
138 result = rc_send_server (&data, msg);
139 rc_avpair_free (data.send_pairs);
140 if (data.receive_pairs)
141 rc_avpair_free (data.receive_pairs);
143 if (result == TIMEOUT_RC)
144 die (STATE_CRITICAL, _("Timeout"));
145 if (result == ERROR_RC)
146 die (STATE_CRITICAL, _("Auth Error"));
147 if (result == BADRESP_RC)
148 die (STATE_WARNING, _("Auth Failed"));
149 if (expect && !strstr (msg, expect))
150 die (STATE_WARNING, "%s", msg);
151 if (result == OK_RC)
152 die (STATE_OK, _("Auth OK"));
153 return (0);
154 }
158 /* process command-line arguments */
159 int
160 process_arguments (int argc, char **argv)
161 {
162 int c;
164 int option = 0;
165 static struct option longopts[] = {
166 {"hostname", required_argument, 0, 'H'},
167 {"port", required_argument, 0, 'P'},
168 {"username", required_argument, 0, 'u'},
169 {"password", required_argument, 0, 'p'},
170 {"filename", required_argument, 0, 'F'},
171 {"expect", required_argument, 0, 'e'},
172 {"retries", required_argument, 0, 'r'},
173 {"timeout", required_argument, 0, 't'},
174 {"verbose", no_argument, 0, 'v'},
175 {"version", no_argument, 0, 'V'},
176 {"help", no_argument, 0, 'h'},
177 {0, 0, 0, 0}
178 };
180 if (argc < 2)
181 return ERROR;
183 if (argc == 9) {
184 config_file = argv[1];
185 username = argv[2];
186 password = argv[3];
187 if (is_intpos (argv[4]))
188 timeout_interval = atoi (argv[4]);
189 else
190 usage (_("Timeout interval must be a positive integer"));
191 if (is_intpos (argv[5]))
192 retries = atoi (argv[5]);
193 else
194 usage (_("Number of retries must be a positive integer"));
195 server = argv[6];
196 if (is_intpos (argv[7]))
197 port = atoi (argv[7]);
198 else
199 usage (_("Server port must be a positive integer"));
200 expect = argv[8];
201 return OK;
202 }
204 while (1) {
205 c = getopt_long (argc, argv, "+hVvH:P:F:u:p:t:r:e:", longopts,
206 &option);
208 if (c == -1 || c == EOF || c == 1)
209 break;
211 switch (c) {
212 case '?': /* print short usage statement if args not parsable */
213 printf (_("%s: Unknown argument: %s\n\n"), progname, optarg);
214 print_usage ();
215 exit (STATE_UNKNOWN);
216 case 'h': /* help */
217 print_help ();
218 exit (OK);
219 case 'V': /* version */
220 print_revision (progname, revision);
221 exit (OK);
222 case 'v': /* verbose mode */
223 verbose = TRUE;
224 break;
225 case 'H': /* hostname */
226 if (is_host (optarg) == FALSE) {
227 printf (_("Invalid host name/address\n\n"));
228 print_usage ();
229 exit (STATE_UNKNOWN);
230 }
231 server = optarg;
232 break;
233 case 'P': /* port */
234 if (is_intnonneg (optarg))
235 port = atoi (optarg);
236 else
237 usage (_("Server port must be a positive integer"));
238 break;
239 case 'u': /* username */
240 username = optarg;
241 break;
242 case 'p': /* password */
243 password = optarg;
244 break;
245 case 'F': /* configuration file */
246 config_file = optarg;
247 break;
248 case 'e': /* expect */
249 expect = optarg;
250 break;
251 case 'r': /* retries */
252 if (is_intpos (optarg))
253 retries = atoi (optarg);
254 else
255 usage (_("Number of retries must be a positive integer"));
256 break;
257 case 't': /* timeout */
258 if (is_intpos (optarg))
259 timeout_interval = atoi (optarg);
260 else
261 usage (_("Timeout interval must be a positive integer"));
262 break;
263 }
264 }
265 return OK;
266 }
272 \f
273 void
274 print_help (void)
275 {
276 char *myport;
277 asprintf (&myport, "%d", PW_AUTH_UDP_PORT);
279 print_revision (progname, revision);
281 printf (_("Copyright (c) 1999 Robert August Vincent II\n"));
282 printf (_(COPYRIGHT), copyright, email);
284 printf(_("Tests to see if a radius server is accepting connections.\n\n"));
286 print_usage ();
288 printf (_(UT_HELP_VRSN));
290 printf (_(UT_HOST_PORT), 'P', myport);
292 printf (_("\
293 -u, --username=STRING\n\
294 The user to authenticate\n\
295 -p, --password=STRING\n\
296 Password for autentication (SECURITY RISK)\n\
297 -F, --filename=STRING\n\
298 Configuration file\n\
299 -e, --expect=STRING\n\
300 Response string to expect from the server\n\
301 -r, --retries=INTEGER\n\
302 Number of times to retry a failed connection\n"));
304 printf (_(UT_TIMEOUT), timeout_interval);
306 printf (_("\n\
307 This plugin tests a radius server to see if it is accepting connections.\n\
308 \n\
309 The server to test must be specified in the invocation, as well as a user\n\
310 name and password. A configuration file may also be present. The format of\n\
311 the configuration file is described in the radiusclient library sources.\n\n"));
313 printf (_("\
314 The password option presents a substantial security issue because the\n\
315 password can be determined by careful watching of the command line in\n\
316 a process listing. This risk is exacerbated because nagios will\n\
317 run the plugin at regular prdictable intervals. Please be sure that\n\
318 the password used does not allow access to sensitive system resources,\n\
319 otherwise compormise could occur.\n"));
321 printf (_(UT_SUPPORT));
322 }
327 void
328 print_usage (void)
329 {
330 printf ("\
331 Usage: %s -H host -F config_file -u username -p password [-P port]\n\
332 [-t timeout] [-r retries] [-e expect]\n", progname);
333 printf (_(UT_HLP_VRS), progname, progname);
334 }