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