check_radius.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /******************************************************************************
  2. *
  3. * Program: radius server check plugin for Nagios
  4. * License: GPL
  5. *
  6. * License Information:
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. *
  22. * $Id$
  23. *
  24. *****************************************************************************/
  25. #define PROGNAME "check_radius"
  26. #define REVISION "$Revision$"
  27. #define COPYRIGHT "1999-2001"
  28. #define AUTHORS "Robert August Vincent II/Karl DeBisschop"
  29. #define EMAIL "kdebisschop@users.sourceforge.net"
  30. #define SUMMARY "Tests to see if a radius server is accepting connections.\n"
  31. #define OPTIONS "\
  32. -H host -F config_file -u username -p password\'\
  33. [-P port] [-t timeout] [-r retries] [-e expect]"
  34. #define LONGOPTIONS "\
  35. -H, --hostname=HOST\n\
  36. Host name argument for servers using host headers (use numeric\n\
  37. address if possible to bypass DNS lookup).\n\
  38. -P, --port=INTEGER\n\
  39. Port number (default: %d)\n\
  40. -u, --username=STRING\n\
  41. The user to authenticate\n\
  42. -p, --password=STRING\n\
  43. Password for autentication (SECURITY RISK)\n\
  44. -F, --filename=STRING\n\
  45. Configuration file\n\
  46. -e, --expect=STRING\n\
  47. Response string to expect from the server\n\
  48. -r, --retries=INTEGER\n\
  49. Number of times to retry a failed connection\n\
  50. -t, --timeout=INTEGER\n\
  51. Seconds before connection times out (default: %d)\n\
  52. -v\n\
  53. Show details for command-line debugging (do not use with nagios server)\n\
  54. -h, --help\n\
  55. Print detailed help screen\n\
  56. -V, --version\n\
  57. Print version information\n"
  58. #define DESCRIPTION "\
  59. The password option presents a substantial security issue because the
  60. password can be determined by careful watching of the command line in
  61. a process listing. This risk is exacerbated because nagios will
  62. run the plugin at regular prdictable intervals. Please be sure that
  63. the password used does not allow access to sensitive system resources,
  64. otherwise compormise could occur.\n"
  65. #include "config.h"
  66. #include "common.h"
  67. #include "utils.h"
  68. #include <radiusclient.h>
  69. int process_arguments (int, char **);
  70. void print_usage (void);
  71. void print_help (void);
  72. char *server = NULL;
  73. int port = PW_AUTH_UDP_PORT;
  74. char *username = NULL;
  75. char *password = NULL;
  76. char *expect = NULL;
  77. char *config_file = NULL;
  78. int retries = 1;
  79. int verbose = FALSE;
  80. ENV *env = NULL;
  81. /******************************************************************************
  82. The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@
  83. tags in the comments. With in the tags, the XML is assembled sequentially.
  84. You can define entities in tags. You also have all the #defines available as
  85. entities.
  86. Please note that all tags must be lowercase to use the DocBook XML DTD.
  87. @@-<article>
  88. <sect1>
  89. <title>Quick Reference</title>
  90. <!-- The refentry forms a manpage -->
  91. <refentry>
  92. <refmeta>
  93. <manvolnum>5<manvolnum>
  94. </refmeta>
  95. <refnamdiv>
  96. <refname>&PROGNAME;</refname>
  97. <refpurpose>&SUMMARY;</refpurpose>
  98. </refnamdiv>
  99. </refentry>
  100. </sect1>
  101. <sect1>
  102. <title>FAQ</title>
  103. </sect1>
  104. <sect1>
  105. <title>Theory, Installation, and Operation</title>
  106. <sect2>
  107. <title>General Description</title>
  108. <para>
  109. &DESCRIPTION;
  110. </para>
  111. </sect2>
  112. <sect2>
  113. <title>Future Enhancements</title>
  114. <para>ToDo List</para>
  115. <itemizedlist>
  116. <listitem>Add option to get password from a secured file rather than the command line</listitem>
  117. </itemizedlist>
  118. </sect2>
  119. <sect2>
  120. <title>Functions</title>
  121. -@@
  122. ******************************************************************************/
  123. int
  124. main (int argc, char **argv)
  125. {
  126. UINT4 service;
  127. char msg[BUFFER_LEN];
  128. SEND_DATA data = { 0 };
  129. int result;
  130. UINT4 client_id;
  131. if (process_arguments (argc, argv) == ERROR)
  132. usage ("Could not parse arguments\n");
  133. if ((config_file && rc_read_config (config_file)) ||
  134. rc_read_dictionary (rc_conf_str ("dictionary")))
  135. terminate (STATE_UNKNOWN, "Config file error");
  136. service = PW_AUTHENTICATE_ONLY;
  137. if (!(rc_avpair_add (&data.send_pairs, PW_SERVICE_TYPE, &service, 0) &&
  138. rc_avpair_add (&data.send_pairs, PW_USER_NAME, username, 0) &&
  139. rc_avpair_add (&data.send_pairs, PW_USER_PASSWORD, password, 0)))
  140. terminate (STATE_UNKNOWN, "Out of Memory?");
  141. /*
  142. * Fill in NAS-IP-Address
  143. */
  144. if ((client_id = rc_own_ipaddress ()) == 0)
  145. return (ERROR_RC);
  146. if (rc_avpair_add (&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) ==
  147. NULL) return (ERROR_RC);
  148. rc_buildreq (&data, PW_ACCESS_REQUEST, server, port, timeout_interval,
  149. retries);
  150. result = rc_send_server (&data, msg);
  151. rc_avpair_free (data.send_pairs);
  152. if (data.receive_pairs)
  153. rc_avpair_free (data.receive_pairs);
  154. if (result == TIMEOUT_RC)
  155. terminate (STATE_CRITICAL, "Timeout");
  156. if (result == ERROR_RC)
  157. terminate (STATE_CRITICAL, "Auth Error");
  158. if (result == BADRESP_RC)
  159. terminate (STATE_WARNING, "Auth Failed");
  160. if (expect && !strstr (msg, expect))
  161. terminate (STATE_WARNING, msg);
  162. if (result == OK_RC)
  163. terminate (STATE_OK, "Auth OK");
  164. return (0);
  165. }
  166. /* process command-line arguments */
  167. int
  168. process_arguments (int argc, char **argv)
  169. {
  170. int c;
  171. #ifdef HAVE_GETOPT_H
  172. int option_index = 0;
  173. static struct option long_options[] = {
  174. {"hostname", required_argument, 0, 'H'},
  175. {"port", required_argument, 0, 'P'},
  176. {"username", required_argument, 0, 'u'},
  177. {"password", required_argument, 0, 'p'},
  178. {"filename", required_argument, 0, 'F'},
  179. {"expect", required_argument, 0, 'e'},
  180. {"retries", required_argument, 0, 'r'},
  181. {"timeout", required_argument, 0, 't'},
  182. {"verbose", no_argument, 0, 'v'},
  183. {"version", no_argument, 0, 'V'},
  184. {"help", no_argument, 0, 'h'},
  185. {0, 0, 0, 0}
  186. };
  187. #endif
  188. if (argc < 2)
  189. 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. usage ("Timeout interval must be a positive integer");
  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 ("Server port must be a positive integer");
  207. expect = argv[8];
  208. return OK;
  209. }
  210. while (1) {
  211. #ifdef HAVE_GETOPT_H
  212. c =
  213. getopt_long (argc, argv, "+hVvH:P:F:u:p:t:r:e:", long_options,
  214. &option_index);
  215. #else
  216. c = getopt (argc, argv, "+hVvH:P:F:u:p:t:r:e:");
  217. #endif
  218. if (c == -1 || c == EOF || c == 1)
  219. break;
  220. switch (c) {
  221. case '?': /* print short usage statement if args not parsable */
  222. printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
  223. print_usage ();
  224. exit (STATE_UNKNOWN);
  225. case 'h': /* help */
  226. print_help ();
  227. exit (OK);
  228. case 'V': /* version */
  229. print_revision (my_basename (argv[0]), "$Revision$");
  230. exit (OK);
  231. case 'v': /* verbose mode */
  232. verbose = TRUE;
  233. break;
  234. case 'H': /* hostname */
  235. if (is_host (optarg) == FALSE) {
  236. printf ("Invalid host name/address\n\n");
  237. print_usage ();
  238. exit (STATE_UNKNOWN);
  239. }
  240. server = optarg;
  241. break;
  242. case 'P': /* port */
  243. if (is_intnonneg (optarg))
  244. port = atoi (optarg);
  245. else
  246. usage ("Server port must be a positive integer");
  247. break;
  248. case 'u': /* username */
  249. username = optarg;
  250. break;
  251. case 'p': /* password */
  252. password = optarg;
  253. break;
  254. case 'F': /* configuration file */
  255. config_file = optarg;
  256. break;
  257. case 'e': /* expect */
  258. expect = optarg;
  259. break;
  260. case 'r': /* retries */
  261. if (is_intpos (optarg))
  262. retries = atoi (optarg);
  263. else
  264. usage ("Number of retries must be a positive integer");
  265. break;
  266. case 't': /* timeout */
  267. if (is_intpos (optarg))
  268. timeout_interval = atoi (optarg);
  269. else
  270. usage ("Timeout interval must be a positive integer");
  271. break;
  272. }
  273. }
  274. return OK;
  275. }
  276. void
  277. print_help (void)
  278. {
  279. print_revision (PROGNAME, REVISION);
  280. printf
  281. ("Copyright (c) %s %s <%s>\n\n%s\n",
  282. COPYRIGHT, AUTHORS, EMAIL, SUMMARY);
  283. print_usage ();
  284. printf
  285. ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n",
  286. port, timeout_interval);
  287. support ();
  288. }
  289. void
  290. print_usage (void)
  291. {
  292. printf ("Usage:\n" " %s %s\n"
  293. #ifdef HAVE_GETOPT_H
  294. " %s (-h | --help) for detailed help\n"
  295. " %s (-V | --version) for version information\n",
  296. #else
  297. " %s -h for detailed help\n"
  298. " %s -V for version information\n",
  299. #endif
  300. PROGNAME, OPTIONS, PROGNAME, PROGNAME);
  301. }