"Fossies" - the Fresh Open Source Software Archive 
Member "nss_ldap-265/util.c" (6 Nov 2009, 38593 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) 1997-2005 Luke Howard.
2 This file is part of the nss_ldap library.
3 Contributed by Luke Howard, <lukeh@padl.com>, 1997.
4 (The author maintains a non-exclusive licence to distribute this file
5 under their own conditions.)
6
7 The nss_ldap library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The nss_ldap library 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 GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the nss_ldap library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
21 */
22
23 #include "config.h"
24
25 #if defined(HAVE_THREAD_H) && !defined(_AIX)
26 #include <thread.h>
27 #elif defined(HAVE_PTHREAD_H)
28 #include <pthread.h>
29 #endif
30
31 #include <stdio.h>
32 #include <string.h>
33 #ifdef HAVE_STRINGS_H
34 #include <strings.h>
35 #endif
36 #include <stdlib.h>
37
38 #include <sys/param.h>
39 #include <sys/stat.h>
40
41 #include <netdb.h>
42 #include <syslog.h>
43 #include <string.h>
44 #include <fcntl.h>
45 #include <assert.h>
46
47 #ifdef HAVE_LBER_H
48 #include <lber.h>
49 #endif
50 #ifdef HAVE_LDAP_H
51 #include <ldap.h>
52 #endif
53
54 #ifndef HAVE_SNPRINTF
55 #include "snprintf.h"
56 #endif
57
58 #include "ldap-nss.h"
59 #include "util.h"
60
61 static char rcsId[] = "$Id: util.c,v 2.138 2009/11/06 10:16:04 lukeh Exp $";
62
63 static NSS_STATUS do_getrdnvalue (const char *dn,
64 const char *rdntype,
65 char **rval, char **buffer,
66 size_t * buflen);
67
68
69 static NSS_STATUS do_parse_map_statement (ldap_config_t * cfg,
70 const char *statement,
71 ldap_map_type_t type);
72
73 static NSS_STATUS do_searchdescriptorconfig (const char *key,
74 const char *value,
75 size_t valueLength,
76 ldap_service_search_descriptor_t
77 ** result, char **buffer,
78 size_t * buflen);
79
80 #include <fcntl.h>
81 static void *__cache = NULL;
82
83 NSS_LDAP_DEFINE_LOCK (__cache_lock);
84
85 #define cache_lock() NSS_LDAP_LOCK(__cache_lock)
86 #define cache_unlock() NSS_LDAP_UNLOCK(__cache_lock)
87
88 static NSS_STATUS
89 dn2uid_cache_put (const char *dn, const char *uid)
90 {
91 NSS_STATUS stat;
92 ldap_datum_t key, val;
93
94 cache_lock ();
95
96 if (__cache == NULL)
97 {
98 __cache = _nss_ldap_db_open ();
99 if (__cache == NULL)
100 {
101 cache_unlock ();
102 return NSS_TRYAGAIN;
103 }
104 }
105
106 key.data = (void *) dn;
107 key.size = strlen (dn);
108 val.data = (void *) uid;
109 val.size = strlen (uid);
110
111 stat = _nss_ldap_db_put (__cache, 0, &key, &val);
112
113 cache_unlock ();
114
115 return stat;
116 }
117
118 static NSS_STATUS
119 dn2uid_cache_get (const char *dn, char **uid, char **buffer, size_t * buflen)
120 {
121 ldap_datum_t key, val;
122 NSS_STATUS stat;
123
124 cache_lock ();
125
126 if (__cache == NULL)
127 {
128 cache_unlock ();
129 return NSS_NOTFOUND;
130 }
131
132 key.data = (void *) dn;
133 key.size = strlen (dn);
134
135 stat = _nss_ldap_db_get (__cache, 0, &key, &val);
136 if (stat != NSS_SUCCESS)
137 {
138 cache_unlock ();
139 return stat;
140 }
141
142 if (*buflen <= val.size)
143 {
144 cache_unlock ();
145 return NSS_TRYAGAIN;
146 }
147
148 *uid = *buffer;
149 memcpy (*uid, (char *) val.data, val.size);
150 (*uid)[val.size] = '\0';
151 *buffer += val.size + 1;
152 *buflen -= val.size + 1;
153
154 cache_unlock ();
155 return NSS_SUCCESS;
156 }
157
158 #ifdef HPUX
159 static int lock_inited = 0;
160 #endif
161
162 NSS_STATUS
163 _nss_ldap_dn2uid (const char *dn, char **uid, char **buffer, size_t * buflen,
164 int *pIsNestedGroup, LDAPMessage ** pRes)
165 {
166 NSS_STATUS stat;
167
168 debug ("==> _nss_ldap_dn2uid");
169
170 *pIsNestedGroup = 0;
171
172 #ifdef HPUX
173 /* XXX this is not thread-safe */
174 if (!lock_inited)
175 {
176 __thread_mutex_init (&__cache_lock, NULL);
177 lock_inited = 1;
178 }
179 #endif
180
181 stat = dn2uid_cache_get (dn, uid, buffer, buflen);
182 if (stat == NSS_NOTFOUND)
183 {
184 const char *attrs[4];
185 LDAPMessage *res;
186
187 attrs[0] = ATM (LM_PASSWD, uid);
188 attrs[1] = ATM (LM_GROUP, uniqueMember);
189 attrs[2] = AT (objectClass);
190 attrs[3] = NULL;
191
192 if (_nss_ldap_read (dn, attrs, &res) == NSS_SUCCESS)
193 {
194 LDAPMessage *e = _nss_ldap_first_entry (res);
195 if (e != NULL)
196 {
197 if (_nss_ldap_oc_check (e, OC (posixGroup)) == NSS_SUCCESS)
198 {
199 *pIsNestedGroup = 1;
200 *pRes = res;
201 debug ("<== _nss_ldap_dn2uid (nested group)");
202 return NSS_SUCCESS;
203 }
204
205 stat =
206 _nss_ldap_assign_attrval (e, ATM (LM_PASSWD, uid), uid,
207 buffer, buflen);
208 if (stat == NSS_SUCCESS)
209 dn2uid_cache_put (dn, *uid);
210 }
211 }
212 ldap_msgfree (res);
213 }
214
215 debug ("<== _nss_ldap_dn2uid");
216
217 return stat;
218 }
219
220 NSS_STATUS
221 _nss_ldap_getrdnvalue (LDAPMessage * entry,
222 const char *rdntype,
223 char **rval, char **buffer, size_t * buflen)
224 {
225 char *dn;
226 NSS_STATUS status;
227
228 dn = _nss_ldap_get_dn (entry);
229 if (dn == NULL)
230 {
231 return NSS_NOTFOUND;
232 }
233
234 status = do_getrdnvalue (dn, rdntype, rval, buffer, buflen);
235 #ifdef HAVE_LDAP_MEMFREE
236 ldap_memfree (dn);
237 #else
238 free (dn);
239 #endif /* HAVE_LDAP_MEMFREE */
240
241 /*
242 * If examining the DN failed, then pick the nominal first
243 * value of cn as the canonical name (recall that attributes
244 * are sets, not sequences)
245 */
246 if (status == NSS_NOTFOUND)
247 {
248 char **vals;
249
250 vals = _nss_ldap_get_values (entry, rdntype);
251
252 if (vals != NULL)
253 {
254 int rdnlen = strlen (*vals);
255 if (*buflen > rdnlen)
256 {
257 char *rdnvalue = *buffer;
258 strncpy (rdnvalue, *vals, rdnlen);
259 rdnvalue[rdnlen] = '\0';
260 *buffer += rdnlen + 1;
261 *buflen -= rdnlen + 1;
262 *rval = rdnvalue;
263 status = NSS_SUCCESS;
264 }
265 else
266 {
267 status = NSS_TRYAGAIN;
268 }
269 ldap_value_free (vals);
270 }
271 }
272
273 return status;
274 }
275
276 static NSS_STATUS
277 do_getrdnvalue (const char *dn,
278 const char *rdntype,
279 char **rval, char **buffer, size_t * buflen)
280 {
281 char **exploded_dn;
282 char *rdnvalue = NULL;
283 char rdnava[64];
284 int rdnlen = 0, rdnavalen;
285
286 snprintf (rdnava, sizeof rdnava, "%s=", rdntype);
287 rdnavalen = strlen (rdnava);
288
289 exploded_dn = ldap_explode_dn (dn, 0);
290
291 if (exploded_dn != NULL)
292 {
293 /*
294 * attempt to get the naming attribute's principal
295 * value by parsing the RDN. We need to support
296 * multivalued RDNs (as they're essentially mandated
297 * for services)
298 */
299 #ifdef HAVE_LDAP_EXPLODE_RDN
300 /*
301 * use ldap_explode_rdn() API, as it's cleaner than
302 * strtok(). This code has not been tested!
303 */
304 char **p, **exploded_rdn;
305
306 exploded_rdn = ldap_explode_rdn (*exploded_dn, 0);
307 if (exploded_rdn != NULL)
308 {
309 for (p = exploded_rdn; *p != NULL; p++)
310 {
311 if (strncasecmp (*p, rdnava, rdnavalen) == 0)
312 {
313 char *r = *p + rdnavalen;
314
315 rdnlen = strlen (r);
316 if (*buflen <= rdnlen)
317 {
318 ldap_value_free (exploded_rdn);
319 ldap_value_free (exploded_dn);
320 return NSS_TRYAGAIN;
321 }
322 rdnvalue = *buffer;
323 strncpy (rdnvalue, r, rdnlen);
324 break;
325 }
326 }
327 ldap_value_free (exploded_rdn);
328 }
329 #else
330 /*
331 * we don't have Netscape's ldap_explode_rdn() API,
332 * so we fudge it with strtok(). Note that this will
333 * not handle escaping properly.
334 */
335 char *p, *r = *exploded_dn;
336 #ifdef HAVE_STRTOK_R
337 char *st = NULL;
338 #endif
339
340 #ifndef HAVE_STRTOK_R
341 for (p = strtok (r, "+");
342 #else
343 for (p = strtok_r (r, "+", &st);
344 #endif
345 p != NULL;
346 #ifndef HAVE_STRTOK_R
347 p = strtok (NULL, "+"))
348 #else
349 p = strtok_r (NULL, "+", &st))
350 #endif
351 {
352 if (strncasecmp (p, rdnava, rdnavalen) == 0)
353 {
354 p += rdnavalen;
355 rdnlen = strlen (p);
356 if (*buflen <= rdnlen)
357 {
358 ldap_value_free (exploded_dn);
359 return NSS_TRYAGAIN;
360 }
361 rdnvalue = *buffer;
362 strncpy (rdnvalue, p, rdnlen);
363 break;
364 }
365 if (r != NULL)
366 r = NULL;
367 }
368 #endif /* HAVE_LDAP_EXPLODE_RDN */
369 }
370
371 if (exploded_dn != NULL)
372 {
373 ldap_value_free (exploded_dn);
374 }
375
376 if (rdnvalue != NULL)
377 {
378 rdnvalue[rdnlen] = '\0';
379 *buffer += rdnlen + 1;
380 *buflen -= rdnlen + 1;
381 *rval = rdnvalue;
382 return NSS_SUCCESS;
383 }
384
385 return NSS_NOTFOUND;
386 }
387
388 static NSS_STATUS
389 do_parse_map_statement (ldap_config_t * cfg,
390 const char *statement, ldap_map_type_t type)
391 {
392 char *key, *val;
393 ldap_map_selector_t sel = LM_NONE;
394
395 key = (char *) statement;
396 val = key;
397 while (*val != ' ' && *val != '\t')
398 val++;
399 *(val++) = '\0';
400
401 while (*val == ' ' || *val == '\t')
402 val++;
403
404 {
405 char *p = strchr (key, ':');
406
407 if (p != NULL)
408 {
409 *p = '\0';
410 sel = _nss_ldap_str2selector (key);
411 key = ++p;
412 }
413 }
414
415 return _nss_ldap_map_put (cfg, sel, type, key, val);
416 }
417
418 /* parse a comma-separated list */
419 static NSS_STATUS
420 do_parse_list (char *values, char ***valptr,
421 char **pbuffer, size_t *pbuflen)
422 {
423 char *s, **p;
424 #ifdef HAVE_STRTOK_R
425 char *tok_r;
426 #endif
427 int valcount;
428
429 int buflen = *pbuflen;
430 char *buffer = *pbuffer;
431
432 /* comma separated list of values to ignore on initgroups() */
433 for (valcount = 1, s = values; *s != '\0'; s++)
434 {
435 if (*s == ',')
436 valcount++;
437 }
438
439 if (bytesleft (buffer, buflen, char *) < (valcount + 1) * sizeof (char *))
440 {
441 return NSS_UNAVAIL;
442 }
443
444 align (buffer, buflen, char *);
445 p = *valptr = (char **) buffer;
446
447 buffer += (valcount + 1) * sizeof (char *);
448 buflen -= (valcount + 1) * sizeof (char *);
449
450 #ifdef HAVE_STRTOK_R
451 for (s = strtok_r(values, ",", &tok_r); s != NULL;
452 s = strtok_r(NULL, ",", &tok_r))
453 #else
454 for (s = strtok(values, ","); s != NULL; s = strtok(NULL, ","))
455 #endif
456 {
457 int vallen;
458 char *elt = NULL;
459
460 vallen = strlen (s);
461 if (buflen < (size_t) (vallen + 1))
462 {
463 return NSS_UNAVAIL;
464 }
465
466 /* copy this value into the next block of buffer space */
467 elt = buffer;
468 buffer += vallen + 1;
469 buflen -= vallen + 1;
470
471 strncpy (elt, s, vallen);
472 elt[vallen] = '\0';
473 *p++ = elt;
474 }
475
476 *p = NULL;
477 *pbuffer = buffer;
478 *pbuflen = buflen;
479
480 return NSS_SUCCESS;
481 }
482
483 ldap_map_selector_t
484 _nss_ldap_str2selector (const char *key)
485 {
486 ldap_map_selector_t sel;
487
488 if (!strcasecmp (key, MP_passwd))
489 sel = LM_PASSWD;
490 else if (!strcasecmp (key, MP_shadow))
491 sel = LM_SHADOW;
492 else if (!strcasecmp (key, MP_group))
493 sel = LM_GROUP;
494 else if (!strcasecmp (key, MP_hosts))
495 sel = LM_HOSTS;
496 else if (!strcasecmp (key, MP_services))
497 sel = LM_SERVICES;
498 else if (!strcasecmp (key, MP_networks))
499 sel = LM_NETWORKS;
500 else if (!strcasecmp (key, MP_protocols))
501 sel = LM_PROTOCOLS;
502 else if (!strcasecmp (key, MP_rpc))
503 sel = LM_RPC;
504 else if (!strcasecmp (key, MP_ethers))
505 sel = LM_ETHERS;
506 else if (!strcasecmp (key, MP_netmasks))
507 sel = LM_NETMASKS;
508 else if (!strcasecmp (key, MP_bootparams))
509 sel = LM_BOOTPARAMS;
510 else if (!strcasecmp (key, MP_aliases))
511 sel = LM_ALIASES;
512 else if (!strcasecmp (key, MP_netgroup))
513 sel = LM_NETGROUP;
514 else if (!strcasecmp (key, MP_automount))
515 sel = LM_AUTOMOUNT;
516 else
517 sel = LM_NONE;
518
519 return sel;
520 }
521
522 static NSS_STATUS
523 do_searchdescriptorconfig (const char *key, const char *value, size_t len,
524 ldap_service_search_descriptor_t ** result,
525 char **buffer, size_t * buflen)
526 {
527 ldap_service_search_descriptor_t **t, *cur;
528 char *base;
529 char *filter, *s;
530 int scope;
531 ldap_map_selector_t sel;
532
533 t = NULL;
534 filter = NULL;
535 scope = -1;
536
537 if (strncasecmp (key, NSS_LDAP_KEY_NSS_BASE_PREFIX,
538 NSS_LDAP_KEY_NSS_BASE_PREFIX_LEN) != 0)
539 return NSS_SUCCESS;
540
541 sel = _nss_ldap_str2selector (&key[NSS_LDAP_KEY_NSS_BASE_PREFIX_LEN]);
542 t = (sel < LM_NONE) ? &result[sel] : NULL;
543
544 if (t == NULL)
545 return NSS_SUCCESS;
546
547 /* we have already checked for room for the value */
548 /* len is set to the length of value */
549 base = *buffer;
550 strncpy (base, value, len);
551 base[len] = '\0';
552
553 *buffer += len + 1;
554 *buflen -= len + 1;
555
556 /* probably is some funky escaping needed here. later... */
557 s = strchr (base, '?');
558 if (s != NULL)
559 {
560 *s = '\0';
561 s++;
562 if (!strcasecmp (s, "sub"))
563 scope = LDAP_SCOPE_SUBTREE;
564 else if (!strcasecmp (s, "one"))
565 scope = LDAP_SCOPE_ONELEVEL;
566 else if (!strcasecmp (s, "base"))
567 scope = LDAP_SCOPE_BASE;
568 filter = strchr (s, '?');
569 if (filter != NULL)
570 {
571 *filter = '\0';
572 filter++;
573 }
574 }
575
576 if (bytesleft (*buffer, *buflen, ldap_service_search_descriptor_t) <
577 sizeof (ldap_service_search_descriptor_t))
578 return NSS_UNAVAIL;
579
580 align (*buffer, *buflen, ldap_service_search_descriptor_t);
581
582 for (cur = *t; cur && cur->lsd_next; cur = cur->lsd_next)
583 ;
584 if (!cur)
585 {
586 *t = (ldap_service_search_descriptor_t *) * buffer;
587 cur = *t;
588 }
589 else
590 {
591 cur->lsd_next = (ldap_service_search_descriptor_t *) * buffer;
592 cur = cur->lsd_next;
593 }
594
595 cur->lsd_base = base;
596 cur->lsd_scope = scope;
597 cur->lsd_filter = filter;
598 cur->lsd_next = NULL;
599
600 *buffer += sizeof (ldap_service_search_descriptor_t);
601 *buflen -= sizeof (ldap_service_search_descriptor_t);
602
603 return NSS_SUCCESS;
604 }
605
606 NSS_STATUS _nss_ldap_init_config (ldap_config_t * result)
607 {
608 int i, j;
609
610 memset (result, 0, sizeof (*result));
611
612 result->ldc_scope = LDAP_SCOPE_SUBTREE;
613 result->ldc_deref = LDAP_DEREF_NEVER;
614 result->ldc_base = NULL;
615 result->ldc_binddn = NULL;
616 result->ldc_bindpw = NULL;
617 result->ldc_saslid = NULL;
618 result->ldc_usesasl = 0;
619 result->ldc_rootbinddn = NULL;
620 result->ldc_rootbindpw = NULL;
621 result->ldc_rootsaslid = NULL;
622 result->ldc_rootusesasl = 0;
623 #ifdef LDAP_VERSION3
624 result->ldc_version = LDAP_VERSION3;
625 #else
626 result->ldc_version = LDAP_VERSION2;
627 #endif /* LDAP_VERSION3 */
628 result->ldc_timelimit = LDAP_NO_LIMIT;
629 result->ldc_bind_timelimit = 30;
630 result->ldc_ssl_on = SSL_OFF;
631 result->ldc_sslpath = NULL;
632 result->ldc_referrals = 1;
633 result->ldc_restart = 1;
634 result->ldc_tls_checkpeer = -1;
635 result->ldc_tls_cacertfile = NULL;
636 result->ldc_tls_cacertdir = NULL;
637 result->ldc_tls_ciphers = NULL;
638 result->ldc_tls_cert = NULL;
639 result->ldc_tls_key = NULL;
640 result->ldc_tls_randfile = NULL;
641 result->ldc_idle_timelimit = 0;
642 result->ldc_reconnect_pol = LP_RECONNECT_HARD_OPEN;
643 result->ldc_sasl_secprops = NULL;
644 result->ldc_srv_domain = NULL;
645 result->ldc_logdir = NULL;
646 result->ldc_debug = 0;
647 result->ldc_pagesize = LDAP_PAGESIZE;
648 #ifdef CONFIGURE_KRB5_CCNAME
649 result->ldc_krb5_ccname = NULL;
650 result->ldc_krb5_rootccname = NULL;
651 result->ldc_krb5_autorenew = 0;
652 result->ldc_krb5_rootautorenew = 0;
653 #endif /* CONFIGURE_KRB5_CCNAME */
654 #ifdef CONFIGURE_KRB5_KEYTAB
655 result->ldc_krb5_keytabname = NULL;
656 result->ldc_krb5_rootkeytabname = NULL;
657 result->ldc_krb5_usekeytab = 0;
658 result->ldc_krb5_rootusekeytab = 0;
659 #endif /* CONFIGURE_KRB5_KEYTAB */
660 result->ldc_flags = 0;
661 #ifdef RFC2307BIS
662 result->ldc_flags |= NSS_LDAP_FLAGS_RFC2307BIS;
663 #endif
664 #ifdef PAGE_RESULTS
665 result->ldc_flags |= NSS_LDAP_FLAGS_PAGED_RESULTS;
666 #endif
667 result->ldc_reconnect_tries = LDAP_NSS_TRIES;
668 result->ldc_reconnect_sleeptime = LDAP_NSS_SLEEPTIME;
669 result->ldc_reconnect_maxsleeptime = LDAP_NSS_MAXSLEEPTIME;
670 result->ldc_reconnect_maxconntries = LDAP_NSS_MAXCONNTRIES;
671 result->ldc_initgroups_ignoreusers = NULL;
672
673 for (i = 0; i <= LM_NONE; i++)
674 {
675 for (j = 0; j <= MAP_MAX; j++)
676 {
677 result->ldc_maps[i][j] = _nss_ldap_db_open ();
678 if (result->ldc_maps[i][j] == NULL)
679 return NSS_UNAVAIL;
680 }
681 }
682
683 return NSS_SUCCESS;
684 }
685
686 NSS_STATUS
687 _nss_ldap_add_uri (ldap_config_t *result, const char *uri,
688 char **buffer, size_t *buflen)
689 {
690 /* add a single URI to the list of URIs in the configuration */
691 int i;
692 size_t uri_len;
693
694 debug ("==> _nss_ldap_add_uri");
695
696 for (i = 0; result->ldc_uris[i] != NULL; i++)
697 ;
698
699 if (i == NSS_LDAP_CONFIG_URI_MAX)
700 {
701 debug ("<== _nss_ldap_add_uri: maximum number of URIs exceeded");
702 return NSS_UNAVAIL;
703 }
704
705 assert (i < NSS_LDAP_CONFIG_URI_MAX);
706
707 uri_len = strlen (uri);
708
709 if (*buflen < uri_len + 1)
710 return NSS_TRYAGAIN;
711
712 memcpy (*buffer, uri, uri_len + 1);
713
714 result->ldc_uris[i] = *buffer;
715 result->ldc_uris[i + 1] = NULL;
716
717 *buffer += uri_len + 1;
718 *buflen -= uri_len + 1;
719
720 debug ("<== _nss_ldap_add_uri: added URI %s", uri);
721
722 return NSS_SUCCESS;
723 }
724
725 static NSS_STATUS
726 do_add_uris (ldap_config_t *result, char *uris,
727 char **buffer, size_t *buflen)
728 {
729 /* Add a space separated list of URIs */
730 char *p;
731 NSS_STATUS stat = NSS_SUCCESS;
732
733 for (p = uris; p != NULL; )
734 {
735 char *q = strchr (p, ' ');
736 if (q != NULL)
737 *q = '\0';
738
739 stat = _nss_ldap_add_uri (result, p, buffer, buflen);
740
741 p = (q != NULL) ? ++q : NULL;
742
743 if (stat != NSS_SUCCESS)
744 break;
745 }
746
747 return stat;
748 }
749
750 static NSS_STATUS
751 do_add_hosts (ldap_config_t *result, char *hosts,
752 char **buffer, size_t *buflen)
753 {
754 /* Add a space separated list of hosts */
755 char *p;
756 NSS_STATUS stat = NSS_SUCCESS;
757
758 for (p = hosts; p != NULL; )
759 {
760 char b[NSS_LDAP_CONFIG_BUFSIZ];
761 char *q = strchr (p, ' ');
762
763 if (q != NULL)
764 *q = '\0';
765
766 snprintf (b, sizeof(b), "ldap://%s", p);
767
768 stat = _nss_ldap_add_uri (result, b, buffer, buflen);
769
770 p = (q != NULL) ? ++q : NULL;
771
772 if (stat != NSS_SUCCESS)
773 break;
774 }
775
776 return stat;
777 }
778
779 NSS_STATUS
780 _nss_ldap_readconfig (ldap_config_t ** presult, char **buffer, size_t *buflen)
781 {
782 FILE *fp;
783 char b[NSS_LDAP_CONFIG_BUFSIZ];
784 NSS_STATUS stat = NSS_SUCCESS;
785 ldap_config_t *result;
786 struct stat statbuf;
787
788 fp = fopen (NSS_LDAP_PATH_CONF, "r");
789 if (fp == NULL)
790 {
791 return NSS_UNAVAIL;
792 }
793
794 if (bytesleft (*buffer, *buflen, ldap_config_t *) < sizeof (ldap_config_t))
795 {
796 fclose (fp);
797 return NSS_TRYAGAIN;
798 }
799 align (*buffer, *buflen, ldap_config_t *);
800 result = *presult = (ldap_config_t *) *buffer;
801 *buffer += sizeof (ldap_config_t);
802 *buflen -= sizeof (ldap_config_t);
803
804 stat = _nss_ldap_init_config (result);
805 if (stat != NSS_SUCCESS)
806 {
807 fclose (fp);
808 return NSS_SUCCESS;
809 }
810
811 if (fstat (fileno (fp), &statbuf) == 0)
812 result->ldc_mtime = statbuf.st_mtime;
813 else
814 result->ldc_mtime = 0;
815
816 while (fgets (b, sizeof (b), fp) != NULL)
817 {
818 char *k, *v;
819 int len;
820 char **t = NULL;
821
822 if (*b == '\n' || *b == '\r' || *b == '#')
823 continue;
824
825 k = b;
826 v = k;
827
828 /* skip past all characters in keyword */
829 while (*v != '\0' && *v != ' ' && *v != '\t')
830 v++;
831
832 if (*v == '\0')
833 continue;
834
835 /* terminate keyword */
836 *(v++) = '\0';
837
838 /* skip empty lines with more than 3 spaces at the start of the line */
839 /* rds.oliver@samera.com.py 01-set-2004 */
840 if (*v == '\n')
841 continue;
842
843 /* skip all whitespaces between keyword and value */
844 /* Lars Oergel <lars.oergel@innominate.de>, 05.10.2000 */
845 while (*v == ' ' || *v == '\t')
846 v++;
847
848 /* kick off all whitespaces and newline at the end of value */
849 /* Bob Guo <bob@mail.ied.ac.cn>, 08.10.2001 */
850
851 /* Also remove \r (CR) to be able to handle files in DOS format (lines
852 * terminated in CR LF). Alejandro Forero Cuervo
853 * <azul@freaks-unidos.net>, 10-may-2005 */
854
855 len = strlen (v) - 1;
856 while (v[len] == ' ' || v[len] == '\t' || v[len] == '\n' || v[len] == '\r')
857 --len;
858 v[++len] = '\0';
859
860 if (*buflen < (size_t) (len + 1))
861 {
862 stat = NSS_TRYAGAIN;
863 break;
864 }
865
866 if (!strcasecmp (k, NSS_LDAP_KEY_HOST))
867 {
868 stat = do_add_hosts (result, v, buffer, buflen);
869 if (stat != NSS_SUCCESS)
870 break;
871 }
872 else if (!strcasecmp (k, NSS_LDAP_KEY_URI))
873 {
874 stat = do_add_uris (result, v, buffer, buflen);
875 if (stat != NSS_SUCCESS)
876 break;
877 }
878 else if (!strcasecmp (k, NSS_LDAP_KEY_BASE))
879 {
880 t = &result->ldc_base;
881 }
882 else if (!strcasecmp (k, NSS_LDAP_KEY_BINDDN))
883 {
884 t = &result->ldc_binddn;
885 }
886 else if (!strcasecmp (k, NSS_LDAP_KEY_BINDPW))
887 {
888 t = &result->ldc_bindpw;
889 }
890 else if (!strcasecmp (k, NSS_LDAP_KEY_USESASL))
891 {
892 result->ldc_usesasl = (!strcasecmp (v, "on")
893 || !strcasecmp (v, "yes")
894 || !strcasecmp (v, "true"));
895 }
896 else if (!strcasecmp (k, NSS_LDAP_KEY_SASLID))
897 {
898 t = &result->ldc_saslid;
899 }
900 else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTBINDDN))
901 {
902 t = &result->ldc_rootbinddn;
903 }
904 else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTUSESASL))
905 {
906 result->ldc_rootusesasl = (!strcasecmp (v, "on")
907 || !strcasecmp (v, "yes")
908 || !strcasecmp (v, "true"));
909 }
910 else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTSASLID))
911 {
912 t = &result->ldc_rootsaslid;
913 }
914 else if (!strcasecmp (k, NSS_LDAP_KEY_SSLPATH))
915 {
916 t = &result->ldc_sslpath;
917 }
918 else if (!strcasecmp (k, NSS_LDAP_KEY_SCOPE))
919 {
920 if (!strcasecmp (v, "sub"))
921 {
922 result->ldc_scope = LDAP_SCOPE_SUBTREE;
923 }
924 else if (!strcasecmp (v, "one"))
925 {
926 result->ldc_scope = LDAP_SCOPE_ONELEVEL;
927 }
928 else if (!strcasecmp (v, "base"))
929 {
930 result->ldc_scope = LDAP_SCOPE_BASE;
931 }
932 }
933 else if (!strcasecmp (k, NSS_LDAP_KEY_DEREF))
934 {
935 if (!strcasecmp (v, "never"))
936 {
937 result->ldc_deref = LDAP_DEREF_NEVER;
938 }
939 else if (!strcasecmp (v, "searching"))
940 {
941 result->ldc_deref = LDAP_DEREF_SEARCHING;
942 }
943 else if (!strcasecmp (v, "finding"))
944 {
945 result->ldc_deref = LDAP_DEREF_FINDING;
946 }
947 else if (!strcasecmp (v, "always"))
948 {
949 result->ldc_deref = LDAP_DEREF_ALWAYS;
950 }
951 }
952 else if (!strcasecmp (k, NSS_LDAP_KEY_PORT))
953 {
954 result->ldc_port = atoi (v);
955 }
956 else if (!strcasecmp (k, NSS_LDAP_KEY_SSL))
957 {
958 if (!strcasecmp (v, "on") || !strcasecmp (v, "yes")
959 || !strcasecmp (v, "true"))
960 {
961 result->ldc_ssl_on = SSL_LDAPS;
962 }
963 else if (!strcasecmp (v, "start_tls"))
964 {
965 result->ldc_ssl_on = SSL_START_TLS;
966 }
967 }
968 else if (!strcasecmp (k, NSS_LDAP_KEY_REFERRALS))
969 {
970 result->ldc_referrals = (!strcasecmp (v, "on")
971 || !strcasecmp (v, "yes")
972 || !strcasecmp (v, "true"));
973 }
974 else if (!strcasecmp (k, NSS_LDAP_KEY_RESTART))
975 {
976 result->ldc_restart = (!strcasecmp (v, "on")
977 || !strcasecmp (v, "yes")
978 || !strcasecmp (v, "true"));
979 }
980 else if (!strcasecmp (k, NSS_LDAP_KEY_LDAP_VERSION))
981 {
982 result->ldc_version = atoi (v);
983 }
984 else if (!strcasecmp (k, NSS_LDAP_KEY_TIMELIMIT))
985 {
986 result->ldc_timelimit = atoi (v);
987 }
988 else if (!strcasecmp (k, NSS_LDAP_KEY_BIND_TIMELIMIT))
989 {
990 result->ldc_bind_timelimit = atoi (v);
991 }
992 else if (!strcasecmp (k, NSS_LDAP_KEY_IDLE_TIMELIMIT))
993 {
994 result->ldc_idle_timelimit = atoi (v);
995 }
996 else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_POLICY))
997 {
998 if (!strcasecmp (v, "hard") ||
999 !strcasecmp (v, "hard_open"))
1000 {
1001 result->ldc_reconnect_pol = LP_RECONNECT_HARD_OPEN;
1002 }
1003 else if (!strcasecmp (v, "hard_init"))
1004 {
1005 result->ldc_reconnect_pol = LP_RECONNECT_HARD_INIT;
1006 }
1007 else if (!strcasecmp (v, "soft"))
1008 {
1009 result->ldc_reconnect_pol = LP_RECONNECT_SOFT;
1010 }
1011 }
1012 else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_TRIES))
1013 {
1014 result->ldc_reconnect_tries = atoi (v);
1015 }
1016 else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_SLEEPTIME))
1017 {
1018 result->ldc_reconnect_sleeptime = atoi (v);
1019 }
1020 else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_MAXSLEEPTIME))
1021 {
1022 result->ldc_reconnect_maxsleeptime = atoi (v);
1023 }
1024 else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_MAXCONNTRIES))
1025 {
1026 result->ldc_reconnect_maxconntries = atoi (v);
1027 }
1028 else if (!strcasecmp (k, NSS_LDAP_KEY_SASL_SECPROPS))
1029 {
1030 t = &result->ldc_sasl_secprops;
1031 }
1032 else if (!strcasecmp (k, NSS_LDAP_KEY_LOGDIR))
1033 {
1034 t = &result->ldc_logdir;
1035 }
1036 else if (!strcasecmp (k, NSS_LDAP_KEY_DEBUG))
1037 {
1038 result->ldc_debug = atoi (v);
1039 }
1040 else if (!strcasecmp (k, NSS_LDAP_KEY_PAGESIZE))
1041 {
1042 result->ldc_pagesize = atoi (v);
1043 }
1044 #ifdef CONFIGURE_KRB5_CCNAME
1045 else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_CCNAME))
1046 {
1047 t = &result->ldc_krb5_ccname;
1048 }
1049 else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_ROOTCCNAME))
1050 {
1051 t = &result->ldc_krb5_rootccname;
1052 }
1053 else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_AUTORENEW))
1054 {
1055 result->ldc_krb5_autorenew = atoi (v);
1056 }
1057 else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_ROOTAUTORENEW))
1058 {
1059 result->ldc_krb5_rootautorenew = atoi (v);
1060 }
1061 #endif /* CONFIGURE_KRB5_CCNAME */
1062 #ifdef CONFIGURE_KRB5_KEYTAB
1063 else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_KEYTAB))
1064 {
1065 t = &result->ldc_krb5_keytabname;
1066 }
1067 else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_ROOTKEYTAB))
1068 {
1069 t = &result->ldc_krb5_rootkeytabname;
1070 }
1071 else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_USEKEYTAB))
1072 {
1073 result->ldc_krb5_usekeytab = atoi (v);
1074 }
1075 else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_ROOTUSEKEYTAB))
1076 {
1077 result->ldc_krb5_rootusekeytab = atoi (v);
1078 }
1079 #endif /* CONFIGURE_KRB5_KEYTAB */
1080 else if (!strcasecmp (k, "tls_checkpeer"))
1081 {
1082 if (!strcasecmp (v, "on") || !strcasecmp (v, "yes")
1083 || !strcasecmp (v, "true"))
1084 {
1085 result->ldc_tls_checkpeer = 1;
1086 }
1087 else if (!strcasecmp (v, "off") || !strcasecmp (v, "no")
1088 || !strcasecmp (v, "false"))
1089 {
1090 result->ldc_tls_checkpeer = 0;
1091 }
1092 }
1093 else if (!strcasecmp (k, "tls_cacertfile"))
1094 {
1095 t = &result->ldc_tls_cacertfile;
1096 }
1097 else if (!strcasecmp (k, "tls_cacertdir"))
1098 {
1099 t = &result->ldc_tls_cacertdir;
1100 }
1101 else if (!strcasecmp (k, "tls_ciphers"))
1102 {
1103 t = &result->ldc_tls_ciphers;
1104 }
1105 else if (!strcasecmp (k, "tls_cert"))
1106 {
1107 t = &result->ldc_tls_cert;
1108 }
1109 else if (!strcasecmp (k, "tls_key"))
1110 {
1111 t = &result->ldc_tls_key;
1112 }
1113 else if (!strcasecmp (k, "tls_randfile"))
1114 {
1115 t = &result->ldc_tls_randfile;
1116 }
1117 else if (!strncasecmp (k, NSS_LDAP_KEY_MAP_ATTRIBUTE,
1118 strlen (NSS_LDAP_KEY_MAP_ATTRIBUTE)))
1119 {
1120 do_parse_map_statement (result, v, MAP_ATTRIBUTE);
1121 }
1122 else if (!strncasecmp (k, NSS_LDAP_KEY_MAP_OBJECTCLASS,
1123 strlen (NSS_LDAP_KEY_MAP_OBJECTCLASS)))
1124 {
1125 do_parse_map_statement (result, v, MAP_OBJECTCLASS);
1126 }
1127 else if (!strncasecmp (k, NSS_LDAP_KEY_SET_OVERRIDE,
1128 strlen (NSS_LDAP_KEY_SET_OVERRIDE)))
1129 {
1130 do_parse_map_statement (result, v, MAP_OVERRIDE);
1131 }
1132 else if (!strncasecmp (k, NSS_LDAP_KEY_SET_DEFAULT,
1133 strlen (NSS_LDAP_KEY_SET_DEFAULT)))
1134 {
1135 do_parse_map_statement (result, v, MAP_DEFAULT);
1136 }
1137 else if (!strcasecmp (k, NSS_LDAP_KEY_INITGROUPS))
1138 {
1139 if (!strcasecmp (v, "backlink"))
1140 {
1141 result->ldc_flags |= NSS_LDAP_FLAGS_INITGROUPS_BACKLINK;
1142 }
1143 else
1144 {
1145 result->ldc_flags &= ~(NSS_LDAP_FLAGS_INITGROUPS_BACKLINK);
1146 }
1147 }
1148 else if (!strcasecmp (k, NSS_LDAP_KEY_SCHEMA))
1149 {
1150 if (!strcasecmp (v, "rfc2307bis"))
1151 {
1152 result->ldc_flags |= NSS_LDAP_FLAGS_RFC2307BIS;
1153 }
1154 else if (!strcasecmp (v, "rfc2307"))
1155 {
1156 result->ldc_flags &= ~(NSS_LDAP_FLAGS_RFC2307BIS);
1157 }
1158 }
1159 else if (!strcasecmp (k, NSS_LDAP_KEY_PAGED_RESULTS))
1160 {
1161 if (!strcasecmp (v, "on")
1162 || !strcasecmp (v, "yes")
1163 || !strcasecmp (v, "true"))
1164 {
1165 result->ldc_flags |= NSS_LDAP_FLAGS_PAGED_RESULTS;
1166 }
1167 else
1168 {
1169 result->ldc_flags &= ~(NSS_LDAP_FLAGS_PAGED_RESULTS);
1170 }
1171 }
1172 else if (!strcasecmp (k, NSS_LDAP_KEY_INITGROUPS_IGNOREUSERS))
1173 {
1174 stat = do_parse_list (v, &result->ldc_initgroups_ignoreusers,
1175 buffer, buflen);
1176 if (stat == NSS_UNAVAIL)
1177 {
1178 break;
1179 }
1180 }
1181 else if (!strcasecmp (k, NSS_LDAP_KEY_GETGRENT_SKIPMEMBERS))
1182 {
1183 if (!strcasecmp (v, "on") || !strcasecmp (v, "yes")
1184 || !strcasecmp (v, "true"))
1185 {
1186 result->ldc_flags |= NSS_LDAP_FLAGS_GETGRENT_SKIPMEMBERS;
1187 }
1188 else if (!strcasecmp (v, "off") || !strcasecmp (v, "no")
1189 || !strcasecmp (v, "false"))
1190 {
1191 result->ldc_flags &= ~(NSS_LDAP_FLAGS_GETGRENT_SKIPMEMBERS);
1192 }
1193 }
1194 else if (!strcasecmp (k, NSS_LDAP_KEY_CONNECT_POLICY))
1195 {
1196 if (!strcasecmp (v, "oneshot"))
1197 {
1198 result->ldc_flags |= NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT;
1199 }
1200 else if (!strcasecmp (v, "persist"))
1201 {
1202 result->ldc_flags &= ~(NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT);
1203 }
1204 }
1205 else if (!strcasecmp (k, NSS_LDAP_KEY_SRV_DOMAIN))
1206 {
1207 t = &result->ldc_srv_domain;
1208 }
1209 else
1210 {
1211 /*
1212 * check whether the key is a naming context key
1213 * if yes, parse; otherwise just return NSS_SUCCESS
1214 * so we can ignore keys we don't understand.
1215 */
1216 stat =
1217 do_searchdescriptorconfig (k, v, len, result->ldc_sds,
1218 buffer, buflen);
1219 if (stat == NSS_UNAVAIL)
1220 {
1221 break;
1222 }
1223 }
1224
1225 if (t != NULL)
1226 {
1227 strncpy (*buffer, v, len);
1228 (*buffer)[len] = '\0';
1229 *t = *buffer;
1230 *buffer += len + 1;
1231 *buflen -= len + 1;
1232 }
1233 }
1234
1235 fclose (fp);
1236
1237 if (stat != NSS_SUCCESS)
1238 {
1239 return stat;
1240 }
1241
1242 if (result->ldc_rootbinddn != NULL)
1243 {
1244 fp = fopen (NSS_LDAP_PATH_ROOTPASSWD, "r");
1245 if (fp)
1246 {
1247 if (fgets (b, sizeof (b), fp) != NULL)
1248 {
1249 int len;
1250
1251 len = strlen (b);
1252 /* BUG#138: check for newline before removing */
1253 if (len > 0 && b[len - 1] == '\n')
1254 len--;
1255
1256 if (*buflen < (size_t) (len + 1))
1257 {
1258 fclose (fp);
1259 return NSS_UNAVAIL;
1260 }
1261
1262 strncpy (*buffer, b, len);
1263 (*buffer)[len] = '\0';
1264 result->ldc_rootbindpw = *buffer;
1265 *buffer += len + 1;
1266 *buflen -= len + 1;
1267 }
1268 fclose (fp);
1269 }
1270 else if (!result->ldc_rootusesasl)
1271 {
1272 result->ldc_rootbinddn = NULL;
1273 }
1274 }
1275
1276 if (result->ldc_port == 0 &&
1277 result->ldc_ssl_on == SSL_LDAPS)
1278 {
1279 result->ldc_port = LDAPS_PORT;
1280 }
1281
1282 if (result->ldc_uris[0] == NULL)
1283 {
1284 stat = NSS_NOTFOUND;
1285 }
1286
1287 return stat;
1288 }
1289
1290 NSS_STATUS
1291 _nss_ldap_escape_string (const char *str, char *buf, size_t buflen)
1292 {
1293 int ret = NSS_TRYAGAIN;
1294 char *p = buf;
1295 char *limit = p + buflen - 3;
1296 const char *s = str;
1297
1298 while (p < limit && *s)
1299 {
1300 switch (*s)
1301 {
1302 case '*':
1303 strcpy (p, "\\2a");
1304 p += 3;
1305 break;
1306 case '(':
1307 strcpy (p, "\\28");
1308 p += 3;
1309 break;
1310 case ')':
1311 strcpy (p, "\\29");
1312 p += 3;
1313 break;
1314 case '\\':
1315 strcpy (p, "\\5c");
1316 p += 3;
1317 break;
1318 default:
1319 *p++ = *s;
1320 break;
1321 }
1322 s++;
1323 }
1324
1325 if (*s == '\0')
1326 {
1327 /* got to end */
1328 *p = '\0';
1329 ret = NSS_SUCCESS;
1330 }
1331
1332 return ret;
1333 }
1334
1335 /* XXX just a linked list for now */
1336
1337 struct ldap_dictionary
1338 {
1339 ldap_datum_t key;
1340 ldap_datum_t value;
1341 struct ldap_dictionary *next;
1342 };
1343
1344 static struct ldap_dictionary *
1345 do_alloc_dictionary (void)
1346 {
1347 struct ldap_dictionary *dict;
1348
1349 dict = malloc (sizeof (*dict));
1350 if (dict == NULL)
1351 {
1352 return NULL;
1353 }
1354 NSS_LDAP_DATUM_ZERO (&dict->key);
1355 NSS_LDAP_DATUM_ZERO (&dict->value);
1356 dict->next = NULL;
1357
1358 return dict;
1359 }
1360
1361 static void
1362 do_free_datum (ldap_datum_t * datum)
1363 {
1364 if (datum->data != NULL)
1365 {
1366 free (datum->data);
1367 datum->data = NULL;
1368 }
1369 datum->size = 0;
1370 }
1371
1372 static struct ldap_dictionary *
1373 do_find_last (struct ldap_dictionary *dict)
1374 {
1375 struct ldap_dictionary *p;
1376
1377 for (p = dict; p->next != NULL; p = p->next)
1378 ;
1379
1380 return p;
1381 }
1382
1383 static void
1384 do_free_dictionary (struct ldap_dictionary *dict)
1385 {
1386 do_free_datum (&dict->key);
1387 do_free_datum (&dict->value);
1388 free (dict);
1389 }
1390
1391 static NSS_STATUS
1392 do_dup_datum (unsigned flags, ldap_datum_t * dst, const ldap_datum_t * src)
1393 {
1394 dst->data = malloc (src->size);
1395 if (dst->data == NULL)
1396 return NSS_TRYAGAIN;
1397
1398 memcpy (dst->data, src->data, src->size);
1399 dst->size = src->size;
1400
1401 return NSS_SUCCESS;
1402 }
1403
1404 void *
1405 _nss_ldap_db_open (void)
1406 {
1407 return (void *) do_alloc_dictionary ();
1408 }
1409
1410 void
1411 _nss_ldap_db_close (void *db)
1412 {
1413 struct ldap_dictionary *dict;
1414
1415 dict = (struct ldap_dictionary *) db;
1416
1417 while (dict != NULL)
1418 {
1419 struct ldap_dictionary *next = dict->next;
1420
1421 do_free_dictionary (dict);
1422
1423 dict = next;
1424 }
1425 }
1426
1427 NSS_STATUS
1428 _nss_ldap_db_get (void *db,
1429 unsigned flags,
1430 const ldap_datum_t * key,
1431 ldap_datum_t * value)
1432 {
1433 struct ldap_dictionary *dict = (struct ldap_dictionary *) db;
1434 struct ldap_dictionary *p;
1435
1436 for (p = dict; p != NULL; p = p->next)
1437 {
1438 int cmp;
1439
1440 if (p->key.size != key->size)
1441 continue;
1442
1443 if (flags & NSS_LDAP_DB_NORMALIZE_CASE)
1444 cmp = strncasecmp ((char *)p->key.data, (char *)key->data, key->size);
1445 else
1446 cmp = memcmp (p->key.data, key->data, key->size);
1447
1448 if (cmp == 0)
1449 {
1450 value->data = p->value.data;
1451 value->size = p->value.size;
1452
1453 return NSS_SUCCESS;
1454 }
1455 }
1456
1457 return NSS_NOTFOUND;
1458 }
1459
1460 NSS_STATUS
1461 _nss_ldap_db_put (void *db,
1462 unsigned flags,
1463 const ldap_datum_t * key,
1464 const ldap_datum_t * value)
1465 {
1466 struct ldap_dictionary *dict = (struct ldap_dictionary *) db;
1467 struct ldap_dictionary *p, *q;
1468
1469 assert (key != NULL);
1470 assert (key->data != NULL);
1471
1472 if (dict->key.data == NULL)
1473 {
1474 /* uninitialized */
1475 q = dict;
1476 p = NULL;
1477 }
1478 else
1479 {
1480 p = do_find_last (dict);
1481 assert (p != NULL);
1482 assert (p->next == NULL);
1483 q = do_alloc_dictionary ();
1484 if (q == NULL)
1485 return NSS_TRYAGAIN;
1486 }
1487
1488 if (do_dup_datum (flags, &q->key, key) != NSS_SUCCESS)
1489 {
1490 do_free_dictionary (q);
1491 return NSS_TRYAGAIN;
1492 }
1493
1494 if (do_dup_datum (flags, &q->value, value) != NSS_SUCCESS)
1495 {
1496 do_free_dictionary (q);
1497 return NSS_TRYAGAIN;
1498 }
1499
1500 if (p != NULL)
1501 p->next = q;
1502
1503 return NSS_SUCCESS;
1504 }
1505
1506 /*
1507 * Add a nested netgroup or group to the namelist
1508 */
1509 NSS_STATUS
1510 _nss_ldap_namelist_push (struct name_list **head, const char *name)
1511 {
1512 struct name_list *nl;
1513
1514 debug ("==> _nss_ldap_namelist_push (%s)", name);
1515
1516 nl = (struct name_list *) malloc (sizeof (*nl));
1517 if (nl == NULL)
1518 {
1519 debug ("<== _nss_ldap_namelist_push");
1520 return NSS_TRYAGAIN;
1521 }
1522
1523 nl->name = strdup (name);
1524 if (nl->name == NULL)
1525 {
1526 debug ("<== _nss_ldap_namelist_push");
1527 free (nl);
1528 return NSS_TRYAGAIN;
1529 }
1530
1531 nl->next = *head;
1532
1533 *head = nl;
1534
1535 debug ("<== _nss_ldap_namelist_push");
1536
1537 return NSS_SUCCESS;
1538 }
1539
1540 /*
1541 * Remove last nested netgroup or group from the namelist
1542 */
1543 void
1544 _nss_ldap_namelist_pop (struct name_list **head)
1545 {
1546 struct name_list *nl;
1547
1548 debug ("==> _nss_ldap_namelist_pop");
1549
1550 assert (*head != NULL);
1551 nl = *head;
1552
1553 *head = nl->next;
1554
1555 assert (nl->name != NULL);
1556 free (nl->name);
1557 free (nl);
1558
1559 debug ("<== _nss_ldap_namelist_pop");
1560 }
1561
1562 /*
1563 * Cleanup nested netgroup or group namelist.
1564 */
1565 void
1566 _nss_ldap_namelist_destroy (struct name_list **head)
1567 {
1568 struct name_list *p, *next;
1569
1570 debug ("==> _nss_ldap_namelist_destroy");
1571
1572 for (p = *head; p != NULL; p = next)
1573 {
1574 next = p->next;
1575
1576 if (p->name != NULL)
1577 free (p->name);
1578 free (p);
1579 }
1580
1581 *head = NULL;
1582
1583 debug ("<== _nss_ldap_namelist_destroy");
1584 }
1585
1586 /*
1587 * Check whether we have already seen a netgroup or group,
1588 * to avoid loops in nested netgroup traversal
1589 */
1590 int
1591 _nss_ldap_namelist_find (struct name_list *head, const char *netgroup)
1592 {
1593 struct name_list *p;
1594 int found = 0;
1595
1596 debug ("==> _nss_ldap_namelist_find");
1597
1598 for (p = head; p != NULL; p = p->next)
1599 {
1600 if (strcasecmp (p->name, netgroup) == 0)
1601 {
1602 found++;
1603 break;
1604 }
1605 }
1606
1607 debug ("<== _nss_ldap_namelist_find");
1608
1609 return found;
1610 }
1611
1612 NSS_STATUS _nss_ldap_validateconfig (ldap_config_t *config)
1613 {
1614 struct stat statbuf;
1615
1616 if (config == NULL)
1617 {
1618 return NSS_UNAVAIL;
1619 }
1620
1621 if (config->ldc_mtime == 0)
1622 {
1623 return NSS_SUCCESS;
1624 }
1625
1626 if (stat (NSS_LDAP_PATH_CONF, &statbuf) == 0)
1627 {
1628 return (statbuf.st_mtime > config->ldc_mtime) ? NSS_TRYAGAIN : NSS_SUCCESS;
1629 }
1630
1631 return NSS_SUCCESS;
1632 }
1633
1634 /*
1635 * Parse a text string into a long integer. If we fail for
1636 * any reason, store the passed-in default value and return
1637 * an error.
1638 */
1639 NSS_STATUS
1640 _nss_ldap_parse_long (const char *text, long default_value, long *value)
1641 {
1642 char *p;
1643 long l;
1644
1645 if (text == NULL || strlen(text) == 0)
1646 {
1647 *value = default_value;
1648 return NSS_NOTFOUND;
1649 }
1650
1651 l = strtol(text, &p, 10);
1652 if (p == NULL || p == text || *p != '\0')
1653 {
1654 *value = default_value;
1655 return NSS_NOTFOUND;
1656 }
1657
1658 *value = l;
1659
1660 return NSS_SUCCESS;
1661 }
1662
1663 NSS_STATUS
1664 _nss_ldap_parse_ulong (const char *text, unsigned long default_value,
1665 unsigned long *value)
1666 {
1667 char *p;
1668 unsigned long l;
1669
1670 if (text == NULL || strlen(text) == 0)
1671 {
1672 *value = default_value;
1673 return NSS_NOTFOUND;
1674 }
1675
1676 l = strtoul(text, &p, 10);
1677 if (p == NULL || p == text || *p != '\0')
1678 {
1679 *value = default_value;
1680 return NSS_NOTFOUND;
1681 }
1682
1683 *value = l;
1684
1685 return NSS_SUCCESS;
1686 }
1687
1688 NSS_STATUS
1689 _nss_ldap_parse_int (const char *text, int default_value, int *value)
1690 {
1691 char *p;
1692 long l;
1693
1694 if (text == NULL || strlen(text) == 0)
1695 {
1696 *value = default_value;
1697 return NSS_NOTFOUND;
1698 }
1699
1700 l = strtol(text, &p, 10);
1701 if (p == NULL || p == text || *p != '\0')
1702 {
1703 *value = default_value;
1704 return NSS_NOTFOUND;
1705 }
1706
1707 if (l < INT_MIN || l > INT_MAX)
1708 {
1709 *value = default_value;
1710 return NSS_NOTFOUND;
1711 }
1712
1713 *value = l;
1714
1715 return NSS_SUCCESS;
1716 }
1717
1718 NSS_STATUS
1719 _nss_ldap_parse_uid_t (const char *text, uid_t default_value, uid_t *value)
1720 {
1721 char *p;
1722 unsigned long l;
1723
1724 if (text == NULL || strlen(text) == 0)
1725 {
1726 *value = default_value;
1727 return NSS_NOTFOUND;
1728 }
1729
1730 l = strtoul(text, &p, 10);
1731 if (p == NULL || p == text || *p != '\0')
1732 {
1733 *value = default_value;
1734 return NSS_NOTFOUND;
1735 }
1736 #if SIZEOF_UID_T == SIZEOF_UNSIGNED_INT
1737 if (l > UINT_MAX)
1738 {
1739 *value = default_value;
1740 return NSS_NOTFOUND;
1741 }
1742 #endif
1743
1744 *value = l;
1745
1746 return NSS_SUCCESS;
1747 }
1748
1749 NSS_STATUS
1750 _nss_ldap_parse_gid_t (const char *text, gid_t default_value, gid_t *value)
1751 {
1752 char *p;
1753 unsigned long l;
1754
1755 if (text == NULL || strlen(text) == 0)
1756 {
1757 *value = default_value;
1758 return NSS_NOTFOUND;
1759 }
1760
1761 l = strtoul(text, &p, 10);
1762 if (p == NULL || p == text || *p != '\0')
1763 {
1764 *value = default_value;
1765 return NSS_NOTFOUND;
1766 }
1767 #if SIZEOF_GID_T == SIZEOF_UNSIGNED_INT
1768 if (l > UINT_MAX)
1769 {
1770 *value = default_value;
1771 return NSS_NOTFOUND;
1772 }
1773 #endif
1774
1775 *value = l;
1776
1777 return NSS_SUCCESS;
1778 }