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 if (process_arguments (argc, argv) == ERROR)
107 usage (_("Could not parse arguments\n"));
109 str = strdup ("dictionary");
110 if ((config_file && rc_read_config (config_file)) ||
111 rc_read_dictionary (rc_conf_str (str)))
112 die (STATE_UNKNOWN, _("Config file error"));
114 service = PW_AUTHENTICATE_ONLY;
116 if (!(rc_avpair_add (&data.send_pairs, PW_SERVICE_TYPE, &service, 0) &&
117 rc_avpair_add (&data.send_pairs, PW_USER_NAME, username, 0) &&
118 rc_avpair_add (&data.send_pairs, PW_USER_PASSWORD, password, 0)))
119 die (STATE_UNKNOWN, _("Out of Memory?"));
121 /*
122 * Fill in NAS-IP-Address
123 */
125 if ((client_id = rc_own_ipaddress ()) == 0)
126 return (ERROR_RC);
128 if (rc_avpair_add (&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) ==
129 NULL) return (ERROR_RC);
131 rc_buildreq (&data, PW_ACCESS_REQUEST, server, port, (int)timeout_interval,
132 retries);
134 result = rc_send_server (&data, msg);
135 rc_avpair_free (data.send_pairs);
136 if (data.receive_pairs)
137 rc_avpair_free (data.receive_pairs);
139 if (result == TIMEOUT_RC)
140 die (STATE_CRITICAL, _("Timeout"));
141 if (result == ERROR_RC)
142 die (STATE_CRITICAL, _("Auth Error"));
143 if (result == BADRESP_RC)
144 die (STATE_WARNING, _("Auth Failed"));
145 if (expect && !strstr (msg, expect))
146 die (STATE_WARNING, "%s", msg);
147 if (result == OK_RC)
148 die (STATE_OK, _("Auth OK"));
149 return (0);
150 }
154 /* process command-line arguments */
155 int
156 process_arguments (int argc, char **argv)
157 {
158 int c;
160 int option = 0;
161 static struct option longopts[] = {
162 {"hostname", required_argument, 0, 'H'},
163 {"port", required_argument, 0, 'P'},
164 {"username", required_argument, 0, 'u'},
165 {"password", required_argument, 0, 'p'},
166 {"filename", required_argument, 0, 'F'},
167 {"expect", required_argument, 0, 'e'},
168 {"retries", required_argument, 0, 'r'},
169 {"timeout", required_argument, 0, 't'},
170 {"verbose", no_argument, 0, 'v'},
171 {"version", no_argument, 0, 'V'},
172 {"help", no_argument, 0, 'h'},
173 {0, 0, 0, 0}
174 };
176 if (argc < 2)
177 return ERROR;
179 if (argc == 9) {
180 config_file = argv[1];
181 username = argv[2];
182 password = argv[3];
183 if (is_intpos (argv[4]))
184 timeout_interval = atoi (argv[4]);
185 else
186 usage (_("Timeout interval must be a positive integer"));
187 if (is_intpos (argv[5]))
188 retries = atoi (argv[5]);
189 else
190 usage (_("Number of retries must be a positive integer"));
191 server = argv[6];
192 if (is_intpos (argv[7]))
193 port = atoi (argv[7]);
194 else
195 usage (_("Server port must be a positive integer"));
196 expect = argv[8];
197 return OK;
198 }
200 while (1) {
201 c = getopt_long (argc, argv, "+hVvH:P:F:u:p:t:r:e:", longopts,
202 &option);
204 if (c == -1 || c == EOF || c == 1)
205 break;
207 switch (c) {
208 case '?': /* print short usage statement if args not parsable */
209 printf (_("%s: Unknown argument: %s\n\n"), progname, optarg);
210 print_usage ();
211 exit (STATE_UNKNOWN);
212 case 'h': /* help */
213 print_help ();
214 exit (OK);
215 case 'V': /* version */
216 print_revision (progname, revision);
217 exit (OK);
218 case 'v': /* verbose mode */
219 verbose = TRUE;
220 break;
221 case 'H': /* hostname */
222 if (is_host (optarg) == FALSE) {
223 printf (_("Invalid host name/address\n\n"));
224 print_usage ();
225 exit (STATE_UNKNOWN);
226 }
227 server = optarg;
228 break;
229 case 'P': /* port */
230 if (is_intnonneg (optarg))
231 port = atoi (optarg);
232 else
233 usage (_("Server port must be a positive integer"));
234 break;
235 case 'u': /* username */
236 username = optarg;
237 break;
238 case 'p': /* password */
239 password = optarg;
240 break;
241 case 'F': /* configuration file */
242 config_file = optarg;
243 break;
244 case 'e': /* expect */
245 expect = optarg;
246 break;
247 case 'r': /* retries */
248 if (is_intpos (optarg))
249 retries = atoi (optarg);
250 else
251 usage (_("Number of retries must be a positive integer"));
252 break;
253 case 't': /* timeout */
254 if (is_intpos (optarg))
255 timeout_interval = atoi (optarg);
256 else
257 usage (_("Timeout interval must be a positive integer"));
258 break;
259 }
260 }
261 return OK;
262 }
268 \f
269 void
270 print_help (void)
271 {
272 char *myport;
273 asprintf (&myport, "%d", PW_AUTH_UDP_PORT);
275 print_revision (progname, revision);
277 printf (_("Copyright (c) 1999 Robert August Vincent II\n"));
278 printf (_(COPYRIGHT), copyright, email);
280 printf(_("Tests to see if a radius server is accepting connections.\n\n"));
282 print_usage ();
284 printf (_(UT_HELP_VRSN));
286 printf (_(UT_HOST_PORT), 'P', myport);
288 printf (_("\
289 -u, --username=STRING\n\
290 The user to authenticate\n\
291 -p, --password=STRING\n\
292 Password for autentication (SECURITY RISK)\n\
293 -F, --filename=STRING\n\
294 Configuration file\n\
295 -e, --expect=STRING\n\
296 Response string to expect from the server\n\
297 -r, --retries=INTEGER\n\
298 Number of times to retry a failed connection\n"));
300 printf (_(UT_TIMEOUT), timeout_interval);
302 printf (_("\n\
303 This plugin tests a radius server to see if it is accepting connections.\n\
304 \n\
305 The server to test must be specified in the invocation, as well as a user\n\
306 name and password. A configuration file may also be present. The format of\n\
307 the configuration file is described in the radiusclient library sources.\n\n"));
309 printf (_("\
310 The password option presents a substantial security issue because the\n\
311 password can be determined by careful watching of the command line in\n\
312 a process listing. This risk is exacerbated because nagios will\n\
313 run the plugin at regular prdictable intervals. Please be sure that\n\
314 the password used does not allow access to sensitive system resources,\n\
315 otherwise compormise could occur.\n"));
317 printf (_(UT_SUPPORT));
318 }
323 void
324 print_usage (void)
325 {
326 printf ("\
327 Usage: %s -H host -F config_file -u username -p password [-P port]\n\
328 [-t timeout] [-r retries] [-e expect]\n", progname);
329 printf (_(UT_HLP_VRS), progname, progname);
330 }