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 usage (_("Timeout interval must be a positive integer"));
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 printf (_("Invalid host name/address\n\n"));
231 print_usage ();
232 exit (STATE_UNKNOWN);
233 }
234 server = optarg;
235 break;
236 case 'P': /* port */
237 if (is_intnonneg (optarg))
238 port = atoi (optarg);
239 else
240 usage (_("Server port must be a positive integer"));
241 break;
242 case 'u': /* username */
243 username = optarg;
244 break;
245 case 'p': /* password */
246 password = optarg;
247 break;
248 case 'n': /* nas id */
249 nasid = optarg;
250 break;
251 case 'F': /* configuration file */
252 config_file = optarg;
253 break;
254 case 'e': /* expect */
255 expect = optarg;
256 break;
257 case 'r': /* retries */
258 if (is_intpos (optarg))
259 retries = atoi (optarg);
260 else
261 usage (_("Number of retries must be a positive integer"));
262 break;
263 case 't': /* timeout */
264 if (is_intpos (optarg))
265 timeout_interval = atoi (optarg);
266 else
267 usage (_("Timeout interval must be a positive integer"));
268 break;
269 }
270 }
271 return OK;
272 }
278 \f
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 }
335 void
336 print_usage (void)
337 {
338 printf ("\
339 Usage: %s -H host -F config_file -u username -p password [-n nas-id] [-P port]\n\
340 [-t timeout] [-r retries] [-e expect]\n", progname);
341 printf (_(UT_HLP_VRS), progname, progname);
342 }