LCOV - code coverage report
Current view: top level - dirmngr - dirmngr_ldap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 280 0.0 %
Date: 2016-11-29 15:00:56 Functions: 0 9 0.0 %

          Line data    Source code
       1             : /* dirmngr-ldap.c  -  The LDAP helper for dirmngr.
       2             :  * Copyright (C) 2004 g10 Code GmbH
       3             :  * Copyright (C) 2010 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : 
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <stddef.h>
      26             : #include <stdarg.h>
      27             : #include <string.h>
      28             : #ifdef HAVE_SIGNAL_H
      29             : # include <signal.h>
      30             : #endif
      31             : #include <errno.h>
      32             : #include <assert.h>
      33             : #include <sys/time.h>
      34             : #include <unistd.h>
      35             : #ifndef USE_LDAPWRAPPER
      36             : # include <npth.h>
      37             : #endif
      38             : 
      39             : #ifdef HAVE_W32_SYSTEM
      40             : # include <winsock2.h>
      41             : # include <winldap.h>
      42             : # include <winber.h>
      43             : # include <fcntl.h>
      44             : # include "ldap-url.h"
      45             : #else
      46             :   /* For OpenLDAP, to enable the API that we're using. */
      47             : # define LDAP_DEPRECATED 1
      48             : # include <ldap.h>
      49             : #endif
      50             : 
      51             : 
      52             : #include <gpg-error.h>
      53             : #include "../common/logging.h"
      54             : #include "../common/argparse.h"
      55             : #include "../common/stringhelp.h"
      56             : #include "../common/mischelp.h"
      57             : #include "../common/strlist.h"
      58             : 
      59             : #include "i18n.h"
      60             : #include "util.h"
      61             : #include "../common/init.h"
      62             : 
      63             : /* With the ldap wrapper, there is no need for the npth_unprotect and leave
      64             :    functions; thus we redefine them to nops.  If we are not using the
      65             :    ldap wrapper process we need to include the prototype for our
      66             :    module's main function.  */
      67             : #ifdef USE_LDAPWRAPPER
      68           0 : static void npth_unprotect (void) { }
      69           0 : static void npth_protect (void) { }
      70             : #else
      71             : # include "./ldap-wrapper.h"
      72             : #endif
      73             : 
      74             : #ifdef HAVE_W32CE_SYSTEM
      75             : # include "w32-ldap-help.h"
      76             : # define my_ldap_init(a,b)                      \
      77             :   _dirmngr_ldap_init ((a), (b))
      78             : # define my_ldap_simple_bind_s(a,b,c)           \
      79             :   _dirmngr_ldap_simple_bind_s ((a),(b),(c))
      80             : # define my_ldap_search_st(a,b,c,d,e,f,g,h)     \
      81             :   _dirmngr_ldap_search_st ((a), (b), (c), (d), (e), (f), (g), (h))
      82             : # define my_ldap_first_attribute(a,b,c)         \
      83             :   _dirmngr_ldap_first_attribute ((a),(b),(c))
      84             : # define my_ldap_next_attribute(a,b,c)          \
      85             :   _dirmngr_ldap_next_attribute ((a),(b),(c))
      86             : # define my_ldap_get_values_len(a,b,c)          \
      87             :   _dirmngr_ldap_get_values_len ((a),(b),(c))
      88             : # define my_ldap_free_attr(a)                   \
      89             :   xfree ((a))
      90             : #else
      91             : # define my_ldap_init(a,b)              ldap_init ((a), (b))
      92             : # define my_ldap_simple_bind_s(a,b,c)   ldap_simple_bind_s ((a), (b), (c))
      93             : # define my_ldap_search_st(a,b,c,d,e,f,g,h)     \
      94             :   ldap_search_st ((a), (b), (c), (d), (e), (f), (g), (h))
      95             : # define my_ldap_first_attribute(a,b,c) ldap_first_attribute ((a),(b),(c))
      96             : # define my_ldap_next_attribute(a,b,c)  ldap_next_attribute ((a),(b),(c))
      97             : # define my_ldap_get_values_len(a,b,c)  ldap_get_values_len ((a),(b),(c))
      98             : # define my_ldap_free_attr(a)           ldap_memfree ((a))
      99             : #endif
     100             : 
     101             : #ifdef HAVE_W32_SYSTEM
     102             :  typedef LDAP_TIMEVAL  my_ldap_timeval_t;
     103             : #else
     104             :  typedef struct timeval my_ldap_timeval_t;
     105             : #endif
     106             : 
     107             : #define DEFAULT_LDAP_TIMEOUT 100 /* Arbitrary long timeout. */
     108             : 
     109             : 
     110             : /* Constants for the options.  */
     111             : enum
     112             :   {
     113             :     oQuiet        = 'q',
     114             :     oVerbose      = 'v',
     115             : 
     116             :     oTimeout      = 500,
     117             :     oMulti,
     118             :     oProxy,
     119             :     oHost,
     120             :     oPort,
     121             :     oUser,
     122             :     oPass,
     123             :     oEnvPass,
     124             :     oDN,
     125             :     oFilter,
     126             :     oAttr,
     127             : 
     128             :     oOnlySearchTimeout,
     129             :     oLogWithPID
     130             :   };
     131             : 
     132             : 
     133             : /* The list of options as used by the argparse.c code.  */
     134             : static ARGPARSE_OPTS opts[] = {
     135             :   { oVerbose,  "verbose",   0, N_("verbose") },
     136             :   { oQuiet,    "quiet",     0, N_("be somewhat more quiet") },
     137             :   { oTimeout,  "timeout",   1, N_("|N|set LDAP timeout to N seconds")},
     138             :   { oMulti,    "multi",     0, N_("return all values in"
     139             :                                   " a record oriented format")},
     140             :   { oProxy,    "proxy",     2,
     141             :     N_("|NAME|ignore host part and connect through NAME")},
     142             :   { oHost,     "host",      2, N_("|NAME|connect to host NAME")},
     143             :   { oPort,     "port",      1, N_("|N|connect to port N")},
     144             :   { oUser,     "user",      2, N_("|NAME|use user NAME for authentication")},
     145             :   { oPass,     "pass",      2, N_("|PASS|use password PASS"
     146             :                                   " for authentication")},
     147             :   { oEnvPass,  "env-pass",  0, N_("take password from $DIRMNGR_LDAP_PASS")},
     148             :   { oDN,       "dn",        2, N_("|STRING|query DN STRING")},
     149             :   { oFilter,   "filter",    2, N_("|STRING|use STRING as filter expression")},
     150             :   { oAttr,     "attr",      2, N_("|STRING|return the attribute STRING")},
     151             :   { oOnlySearchTimeout, "only-search-timeout", 0, "@"},
     152             :   { oLogWithPID,"log-with-pid", 0, "@"},
     153             :   { 0, NULL, 0, NULL }
     154             : };
     155             : 
     156             : 
     157             : /* A structure with module options.  This is not a static variable
     158             :    because if we are not build as a standalone binary, each thread
     159             :    using this module needs to handle its own values.  */
     160             : struct my_opt_s
     161             : {
     162             :   int quiet;
     163             :   int verbose;
     164             :   my_ldap_timeval_t timeout;/* Timeout for the LDAP search functions.  */
     165             :   unsigned int alarm_timeout; /* And for the alarm based timeout.  */
     166             :   int multi;
     167             : 
     168             :   estream_t outstream;    /* Send output to this stream.  */
     169             : 
     170             :   /* Note that we can't use const for the strings because ldap_* are
     171             :      not defined that way.  */
     172             :   char *proxy; /* Host and Port override.  */
     173             :   char *user;  /* Authentication user.  */
     174             :   char *pass;  /* Authentication password.  */
     175             :   char *host;  /* Override host.  */
     176             :   int port;    /* Override port.  */
     177             :   char *dn;    /* Override DN.  */
     178             :   char *filter;/* Override filter.  */
     179             :   char *attr;  /* Override attribute.  */
     180             : };
     181             : typedef struct my_opt_s *my_opt_t;
     182             : 
     183             : 
     184             : /* Prototypes.  */
     185             : #ifndef HAVE_W32_SYSTEM
     186             : static void catch_alarm (int dummy);
     187             : #endif
     188             : static int process_url (my_opt_t myopt, const char *url);
     189             : 
     190             : 
     191             : 
     192             : /* Function called by argparse.c to display information.  */
     193             : #ifdef USE_LDAPWRAPPER
     194             : static const char *
     195           0 : my_strusage (int level)
     196             : {
     197             :   const char *p;
     198             : 
     199           0 :   switch(level)
     200             :     {
     201           0 :     case 11: p = "dirmngr_ldap (@GNUPG@)";
     202           0 :       break;
     203           0 :     case 13: p = VERSION; break;
     204           0 :     case 17: p = PRINTABLE_OS_NAME; break;
     205           0 :     case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
     206           0 :     case 49: p = PACKAGE_BUGREPORT; break;
     207             :     case 1:
     208           0 :     case 40: p =
     209             :                _("Usage: dirmngr_ldap [options] [URL] (-h for help)\n");
     210           0 :       break;
     211           0 :     case 41: p =
     212             :           _("Syntax: dirmngr_ldap [options] [URL]\n"
     213             :             "Internal LDAP helper for Dirmngr\n"
     214             :             "Interface and options may change without notice\n");
     215           0 :       break;
     216             : 
     217           0 :     default: p = NULL;
     218             :     }
     219           0 :   return p;
     220             : }
     221             : #endif /*!USE_LDAPWRAPPER*/
     222             : 
     223             : 
     224             : int
     225             : #ifdef USE_LDAPWRAPPER
     226           0 : main (int argc, char **argv)
     227             : #else
     228             : ldap_wrapper_main (char **argv, estream_t outstream)
     229             : #endif
     230             : {
     231             : #ifndef USE_LDAPWRAPPER
     232             :   int argc;
     233             : #endif
     234             :   ARGPARSE_ARGS pargs;
     235           0 :   int any_err = 0;
     236             :   char *p;
     237           0 :   int only_search_timeout = 0;
     238             :   struct my_opt_s my_opt_buffer;
     239           0 :   my_opt_t myopt = &my_opt_buffer;
     240           0 :   char *malloced_buffer1 = NULL;
     241             : 
     242           0 :   memset (&my_opt_buffer, 0, sizeof my_opt_buffer);
     243             : 
     244           0 :   early_system_init ();
     245             : 
     246             : #ifdef USE_LDAPWRAPPER
     247           0 :   set_strusage (my_strusage);
     248           0 :   log_set_prefix ("dirmngr_ldap", GPGRT_LOG_WITH_PREFIX);
     249             : 
     250             :   /* Setup I18N and common subsystems. */
     251           0 :   i18n_init();
     252             : 
     253           0 :   init_common_subsystems (&argc, &argv);
     254             : 
     255           0 :   es_set_binary (es_stdout);
     256           0 :   myopt->outstream = es_stdout;
     257             : #else /*!USE_LDAPWRAPPER*/
     258             :   myopt->outstream = outstream;
     259             :   for (argc=0; argv[argc]; argc++)
     260             :     ;
     261             : #endif /*!USE_LDAPWRAPPER*/
     262             : 
     263             :   /* LDAP defaults */
     264           0 :   myopt->timeout.tv_sec = DEFAULT_LDAP_TIMEOUT;
     265           0 :   myopt->timeout.tv_usec = 0;
     266           0 :   myopt->alarm_timeout = 0;
     267             : 
     268             :   /* Parse the command line.  */
     269           0 :   pargs.argc = &argc;
     270           0 :   pargs.argv = &argv;
     271           0 :   pargs.flags= 1;  /* Do not remove the args. */
     272           0 :   while (arg_parse (&pargs, opts) )
     273             :     {
     274           0 :       switch (pargs.r_opt)
     275             :         {
     276           0 :         case oVerbose: myopt->verbose++; break;
     277           0 :         case oQuiet: myopt->quiet++; break;
     278             :         case oTimeout:
     279           0 :           myopt->timeout.tv_sec = pargs.r.ret_int;
     280           0 :           myopt->timeout.tv_usec = 0;
     281           0 :           myopt->alarm_timeout = pargs.r.ret_int;
     282           0 :           break;
     283           0 :         case oOnlySearchTimeout: only_search_timeout = 1; break;
     284           0 :         case oMulti: myopt->multi = 1; break;
     285           0 :         case oUser: myopt->user = pargs.r.ret_str; break;
     286           0 :         case oPass: myopt->pass = pargs.r.ret_str; break;
     287             :         case oEnvPass:
     288           0 :           myopt->pass = getenv ("DIRMNGR_LDAP_PASS");
     289           0 :           break;
     290           0 :         case oProxy: myopt->proxy = pargs.r.ret_str; break;
     291           0 :         case oHost: myopt->host = pargs.r.ret_str; break;
     292           0 :         case oPort: myopt->port = pargs.r.ret_int; break;
     293           0 :         case oDN:   myopt->dn = pargs.r.ret_str; break;
     294           0 :         case oFilter: myopt->filter = pargs.r.ret_str; break;
     295           0 :         case oAttr: myopt->attr = pargs.r.ret_str; break;
     296             :         case oLogWithPID:
     297             :           {
     298             :             unsigned int oldflags;
     299           0 :             log_get_prefix (&oldflags);
     300           0 :             log_set_prefix (NULL, oldflags | GPGRT_LOG_WITH_PID);
     301             :           }
     302           0 :           break;
     303             : 
     304             :         default :
     305             : #ifdef USE_LDAPWRAPPER
     306           0 :           pargs.err = ARGPARSE_PRINT_ERROR;
     307             : #else
     308             :           pargs.err = ARGPARSE_PRINT_WARNING;  /* No exit() please.  */
     309             : #endif
     310           0 :           break;
     311             :         }
     312             :     }
     313             : 
     314           0 :   if (only_search_timeout)
     315           0 :     myopt->alarm_timeout = 0;
     316             : 
     317           0 :   if (myopt->proxy)
     318             :     {
     319           0 :       malloced_buffer1 = xtrystrdup (myopt->proxy);
     320           0 :       if (!malloced_buffer1)
     321             :         {
     322           0 :           log_error ("error copying string: %s\n", strerror (errno));
     323           0 :           return 1;
     324             :         }
     325           0 :       myopt->host = malloced_buffer1;
     326           0 :       p = strchr (myopt->host, ':');
     327           0 :       if (p)
     328             :         {
     329           0 :           *p++ = 0;
     330           0 :           myopt->port = atoi (p);
     331             :         }
     332           0 :       if (!myopt->port)
     333           0 :         myopt->port = 389;  /* make sure ports gets overridden.  */
     334             :     }
     335             : 
     336           0 :   if (myopt->port < 0 || myopt->port > 65535)
     337           0 :     log_error (_("invalid port number %d\n"), myopt->port);
     338             : 
     339             : #ifdef USE_LDAPWRAPPER
     340           0 :   if (log_get_errorcount (0))
     341           0 :     exit (2);
     342           0 :   if (argc < 1)
     343           0 :     usage (1);
     344             : #else
     345             :   /* All passed arguments should be fine in this case.  */
     346             :   assert (argc);
     347             : #endif
     348             : 
     349             : #ifdef USE_LDAPWRAPPER
     350           0 :   if (myopt->alarm_timeout)
     351             :     {
     352             : #ifndef HAVE_W32_SYSTEM
     353             : # if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
     354             :       struct sigaction act;
     355             : 
     356           0 :       act.sa_handler = catch_alarm;
     357           0 :       sigemptyset (&act.sa_mask);
     358           0 :       act.sa_flags = 0;
     359           0 :       if (sigaction (SIGALRM,&act,NULL))
     360             : # else
     361             :       if (signal (SIGALRM, catch_alarm) == SIG_ERR)
     362             : # endif
     363           0 :           log_fatal ("unable to register timeout handler\n");
     364             : #endif
     365             :     }
     366             : #endif /*USE_LDAPWRAPPER*/
     367             : 
     368           0 :   for (; argc; argc--, argv++)
     369           0 :     if (process_url (myopt, *argv))
     370           0 :       any_err = 1;
     371             : 
     372           0 :   xfree (malloced_buffer1);
     373           0 :   return any_err;
     374             : }
     375             : 
     376             : #ifndef HAVE_W32_SYSTEM
     377             : static void
     378           0 : catch_alarm (int dummy)
     379             : {
     380             :   (void)dummy;
     381           0 :   _exit (10);
     382             : }
     383             : #endif
     384             : 
     385             : static void
     386           0 : set_timeout (my_opt_t myopt)
     387             : {
     388             : #ifdef HAVE_W32_SYSTEM
     389             :   /* FIXME for W32.  */
     390             :   (void)myopt;
     391             : #else
     392           0 :   if (myopt->alarm_timeout)
     393           0 :     alarm (myopt->alarm_timeout);
     394             : #endif
     395           0 : }
     396             : 
     397             : 
     398             : /* Helper for fetch_ldap().  */
     399             : static int
     400           0 : print_ldap_entries (my_opt_t myopt, LDAP *ld, LDAPMessage *msg, char *want_attr)
     401             : {
     402             :   LDAPMessage *item;
     403           0 :   int any = 0;
     404             : 
     405           0 :   for (npth_unprotect (), item = ldap_first_entry (ld, msg), npth_protect ();
     406             :        item;
     407           0 :        npth_unprotect (), item = ldap_next_entry (ld, item), npth_protect ())
     408             :     {
     409             :       BerElement *berctx;
     410             :       char *attr;
     411             : 
     412           0 :       if (myopt->verbose > 1)
     413           0 :         log_info (_("scanning result for attribute '%s'\n"),
     414             :                   want_attr? want_attr : "[all]");
     415             : 
     416           0 :       if (myopt->multi)
     417             :         { /*  Write item marker. */
     418           0 :           if (es_fwrite ("I\0\0\0\0", 5, 1, myopt->outstream) != 1)
     419             :             {
     420           0 :               log_error (_("error writing to stdout: %s\n"),
     421           0 :                          strerror (errno));
     422           0 :               return -1;
     423             :             }
     424             :         }
     425             : 
     426             : 
     427           0 :       for (npth_unprotect (), attr = my_ldap_first_attribute (ld, item, &berctx),
     428           0 :              npth_protect ();
     429             :            attr;
     430           0 :            npth_unprotect (), attr = my_ldap_next_attribute (ld, item, berctx),
     431           0 :              npth_protect ())
     432             :         {
     433             :           struct berval **values;
     434             :           int idx;
     435             : 
     436           0 :           if (myopt->verbose > 1)
     437           0 :             log_info (_("          available attribute '%s'\n"), attr);
     438             : 
     439           0 :           set_timeout (myopt);
     440             : 
     441             :           /* I case we want only one attribute we do a case
     442             :              insensitive compare without the optional extension
     443             :              (i.e. ";binary").  Case insensitive is not really correct
     444             :              but the best we can do.  */
     445           0 :           if (want_attr)
     446             :             {
     447             :               char *cp1, *cp2;
     448             :               int cmpres;
     449             : 
     450           0 :               cp1 = strchr (want_attr, ';');
     451           0 :               if (cp1)
     452           0 :                 *cp1 = 0;
     453           0 :               cp2 = strchr (attr, ';');
     454           0 :               if (cp2)
     455           0 :                 *cp2 = 0;
     456           0 :               cmpres = ascii_strcasecmp (want_attr, attr);
     457           0 :               if (cp1)
     458           0 :                 *cp1 = ';';
     459           0 :               if (cp2)
     460           0 :                 *cp2 = ';';
     461           0 :               if (cmpres)
     462             :                 {
     463           0 :                   my_ldap_free_attr (attr);
     464           0 :                   continue; /* Not found:  Try next attribute.  */
     465             :                 }
     466             :             }
     467             : 
     468           0 :           npth_unprotect ();
     469           0 :           values = my_ldap_get_values_len (ld, item, attr);
     470           0 :           npth_protect ();
     471             : 
     472           0 :           if (!values)
     473             :             {
     474           0 :               if (myopt->verbose)
     475           0 :                 log_info (_("attribute '%s' not found\n"), attr);
     476           0 :               my_ldap_free_attr (attr);
     477           0 :               continue;
     478             :             }
     479             : 
     480           0 :           if (myopt->verbose)
     481             :             {
     482           0 :               log_info (_("found attribute '%s'\n"), attr);
     483           0 :               if (myopt->verbose > 1)
     484           0 :                 for (idx=0; values[idx]; idx++)
     485           0 :                   log_info ("         length[%d]=%d\n",
     486           0 :                             idx, (int)values[0]->bv_len);
     487             : 
     488             :             }
     489             : 
     490           0 :           if (myopt->multi)
     491             :             { /*  Write attribute marker. */
     492             :               unsigned char tmp[5];
     493           0 :               size_t n = strlen (attr);
     494             : 
     495           0 :               tmp[0] = 'A';
     496           0 :               tmp[1] = (n >> 24);
     497           0 :               tmp[2] = (n >> 16);
     498           0 :               tmp[3] = (n >> 8);
     499           0 :               tmp[4] = (n);
     500           0 :               if (es_fwrite (tmp, 5, 1, myopt->outstream) != 1
     501           0 :                   || es_fwrite (attr, n, 1, myopt->outstream) != 1)
     502             :                 {
     503           0 :                   log_error (_("error writing to stdout: %s\n"),
     504           0 :                              strerror (errno));
     505           0 :                   ldap_value_free_len (values);
     506           0 :                   my_ldap_free_attr (attr);
     507           0 :                   ber_free (berctx, 0);
     508           0 :                   return -1;
     509             :                 }
     510             :             }
     511             : 
     512           0 :           for (idx=0; values[idx]; idx++)
     513             :             {
     514           0 :               if (myopt->multi)
     515             :                 { /* Write value marker.  */
     516             :                   unsigned char tmp[5];
     517           0 :                   size_t n = values[0]->bv_len;
     518             : 
     519           0 :                   tmp[0] = 'V';
     520           0 :                   tmp[1] = (n >> 24);
     521           0 :                   tmp[2] = (n >> 16);
     522           0 :                   tmp[3] = (n >> 8);
     523           0 :                   tmp[4] = (n);
     524             : 
     525           0 :                   if (es_fwrite (tmp, 5, 1, myopt->outstream) != 1)
     526             :                     {
     527           0 :                       log_error (_("error writing to stdout: %s\n"),
     528           0 :                                  strerror (errno));
     529           0 :                       ldap_value_free_len (values);
     530           0 :                       my_ldap_free_attr (attr);
     531           0 :                       ber_free (berctx, 0);
     532           0 :                       return -1;
     533             :                     }
     534             :                 }
     535             : 
     536           0 :               if (es_fwrite (values[0]->bv_val, values[0]->bv_len,
     537             :                              1, myopt->outstream) != 1)
     538             :                 {
     539           0 :                   log_error (_("error writing to stdout: %s\n"),
     540           0 :                              strerror (errno));
     541           0 :                   ldap_value_free_len (values);
     542           0 :                   my_ldap_free_attr (attr);
     543           0 :                   ber_free (berctx, 0);
     544           0 :                   return -1;
     545             :                 }
     546             : 
     547           0 :               any = 1;
     548           0 :               if (!myopt->multi)
     549           0 :                 break; /* Print only the first value.  */
     550             :             }
     551           0 :           ldap_value_free_len (values);
     552           0 :           my_ldap_free_attr (attr);
     553           0 :           if (want_attr || !myopt->multi)
     554             :             break; /* We only want to return the first attribute.  */
     555             :         }
     556           0 :       ber_free (berctx, 0);
     557             :     }
     558             : 
     559           0 :   if (myopt->verbose > 1 && any)
     560           0 :     log_info ("result has been printed\n");
     561             : 
     562           0 :   return any?0:-1;
     563             : }
     564             : 
     565             : 
     566             : 
     567             : /* Helper for the URL based LDAP query. */
     568             : static int
     569           0 : fetch_ldap (my_opt_t myopt, const char *url, const LDAPURLDesc *ludp)
     570             : {
     571             :   LDAP *ld;
     572             :   LDAPMessage *msg;
     573           0 :   int rc = 0;
     574             :   char *host, *dn, *filter, *attrs[2], *attr;
     575             :   int port;
     576             :   int ret;
     577             : 
     578           0 :   host     = myopt->host?   myopt->host   : ludp->lud_host;
     579           0 :   port     = myopt->port?   myopt->port   : ludp->lud_port;
     580           0 :   dn       = myopt->dn?     myopt->dn     : ludp->lud_dn;
     581           0 :   filter   = myopt->filter? myopt->filter : ludp->lud_filter;
     582           0 :   attrs[0] = myopt->attr?   myopt->attr   : ludp->lud_attrs? ludp->lud_attrs[0]:NULL;
     583           0 :   attrs[1] = NULL;
     584           0 :   attr = attrs[0];
     585             : 
     586           0 :   if (!port)
     587           0 :     port = (ludp->lud_scheme && !strcmp (ludp->lud_scheme, "ldaps"))? 636:389;
     588             : 
     589           0 :   if (myopt->verbose)
     590             :     {
     591           0 :       log_info (_("processing url '%s'\n"), url);
     592           0 :       if (myopt->user)
     593           0 :         log_info (_("          user '%s'\n"), myopt->user);
     594           0 :       if (myopt->pass)
     595           0 :         log_info (_("          pass '%s'\n"), *myopt->pass?"*****":"");
     596           0 :       if (host)
     597           0 :         log_info (_("          host '%s'\n"), host);
     598           0 :       log_info (_("          port %d\n"), port);
     599           0 :       if (dn)
     600           0 :         log_info (_("            DN '%s'\n"), dn);
     601           0 :       if (filter)
     602           0 :         log_info (_("        filter '%s'\n"), filter);
     603           0 :       if (myopt->multi && !myopt->attr && ludp->lud_attrs)
     604           0 :         {
     605             :           int i;
     606           0 :           for (i=0; ludp->lud_attrs[i]; i++)
     607           0 :             log_info (_("          attr '%s'\n"), ludp->lud_attrs[i]);
     608             :         }
     609           0 :       else if (attr)
     610           0 :         log_info (_("          attr '%s'\n"), attr);
     611             :     }
     612             : 
     613             : 
     614           0 :   if (!host || !*host)
     615             :     {
     616           0 :       log_error (_("no host name in '%s'\n"), url);
     617           0 :       return -1;
     618             :     }
     619           0 :   if (!myopt->multi && !attr)
     620             :     {
     621           0 :       log_error (_("no attribute given for query '%s'\n"), url);
     622           0 :       return -1;
     623             :     }
     624             : 
     625           0 :   if (!myopt->multi && !myopt->attr
     626           0 :       && ludp->lud_attrs && ludp->lud_attrs[0] && ludp->lud_attrs[1])
     627           0 :     log_info (_("WARNING: using first attribute only\n"));
     628             : 
     629             : 
     630           0 :   set_timeout (myopt);
     631           0 :   npth_unprotect ();
     632           0 :   ld = my_ldap_init (host, port);
     633           0 :   npth_protect ();
     634           0 :   if (!ld)
     635             :     {
     636           0 :       log_error (_("LDAP init to '%s:%d' failed: %s\n"),
     637           0 :                  host, port, strerror (errno));
     638           0 :       return -1;
     639             :     }
     640           0 :   npth_unprotect ();
     641             :   /* Fixme:  Can we use MYOPT->user or is it shared with other theeads?.  */
     642           0 :   ret = my_ldap_simple_bind_s (ld, myopt->user, myopt->pass);
     643           0 :   npth_protect ();
     644             : #ifdef LDAP_VERSION3
     645           0 :   if (ret == LDAP_PROTOCOL_ERROR)
     646             :     {
     647             :       /* Protocol error could mean that the server only supports v3. */
     648           0 :       int version = LDAP_VERSION3;
     649           0 :       if (myopt->verbose)
     650           0 :         log_info ("protocol error; retrying bind with v3 protocol\n");
     651           0 :       npth_unprotect ();
     652           0 :       ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version);
     653           0 :       ret = my_ldap_simple_bind_s (ld, myopt->user, myopt->pass);
     654           0 :       npth_protect ();
     655             :     }
     656             : #endif
     657           0 :   if (ret)
     658             :     {
     659           0 :       log_error (_("binding to '%s:%d' failed: %s\n"),
     660             :                  host, port, ldap_err2string (ret));
     661           0 :       ldap_unbind (ld);
     662           0 :       return -1;
     663             :     }
     664             : 
     665           0 :   set_timeout (myopt);
     666           0 :   npth_unprotect ();
     667           0 :   rc = my_ldap_search_st (ld, dn, ludp->lud_scope, filter,
     668             :                           myopt->multi && !myopt->attr && ludp->lud_attrs?
     669             :                           ludp->lud_attrs:attrs,
     670             :                           0,
     671             :                           &myopt->timeout, &msg);
     672           0 :   npth_protect ();
     673           0 :   if (rc == LDAP_SIZELIMIT_EXCEEDED && myopt->multi)
     674             :     {
     675           0 :       if (es_fwrite ("E\0\0\0\x09truncated", 14, 1, myopt->outstream) != 1)
     676             :         {
     677           0 :           log_error (_("error writing to stdout: %s\n"), strerror (errno));
     678           0 :           return -1;
     679             :         }
     680             :     }
     681           0 :   else if (rc)
     682             :     {
     683             : #ifdef HAVE_W32CE_SYSTEM
     684             :       log_error ("searching '%s' failed: %d\n", url, rc);
     685             : #else
     686           0 :       log_error (_("searching '%s' failed: %s\n"),
     687             :                  url, ldap_err2string (rc));
     688             : #endif
     689           0 :       if (rc != LDAP_NO_SUCH_OBJECT)
     690             :         {
     691             :           /* FIXME: Need deinit (ld)?  */
     692             :           /* Hmmm: Do we need to released MSG in case of an error? */
     693           0 :           return -1;
     694             :         }
     695             :     }
     696             : 
     697           0 :   rc = print_ldap_entries (myopt, ld, msg, myopt->multi? NULL:attr);
     698             : 
     699           0 :   ldap_msgfree (msg);
     700           0 :   ldap_unbind (ld);
     701           0 :   return rc;
     702             : }
     703             : 
     704             : 
     705             : 
     706             : 
     707             : /* Main processing.  Take the URL and run the LDAP query. The result
     708             :    is printed to stdout, errors are logged to the log stream. */
     709             : static int
     710           0 : process_url (my_opt_t myopt, const char *url)
     711             : {
     712             :   int rc;
     713           0 :   LDAPURLDesc *ludp = NULL;
     714             : 
     715             : 
     716           0 :   if (!ldap_is_ldap_url (url))
     717             :     {
     718           0 :       log_error (_("'%s' is not an LDAP URL\n"), url);
     719           0 :       return -1;
     720             :     }
     721             : 
     722           0 :   if (ldap_url_parse (url, &ludp))
     723             :     {
     724           0 :       log_error (_("'%s' is an invalid LDAP URL\n"), url);
     725           0 :       return -1;
     726             :     }
     727             : 
     728           0 :   rc = fetch_ldap (myopt, url, ludp);
     729             : 
     730           0 :   ldap_free_urldesc (ludp);
     731           0 :   return rc;
     732             : }

Generated by: LCOV version 1.11