Code

Option to fill in NAS-identifier to Emulate pam_radius behaviour (Alexander Kulak)
[nagiosplug.git] / plugins / check_radius.c
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);
160 /* process command-line arguments */
161 int
162 process_arguments (int argc, char **argv)
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;
278 \f
279 void
280 print_help (void)
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));
335 void
336 print_usage (void)
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);