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 $Id$
19 ******************************************************************************/
21 const char *progname = "check_ldap";
22 const char *revision = "$Revision$";
23 const char *copyright = "2000-2004";
24 const char *email = "nagiosplug-devel@lists.sourceforge.net";
26 #include "common.h"
27 #include "netutils.h"
28 #include "utils.h"
30 #include <lber.h>
31 #include <ldap.h>
33 enum {
34 UNDEFINED = 0,
35 #ifdef HAVE_LDAP_SET_OPTION
36 DEFAULT_PROTOCOL = 2,
37 #endif
38 DEFAULT_PORT = 389
39 };
41 int process_arguments (int, char **);
42 int validate_arguments (void);
43 void print_help (void);
44 void print_usage (void);
46 char ld_defattr[] = "(objectclass=*)";
47 char *ld_attr = ld_defattr;
48 char *ld_host = NULL;
49 char *ld_base = NULL;
50 char *ld_passwd = NULL;
51 char *ld_binddn = NULL;
52 int ld_port = DEFAULT_PORT;
53 #ifdef HAVE_LDAP_SET_OPTION
54 int ld_protocol = DEFAULT_PROTOCOL;
55 #endif
56 double warn_time = UNDEFINED;
57 double crit_time = UNDEFINED;
58 struct timeval tv;
60 /* for ldap tls */
62 char *SERVICE = "LDAP";
64 int
65 main (int argc, char *argv[])
66 {
68 LDAP *ld;
69 LDAPMessage *result;
71 /* should be int result = STATE_UNKNOWN; */
73 int status = STATE_UNKNOWN;
74 long microsec;
75 double elapsed_time;
77 /* for ldap tls */
79 int tls;
80 int version=3;
82 setlocale (LC_ALL, "");
83 bindtextdomain (PACKAGE, LOCALEDIR);
84 textdomain (PACKAGE);
86 if (strstr(argv[0],"check_ldaps")) {
87 asprintf (&progname, "check_ldaps");
88 }
90 if (process_arguments (argc, argv) == ERROR)
91 usage4 (_("Could not parse arguments"));
93 /* initialize alarm signal handling */
94 signal (SIGALRM, socket_timeout_alarm_handler);
96 /* set socket timeout */
97 alarm (socket_timeout);
99 /* get the start time */
100 gettimeofday (&tv, NULL);
102 /* initialize ldap */
103 #ifdef HAVE_LDAP_INIT
104 if (!(ld = ldap_init (ld_host, ld_port))) {
105 printf ("Could not connect to the server at port %i\n", ld_port);
106 return STATE_CRITICAL;
107 }
108 #else
109 if (!(ld = ldap_open (ld_host, ld_port))) {
110 /*ldap_perror(ld, "ldap_open"); */
111 printf (_("Could not connect to the server at port %i\n"), ld_port);
112 return STATE_CRITICAL;
113 }
114 #endif /* HAVE_LDAP_INIT */
116 #ifdef HAVE_LDAP_SET_OPTION
117 /* set ldap options */
118 if (ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &ld_protocol) !=
119 LDAP_OPT_SUCCESS ) {
120 printf(_("Could not set protocol version %d\n"), ld_protocol);
121 return STATE_CRITICAL;
122 }
123 #endif
125 if (strstr(argv[0],"check_ldaps")) {
126 /* with TLS */
127 if ( ld_port == LDAPS_PORT ) {
128 asprintf (&SERVICE, "LDAPS");
129 #if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)
130 /* ldaps: set option tls */
131 tls = LDAP_OPT_X_TLS_HARD;
133 if (ldap_set_option (ld, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
134 {
135 /*ldap_perror(ld, "ldaps_option"); */
136 printf ("Could not init TLS at port %i!\n", ld_port);
137 return STATE_CRITICAL;
138 }
139 #else
140 printf ("TLS not supported by the libraries!\n", ld_port);
141 return STATE_CRITICAL;
142 #endif /* LDAP_OPT_X_TLS */
143 } else {
144 asprintf (&SERVICE, "LDAP-TLS");
145 #if defined(HAVE_LDAP_SET_OPTION) && defined(HAVE_LDAP_START_TLS_S)
146 /* ldap with startTLS: set option version */
147 if (ldap_get_option(ld,LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS )
148 {
149 if (version < LDAP_VERSION3)
150 {
151 version = LDAP_VERSION3;
152 ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
153 }
154 }
155 /* call start_tls */
156 if (ldap_start_tls_s(ld, NULL, NULL) != LDAP_SUCCESS)
157 {
158 /*ldap_perror(ld, "ldap_start_tls"); */
159 printf ("Could not init startTLS at port %i!\n", ld_port);
160 return STATE_CRITICAL;
161 }
162 #else
163 printf ("startTLS not supported by the library, needs LDAPv3!\n");
164 return STATE_CRITICAL;
165 #endif /* HAVE_LDAP_START_TLS_S */
166 }
167 }
169 /* bind to the ldap server */
170 if (ldap_bind_s (ld, ld_binddn, ld_passwd, LDAP_AUTH_SIMPLE) !=
171 LDAP_SUCCESS) {
172 /*ldap_perror(ld, "ldap_bind"); */
173 printf (_("Could not bind to the ldap-server\n"));
174 return STATE_CRITICAL;
175 }
177 /* do a search of all objectclasses in the base dn */
178 if (ldap_search_s (ld, ld_base, LDAP_SCOPE_BASE, ld_attr, NULL, 0, &result)
179 != LDAP_SUCCESS) {
180 /*ldap_perror(ld, "ldap_search"); */
181 printf (_("Could not search/find objectclasses in %s\n"), ld_base);
182 return STATE_CRITICAL;
183 }
185 /* unbind from the ldap server */
186 ldap_unbind (ld);
188 /* reset the alarm handler */
189 alarm (0);
191 /* calcutate the elapsed time and compare to thresholds */
193 microsec = deltime (tv);
194 elapsed_time = (double)microsec / 1.0e6;
196 if (crit_time!=UNDEFINED && elapsed_time>crit_time)
197 status = STATE_CRITICAL;
198 else if (warn_time!=UNDEFINED && elapsed_time>warn_time)
199 status = STATE_WARNING;
200 else
201 status = STATE_OK;
203 /* print out the result */
204 printf (_("LDAP %s - %.3f seconds response time|%s\n"),
205 state_text (status),
206 elapsed_time,
207 fperfdata ("time", elapsed_time, "s",
208 (int)warn_time, warn_time,
209 (int)crit_time, crit_time,
210 TRUE, 0, FALSE, 0));
212 return status;
213 }
215 /* process command-line arguments */
216 int
217 process_arguments (int argc, char **argv)
218 {
219 int c;
221 int option = 0;
222 /* initialize the long option struct */
223 static struct option longopts[] = {
224 {"help", no_argument, 0, 'h'},
225 {"version", no_argument, 0, 'V'},
226 {"timeout", required_argument, 0, 't'},
227 {"host", required_argument, 0, 'H'},
228 {"base", required_argument, 0, 'b'},
229 {"attr", required_argument, 0, 'a'},
230 {"bind", required_argument, 0, 'D'},
231 {"pass", required_argument, 0, 'P'},
232 #ifdef HAVE_LDAP_SET_OPTION
233 {"ver2", no_argument, 0, '2'},
234 {"ver3", no_argument, 0, '3'},
235 #endif
236 {"use-ipv4", no_argument, 0, '4'},
237 {"use-ipv6", no_argument, 0, '6'},
238 {"port", required_argument, 0, 'p'},
239 {"warn", required_argument, 0, 'w'},
240 {"crit", required_argument, 0, 'c'},
241 {0, 0, 0, 0}
242 };
244 if (argc < 2)
245 return ERROR;
247 for (c = 1; c < argc; c++) {
248 if (strcmp ("-to", argv[c]) == 0)
249 strcpy (argv[c], "-t");
250 }
252 while (1) {
253 c = getopt_long (argc, argv, "hV2346t:c:w:H:b:p:a:D:P:", longopts, &option);
255 if (c == -1 || c == EOF)
256 break;
258 switch (c) {
259 case 'h': /* help */
260 print_help ();
261 exit (STATE_OK);
262 case 'V': /* version */
263 print_revision (progname, revision);
264 exit (STATE_OK);
265 case 't': /* timeout period */
266 if (!is_intnonneg (optarg))
267 usage2 (_("Timeout interval must be a positive integer"), optarg);
268 else
269 socket_timeout = atoi (optarg);
270 break;
271 case 'H':
272 ld_host = optarg;
273 break;
274 case 'b':
275 ld_base = optarg;
276 break;
277 case 'p':
278 ld_port = atoi (optarg);
279 break;
280 case 'a':
281 ld_attr = optarg;
282 break;
283 case 'D':
284 ld_binddn = optarg;
285 break;
286 case 'P':
287 ld_passwd = optarg;
288 break;
289 case 'w':
290 warn_time = strtod (optarg, NULL);
291 break;
292 case 'c':
293 crit_time = strtod (optarg, NULL);
294 break;
295 #ifdef HAVE_LDAP_SET_OPTION
296 case '2':
297 ld_protocol = 2;
298 break;
299 case '3':
300 ld_protocol = 3;
301 break;
302 #endif
303 case '4':
304 address_family = AF_INET;
305 break;
306 case '6':
307 #ifdef USE_IPV6
308 address_family = AF_INET6;
309 #else
310 usage (_("IPv6 support not available\n"));
311 #endif
312 break;
313 default:
314 printf (_("%s: Unknown argument: %s\n\n"), progname, optarg);
315 print_usage ();
316 exit (STATE_UNKNOWN);
317 }
318 }
320 c = optind;
321 if (ld_host == NULL && is_host(argv[c]))
322 ld_host = strdup (argv[c++]);
324 if (ld_base == NULL && argv[c])
325 ld_base = strdup (argv[c++]);
327 return validate_arguments ();
328 }
330 int
331 validate_arguments ()
332 {
333 if (ld_host==NULL || strlen(ld_host)==0)
334 usage (_("please specify the host name\n"));
336 if (ld_base==NULL || strlen(ld_base)==0)
337 usage (_("please specify the LDAP base\n"));
339 return OK;
341 }
345 void
346 print_help (void)
347 {
348 char *myport;
349 asprintf (&myport, "%d", DEFAULT_PORT);
351 print_revision (progname, revision);
353 printf ("Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)\n");
354 printf (COPYRIGHT, copyright, email);
356 print_usage ();
358 printf (_(UT_HELP_VRSN));
360 printf (_(UT_HOST_PORT), 'p', myport);
362 printf (_(UT_IPv46));
364 printf (_("\
365 -a [--attr]\n\
366 ldap attribute to search (default: \"(objectclass=*)\"\n\
367 -b [--base]\n\
368 ldap base (eg. ou=my unit, o=my org, c=at)\n\
369 -D [--bind]\n\
370 ldap bind DN (if required)\n\
371 -P [--pass]\n\
372 ldap password (if required)\n"));
374 #ifdef HAVE_LDAP_SET_OPTION
375 printf (_("\
376 -2 [--ver2]\n\
377 use ldap protocol version 2\n\
378 -3 [--ver3]\n\
379 use ldap protocol version 3\n\
380 (default protocol version: %d)\n"),
381 DEFAULT_PROTOCOL);
382 #endif
384 printf (_(UT_WARN_CRIT));
386 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
388 printf (_(UT_VERBOSE));
390 printf (_(UT_SUPPORT));
391 }
395 void
396 print_usage (void)
397 {
398 printf ("\
399 Usage: %s -H <host> -b <base_dn> [-p <port>] [-a <attr>] [-D <binddn>]\n\
400 [-P <password>] [-w <warn_time>] [-c <crit_time>]\n\
401 [-t timeout]%s\n",
402 //(Note: all times are in seconds.)\n",
403 progname,
404 #ifdef HAVE_LDAP_SET_OPTION
405 " [-2|-3] [-4|-6]"
406 #else
407 ""
408 #endif
409 );
410 }