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