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.)
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.
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.
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.
25
#if defined(HAVE_THREAD_H) && !defined(_AIX)
27
#elif defined(HAVE_PTHREAD_H)
38
#include <sys/param.h>
61
static char rcsId[] = "$Id: util.c,v 2.132 2006/01/25 20:30:27 lukeh Exp $";
63
static NSS_STATUS do_getrdnvalue (const char *dn,
65
char **rval, char **buffer,
69
static NSS_STATUS do_parse_map_statement (ldap_config_t * cfg,
70
const char *statement,
71
ldap_map_type_t type);
73
static NSS_STATUS do_searchdescriptorconfig (const char *key,
76
ldap_service_search_descriptor_t
77
** result, char **buffer,
81
static void *__cache = NULL;
83
NSS_LDAP_DEFINE_LOCK (__cache_lock);
85
#define cache_lock() NSS_LDAP_LOCK(__cache_lock)
86
#define cache_unlock() NSS_LDAP_UNLOCK(__cache_lock)
89
dn2uid_cache_put (const char *dn, const char *uid)
92
ldap_datum_t key, val;
98
__cache = _nss_ldap_db_open ();
106
key.data = (void *) dn;
107
key.size = strlen (dn);
108
val.data = (void *) uid;
109
val.size = strlen (uid);
111
stat = _nss_ldap_db_put (__cache, 0, &key, &val);
119
dn2uid_cache_get (const char *dn, char **uid, char **buffer, size_t * buflen)
121
ldap_datum_t key, val;
132
key.data = (void *) dn;
133
key.size = strlen (dn);
135
stat = _nss_ldap_db_get (__cache, 0, &key, &val);
136
if (stat != NSS_SUCCESS)
142
if (*buflen <= val.size)
149
memcpy (*uid, (char *) val.data, val.size);
150
(*uid)[val.size] = '\0';
151
*buffer += val.size + 1;
152
*buflen -= val.size + 1;
159
static int lock_inited = 0;
163
_nss_ldap_dn2uid (const char *dn, char **uid, char **buffer, size_t * buflen,
164
int *pIsNestedGroup, LDAPMessage ** pRes)
168
debug ("==> _nss_ldap_dn2uid");
173
/* XXX this is not thread-safe */
176
__thread_mutex_init (&__cache_lock, NULL);
181
stat = dn2uid_cache_get (dn, uid, buffer, buflen);
182
if (stat == NSS_NOTFOUND)
184
const char *attrs[4];
187
attrs[0] = ATM (LM_PASSWD, uid);
188
attrs[1] = ATM (LM_GROUP, uniqueMember);
189
attrs[2] = AT (objectClass);
192
if (_nss_ldap_read (dn, attrs, &res) == NSS_SUCCESS)
194
LDAPMessage *e = _nss_ldap_first_entry (res);
197
if (_nss_ldap_oc_check (e, OC (posixGroup)) == NSS_SUCCESS)
201
debug ("<== _nss_ldap_dn2uid (nested group)");
206
_nss_ldap_assign_attrval (e, ATM (LM_PASSWD, uid), uid,
208
if (stat == NSS_SUCCESS)
209
dn2uid_cache_put (dn, *uid);
215
debug ("<== _nss_ldap_dn2uid");
221
_nss_ldap_getrdnvalue (LDAPMessage * entry,
223
char **rval, char **buffer, size_t * buflen)
228
dn = _nss_ldap_get_dn (entry);
234
status = do_getrdnvalue (dn, rdntype, rval, buffer, buflen);
235
#ifdef HAVE_LDAP_MEMFREE
239
#endif /* HAVE_LDAP_MEMFREE */
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)
246
if (status == NSS_NOTFOUND)
250
vals = _nss_ldap_get_values (entry, rdntype);
254
int rdnlen = strlen (*vals);
255
if (*buflen > rdnlen)
257
char *rdnvalue = *buffer;
258
strncpy (rdnvalue, *vals, rdnlen);
259
rdnvalue[rdnlen] = '\0';
260
*buffer += rdnlen + 1;
261
*buflen -= rdnlen + 1;
263
status = NSS_SUCCESS;
267
status = NSS_TRYAGAIN;
269
ldap_value_free (vals);
277
do_getrdnvalue (const char *dn,
279
char **rval, char **buffer, size_t * buflen)
282
char *rdnvalue = NULL;
284
int rdnlen = 0, rdnavalen;
286
snprintf (rdnava, sizeof rdnava, "%s=", rdntype);
287
rdnavalen = strlen (rdnava);
289
exploded_dn = ldap_explode_dn (dn, 0);
291
if (exploded_dn != NULL)
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
299
#ifdef HAVE_LDAP_EXPLODE_RDN
301
* use ldap_explode_rdn() API, as it's cleaner than
302
* strtok(). This code has not been tested!
304
char **p, **exploded_rdn;
306
exploded_rdn = ldap_explode_rdn (*exploded_dn, 0);
307
if (exploded_rdn != NULL)
309
for (p = exploded_rdn; *p != NULL; p++)
311
if (strncasecmp (*p, rdnava, rdnavalen) == 0)
313
char *r = *p + rdnavalen;
316
if (*buflen <= rdnlen)
318
ldap_value_free (exploded_rdn);
319
ldap_value_free (exploded_dn);
323
strncpy (rdnvalue, r, rdnlen);
327
ldap_value_free (exploded_rdn);
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.
335
char *p, *r = *exploded_dn;
340
#ifndef HAVE_STRTOK_R
341
for (p = strtok (r, "+");
343
for (p = strtok_r (r, "+", &st);
346
#ifndef HAVE_STRTOK_R
347
p = strtok (NULL, "+"))
349
p = strtok_r (NULL, "+", &st))
352
if (strncasecmp (p, rdnava, rdnavalen) == 0)
356
if (*buflen <= rdnlen)
358
ldap_value_free (exploded_dn);
362
strncpy (rdnvalue, p, rdnlen);
368
#endif /* HAVE_LDAP_EXPLODE_RDN */
371
if (exploded_dn != NULL)
373
ldap_value_free (exploded_dn);
376
if (rdnvalue != NULL)
378
rdnvalue[rdnlen] = '\0';
379
*buffer += rdnlen + 1;
380
*buflen -= rdnlen + 1;
389
do_parse_map_statement (ldap_config_t * cfg,
390
const char *statement, ldap_map_type_t type)
393
ldap_map_selector_t sel = LM_NONE;
395
key = (char *) statement;
397
while (*val != ' ' && *val != '\t')
401
while (*val == ' ' || *val == '\t')
405
char *p = strchr (key, ':');
410
sel = _nss_ldap_str2selector (key);
415
return _nss_ldap_map_put (cfg, sel, type, key, val);
418
/* parse a comma-separated list */
420
do_parse_list (char *values, char ***valptr,
421
char **pbuffer, size_t *pbuflen)
429
int buflen = *pbuflen;
430
char *buffer = *pbuffer;
432
/* comma separated list of values to ignore on initgroups() */
433
for (valcount = 1, s = values; *s != '\0'; s++)
439
if (bytesleft (buffer, buflen, char *) < (valcount + 1) * sizeof (char *))
444
align (buffer, buflen, char *);
445
p = *valptr = (char **) buffer;
447
buffer += (valcount + 1) * sizeof (char *);
448
buflen -= (valcount + 1) * sizeof (char *);
451
for (s = strtok_r(values, ",", &tok_r); s != NULL;
452
s = strtok_r(NULL, ",", &tok_r))
454
for (s = strtok(values, ","); s != NULL; s = strtok(NULL, ","))
461
if (buflen < (size_t) (vallen + 1))
466
/* copy this value into the next block of buffer space */
468
buffer += vallen + 1;
469
buflen -= vallen + 1;
471
strncpy (elt, s, vallen);
484
_nss_ldap_str2selector (const char *key)
486
ldap_map_selector_t sel;
488
if (!strcasecmp (key, MP_passwd))
490
else if (!strcasecmp (key, MP_shadow))
492
else if (!strcasecmp (key, MP_group))
494
else if (!strcasecmp (key, MP_hosts))
496
else if (!strcasecmp (key, MP_services))
498
else if (!strcasecmp (key, MP_networks))
500
else if (!strcasecmp (key, MP_protocols))
502
else if (!strcasecmp (key, MP_rpc))
504
else if (!strcasecmp (key, MP_ethers))
506
else if (!strcasecmp (key, MP_netmasks))
508
else if (!strcasecmp (key, MP_bootparams))
510
else if (!strcasecmp (key, MP_aliases))
512
else if (!strcasecmp (key, MP_netgroup))
514
else if (!strcasecmp (key, MP_automount))
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)
527
ldap_service_search_descriptor_t **t, *cur;
531
ldap_map_selector_t sel;
537
if (strncasecmp (key, NSS_LDAP_KEY_NSS_BASE_PREFIX,
538
NSS_LDAP_KEY_NSS_BASE_PREFIX_LEN) != 0)
541
sel = _nss_ldap_str2selector (&key[NSS_LDAP_KEY_NSS_BASE_PREFIX_LEN]);
542
t = (sel < LM_NONE) ? &result[sel] : NULL;
547
/* we have already checked for room for the value */
548
/* len is set to the length of value */
550
strncpy (base, value, len);
556
/* probably is some funky escaping needed here. later... */
557
s = strchr (base, '?');
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, '?');
576
if (bytesleft (*buffer, *buflen, ldap_service_search_descriptor_t) <
577
sizeof (ldap_service_search_descriptor_t))
580
align (*buffer, *buflen, ldap_service_search_descriptor_t);
582
for (cur = *t; cur && cur->lsd_next; cur = cur->lsd_next)
586
*t = (ldap_service_search_descriptor_t *) * buffer;
591
cur->lsd_next = (ldap_service_search_descriptor_t *) * buffer;
595
cur->lsd_base = base;
596
cur->lsd_scope = scope;
597
cur->lsd_filter = filter;
598
cur->lsd_next = NULL;
600
*buffer += sizeof (ldap_service_search_descriptor_t);
601
*buflen -= sizeof (ldap_service_search_descriptor_t);
606
NSS_STATUS _nss_ldap_init_config (ldap_config_t * result)
610
memset (result, 0, sizeof (*result));
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;
624
result->ldc_version = LDAP_VERSION3;
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
#endif /* CONFIGURE_KRB5_CCNAME */
651
result->ldc_flags = 0;
653
result->ldc_flags |= NSS_LDAP_FLAGS_RFC2307BIS;
656
result->ldc_flags |= NSS_LDAP_FLAGS_PAGED_RESULTS;
658
result->ldc_reconnect_tries = LDAP_NSS_TRIES;
659
result->ldc_reconnect_sleeptime = LDAP_NSS_SLEEPTIME;
660
result->ldc_reconnect_maxsleeptime = LDAP_NSS_MAXSLEEPTIME;
661
result->ldc_reconnect_maxconntries = LDAP_NSS_MAXCONNTRIES;
662
result->ldc_initgroups_ignoreusers = NULL;
664
for (i = 0; i <= LM_NONE; i++)
666
for (j = 0; j <= MAP_MAX; j++)
668
result->ldc_maps[i][j] = _nss_ldap_db_open ();
669
if (result->ldc_maps[i][j] == NULL)
678
_nss_ldap_add_uri (ldap_config_t *result, const char *uri,
679
char **buffer, size_t *buflen)
681
/* add a single URI to the list of URIs in the configuration */
685
debug ("==> _nss_ldap_add_uri");
687
for (i = 0; result->ldc_uris[i] != NULL; i++)
690
if (i == NSS_LDAP_CONFIG_URI_MAX)
692
debug ("<== _nss_ldap_add_uri: maximum number of URIs exceeded");
696
assert (i < NSS_LDAP_CONFIG_URI_MAX);
698
uri_len = strlen (uri);
700
if (*buflen < uri_len + 1)
703
memcpy (*buffer, uri, uri_len + 1);
705
result->ldc_uris[i] = *buffer;
706
result->ldc_uris[i + 1] = NULL;
708
*buffer += uri_len + 1;
709
*buflen -= uri_len + 1;
711
debug ("<== _nss_ldap_add_uri: added URI %s", uri);
717
do_add_uris (ldap_config_t *result, char *uris,
718
char **buffer, size_t *buflen)
720
/* Add a space separated list of URIs */
722
NSS_STATUS stat = NSS_SUCCESS;
724
for (p = uris; p != NULL; )
726
char *q = strchr (p, ' ');
730
stat = _nss_ldap_add_uri (result, p, buffer, buflen);
732
p = (q != NULL) ? ++q : NULL;
734
if (stat != NSS_SUCCESS)
742
do_add_hosts (ldap_config_t *result, char *hosts,
743
char **buffer, size_t *buflen)
745
/* Add a space separated list of hosts */
747
NSS_STATUS stat = NSS_SUCCESS;
749
for (p = hosts; p != NULL; )
751
char b[NSS_LDAP_CONFIG_BUFSIZ];
752
char *q = strchr (p, ' ');
757
snprintf (b, sizeof(b), "ldap://%s", p);
759
stat = _nss_ldap_add_uri (result, b, buffer, buflen);
761
p = (q != NULL) ? ++q : NULL;
763
if (stat != NSS_SUCCESS)
771
_nss_ldap_readconfig (ldap_config_t ** presult, char **buffer, size_t *buflen)
774
char b[NSS_LDAP_CONFIG_BUFSIZ];
775
NSS_STATUS stat = NSS_SUCCESS;
776
ldap_config_t *result;
779
if (bytesleft (*buffer, *buflen, ldap_config_t *) < sizeof (ldap_config_t))
783
align (*buffer, *buflen, ldap_config_t *);
784
result = *presult = (ldap_config_t *) *buffer;
785
*buffer += sizeof (ldap_config_t);
786
*buflen -= sizeof (ldap_config_t);
788
stat = _nss_ldap_init_config (result);
789
if (stat != NSS_SUCCESS)
794
fp = fopen (NSS_LDAP_PATH_CONF, "r");
800
if (fstat (fileno (fp), &statbuf) == 0)
801
result->ldc_mtime = statbuf.st_mtime;
803
result->ldc_mtime = 0;
805
while (fgets (b, sizeof (b), fp) != NULL)
811
if (*b == '\n' || *b == '\r' || *b == '#')
817
/* skip past all characters in keyword */
818
while (*v != '\0' && *v != ' ' && *v != '\t')
824
/* terminate keyword */
827
/* skip empty lines with more than 3 spaces at the start of the line */
828
/* rds.oliver@samera.com.py 01-set-2004 */
832
/* skip all whitespaces between keyword and value */
833
/* Lars Oergel <lars.oergel@innominate.de>, 05.10.2000 */
834
while (*v == ' ' || *v == '\t')
837
/* kick off all whitespaces and newline at the end of value */
838
/* Bob Guo <bob@mail.ied.ac.cn>, 08.10.2001 */
840
/* Also remove \r (CR) to be able to handle files in DOS format (lines
841
* terminated in CR LF). Alejandro Forero Cuervo
842
* <azul@freaks-unidos.net>, 10-may-2005 */
844
len = strlen (v) - 1;
845
while (v[len] == ' ' || v[len] == '\t' || v[len] == '\n' || v[len] == '\r')
849
if (*buflen < (size_t) (len + 1))
855
if (!strcasecmp (k, NSS_LDAP_KEY_HOST))
857
stat = do_add_hosts (result, v, buffer, buflen);
858
if (stat != NSS_SUCCESS)
861
else if (!strcasecmp (k, NSS_LDAP_KEY_URI))
863
stat = do_add_uris (result, v, buffer, buflen);
864
if (stat != NSS_SUCCESS)
867
else if (!strcasecmp (k, NSS_LDAP_KEY_BASE))
869
t = &result->ldc_base;
871
else if (!strcasecmp (k, NSS_LDAP_KEY_BINDDN))
873
t = &result->ldc_binddn;
875
else if (!strcasecmp (k, NSS_LDAP_KEY_BINDPW))
877
t = &result->ldc_bindpw;
879
else if (!strcasecmp (k, NSS_LDAP_KEY_USESASL))
881
result->ldc_usesasl = (!strcasecmp (v, "on")
882
|| !strcasecmp (v, "yes")
883
|| !strcasecmp (v, "true"));
885
else if (!strcasecmp (k, NSS_LDAP_KEY_SASLID))
887
t = &result->ldc_saslid;
889
else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTBINDDN))
891
t = &result->ldc_rootbinddn;
893
else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTUSESASL))
895
result->ldc_rootusesasl = (!strcasecmp (v, "on")
896
|| !strcasecmp (v, "yes")
897
|| !strcasecmp (v, "true"));
899
else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTSASLID))
901
t = &result->ldc_rootsaslid;
903
else if (!strcasecmp (k, NSS_LDAP_KEY_SSLPATH))
905
t = &result->ldc_sslpath;
907
else if (!strcasecmp (k, NSS_LDAP_KEY_SCOPE))
909
if (!strcasecmp (v, "sub"))
911
result->ldc_scope = LDAP_SCOPE_SUBTREE;
913
else if (!strcasecmp (v, "one"))
915
result->ldc_scope = LDAP_SCOPE_ONELEVEL;
917
else if (!strcasecmp (v, "base"))
919
result->ldc_scope = LDAP_SCOPE_BASE;
922
else if (!strcasecmp (k, NSS_LDAP_KEY_DEREF))
924
if (!strcasecmp (v, "never"))
926
result->ldc_deref = LDAP_DEREF_NEVER;
928
else if (!strcasecmp (v, "searching"))
930
result->ldc_deref = LDAP_DEREF_SEARCHING;
932
else if (!strcasecmp (v, "finding"))
934
result->ldc_deref = LDAP_DEREF_FINDING;
936
else if (!strcasecmp (v, "always"))
938
result->ldc_deref = LDAP_DEREF_ALWAYS;
941
else if (!strcasecmp (k, NSS_LDAP_KEY_PORT))
943
result->ldc_port = atoi (v);
945
else if (!strcasecmp (k, NSS_LDAP_KEY_SSL))
947
if (!strcasecmp (v, "on") || !strcasecmp (v, "yes")
948
|| !strcasecmp (v, "true"))
950
result->ldc_ssl_on = SSL_LDAPS;
952
else if (!strcasecmp (v, "start_tls"))
954
result->ldc_ssl_on = SSL_START_TLS;
957
else if (!strcasecmp (k, NSS_LDAP_KEY_REFERRALS))
959
result->ldc_referrals = (!strcasecmp (v, "on")
960
|| !strcasecmp (v, "yes")
961
|| !strcasecmp (v, "true"));
963
else if (!strcasecmp (k, NSS_LDAP_KEY_RESTART))
965
result->ldc_restart = (!strcasecmp (v, "on")
966
|| !strcasecmp (v, "yes")
967
|| !strcasecmp (v, "true"));
969
else if (!strcasecmp (k, NSS_LDAP_KEY_LDAP_VERSION))
971
result->ldc_version = atoi (v);
973
else if (!strcasecmp (k, NSS_LDAP_KEY_TIMELIMIT))
975
result->ldc_timelimit = atoi (v);
977
else if (!strcasecmp (k, NSS_LDAP_KEY_BIND_TIMELIMIT))
979
result->ldc_bind_timelimit = atoi (v);
981
else if (!strcasecmp (k, NSS_LDAP_KEY_IDLE_TIMELIMIT))
983
result->ldc_idle_timelimit = atoi (v);
985
else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_POLICY))
987
if (!strcasecmp (v, "hard") ||
988
!strcasecmp (v, "hard_open"))
990
result->ldc_reconnect_pol = LP_RECONNECT_HARD_OPEN;
992
else if (!strcasecmp (v, "hard_init"))
994
result->ldc_reconnect_pol = LP_RECONNECT_HARD_INIT;
996
else if (!strcasecmp (v, "soft"))
998
result->ldc_reconnect_pol = LP_RECONNECT_SOFT;
1001
else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_TRIES))
1003
result->ldc_reconnect_tries = atoi (v);
1005
else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_SLEEPTIME))
1007
result->ldc_reconnect_sleeptime = atoi (v);
1009
else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_MAXSLEEPTIME))
1011
result->ldc_reconnect_maxsleeptime = atoi (v);
1013
else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_MAXCONNTRIES))
1015
result->ldc_reconnect_maxconntries = atoi (v);
1017
else if (!strcasecmp (k, NSS_LDAP_KEY_SASL_SECPROPS))
1019
t = &result->ldc_sasl_secprops;
1021
else if (!strcasecmp (k, NSS_LDAP_KEY_LOGDIR))
1023
t = &result->ldc_logdir;
1025
else if (!strcasecmp (k, NSS_LDAP_KEY_DEBUG))
1027
result->ldc_debug = atoi (v);
1029
else if (!strcasecmp (k, NSS_LDAP_KEY_PAGESIZE))
1031
result->ldc_pagesize = atoi (v);
1033
#ifdef CONFIGURE_KRB5_CCNAME
1034
else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_CCNAME))
1036
t = &result->ldc_krb5_ccname;
1038
#endif /* CONFIGURE_KRB5_CCNAME */
1039
else if (!strcasecmp (k, "tls_checkpeer"))
1041
if (!strcasecmp (v, "on") || !strcasecmp (v, "yes")
1042
|| !strcasecmp (v, "true"))
1044
result->ldc_tls_checkpeer = 1;
1046
else if (!strcasecmp (v, "off") || !strcasecmp (v, "no")
1047
|| !strcasecmp (v, "false"))
1049
result->ldc_tls_checkpeer = 0;
1052
else if (!strcasecmp (k, "tls_cacertfile"))
1054
t = &result->ldc_tls_cacertfile;
1056
else if (!strcasecmp (k, "tls_cacertdir"))
1058
t = &result->ldc_tls_cacertdir;
1060
else if (!strcasecmp (k, "tls_ciphers"))
1062
t = &result->ldc_tls_ciphers;
1064
else if (!strcasecmp (k, "tls_cert"))
1066
t = &result->ldc_tls_cert;
1068
else if (!strcasecmp (k, "tls_key"))
1070
t = &result->ldc_tls_key;
1072
else if (!strcasecmp (k, "tls_randfile"))
1074
t = &result->ldc_tls_randfile;
1076
else if (!strncasecmp (k, NSS_LDAP_KEY_MAP_ATTRIBUTE,
1077
strlen (NSS_LDAP_KEY_MAP_ATTRIBUTE)))
1079
do_parse_map_statement (result, v, MAP_ATTRIBUTE);
1081
else if (!strncasecmp (k, NSS_LDAP_KEY_MAP_OBJECTCLASS,
1082
strlen (NSS_LDAP_KEY_MAP_OBJECTCLASS)))
1084
do_parse_map_statement (result, v, MAP_OBJECTCLASS);
1086
else if (!strncasecmp (k, NSS_LDAP_KEY_SET_OVERRIDE,
1087
strlen (NSS_LDAP_KEY_SET_OVERRIDE)))
1089
do_parse_map_statement (result, v, MAP_OVERRIDE);
1091
else if (!strncasecmp (k, NSS_LDAP_KEY_SET_DEFAULT,
1092
strlen (NSS_LDAP_KEY_SET_DEFAULT)))
1094
do_parse_map_statement (result, v, MAP_DEFAULT);
1096
else if (!strcasecmp (k, NSS_LDAP_KEY_INITGROUPS))
1098
if (!strcasecmp (v, "backlink"))
1100
result->ldc_flags |= NSS_LDAP_FLAGS_INITGROUPS_BACKLINK;
1104
result->ldc_flags &= ~(NSS_LDAP_FLAGS_INITGROUPS_BACKLINK);
1107
else if (!strcasecmp (k, NSS_LDAP_KEY_SCHEMA))
1109
if (!strcasecmp (v, "rfc2307bis"))
1111
result->ldc_flags |= NSS_LDAP_FLAGS_RFC2307BIS;
1113
else if (!strcasecmp (v, "rfc2307"))
1115
result->ldc_flags &= ~(NSS_LDAP_FLAGS_RFC2307BIS);
1118
else if (!strcasecmp (k, NSS_LDAP_KEY_PAGED_RESULTS))
1120
if (!strcasecmp (v, "on")
1121
|| !strcasecmp (v, "yes")
1122
|| !strcasecmp (v, "true"))
1124
result->ldc_flags |= NSS_LDAP_FLAGS_PAGED_RESULTS;
1128
result->ldc_flags &= ~(NSS_LDAP_FLAGS_PAGED_RESULTS);
1131
else if (!strcasecmp (k, NSS_LDAP_KEY_INITGROUPS_IGNOREUSERS))
1133
stat = do_parse_list (v, &result->ldc_initgroups_ignoreusers,
1135
if (stat == NSS_UNAVAIL)
1140
else if (!strcasecmp (k, NSS_LDAP_KEY_CONNECT_POLICY))
1142
if (!strcasecmp (v, "oneshot"))
1144
result->ldc_flags |= NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT;
1146
else if (!strcasecmp (v, "persist"))
1148
result->ldc_flags &= ~(NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT);
1151
else if (!strcasecmp (k, NSS_LDAP_KEY_SRV_DOMAIN))
1153
t = &result->ldc_srv_domain;
1158
* check whether the key is a naming context key
1159
* if yes, parse; otherwise just return NSS_SUCCESS
1160
* so we can ignore keys we don't understand.
1163
do_searchdescriptorconfig (k, v, len, result->ldc_sds,
1165
if (stat == NSS_UNAVAIL)
1173
strncpy (*buffer, v, len);
1174
(*buffer)[len] = '\0';
1183
if (stat != NSS_SUCCESS)
1188
if (result->ldc_rootbinddn != NULL)
1190
fp = fopen (NSS_LDAP_PATH_ROOTPASSWD, "r");
1193
if (fgets (b, sizeof (b), fp) != NULL)
1198
/* BUG#138: check for newline before removing */
1199
if (len > 0 && b[len - 1] == '\n')
1202
if (*buflen < (size_t) (len + 1))
1207
strncpy (*buffer, b, len);
1208
(*buffer)[len] = '\0';
1209
result->ldc_rootbindpw = *buffer;
1215
else if (!result->ldc_rootusesasl)
1217
result->ldc_rootbinddn = NULL;
1221
if (result->ldc_port == 0)
1223
if (result->ldc_ssl_on == SSL_LDAPS)
1225
result->ldc_port = LDAPS_PORT;
1229
result->ldc_port = LDAP_PORT;
1233
if (result->ldc_uris[0] == NULL)
1235
stat = NSS_NOTFOUND;
1242
_nss_ldap_escape_string (const char *str, char *buf, size_t buflen)
1244
int ret = NSS_TRYAGAIN;
1246
char *limit = p + buflen - 3;
1247
const char *s = str;
1249
while (p < limit && *s)
1286
/* XXX just a linked list for now */
1288
struct ldap_dictionary
1292
struct ldap_dictionary *next;
1295
static struct ldap_dictionary *
1296
do_alloc_dictionary (void)
1298
struct ldap_dictionary *dict;
1300
dict = malloc (sizeof (*dict));
1305
NSS_LDAP_DATUM_ZERO (&dict->key);
1306
NSS_LDAP_DATUM_ZERO (&dict->value);
1313
do_free_datum (ldap_datum_t * datum)
1315
if (datum->data != NULL)
1323
static struct ldap_dictionary *
1324
do_find_last (struct ldap_dictionary *dict)
1326
struct ldap_dictionary *p;
1328
for (p = dict; p->next != NULL; p = p->next)
1335
do_free_dictionary (struct ldap_dictionary *dict)
1337
do_free_datum (&dict->key);
1338
do_free_datum (&dict->value);
1343
do_dup_datum (unsigned flags, ldap_datum_t * dst, const ldap_datum_t * src)
1345
dst->data = malloc (src->size);
1346
if (dst->data == NULL)
1347
return NSS_TRYAGAIN;
1349
memcpy (dst->data, src->data, src->size);
1350
dst->size = src->size;
1356
_nss_ldap_db_open (void)
1358
return (void *) do_alloc_dictionary ();
1362
_nss_ldap_db_close (void *db)
1364
struct ldap_dictionary *dict;
1366
dict = (struct ldap_dictionary *) db;
1368
while (dict != NULL)
1370
struct ldap_dictionary *next = dict->next;
1372
do_free_dictionary (dict);
1379
_nss_ldap_db_get (void *db,
1381
const ldap_datum_t * key,
1382
ldap_datum_t * value)
1384
struct ldap_dictionary *dict = (struct ldap_dictionary *) db;
1385
struct ldap_dictionary *p;
1387
for (p = dict; p != NULL; p = p->next)
1391
if (p->key.size != key->size)
1394
if (flags & NSS_LDAP_DB_NORMALIZE_CASE)
1395
cmp = strncasecmp ((char *)p->key.data, (char *)key->data, key->size);
1397
cmp = memcmp (p->key.data, key->data, key->size);
1401
value->data = p->value.data;
1402
value->size = p->value.size;
1408
return NSS_NOTFOUND;
1412
_nss_ldap_db_put (void *db,
1414
const ldap_datum_t * key,
1415
const ldap_datum_t * value)
1417
struct ldap_dictionary *dict = (struct ldap_dictionary *) db;
1418
struct ldap_dictionary *p, *q;
1420
assert (key != NULL);
1421
assert (key->data != NULL);
1423
if (dict->key.data == NULL)
1431
p = do_find_last (dict);
1433
assert (p->next == NULL);
1434
q = do_alloc_dictionary ();
1436
return NSS_TRYAGAIN;
1439
if (do_dup_datum (flags, &q->key, key) != NSS_SUCCESS)
1441
do_free_dictionary (q);
1442
return NSS_TRYAGAIN;
1445
if (do_dup_datum (flags, &q->value, value) != NSS_SUCCESS)
1447
do_free_dictionary (q);
1448
return NSS_TRYAGAIN;
1458
* Add a nested netgroup or group to the namelist
1461
_nss_ldap_namelist_push (struct name_list **head, const char *name)
1463
struct name_list *nl;
1465
debug ("==> _nss_ldap_namelist_push (%s)", name);
1467
nl = (struct name_list *) malloc (sizeof (*nl));
1470
debug ("<== _nss_ldap_namelist_push");
1471
return NSS_TRYAGAIN;
1474
nl->name = strdup (name);
1475
if (nl->name == NULL)
1477
debug ("<== _nss_ldap_namelist_push");
1479
return NSS_TRYAGAIN;
1486
debug ("<== _nss_ldap_namelist_push");
1492
* Remove last nested netgroup or group from the namelist
1495
_nss_ldap_namelist_pop (struct name_list **head)
1497
struct name_list *nl;
1499
debug ("==> _nss_ldap_namelist_pop");
1501
assert (*head != NULL);
1506
assert (nl->name != NULL);
1510
debug ("<== _nss_ldap_namelist_pop");
1514
* Cleanup nested netgroup or group namelist.
1517
_nss_ldap_namelist_destroy (struct name_list **head)
1519
struct name_list *p, *next;
1521
debug ("==> _nss_ldap_namelist_destroy");
1523
for (p = *head; p != NULL; p = next)
1527
if (p->name != NULL)
1534
debug ("<== _nss_ldap_namelist_destroy");
1538
* Check whether we have already seen a netgroup or group,
1539
* to avoid loops in nested netgroup traversal
1542
_nss_ldap_namelist_find (struct name_list *head, const char *netgroup)
1544
struct name_list *p;
1547
debug ("==> _nss_ldap_namelist_find");
1549
for (p = head; p != NULL; p = p->next)
1551
if (strcasecmp (p->name, netgroup) == 0)
1558
debug ("<== _nss_ldap_namelist_find");
1563
NSS_STATUS _nss_ldap_validateconfig (ldap_config_t *config)
1565
struct stat statbuf;
1572
if (config->ldc_mtime == 0)
1577
if (stat (NSS_LDAP_PATH_CONF, &statbuf) == 0)
1579
return (statbuf.st_mtime > config->ldc_mtime) ? NSS_TRYAGAIN : NSS_SUCCESS;