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