"Fossies" - the Fresh Open Source Software Archive

Member "nss_ldap-265/ldap-sldap.c" (6 Nov 2009, 27553 Bytes) of package /linux/privat/old/nss_ldap-265.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* Copyright (C) 2006 Luke Howard.
    2    This file is part of the nss_ldap library.
    3    Contributed by Luke Howard, <lukeh@padl.com>, 2006.
    4 
    5    The nss_ldap library is free software; you can redistribute it and/or
    6    modify it under the terms of the GNU Library General Public License as
    7    published by the Free Software Foundation; either version 2 of the
    8    License, or (at your option) any later version.
    9 
   10    The nss_ldap library is distributed in the hope that it will be useful,
   11    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13    Library General Public License for more details.
   14 
   15    You should have received a copy of the GNU Library General Public
   16    License along with the nss_ldap library; see the file COPYING.LIB.  If not,
   17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   18    Boston, MA 02111-1307, USA.
   19 
   20    $Id: ldap-sldap.c,v 2.14 2009/11/06 10:15:26 lukeh Exp $
   21  */
   22 
   23 
   24 static char rcsId[] =
   25   "$Id: ldap-sldap.c,v 2.14 2009/11/06 10:15:26 lukeh Exp $";
   26 
   27 #include "config.h"
   28 
   29 #ifdef HAVE_PORT_BEFORE_H
   30 #include <port_before.h>
   31 #endif
   32 
   33 #if defined(HAVE_THREAD_H) && !defined(_AIX)
   34 #include <thread.h>
   35 #elif defined(HAVE_PTHREAD_H)
   36 #include <pthread.h>
   37 #endif
   38 
   39 #include <stdio.h>
   40 #include <stdlib.h>
   41 #include <string.h>
   42 #include <netdb.h>
   43 #include <assert.h>
   44 
   45 #ifdef HAVE_LBER_H
   46 #include <lber.h>
   47 #endif
   48 #ifdef HAVE_LDAP_H
   49 #include <ldap.h>
   50 #endif
   51 
   52 #include <sys/types.h>
   53 #include <sys/socket.h>
   54 #ifdef HAVE_NET_ROUTE_H
   55 #include <net/route.h>
   56 #endif
   57 #include <net/if.h>
   58 #include <netinet/in.h>
   59 
   60 #include "ldap-nss.h"
   61 #include "ldap-automount.h"
   62 #include "ldap-sldap.h"
   63 #include "util.h"
   64 
   65 #ifdef HAVE_PORT_AFTER_H
   66 #include <port_after.h>
   67 #endif
   68 
   69 #ifdef HAVE_NSSWITCH_H
   70 
   71 /*
   72  * This implements enough of the Solaris libsldap interface in order
   73  * for the automounter to work.
   74  */
   75 
   76 static ns_ldap_return_code __ns_ldap_initResult (ns_ldap_result_t ** pResult);
   77 static ns_ldap_return_code __ns_ldap_initSearch (ns_ldap_cookie_t * cookie);
   78 static ldap_map_selector_t __ns_ldap_str2selector (const char *map);
   79 static ns_ldap_return_code __ns_ldap_unmapObjectClasses (ns_ldap_cookie_t *
   80                              cookie,
   81                              char **mappedClasses,
   82                              char
   83                              ***pOrigClasses);
   84 
   85 static const char *
   86 NS_LDAP_ERR2STR (ns_ldap_return_code err)
   87 {
   88   char *str = NULL;
   89 
   90   __ns_ldap_err2str (err, &str);
   91 
   92   return str;
   93 }
   94 
   95 static void **
   96 __ns_ldap_makeStringParam (const char *string)
   97 {
   98   void **p;
   99 
  100   p = (void **) malloc (2 * sizeof (void *));
  101   if (p == NULL)
  102     {
  103       return NULL;
  104     }
  105   p[0] = strdup (string);
  106   if (p[0] == NULL)
  107     {
  108       free (p);
  109       return NULL;
  110     }
  111   p[1] = NULL;
  112 
  113   return p;
  114 }
  115 
  116 char **
  117 __ns_ldap_getMappedAttributes (const char *service, const char *attribute)
  118 {
  119   const char *mapped;
  120 
  121   mapped = _nss_ldap_map_at (__ns_ldap_str2selector (service), attribute);
  122   if (mapped == NULL)
  123     {
  124       return NULL;
  125     }
  126 
  127   return (char **) __ns_ldap_makeStringParam (mapped);
  128 }
  129 
  130 char **
  131 __ns_ldap_getMappedObjectClass (const char *service, const char *objectClass)
  132 {
  133   const char *mapped;
  134 
  135   mapped = _nss_ldap_map_oc (__ns_ldap_str2selector (service), objectClass);
  136   if (mapped == NULL)
  137     {
  138       return NULL;
  139     }
  140 
  141   return (char **) __ns_ldap_makeStringParam (mapped);
  142 }
  143 
  144 static ns_ldap_return_code
  145 __ns_ldap_mapError (NSS_STATUS error)
  146 {
  147   ns_ldap_return_code code;
  148 
  149   switch (error)
  150     {
  151     case NSS_SUCCESS:
  152       code = NS_LDAP_SUCCESS;
  153       break;
  154     case NSS_TRYAGAIN:
  155       code = NS_LDAP_MEMORY;
  156       break;
  157     case NSS_NOTFOUND:
  158       code = NS_LDAP_NOTFOUND;
  159       break;
  160     case NSS_UNAVAIL:
  161     default:
  162       code = NS_LDAP_OP_FAILED;
  163       break;
  164     }
  165 
  166   return code;
  167 }
  168 
  169 static ns_ldap_return_code
  170 __ns_ldap_mapErrorDetail (ns_ldap_return_code code, ns_ldap_error_t ** errorp)
  171 {
  172   char *m = NULL;
  173   char *s = NULL;
  174 
  175   *errorp = (ns_ldap_error_t *) calloc (1, sizeof (ns_ldap_error_t));
  176   if (*errorp == NULL)
  177     {
  178       return NS_LDAP_MEMORY;
  179     }
  180 
  181   (*errorp)->status = _nss_ldap_get_ld_errno (&m, &s);
  182   (*errorp)->message = (m != NULL) ? strdup (m) : NULL;
  183 
  184   return code;
  185 }
  186 
  187 ns_ldap_return_code
  188 __ns_ldap_freeError (ns_ldap_error_t ** errorp)
  189 {
  190   if (errorp == NULL)
  191     {
  192       return NS_LDAP_INVALID_PARAM;
  193     }
  194   if (*errorp != NULL)
  195     {
  196       if ((*errorp)->message != NULL)
  197     {
  198       free ((*errorp)->message);
  199       (*errorp)->message = NULL;
  200     }
  201       free (*errorp);
  202       *errorp = NULL;
  203     }
  204   return NS_LDAP_SUCCESS;
  205 }
  206 
  207 ns_ldap_return_code
  208 __ns_ldap_freeParam (void ***data)
  209 {
  210   void **p;
  211 
  212   if (*data != NULL)
  213     {
  214       for (p = *data; *p != NULL; p++)
  215     {
  216       free (*p);
  217       *p = NULL;
  218     }
  219       free (*data);
  220       *data = NULL;
  221     }
  222 
  223   return NS_LDAP_SUCCESS;
  224 }
  225 
  226 
  227 ns_ldap_return_code
  228 __ns_ldap_getParam (const ParamIndexType type, void ***data,
  229             ns_ldap_error_t ** errorp)
  230 {
  231   ns_ldap_return_code ret;
  232 
  233   *errorp = NULL;
  234 
  235   debug ("==> __ns_ldap_getParam (param=%d)", type);
  236 
  237   switch (type)
  238     {
  239     case NS_LDAP_FILE_VERSION_P:
  240       *data = __ns_ldap_makeStringParam (NS_LDAP_VERSION);
  241       ret = NS_LDAP_SUCCESS;
  242       break;
  243     default:
  244       ret = NS_LDAP_INVALID_PARAM;
  245       break;
  246     }
  247 
  248   debug ("<== __ns_ldap_getParam (ret=%s)", NS_LDAP_ERR2STR (ret));
  249 
  250   return ret;
  251 }
  252 
  253 ns_ldap_return_code
  254 __ns_ldap_freeAttr (ns_ldap_attr_t ** pAttr)
  255 {
  256   int i;
  257   ns_ldap_attr_t *attr = *pAttr;
  258 
  259   if (attr != NULL)
  260     {
  261       if (attr->attrname != NULL)
  262     {
  263       free (attr->attrname);
  264     }
  265       if (attr->attrvalue != NULL)
  266     {
  267       for (i = 0; i < attr->value_count; i++)
  268         {
  269           free (attr->attrvalue[i]);
  270         }
  271       free (attr->attrvalue);
  272     }
  273     }
  274 
  275   return NS_LDAP_SUCCESS;
  276 }
  277 
  278 ns_ldap_return_code
  279 __ns_ldap_freeEntry (ns_ldap_entry_t ** pentry)
  280 {
  281   int i;
  282   ns_ldap_entry_t *entry = *pentry;
  283 
  284   if (entry != NULL)
  285     {
  286       if (entry->attr_pair != NULL)
  287     {
  288       for (i = 0; i < entry->attr_count; i++)
  289         {
  290           __ns_ldap_freeAttr (&entry->attr_pair[i]);
  291         }
  292       free (entry->attr_pair);
  293     }
  294       free (entry);
  295       *pentry = NULL;
  296     }
  297 
  298   return NS_LDAP_SUCCESS;
  299 }
  300 
  301 ns_ldap_return_code
  302 __ns_ldap_freeResult (ns_ldap_result_t ** pResult)
  303 {
  304   ns_ldap_result_t *result;
  305   ns_ldap_entry_t *entry, *next = NULL;
  306 
  307   if (pResult == NULL)
  308     {
  309       return NS_LDAP_INVALID_PARAM;
  310     }
  311 
  312   result = *pResult;
  313   if (result == NULL)
  314     {
  315       return NS_LDAP_SUCCESS;
  316     }
  317 
  318   entry = result->entry;
  319 
  320   while (entry != NULL)
  321     {
  322       next = entry->next;
  323       __ns_ldap_freeEntry (&entry);
  324       entry = next;
  325     }
  326 
  327   free (result);
  328   *pResult = NULL;
  329 
  330   return NS_LDAP_SUCCESS;
  331 }
  332 
  333 ns_ldap_return_code
  334 __ns_ldap_allocAttr (ns_ldap_attr_t ** pAttr)
  335 {
  336   ns_ldap_attr_t *attr;
  337 
  338   *pAttr = NULL;
  339 
  340   attr = (ns_ldap_attr_t *) malloc (sizeof (*attr));
  341   if (attr == NULL)
  342     {
  343       return NS_LDAP_MEMORY;
  344     }
  345 
  346   attr->attrname = NULL;
  347   attr->attrvalue = NULL;
  348   attr->value_count = 0;
  349 
  350   *pAttr = attr;
  351 
  352   return NS_LDAP_SUCCESS;
  353 }
  354 
  355 ns_ldap_return_code
  356 __ns_ldap_parseAttr (ns_ldap_cookie_t * cookie,
  357              LDAPMessage * entry,
  358              const char *attribute, ns_ldap_attr_t ** pAttr)
  359 {
  360   ns_ldap_attr_t *attr;
  361   const char *unmappedAttribute;
  362   ns_ldap_return_code ret;
  363   char **values;
  364   int freeValues = 1;
  365 
  366   ret = __ns_ldap_allocAttr (&attr);
  367   if (ret != NS_LDAP_SUCCESS)
  368     {
  369       return ret;
  370     }
  371 
  372   if ((cookie->flags & NS_LDAP_NOMAP) == 0)
  373     {
  374       unmappedAttribute = _nss_ldap_unmap_at (cookie->sel, attribute);
  375       if (unmappedAttribute == NULL)
  376     {
  377       __ns_ldap_freeAttr (&attr);
  378       return NS_LDAP_INVALID_PARAM;
  379     }
  380     }
  381   else
  382     {
  383       unmappedAttribute = attribute;
  384     }
  385 
  386   attr->attrname = strdup (unmappedAttribute);
  387   if (attr->attrname == NULL)
  388     {
  389       __ns_ldap_freeAttr (&attr);
  390       return NS_LDAP_MEMORY;
  391     }
  392   attr->attrvalue = NULL;
  393 
  394   values = _nss_ldap_get_values (entry, attribute);
  395 
  396   if ((cookie->flags & NS_LDAP_NOMAP) == 0)
  397     {
  398       if (strcasecmp (attribute, "objectClass") == 0)
  399     {
  400       /* Map object class values */
  401       ret =
  402         __ns_ldap_unmapObjectClasses (cookie, values, &attr->attrvalue);
  403       if (ret != NS_LDAP_SUCCESS)
  404         {
  405           __ns_ldap_freeAttr (&attr);
  406           return ret;
  407         }
  408     }
  409     }
  410 
  411   if (attr->attrvalue == NULL)
  412     {
  413       attr->attrvalue = values;
  414       freeValues = 0;
  415     }
  416 
  417   attr->value_count =
  418     (attr->attrvalue != NULL) ? ldap_count_values (attr->attrvalue) : 0;
  419 
  420   if (freeValues)
  421     {
  422       ldap_value_free (values);
  423     }
  424 
  425   *pAttr = attr;
  426 
  427   return NS_LDAP_SUCCESS;
  428 }
  429 
  430 ns_ldap_return_code
  431 __ns_ldap_parseDn (ns_ldap_cookie_t * cookie, LDAPMessage * entry,
  432            ns_ldap_attr_t ** pAttr)
  433 {
  434   ns_ldap_attr_t *attr;
  435   ns_ldap_return_code ret;
  436 
  437   ret = __ns_ldap_allocAttr (&attr);
  438   if (ret != NS_LDAP_SUCCESS)
  439     {
  440       return ret;
  441     }
  442 
  443   attr->attrname = strdup ("dn");
  444   if (attr->attrname == NULL)
  445     {
  446       __ns_ldap_freeAttr (&attr);
  447       return NS_LDAP_MEMORY;
  448     }
  449 
  450   attr->value_count = 1;
  451 
  452   attr->attrvalue = (char **) malloc (1 * sizeof (char *));
  453   if (attr->attrvalue == NULL)
  454     {
  455       __ns_ldap_freeAttr (&attr);
  456       return NS_LDAP_MEMORY;
  457     }
  458 
  459   attr->attrvalue[0] = _nss_ldap_get_dn (entry);
  460   if (attr->attrvalue[0] == NULL)
  461     {
  462       __ns_ldap_freeAttr (&attr);
  463       return NS_LDAP_MEMORY;
  464     }
  465 
  466   *pAttr = attr;
  467 
  468   return NS_LDAP_SUCCESS;
  469 }
  470 
  471 NSS_STATUS
  472 __ns_ldap_parseEntry (LDAPMessage * msg, ldap_state_t * state,
  473               void *result, char *buffer, size_t buflen)
  474 {
  475   ns_ldap_cookie_t *cookie = (ns_ldap_cookie_t *) result;
  476   char *attribute;
  477   BerElement *ber = NULL;
  478   ns_ldap_return_code ret = NS_LDAP_SUCCESS;
  479   ns_ldap_entry_t *entry;
  480   int attr_count;
  481 
  482 #ifdef DEBUG
  483   {
  484     char *dn = _nss_ldap_get_dn (msg);
  485     debug ("==> __ns_ldap_parseEntry (%s)", dn);
  486     ldap_memfree (dn);
  487   }
  488 #endif
  489 
  490   entry = (ns_ldap_entry_t *) malloc (sizeof (*entry));
  491   if (entry == NULL)
  492     {
  493       cookie->ret = NS_LDAP_MEMORY;
  494       debug ("<== __ns_ldap_parseEntry (no memory)");
  495       return NSS_NOTFOUND;
  496     }
  497 
  498   entry->attr_count = 0;
  499   entry->attr_pair = NULL;
  500   entry->next = NULL;
  501 
  502   attr_count = 1;       /* for DN */
  503 
  504   for (attribute = _nss_ldap_first_attribute (msg, &ber);
  505        attribute != NULL; attribute = _nss_ldap_next_attribute (msg, ber))
  506     {
  507       attr_count++;
  508 #ifdef HAVE_LDAP_MEMFREE
  509       ldap_memfree (attribute);
  510 #endif
  511     }
  512 
  513   if (ber != NULL)
  514     ber_free (ber, 0);
  515 
  516   entry->attr_pair =
  517     (ns_ldap_attr_t **) calloc (attr_count, sizeof (ns_ldap_attr_t *));
  518   if (entry->attr_pair == NULL)
  519     {
  520       __ns_ldap_freeEntry (&entry);
  521       cookie->ret = NS_LDAP_MEMORY;
  522       debug ("<== __ns_ldap_parseEntry (no memory)");
  523       return NSS_NOTFOUND;
  524     }
  525 
  526   ret = __ns_ldap_parseDn (cookie, msg, &entry->attr_pair[entry->attr_count]);
  527   if (ret != NS_LDAP_SUCCESS)
  528     {
  529       __ns_ldap_freeEntry (&entry);
  530       cookie->ret = ret;
  531       debug ("<== __ns_ldap_parseEntry (failed to parse DN)");
  532       return ret;
  533     }
  534 
  535   entry->attr_count++;
  536 
  537   for (attribute = _nss_ldap_first_attribute (msg, &ber);
  538        attribute != NULL; attribute = _nss_ldap_next_attribute (msg, ber))
  539     {
  540       ns_ldap_attr_t *attr;
  541 
  542       ret = __ns_ldap_parseAttr (cookie, msg, attribute, &attr);
  543 #ifdef HAVE_LDAP_MEMFREE
  544       ldap_memfree (attribute);
  545 #endif
  546       if (ret != NS_LDAP_SUCCESS)
  547     {
  548       continue;
  549     }
  550       entry->attr_pair[entry->attr_count++] = attr;
  551     }
  552 
  553   if (ber != NULL)
  554     ber_free (ber, 0);
  555 
  556   if (ret == NS_LDAP_SUCCESS)
  557     {
  558       ns_ldap_entry_t *last;
  559 
  560       if (cookie->result == NULL)
  561     {
  562       ret = __ns_ldap_initResult (&cookie->result);
  563       if (ret != NS_LDAP_SUCCESS)
  564         {
  565           __ns_ldap_freeEntry (&entry);
  566           cookie->ret = ret;
  567           debug ("<== __ns_ldap_parseEntry (failed to init result: %s)",
  568              NS_LDAP_ERR2STR (ret));
  569           return __ns_ldap_mapError (ret);
  570         }
  571       cookie->result->entry = entry;
  572     }
  573       else
  574     {
  575       assert (cookie->entry != NULL);
  576 
  577       for (last = cookie->entry; last->next != NULL; last = last->next)
  578         ;
  579       last->next = entry;
  580     }
  581 
  582       cookie->entry = entry;
  583 
  584       if (cookie->callback != NULL)
  585     {
  586       cookie->cb_ret = (*cookie->callback) (entry, cookie->userdata);
  587     }
  588 
  589       cookie->result->entries_count++;
  590     }
  591   else
  592     {
  593       __ns_ldap_freeEntry (&entry);
  594     }
  595 
  596   cookie->ret = ret;
  597 
  598   debug ("<== __ns_ldap_parseEntry (ret=%s)", NS_LDAP_ERR2STR (ret));
  599 
  600   return __ns_ldap_mapError (ret);
  601 }
  602 
  603 static ns_ldap_return_code
  604 __ns_ldap_initResult (ns_ldap_result_t ** pResult)
  605 {
  606   ns_ldap_result_t *result;
  607 
  608   result = (ns_ldap_result_t *) malloc (sizeof (ns_ldap_result_t));
  609   if (result == NULL)
  610     {
  611       return NS_LDAP_MEMORY;
  612     }
  613 
  614   result->entries_count = 0;
  615   result->entry = NULL;
  616 
  617   *pResult = result;
  618 
  619   return NS_LDAP_SUCCESS;
  620 }
  621 
  622 static ldap_map_selector_t
  623 __ns_ldap_str2selector (const char *map)
  624 {
  625   ldap_map_selector_t sel;
  626 
  627   if (map == NULL)
  628     {
  629       sel = LM_NONE;
  630     }
  631   else
  632     {
  633       sel = _nss_ldap_str2selector (map);
  634 
  635       if (strcmp (map, "automount") == 0)
  636     {
  637       sel = LM_NONE;    /* for enumeration only */
  638     }
  639       else if (sel == LM_NONE && (strncmp (map, "auto_", 5)) == 0)
  640     {
  641       sel = LM_AUTOMOUNT;
  642     }
  643       else
  644     {
  645       sel = _nss_ldap_str2selector (map);
  646     }
  647     }
  648 
  649   return sel;
  650 }
  651 
  652 static ns_ldap_return_code
  653 __ns_ldap_unmapObjectClasses (ns_ldap_cookie_t * cookie, char **mappedClasses,
  654                   char ***pOrigClasses)
  655 {
  656   char **origClasses = NULL;
  657   int count, i;
  658 
  659   count = ldap_count_values (mappedClasses);
  660   origClasses = (char **) calloc (count + 1, sizeof (char *));
  661   if (origClasses == NULL)
  662     {
  663       return NS_LDAP_MEMORY;
  664     }
  665 
  666   for (i = 0; i < count; i++)
  667     {
  668       origClasses[i] =
  669     strdup (_nss_ldap_unmap_oc (cookie->sel, mappedClasses[i]));
  670       if (origClasses[i] == NULL)
  671     {
  672       ldap_value_free (origClasses);
  673       return NS_LDAP_MEMORY;
  674     }
  675     }
  676   origClasses[i] = NULL;
  677   *pOrigClasses = origClasses;
  678 
  679   return NS_LDAP_SUCCESS;
  680 }
  681 
  682 static ns_ldap_return_code
  683 __ns_ldap_mapAttributes (ns_ldap_cookie_t * cookie, const char ***pAttributes)
  684 {
  685   const char **attributes;
  686   int i;
  687 
  688   *pAttributes = NULL;
  689 
  690   if (cookie->attribute == NULL)
  691     {
  692       return NS_LDAP_SUCCESS;
  693     }
  694 
  695   for (i = 0; cookie->attribute[i] != NULL; i++)
  696     ;
  697 
  698   attributes = (const char **) calloc (i + 1, sizeof (char **));
  699   if (attributes == NULL)
  700     {
  701       return NS_LDAP_MEMORY;
  702     }
  703 
  704   for (i = 0; cookie->attribute[i] != NULL; i++)
  705     {
  706       attributes[i] = _nss_ldap_map_at (cookie->sel, cookie->attribute[i]);
  707       assert (attributes[i] != NULL);
  708     }
  709   attributes[i] = NULL;
  710   *pAttributes = attributes;
  711 
  712   return NS_LDAP_SUCCESS;
  713 }
  714 
  715 static ns_ldap_return_code
  716 __ns_ldap_emitFilterString (char **pFilter, size_t * len, size_t * size,
  717                 const char *s)
  718 {
  719   size_t slen = strlen (s);
  720   char *filter;
  721 
  722   if (*len + slen >= *size)
  723     {
  724       /* need some more space */
  725       size_t newSize = *size;
  726       char *newFilter;
  727 
  728       if (newSize == 0)
  729     newSize = NSS_BUFSIZ;
  730       else
  731     newSize *= 2;
  732 
  733       newFilter = realloc (*pFilter, newSize);
  734       if (newFilter == NULL)
  735     {
  736       return NS_LDAP_MEMORY;
  737     }
  738       *pFilter = newFilter;
  739       *size = newSize;
  740     }
  741 
  742   filter = *pFilter;
  743 
  744   memcpy (&filter[*len], s, slen);
  745   filter[*len + slen] = '\0';
  746 
  747   *len += slen;
  748 
  749   return NS_LDAP_SUCCESS;
  750 }
  751 
  752 
  753 #define EMIT_STRING(_s) do { \
  754         ns_ldap_return_code ret = __ns_ldap_emitFilterString(&filter, &len, &size, (_s)); \
  755         if (ret != NS_LDAP_SUCCESS) { \
  756             if (filter != NULL) free(filter); \
  757             return ret; \
  758         } \
  759     } while (0)
  760 
  761 #define EMIT_CHAR(_c)   do { \
  762         char _s[2]; \
  763         ns_ldap_return_code ret; \
  764         _s[0] = _c; \
  765         _s[1] = '\0'; \
  766         ret = __ns_ldap_emitFilterString(&filter, &len, &size, (_s)); \
  767         if (ret != NS_LDAP_SUCCESS) { \
  768             if (filter != NULL) free(filter); \
  769             return ret; \
  770         } \
  771     } while (0)
  772 
  773 
  774 static ns_ldap_return_code
  775 __ns_ldap_mapFilter (ns_ldap_cookie_t * cookie, char **pFilter)
  776 {
  777   enum
  778   { EXPECT_LHS, FOUND_LHS, EXPECT_RHS, FOUND_RHS } state;
  779   char *lhs = NULL;
  780   char *rhs = NULL;
  781   size_t len = 0, size = 0;
  782   char tmp;
  783   size_t i;
  784   char *filter = NULL;
  785   size_t filterLen = strlen (cookie->filter);
  786 
  787   state = EXPECT_LHS;
  788 
  789   for (i = 0; i <= filterLen; i++)
  790     {
  791       switch (state)
  792     {
  793     case EXPECT_LHS:
  794       switch (cookie->filter[i])
  795         {
  796         case '(':
  797         case ')':
  798         case '&':
  799         case '|':
  800         case '!':
  801           EMIT_CHAR (cookie->filter[i]);
  802           break;
  803         default:
  804           state = FOUND_LHS;
  805           lhs = &cookie->filter[i];
  806           break;
  807         }
  808       break;
  809     case FOUND_LHS:
  810       switch (cookie->filter[i])
  811         {
  812         case '<':
  813         case '=':
  814         case '>':
  815         case '~':
  816           state = EXPECT_RHS;
  817           tmp = cookie->filter[i];
  818           cookie->filter[i] = '\0';
  819           /* map LHS (attribute type) */
  820           EMIT_STRING (_nss_ldap_map_at (cookie->sel, lhs));
  821           EMIT_CHAR (tmp);
  822           break;
  823         default:
  824           break;
  825         }
  826       break;
  827     case EXPECT_RHS:
  828       switch (cookie->filter[i])
  829         {
  830         case '<':
  831         case '=':
  832         case '>':
  833         case '~':
  834           EMIT_CHAR (cookie->filter[i]);
  835           break;
  836         default:
  837           state = FOUND_RHS;
  838           rhs = &cookie->filter[i];
  839           break;
  840         }
  841       break;
  842     case FOUND_RHS:
  843       switch (cookie->filter[i])
  844         {
  845         case '&':
  846         case '|':
  847         case '!':
  848         case ')':
  849         case '\0':
  850           state = EXPECT_LHS;
  851           tmp = cookie->filter[i];;
  852           cookie->filter[i] = '\0';
  853           if (strcasecmp (lhs, "objectClass") == 0)
  854         EMIT_STRING (_nss_ldap_map_oc (cookie->sel, rhs));
  855           else
  856         EMIT_STRING (rhs);
  857           if (strcasecmp (rhs, "automount") == 0)
  858         cookie->sel = LM_AUTOMOUNT;
  859           EMIT_CHAR (tmp);
  860           break;
  861         default:
  862           break;
  863         }
  864       break;
  865     }
  866     }
  867 
  868   *pFilter = filter;
  869 
  870   return NS_LDAP_SUCCESS;
  871 }
  872 
  873 static ns_ldap_return_code
  874 __ns_ldap_freeCookie (ns_ldap_cookie_t ** pCookie)
  875 {
  876   ns_ldap_cookie_t *cookie;
  877 
  878   cookie = *pCookie;
  879 
  880   if (cookie != NULL)
  881     {
  882       if (cookie->map != NULL)
  883     free (cookie->map);
  884       if (cookie->filter != NULL)
  885     free (cookie->filter);
  886       if (cookie->attribute != NULL)
  887     ldap_value_free (cookie->attribute);
  888       if (cookie->state != NULL)
  889     {
  890       _nss_ldap_ent_context_release (&(cookie->state));
  891     }
  892       if (cookie->mapped_filter != NULL)
  893     free (cookie->mapped_filter);
  894       if (cookie->mapped_attribute != NULL)
  895     free (cookie->mapped_attribute);
  896       _nss_ldap_am_context_free (&cookie->am_state);
  897       __ns_ldap_freeResult (&cookie->result);
  898       free (cookie);
  899     }
  900 
  901   *pCookie = NULL;
  902 
  903   return NS_LDAP_SUCCESS;
  904 }
  905 
  906 static ns_ldap_return_code
  907 __ns_ldap_initCookie (const char *map,
  908               const char *filter,
  909               int (*init_filter_cb) (const ns_ldap_search_desc_t *
  910                          desc, char **realfilter,
  911                          const void *userdata),
  912               const char *const *attribute, const ns_cred_t * cred,
  913               const int flags, ns_ldap_cookie_t ** pCookie,
  914               int (*callback) (const ns_ldap_entry_t * entry,
  915                        const void *userdata),
  916               const void *userdata)
  917 {
  918   ns_ldap_cookie_t *cookie;
  919   ns_ldap_return_code ret;
  920   size_t i;
  921 
  922   assert (pCookie != NULL && *pCookie == NULL);
  923 
  924   ret = __ns_ldap_mapError (_nss_ldap_init ());
  925   if (ret != NS_LDAP_SUCCESS)
  926     {
  927       return ret;
  928     }
  929 
  930   cookie = (ns_ldap_cookie_t *) calloc (1, sizeof (*cookie));
  931   if (cookie == NULL)
  932     {
  933       return NS_LDAP_MEMORY;
  934     }
  935 
  936   if (filter == NULL)
  937     {
  938       __ns_ldap_freeCookie (&cookie);
  939       return NS_LDAP_INVALID_PARAM;
  940     }
  941 
  942   if (map != NULL)
  943     {
  944       cookie->map = strdup (map);
  945       if (cookie->map == NULL)
  946     {
  947       __ns_ldap_freeCookie (&cookie);
  948       return NS_LDAP_MEMORY;
  949     }
  950     }
  951 
  952   cookie->filter = strdup (filter);
  953   if (cookie->filter == NULL)
  954     {
  955       __ns_ldap_freeCookie (&cookie);
  956       return NS_LDAP_MEMORY;
  957     }
  958 
  959   if (attribute != NULL)
  960     {
  961       for (i = 0; attribute[i] != NULL; i++)
  962     ;
  963 
  964       cookie->attribute = (char **) calloc (i + 1, sizeof (char *));
  965       if (cookie->attribute == NULL)
  966     {
  967       __ns_ldap_freeCookie (&cookie);
  968       return NS_LDAP_MEMORY;
  969     }
  970 
  971       for (i = 0; attribute[i] != NULL; i++)
  972     {
  973       cookie->attribute[i] = strdup (attribute[i]);
  974       if (cookie->attribute[i] == NULL)
  975         {
  976           __ns_ldap_freeCookie (&cookie);
  977           return NS_LDAP_MEMORY;
  978         }
  979     }
  980       cookie->attribute[i] = NULL;
  981     }
  982 
  983   cookie->flags = flags;
  984   cookie->init_filter_cb = init_filter_cb;
  985   cookie->callback = callback;
  986   cookie->userdata = userdata;
  987   cookie->ret = -1;
  988   cookie->cb_ret = NS_LDAP_CB_NEXT;
  989   cookie->erange = 0;
  990   cookie->sel = __ns_ldap_str2selector (map);
  991 
  992   if (_nss_ldap_ent_context_init_locked (&cookie->state) == NULL)
  993     {
  994       __ns_ldap_freeCookie (&cookie);
  995       return NS_LDAP_INTERNAL;
  996     }
  997 
  998   cookie->result = NULL;
  999   cookie->entry = NULL;
 1000 
 1001   ret = __ns_ldap_initSearch (cookie);
 1002   if (ret != NS_LDAP_SUCCESS)
 1003     {
 1004       __ns_ldap_freeCookie (&cookie);
 1005       return ret;
 1006     }
 1007 
 1008   *pCookie = cookie;
 1009 
 1010   return NS_LDAP_SUCCESS;
 1011 }
 1012 
 1013 static ns_ldap_return_code
 1014 __ns_ldap_initSearch (ns_ldap_cookie_t * cookie)
 1015 {
 1016   ns_ldap_return_code ret;
 1017   NSS_STATUS stat;
 1018 
 1019   assert (cookie != NULL);
 1020   assert (cookie->state != NULL);
 1021 
 1022   ret = __ns_ldap_mapAttributes (cookie, &cookie->mapped_attribute);
 1023   if (ret != NS_LDAP_SUCCESS)
 1024     {
 1025       return ret;
 1026     }
 1027 
 1028   ret = __ns_ldap_mapFilter (cookie, &cookie->mapped_filter);
 1029   if (ret != NS_LDAP_SUCCESS)
 1030     {
 1031       return ret;
 1032     }
 1033 
 1034   /*
 1035    * In the automount case, we need to do a search for a list of
 1036    * search bases
 1037    */
 1038   if (cookie->sel == LM_AUTOMOUNT)
 1039     {
 1040       assert (cookie->am_state == NULL);
 1041       assert (cookie->map != NULL);
 1042 
 1043       stat = _nss_ldap_am_context_init (cookie->map, &cookie->am_state);
 1044       if (stat != NSS_SUCCESS)
 1045     {
 1046       return __ns_ldap_mapError (stat);
 1047     }
 1048     }
 1049 
 1050   return ret;
 1051 }
 1052 
 1053 /*
 1054  * Performs a search given an existing cookie
 1055  *
 1056  * If cookie->result != NULL then the entry will be appended to
 1057  * the result list. Use this for implementing __ns_ldap_list().
 1058  *
 1059  * If cookie->result == NULL then a new result list will be
 1060  * allocated. Use this for implementing __ns_ldap_nextEntry().
 1061  *
 1062  * cookie->entry always points to the last entry in cookie->result
 1063  * 
 1064  * Caller should acquire global lock
 1065  */
 1066 static ns_ldap_return_code
 1067 __ns_ldap_search (ns_ldap_cookie_t * cookie)
 1068 {
 1069   ldap_args_t a;
 1070   NSS_STATUS stat;
 1071   ldap_automount_context_t *am = cookie->am_state;
 1072 
 1073   LA_INIT (a);
 1074   LA_TYPE (a) = LA_TYPE_NONE;
 1075 
 1076   if (cookie->sel == LM_AUTOMOUNT)
 1077     {
 1078       assert (am != NULL);
 1079       assert (am->lac_dn_count > 0);
 1080 
 1081       LA_BASE (a) = am->lac_dn_list[am->lac_dn_index];
 1082     }               /* XXX todo is support maps that are RDNs relative to default search base */
 1083 
 1084   assert (cookie->mapped_filter != NULL);
 1085 
 1086 retry_search:
 1087   cookie->ret = -1;
 1088 
 1089   stat = _nss_ldap_getent_ex (&a, &cookie->state, cookie,
 1090                   NULL, 0, &cookie->erange,
 1091                   cookie->mapped_filter,
 1092                   cookie->sel,
 1093                   cookie->mapped_attribute, __ns_ldap_parseEntry);
 1094 
 1095   if (stat == NSS_NOTFOUND &&
 1096       cookie->sel == LM_AUTOMOUNT && am->lac_dn_index < am->lac_dn_count - 1)
 1097     {
 1098       am->lac_dn_index++;
 1099       goto retry_search;
 1100     }
 1101 
 1102   if (cookie->ret < 0)
 1103     {
 1104       cookie->ret = __ns_ldap_mapError (stat);
 1105     }
 1106 
 1107   return cookie->ret;
 1108 }
 1109 
 1110 ns_ldap_return_code
 1111 __ns_ldap_firstEntry (const char *service,
 1112               const char *filter,
 1113               int (*init_filter_cb) (const ns_ldap_search_desc_t *
 1114                          desc, char **realfilter,
 1115                          const void *userdata),
 1116               const char *const *attribute, const ns_cred_t * cred,
 1117               const int flags, void **pCookie,
 1118               ns_ldap_result_t ** result, ns_ldap_error_t ** errorp,
 1119               const void *userdata)
 1120 {
 1121   ns_ldap_return_code ret;
 1122   ns_ldap_cookie_t *cookie = NULL;
 1123 
 1124   *pCookie = NULL;
 1125   *result = NULL;
 1126   *errorp = NULL;
 1127 
 1128   debug ("==> __ns_ldap_firstEntry (map=%s filter=%s)",
 1129      service != NULL ? service : "(null)", filter);
 1130 
 1131   _nss_ldap_enter ();
 1132 
 1133   ret = __ns_ldap_initCookie (service, filter, init_filter_cb,
 1134                   attribute, cred, flags, &cookie, NULL,
 1135                   userdata);
 1136   if (ret == NS_LDAP_SUCCESS)
 1137     {
 1138       ret = __ns_ldap_search (cookie);
 1139 
 1140       *result = cookie->result;
 1141       cookie->result = NULL;
 1142     }
 1143 
 1144   __ns_ldap_mapErrorDetail (ret, errorp);
 1145 
 1146   _nss_ldap_leave ();
 1147 
 1148   *pCookie = cookie;
 1149 
 1150   debug ("<== __ns_ldap_firstEntry ret=%s cookie=%p", NS_LDAP_ERR2STR (ret),
 1151      cookie);
 1152 
 1153   return ret;
 1154 }
 1155 
 1156 ns_ldap_return_code
 1157 __ns_ldap_nextEntry (void *_cookie,
 1158              ns_ldap_result_t ** result, ns_ldap_error_t ** errorp)
 1159 {
 1160   ns_ldap_return_code ret;
 1161   ns_ldap_cookie_t *cookie;
 1162 
 1163   *result = NULL;
 1164   *errorp = NULL;
 1165 
 1166   cookie = (ns_ldap_cookie_t *) _cookie;
 1167   if (cookie == NULL)
 1168     {
 1169       return NS_LDAP_INVALID_PARAM;
 1170     }
 1171 
 1172   debug ("==> __ns_ldap_nextEntry cookie=%p", cookie);
 1173 
 1174   _nss_ldap_enter ();
 1175 
 1176   ret = __ns_ldap_search (cookie);
 1177 
 1178   *result = cookie->result;
 1179   cookie->result = NULL;
 1180 
 1181   __ns_ldap_mapErrorDetail (ret, errorp);
 1182 
 1183   _nss_ldap_leave ();
 1184 
 1185   debug ("<== __ns_ldap_nextEntry ret=%s", NS_LDAP_ERR2STR (ret));
 1186 
 1187   return ret;
 1188 }
 1189 
 1190 ns_ldap_return_code
 1191 __ns_ldap_endEntry (void **pCookie, ns_ldap_error_t ** errorp)
 1192 {
 1193   ns_ldap_cookie_t *cookie;
 1194 
 1195   _nss_ldap_enter ();
 1196 
 1197   cookie = (ns_ldap_cookie_t *) * pCookie;
 1198 
 1199   debug ("==> __ns_ldap_freeEntry cookie=%p", cookie);
 1200 
 1201   __ns_ldap_mapErrorDetail (cookie->ret, errorp);
 1202   __ns_ldap_freeCookie (&cookie);
 1203 
 1204   *pCookie = NULL;
 1205 
 1206   _nss_ldap_leave ();
 1207 
 1208   debug ("<== __ns_ldap_freeEntry");
 1209 
 1210   return NS_LDAP_SUCCESS;
 1211 }
 1212 
 1213 ns_ldap_return_code
 1214 __ns_ldap_list (const char *map,
 1215         const char *filter,
 1216         int (*init_filter_cb) (const ns_ldap_search_desc_t * desc,
 1217                        char **realfilter,
 1218                        const void *userdata),
 1219         const char *const *attribute, const ns_cred_t * cred,
 1220         const int flags, ns_ldap_result_t ** pResult,
 1221         ns_ldap_error_t ** errorp,
 1222         int (*callback) (const ns_ldap_entry_t * entry,
 1223                  const void *userdata), const void *userdata)
 1224 {
 1225   ns_ldap_cookie_t *cookie = NULL;
 1226   ns_ldap_result_t *result = NULL;
 1227   ns_ldap_return_code ret;
 1228 
 1229   debug ("==> __ns_ldap_list map=%s filter=%s",
 1230      map != NULL ? map : "(null)", filter);
 1231 
 1232   *pResult = NULL;
 1233   *errorp = NULL;
 1234 
 1235   _nss_ldap_enter ();
 1236 
 1237   ret = __ns_ldap_initCookie (map, filter, init_filter_cb,
 1238                   attribute, cred, flags, &cookie, callback,
 1239                   userdata);
 1240 
 1241   while (ret == NS_LDAP_SUCCESS)
 1242     {
 1243       ret = __ns_ldap_search (cookie);
 1244 
 1245       if (result == NULL)
 1246     {
 1247       result = cookie->result;
 1248     }
 1249 
 1250       if (cookie->cb_ret != NS_LDAP_CB_NEXT)
 1251     {
 1252       assert (cookie->callback != NULL);
 1253       break;
 1254     }
 1255     }
 1256 
 1257   if (cookie != NULL)
 1258     {
 1259       if (ret == NS_LDAP_NOTFOUND && cookie->entry != NULL)
 1260     {
 1261       ret = NS_LDAP_SUCCESS;
 1262     }
 1263 
 1264       *pResult = result;
 1265       cookie->result = NULL;
 1266     }
 1267 
 1268   __ns_ldap_freeCookie (&cookie);
 1269   __ns_ldap_mapErrorDetail (ret, errorp);
 1270 
 1271   _nss_ldap_leave ();
 1272 
 1273   debug ("<== __ns_ldap_list ret=%s", NS_LDAP_ERR2STR (ret));
 1274 
 1275   return ret;
 1276 }
 1277 
 1278 ns_ldap_return_code
 1279 __ns_ldap_err2str (ns_ldap_return_code err, char **strmsg)
 1280 {
 1281   switch (err)
 1282     {
 1283     case NS_LDAP_SUCCESS:
 1284     case NS_LDAP_SUCCESS_WITH_INFO:
 1285       *strmsg = "Success";
 1286       break;
 1287     case NS_LDAP_OP_FAILED:
 1288       *strmsg = "Operation failed";
 1289       break;
 1290     case NS_LDAP_NOTFOUND:
 1291       *strmsg = "Not found";
 1292       break;
 1293     case NS_LDAP_MEMORY:
 1294       *strmsg = "Out of memory";
 1295       break;
 1296     case NS_LDAP_CONFIG:
 1297       *strmsg = "Configuration error";
 1298       break;
 1299     case NS_LDAP_PARTIAL:
 1300       *strmsg = "Partial results received";
 1301       break;
 1302     case NS_LDAP_INTERNAL:
 1303       *strmsg = "Internal LDAP error";
 1304       break;
 1305     case NS_LDAP_INVALID_PARAM:
 1306       *strmsg = "Invalid parameter";
 1307       break;
 1308     default:
 1309       *strmsg = "Unknown error";
 1310       return NS_LDAP_INVALID_PARAM;
 1311       break;
 1312     }
 1313 
 1314   return NS_LDAP_SUCCESS;
 1315 }
 1316 
 1317 #endif /* HAVE_NSSWITCH_H */