Back to index

nagios-plugins  1.4.16
check_ldap.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002 * 
00003 * Nagios check_ldap plugin
00004 * 
00005 * License: GPL
00006 * Copyright (c) 2000-2008 Nagios Plugins Development Team
00007 * 
00008 * Description:
00009 * 
00010 * This file contains the check_ldap plugin
00011 * 
00012 * 
00013 * This program is free software: you can redistribute it and/or modify
00014 * it under the terms of the GNU General Public License as published by
00015 * the Free Software Foundation, either version 3 of the License, or
00016 * (at your option) any later version.
00017 * 
00018 * This program is distributed in the hope that it will be useful,
00019 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021 * GNU General Public License for more details.
00022 * 
00023 * You should have received a copy of the GNU General Public License
00024 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025 * 
00026 * 
00027 *****************************************************************************/
00028 
00029 /* progname may be check_ldaps */
00030 char *progname = "check_ldap";
00031 const char *copyright = "2000-2008";
00032 const char *email = "nagiosplug-devel@lists.sourceforge.net";
00033 
00034 #include "common.h"
00035 #include "netutils.h"
00036 #include "utils.h"
00037 
00038 #include <lber.h>
00039 #define LDAP_DEPRECATED 1
00040 #include <ldap.h>
00041 
00042 enum {
00043        UNDEFINED = 0,
00044 #ifdef HAVE_LDAP_SET_OPTION
00045        DEFAULT_PROTOCOL = 2,
00046 #endif
00047        DEFAULT_PORT = 389
00048 };
00049 
00050 int process_arguments (int, char **);
00051 int validate_arguments (void);
00052 void print_help (void);
00053 void print_usage (void);
00054 
00055 char ld_defattr[] = "(objectclass=*)";
00056 char *ld_attr = ld_defattr;
00057 char *ld_host = NULL;
00058 char *ld_base = NULL;
00059 char *ld_passwd = NULL;
00060 char *ld_binddn = NULL;
00061 int ld_port = -1;
00062 #ifdef HAVE_LDAP_SET_OPTION
00063 int ld_protocol = DEFAULT_PROTOCOL;
00064 #endif
00065 #ifndef LDAP_OPT_SUCCESS
00066 # define LDAP_OPT_SUCCESS LDAP_SUCCESS
00067 #endif
00068 double warn_time = UNDEFINED;
00069 double crit_time = UNDEFINED;
00070 struct timeval tv;
00071 int starttls = FALSE;
00072 int ssl_on_connect = FALSE;
00073 int verbose = 0;
00074 
00075 /* for ldap tls */
00076 
00077 char *SERVICE = "LDAP";
00078 
00079 int
00080 main (int argc, char *argv[])
00081 {
00082 
00083        LDAP *ld;
00084        LDAPMessage *result;
00085 
00086        /* should be  int result = STATE_UNKNOWN; */
00087 
00088        int status = STATE_UNKNOWN;
00089        long microsec;
00090        double elapsed_time;
00091 
00092        /* for ldap tls */
00093 
00094        int tls;
00095        int version=3;
00096 
00097        setlocale (LC_ALL, "");
00098        bindtextdomain (PACKAGE, LOCALEDIR);
00099        textdomain (PACKAGE);
00100 
00101        if (strstr(argv[0],"check_ldaps")) {
00102               asprintf (&progname, "check_ldaps");
00103        }
00104 
00105        /* Parse extra opts if any */
00106        argv=np_extra_opts (&argc, argv, progname);
00107 
00108        if (process_arguments (argc, argv) == ERROR)
00109               usage4 (_("Could not parse arguments"));
00110 
00111        if (strstr(argv[0],"check_ldaps") && ! starttls && ! ssl_on_connect)
00112               starttls = TRUE;
00113 
00114        /* initialize alarm signal handling */
00115        signal (SIGALRM, socket_timeout_alarm_handler);
00116 
00117        /* set socket timeout */
00118        alarm (socket_timeout);
00119 
00120        /* get the start time */
00121        gettimeofday (&tv, NULL);
00122 
00123        /* initialize ldap */
00124 #ifdef HAVE_LDAP_INIT
00125        if (!(ld = ldap_init (ld_host, ld_port))) {
00126               printf ("Could not connect to the server at port %i\n", ld_port);
00127               return STATE_CRITICAL;
00128        }
00129 #else
00130        if (!(ld = ldap_open (ld_host, ld_port))) {
00131               if (verbose)
00132                      ldap_perror(ld, "ldap_open");
00133               printf (_("Could not connect to the server at port %i\n"), ld_port);
00134               return STATE_CRITICAL;
00135        }
00136 #endif /* HAVE_LDAP_INIT */
00137 
00138 #ifdef HAVE_LDAP_SET_OPTION
00139        /* set ldap options */
00140        if (ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &ld_protocol) !=
00141                      LDAP_OPT_SUCCESS ) {
00142               printf(_("Could not set protocol version %d\n"), ld_protocol);
00143               return STATE_CRITICAL;
00144        }
00145 #endif
00146 
00147        if (ld_port == LDAPS_PORT || ssl_on_connect) {
00148               asprintf (&SERVICE, "LDAPS");
00149 #if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)
00150               /* ldaps: set option tls */
00151               tls = LDAP_OPT_X_TLS_HARD;
00152 
00153               if (ldap_set_option (ld, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
00154               {
00155                      if (verbose)
00156                             ldap_perror(ld, "ldaps_option");
00157                      printf (_("Could not init TLS at port %i!\n"), ld_port);
00158                      return STATE_CRITICAL;
00159               }
00160 #else
00161               printf (_("TLS not supported by the libraries!\n"));
00162               return STATE_CRITICAL;
00163 #endif /* LDAP_OPT_X_TLS */
00164        } else if (starttls) {
00165               asprintf (&SERVICE, "LDAP-TLS");
00166 #if defined(HAVE_LDAP_SET_OPTION) && defined(HAVE_LDAP_START_TLS_S)
00167               /* ldap with startTLS: set option version */
00168               if (ldap_get_option(ld,LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS )
00169               {
00170                      if (version < LDAP_VERSION3)
00171                      {
00172                             version = LDAP_VERSION3;
00173                             ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
00174                      }
00175               }
00176               /* call start_tls */
00177               if (ldap_start_tls_s(ld, NULL, NULL) != LDAP_SUCCESS)
00178               {
00179                      if (verbose)
00180                             ldap_perror(ld, "ldap_start_tls");
00181                      printf (_("Could not init startTLS at port %i!\n"), ld_port);
00182                      return STATE_CRITICAL;
00183               }
00184 #else
00185               printf (_("startTLS not supported by the library, needs LDAPv3!\n"));
00186               return STATE_CRITICAL;
00187 #endif /* HAVE_LDAP_START_TLS_S */
00188        }
00189 
00190        /* bind to the ldap server */
00191        if (ldap_bind_s (ld, ld_binddn, ld_passwd, LDAP_AUTH_SIMPLE) !=
00192                      LDAP_SUCCESS) {
00193               if (verbose)
00194                      ldap_perror(ld, "ldap_bind");
00195               printf (_("Could not bind to the LDAP server\n"));
00196               return STATE_CRITICAL;
00197        }
00198 
00199        /* do a search of all objectclasses in the base dn */
00200        if (ldap_search_s (ld, ld_base, LDAP_SCOPE_BASE, ld_attr, NULL, 0, &result)
00201                      != LDAP_SUCCESS) {
00202               if (verbose)
00203                      ldap_perror(ld, "ldap_search");
00204               printf (_("Could not search/find objectclasses in %s\n"), ld_base);
00205               return STATE_CRITICAL;
00206        }
00207 
00208        /* unbind from the ldap server */
00209        ldap_unbind (ld);
00210 
00211        /* reset the alarm handler */
00212        alarm (0);
00213 
00214        /* calcutate the elapsed time and compare to thresholds */
00215 
00216        microsec = deltime (tv);
00217        elapsed_time = (double)microsec / 1.0e6;
00218 
00219        if (crit_time!=UNDEFINED && elapsed_time>crit_time)
00220               status = STATE_CRITICAL;
00221        else if (warn_time!=UNDEFINED && elapsed_time>warn_time)
00222               status = STATE_WARNING;
00223        else
00224               status = STATE_OK;
00225 
00226        /* print out the result */
00227        printf (_("LDAP %s - %.3f seconds response time|%s\n"),
00228                state_text (status),
00229                elapsed_time,
00230                fperfdata ("time", elapsed_time, "s",
00231                          (int)warn_time, warn_time,
00232                          (int)crit_time, crit_time,
00233                          TRUE, 0, FALSE, 0));
00234 
00235        return status;
00236 }
00237 
00238 /* process command-line arguments */
00239 int
00240 process_arguments (int argc, char **argv)
00241 {
00242        int c;
00243 
00244        int option = 0;
00245        /* initialize the long option struct */
00246        static struct option longopts[] = {
00247               {"help", no_argument, 0, 'h'},
00248               {"version", no_argument, 0, 'V'},
00249               {"timeout", required_argument, 0, 't'},
00250               {"hostname", required_argument, 0, 'H'},
00251               {"base", required_argument, 0, 'b'},
00252               {"attr", required_argument, 0, 'a'},
00253               {"bind", required_argument, 0, 'D'},
00254               {"pass", required_argument, 0, 'P'},
00255 #ifdef HAVE_LDAP_SET_OPTION
00256               {"ver2", no_argument, 0, '2'},
00257               {"ver3", no_argument, 0, '3'},
00258 #endif
00259               {"starttls", no_argument, 0, 'T'},
00260               {"ssl", no_argument, 0, 'S'},
00261               {"use-ipv4", no_argument, 0, '4'},
00262               {"use-ipv6", no_argument, 0, '6'},
00263               {"port", required_argument, 0, 'p'},
00264               {"warn", required_argument, 0, 'w'},
00265               {"crit", required_argument, 0, 'c'},
00266               {"verbose", no_argument, 0, 'v'},
00267               {0, 0, 0, 0}
00268        };
00269 
00270        if (argc < 2)
00271               return ERROR;
00272 
00273        for (c = 1; c < argc; c++) {
00274               if (strcmp ("-to", argv[c]) == 0)
00275                      strcpy (argv[c], "-t");
00276        }
00277 
00278        while (1) {
00279               c = getopt_long (argc, argv, "hvV234TS6t:c:w:H:b:p:a:D:P:", longopts, &option);
00280 
00281               if (c == -1 || c == EOF)
00282                      break;
00283 
00284               switch (c) {
00285               case 'h':                                                             /* help */
00286                      print_help ();
00287                      exit (STATE_OK);
00288               case 'V':                                                             /* version */
00289                      print_revision (progname, NP_VERSION);
00290                      exit (STATE_OK);
00291               case 't':                                                             /* timeout period */
00292                      if (!is_intnonneg (optarg))
00293                             usage2 (_("Timeout interval must be a positive integer"), optarg);
00294                      else
00295                             socket_timeout = atoi (optarg);
00296                      break;
00297               case 'H':
00298                      ld_host = optarg;
00299                      break;
00300               case 'b':
00301                      ld_base = optarg;
00302                      break;
00303               case 'p':
00304                      ld_port = atoi (optarg);
00305                      break;
00306               case 'a':
00307                      ld_attr = optarg;
00308                      break;
00309               case 'D':
00310                      ld_binddn = optarg;
00311                      break;
00312               case 'P':
00313                      ld_passwd = optarg;
00314                      break;
00315               case 'w':
00316                      warn_time = strtod (optarg, NULL);
00317                      break;
00318               case 'c':
00319                      crit_time = strtod (optarg, NULL);
00320                      break;
00321 #ifdef HAVE_LDAP_SET_OPTION
00322               case '2':
00323                      ld_protocol = 2;
00324                      break;
00325               case '3':
00326                      ld_protocol = 3;
00327                      break;
00328 #endif
00329               case '4':
00330                      address_family = AF_INET;
00331                      break;
00332               case 'v':
00333                      verbose++;
00334                      break;
00335               case 'T':
00336                      if (! ssl_on_connect)
00337                             starttls = TRUE;
00338                      else
00339                             usage_va(_("%s cannot be combined with %s"), "-T/--starttls", "-S/--ssl");
00340                      break;
00341               case 'S':
00342                      if (! starttls) {
00343                             ssl_on_connect = TRUE;
00344                             if (ld_port == -1)
00345                                    ld_port = LDAPS_PORT;
00346                      } else
00347                             usage_va(_("%s cannot be combined with %s"), "-S/--ssl", "-T/--starttls");
00348                      break;
00349               case '6':
00350 #ifdef USE_IPV6
00351                      address_family = AF_INET6;
00352 #else
00353                      usage (_("IPv6 support not available\n"));
00354 #endif
00355                      break;
00356               default:
00357                      usage5 ();
00358               }
00359        }
00360 
00361        c = optind;
00362        if (ld_host == NULL && is_host(argv[c]))
00363               ld_host = strdup (argv[c++]);
00364 
00365        if (ld_base == NULL && argv[c])
00366               ld_base = strdup (argv[c++]);
00367 
00368        if (ld_port == -1)
00369               ld_port = DEFAULT_PORT;
00370 
00371        return validate_arguments ();
00372 }
00373 
00374 
00375 int
00376 validate_arguments ()
00377 {
00378        if (ld_host==NULL || strlen(ld_host)==0)
00379               usage4 (_("Please specify the host name\n"));
00380 
00381        if (ld_base==NULL)
00382               usage4 (_("Please specify the LDAP base\n"));
00383 
00384        return OK;
00385 }
00386 
00387 
00388 void
00389 print_help (void)
00390 {
00391        char *myport;
00392        asprintf (&myport, "%d", DEFAULT_PORT);
00393 
00394        print_revision (progname, NP_VERSION);
00395 
00396        printf ("Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)\n");
00397        printf (COPYRIGHT, copyright, email);
00398 
00399        printf ("\n\n");
00400 
00401        print_usage ();
00402 
00403        printf (UT_HELP_VRSN);
00404        printf (UT_EXTRA_OPTS);
00405 
00406        printf (UT_HOST_PORT, 'p', myport);
00407 
00408        printf (UT_IPv46);
00409 
00410        printf (" %s\n", "-a [--attr]");
00411   printf ("    %s\n", _("ldap attribute to search (default: \"(objectclass=*)\""));
00412   printf (" %s\n", "-b [--base]");
00413   printf ("    %s\n", _("ldap base (eg. ou=my unit, o=my org, c=at"));
00414   printf (" %s\n", "-D [--bind]");
00415   printf ("    %s\n", _("ldap bind DN (if required)"));
00416   printf (" %s\n", "-P [--pass]");
00417   printf ("    %s\n", _("ldap password (if required)"));
00418   printf (" %s\n", "-T [--starttls]");
00419   printf ("    %s\n", _("use starttls mechanism introduced in protocol version 3"));
00420   printf (" %s\n", "-S [--ssl]");
00421   printf ("    %s %i\n", _("use ldaps (ldap v2 ssl method). this also sets the default port to"), LDAPS_PORT);
00422 
00423 #ifdef HAVE_LDAP_SET_OPTION
00424        printf (" %s\n", "-2 [--ver2]");
00425   printf ("    %s\n", _("use ldap protocol version 2"));
00426   printf (" %s\n", "-3 [--ver3]");
00427   printf ("    %s\n", _("use ldap protocol version 3"));
00428   printf ("    (%s %d)\n", _("default protocol version:"), DEFAULT_PROTOCOL);
00429 #endif
00430 
00431        printf (UT_WARN_CRIT);
00432 
00433        printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
00434 
00435        printf (UT_VERBOSE);
00436 
00437        printf ("\n");
00438        printf ("%s\n", _("Notes:"));
00439        printf (" %s\n", _("If this plugin is called via 'check_ldaps', method 'STARTTLS' will be"));
00440        printf (_(" implied (using default port %i) unless --port=636 is specified. In that case\n"), DEFAULT_PORT);
00441        printf (" %s\n", _("'SSL on connect' will be used no matter how the plugin was called."));
00442        printf (" %s\n", _("This detection is deprecated, please use 'check_ldap' with the '--starttls' or '--ssl' flags"));
00443        printf (" %s\n", _("to define the behaviour explicitly instead."));
00444 
00445        printf (UT_SUPPORT);
00446 }
00447 
00448 /* todo
00449 * add option -4 and -6 to the long manual
00450 *
00451 */
00452 
00453 void
00454 print_usage (void)
00455 {
00456   printf ("%s\n", _("Usage:"));
00457        printf (" %s -H <host> -b <base_dn> [-p <port>] [-a <attr>] [-D <binddn>]",progname);
00458   printf ("\n       [-P <password>] [-w <warn_time>] [-c <crit_time>] [-t timeout]%s\n",
00459 #ifdef HAVE_LDAP_SET_OPTION
00460                      "\n       [-2|-3] [-4|-6]"
00461 #else
00462                      ""
00463 #endif
00464                      );
00465 }