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