/* cfg.c - functions for configuration information This file contains parts that were part of the nss-ldap library which has been forked into the nss-ldapd library. Copyright (C) 1997-2005 Luke Howard Copyright (C) 2007 West Consulting Copyright (C) 2007 Arthur de Jong This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include #include "ldap-nss.h" #include "util.h" #include "log.h" #include "dnsconfig.h" struct ldap_config *nslcd_cfg=NULL; #define LDAP_PAGESIZE 1000 /* * Timeouts for reconnecting code. Similar to rebind * logic in Darwin NetInfo. Some may find sleeping * unacceptable, in which case you may wish to adjust * the constants below. */ #define LDAP_NSS_TRIES 5 /* number of sleeping reconnect attempts */ #define LDAP_NSS_SLEEPTIME 4 /* seconds to sleep; doubled until max */ #define LDAP_NSS_MAXSLEEPTIME 64 /* maximum seconds to sleep */ #define LDAP_NSS_MAXCONNTRIES 2 /* reconnect attempts before sleeping */ #define NSS_LDAP_KEY_MAP_ATTRIBUTE "nss_map_attribute" #define NSS_LDAP_KEY_MAP_OBJECTCLASS "nss_map_objectclass" #define NSS_LDAP_KEY_SET_OVERRIDE "nss_override_attribute_value" #define NSS_LDAP_KEY_SET_DEFAULT "nss_default_attribute_value" #define NSS_LDAP_KEY_HOST "host" #define NSS_LDAP_KEY_SCOPE "scope" #define NSS_LDAP_KEY_BASE "base" #define NSS_LDAP_KEY_PORT "port" #define NSS_LDAP_KEY_BINDDN "binddn" #define NSS_LDAP_KEY_BINDPW "bindpw" #define NSS_LDAP_KEY_USESASL "use_sasl" #define NSS_LDAP_KEY_SASLID "sasl_auth_id" #define NSS_LDAP_KEY_DEREF "deref" #define NSS_LDAP_KEY_ROOTBINDDN "rootbinddn" #define NSS_LDAP_KEY_ROOTUSESASL "rootuse_sasl" #define NSS_LDAP_KEY_ROOTSASLID "rootsasl_auth_id" #define NSS_LDAP_KEY_LDAP_VERSION "ldap_version" #define NSS_LDAP_KEY_TIMELIMIT "timelimit" #define NSS_LDAP_KEY_BIND_TIMELIMIT "bind_timelimit" #define NSS_LDAP_KEY_SSL "ssl" #define NSS_LDAP_KEY_SSLPATH "sslpath" #define NSS_LDAP_KEY_REFERRALS "referrals" #define NSS_LDAP_KEY_RESTART "restart" #define NSS_LDAP_KEY_URI "uri" #define NSS_LDAP_KEY_IDLE_TIMELIMIT "idle_timelimit" #define NSS_LDAP_KEY_RECONNECT_POLICY "bind_policy" #define NSS_LDAP_KEY_SASL_SECPROPS "sasl_secprops" #ifdef CONFIGURE_KRB5_CCNAME #define NSS_LDAP_KEY_KRB5_CCNAME "krb5_ccname" #endif /* CONFIGURE_KRB5_CCNAME */ #define NSS_LDAP_KEY_LOGDIR "logdir" #define NSS_LDAP_KEY_DEBUG "debug" #define NSS_LDAP_KEY_PAGESIZE "pagesize" #define NSS_LDAP_KEY_INITGROUPS "nss_initgroups" #define NSS_LDAP_KEY_INITGROUPS_IGNOREUSERS "nss_initgroups_ignoreusers" /* more reconnect policy fine-tuning */ #define NSS_LDAP_KEY_RECONNECT_TRIES "nss_reconnect_tries" #define NSS_LDAP_KEY_RECONNECT_SLEEPTIME "nss_reconnect_sleeptime" #define NSS_LDAP_KEY_RECONNECT_MAXSLEEPTIME "nss_reconnect_maxsleeptime" #define NSS_LDAP_KEY_RECONNECT_MAXCONNTRIES "nss_reconnect_maxconntries" #define NSS_LDAP_KEY_PAGED_RESULTS "nss_paged_results" #define NSS_LDAP_KEY_SCHEMA "nss_schema" #define NSS_LDAP_KEY_SRV_DOMAIN "nss_srv_domain" #define NSS_LDAP_KEY_CONNECT_POLICY "nss_connect_policy" /* * support separate naming contexts for each map * eventually this will support the syntax defined in * the DUAConfigProfile searchDescriptor attribute */ #define NSS_LDAP_KEY_NSS_BASE_PREFIX "nss_base_" #define NSS_LDAP_KEY_NSS_BASE_PREFIX_LEN ( sizeof(NSS_LDAP_KEY_NSS_BASE_PREFIX) - 1 ) #define NSS_LDAP_CONFIG_BUFSIZ 4096 int _nss_ldap_test_config_flag(unsigned int flag) { return nslcd_cfg != NULL && (nslcd_cfg->ldc_flags&flag); } static enum nss_status _nss_ldap_init_config(struct ldap_config *result) { int i, j; memset (result, 0, sizeof (*result)); result->ldc_scope = LDAP_SCOPE_SUBTREE; result->ldc_deref = LDAP_DEREF_NEVER; result->ldc_base = NULL; result->ldc_binddn = NULL; result->ldc_bindpw = NULL; result->ldc_saslid = NULL; result->ldc_usesasl = 0; result->ldc_rootbinddn = NULL; result->ldc_rootbindpw = NULL; result->ldc_rootsaslid = NULL; result->ldc_rootusesasl = 0; #ifdef LDAP_VERSION3 result->ldc_version = LDAP_VERSION3; #else /* LDAP_VERSION3 */ result->ldc_version = LDAP_VERSION2; #endif /* not LDAP_VERSION3 */ result->ldc_timelimit = LDAP_NO_LIMIT; result->ldc_bind_timelimit = 30; result->ldc_ssl_on = SSL_OFF; result->ldc_sslpath = NULL; result->ldc_referrals = 1; result->ldc_restart = 1; result->ldc_tls_checkpeer = -1; result->ldc_tls_cacertfile = NULL; result->ldc_tls_cacertdir = NULL; result->ldc_tls_ciphers = NULL; result->ldc_tls_cert = NULL; result->ldc_tls_key = NULL; result->ldc_tls_randfile = NULL; result->ldc_idle_timelimit = 0; result->ldc_reconnect_pol = LP_RECONNECT_HARD_OPEN; result->ldc_sasl_secprops = NULL; result->ldc_srv_domain = NULL; result->ldc_logdir = NULL; result->ldc_debug = 0; result->ldc_pagesize = LDAP_PAGESIZE; #ifdef CONFIGURE_KRB5_CCNAME result->ldc_krb5_ccname = NULL; #endif /* CONFIGURE_KRB5_CCNAME */ result->ldc_flags = 0; #ifdef RFC2307BIS result->ldc_flags |= NSS_LDAP_FLAGS_RFC2307BIS; #endif /* RFC2307BIS */ #ifdef PAGE_RESULTS result->ldc_flags |= NSS_LDAP_FLAGS_PAGED_RESULTS; #endif /* PAGE_RESULTS */ result->ldc_reconnect_tries = LDAP_NSS_TRIES; result->ldc_reconnect_sleeptime = LDAP_NSS_SLEEPTIME; result->ldc_reconnect_maxsleeptime = LDAP_NSS_MAXSLEEPTIME; result->ldc_reconnect_maxconntries = LDAP_NSS_MAXCONNTRIES; result->ldc_initgroups_ignoreusers = NULL; for (i=0;i<=LM_NONE;i++) { for (j=0;j<=MAP_MAX;j++) { result->ldc_maps[i][j]=dict_new(); if (result->ldc_maps[i][j] == NULL) return NSS_STATUS_UNAVAIL; } } return NSS_STATUS_SUCCESS; } static enum nss_status do_add_hosts (struct ldap_config *result, char *hosts, char **buffer, size_t *buflen) { /* Add a space separated list of hosts */ char *p; enum nss_status status = NSS_STATUS_SUCCESS; for (p = hosts; p != NULL; ) { char b[NSS_LDAP_CONFIG_BUFSIZ]; char *q = strchr (p, ' '); if (q != NULL) *q = '\0'; snprintf (b, sizeof(b), "ldap://%s", p); status = _nss_ldap_add_uri (result, b, buffer, buflen); p = (q != NULL) ? ++q : NULL; if (status != NSS_STATUS_SUCCESS) break; } return status; } static enum nss_status do_add_uris (struct ldap_config *result, char *uris, char **buffer, size_t *buflen) { /* Add a space separated list of URIs */ char *p; enum nss_status status = NSS_STATUS_SUCCESS; for (p = uris; p != NULL; ) { char *q = strchr (p, ' '); if (q != NULL) *q = '\0'; status = _nss_ldap_add_uri (result, p, buffer, buflen); p = (q != NULL) ? ++q : NULL; if (status != NSS_STATUS_SUCCESS) break; } return status; } static enum ldap_map_selector _nss_ldap_str2selector(const char *key) { enum ldap_map_selector sel; if (!strcasecmp (key, MP_passwd)) sel = LM_PASSWD; else if (!strcasecmp (key, MP_shadow)) sel = LM_SHADOW; else if (!strcasecmp (key, MP_group)) sel = LM_GROUP; else if (!strcasecmp (key, MP_hosts)) sel = LM_HOSTS; else if (!strcasecmp (key, MP_services)) sel = LM_SERVICES; else if (!strcasecmp (key, MP_networks)) sel = LM_NETWORKS; else if (!strcasecmp (key, MP_protocols)) sel = LM_PROTOCOLS; else if (!strcasecmp (key, MP_rpc)) sel = LM_RPC; else if (!strcasecmp (key, MP_ethers)) sel = LM_ETHERS; else if (!strcasecmp (key, MP_netmasks)) sel = LM_NETMASKS; else if (!strcasecmp (key, MP_bootparams)) sel = LM_BOOTPARAMS; else if (!strcasecmp (key, MP_aliases)) sel = LM_ALIASES; else if (!strcasecmp (key, MP_netgroup)) sel = LM_NETGROUP; else sel = LM_NONE; return sel; } static enum nss_status _nss_ldap_map_put( struct ldap_config *config, enum ldap_map_selector sel, enum ldap_map_type type, const char *from, const char *to) { DICT *map; /* we do some special handling for attribute type mapping to do some basic detection of what kind of LDAP server we're talking to */ if (type==MAP_ATTRIBUTE) { /* special handling for attribute mapping */ if (strcasecmp(from,"userPassword")==0) { if (strcasecmp(to,"userPassword")==0) config->ldc_password_type=LU_RFC2307_USERPASSWORD; else if (strcasecmp (to,"authPassword")==0) config->ldc_password_type=LU_RFC3112_AUTHPASSWORD; else config->ldc_password_type=LU_OTHER_PASSWORD; } else if (strcasecmp(from,"shadowLastChange")==0) { if (strcasecmp(to,"shadowLastChange")==0) config->ldc_shadow_type=LS_RFC2307_SHADOW; else if (strcasecmp (to,"pwdLastSet")==0) config->ldc_shadow_type=LS_AD_SHADOW; else config->ldc_shadow_type=LS_OTHER_SHADOW; } } assert(sel <= LM_NONE); map=config->ldc_maps[sel][type]; assert(map!=NULL); if (dict_put(map,from,to)) return NSS_STATUS_TRYAGAIN; if (type==MAP_ATTRIBUTE) { map = config->ldc_maps[sel][MAP_ATTRIBUTE_REVERSE]; if (dict_put(map,to,from)) return NSS_STATUS_TRYAGAIN; } else if (type==MAP_OBJECTCLASS) { map = config->ldc_maps[sel][MAP_OBJECTCLASS_REVERSE]; if (dict_put(map,to,from)) return NSS_STATUS_TRYAGAIN; } return NSS_STATUS_SUCCESS; } static enum nss_status do_parse_map_statement( struct ldap_config *cfg,char *statement, enum ldap_map_type type) { char *key,*val; enum ldap_map_selector sel=LM_NONE; char *p; key=(char *)statement; val=key; while (*val!=' '&&*val!='\t') val++; *(val++)='\0'; while (*val==' '||*val=='\t') val++; p=strchr(key,':'); if (p!=NULL) { *p='\0'; sel=_nss_ldap_str2selector(key); key=++p; } return _nss_ldap_map_put(cfg,sel,type,key,val); } /* parse a comma-separated list */ static enum nss_status do_parse_list(char *values,char ***valptr, char **pbuffer,size_t *pbuflen) { char *s, **p; #ifdef HAVE_STRTOK_R char *tok_r; #endif /* HAVE_STRTOK_R */ size_t valcount; int buflen = *pbuflen; char *buffer = *pbuffer; /* comma separated list of values to ignore on initgroups() */ for (valcount = 1, s = values; *s != '\0'; s++) { if (*s == ',') valcount++; } if (bytesleft (buffer, buflen, char *) < (valcount + 1) * sizeof (char *)) { return NSS_STATUS_UNAVAIL; } align (buffer, buflen, char *); p = *valptr = (char **) buffer; buffer += (valcount + 1) * sizeof (char *); buflen -= (valcount + 1) * sizeof (char *); #ifdef HAVE_STRTOK_R for (s = strtok_r(values, ",", &tok_r); s != NULL; s = strtok_r(NULL, ",", &tok_r)) #else /* HAVE_STRTOK_R */ for (s = strtok(values, ","); s != NULL; s = strtok(NULL, ",")) #endif /* not HAVE_STRTOK_R */ { int vallen; char *elt = NULL; vallen = strlen (s); if (buflen < (size_t) (vallen + 1)) { return NSS_STATUS_UNAVAIL; } /* copy this value into the next block of buffer space */ elt = buffer; buffer += vallen + 1; buflen -= vallen + 1; strncpy (elt, s, vallen); elt[vallen] = '\0'; *p++ = elt; } *p = NULL; *pbuffer = buffer; *pbuflen = buflen; return NSS_STATUS_SUCCESS; } static enum nss_status do_searchdescriptorconfig (const char *key, const char *value, size_t len, struct ldap_service_search_descriptor ** result, char **buffer, size_t * buflen) { struct ldap_service_search_descriptor **t, *cur; char *base; char *filter, *s; int scope; enum ldap_map_selector sel; t = NULL; filter = NULL; scope = -1; if (strncasecmp (key, NSS_LDAP_KEY_NSS_BASE_PREFIX, NSS_LDAP_KEY_NSS_BASE_PREFIX_LEN) != 0) return NSS_STATUS_SUCCESS; sel = _nss_ldap_str2selector (&key[NSS_LDAP_KEY_NSS_BASE_PREFIX_LEN]); t = (sel < LM_NONE) ? &result[sel] : NULL; if (t == NULL) return NSS_STATUS_SUCCESS; /* we have already checked for room for the value */ /* len is set to the length of value */ base = *buffer; strncpy (base, value, len); base[len] = '\0'; *buffer += len + 1; *buflen -= len + 1; /* probably is some funky escaping needed here. later... */ s = strchr (base, '?'); if (s != NULL) { *s = '\0'; s++; if (!strcasecmp (s, "sub")) scope = LDAP_SCOPE_SUBTREE; else if (!strcasecmp (s, "one")) scope = LDAP_SCOPE_ONELEVEL; else if (!strcasecmp (s, "base")) scope = LDAP_SCOPE_BASE; filter = strchr (s, '?'); if (filter != NULL) { *filter = '\0'; filter++; } } if (bytesleft (*buffer, *buflen, struct ldap_service_search_descriptor) < sizeof (struct ldap_service_search_descriptor)) return NSS_STATUS_UNAVAIL; align (*buffer, *buflen, struct ldap_service_search_descriptor); for (cur = *t; cur && cur->lsd_next; cur = cur->lsd_next) ; if (!cur) { *t = (struct ldap_service_search_descriptor *) * buffer; cur = *t; } else { cur->lsd_next = (struct ldap_service_search_descriptor *) * buffer; cur = cur->lsd_next; } cur->lsd_base = base; cur->lsd_scope = scope; cur->lsd_filter = filter; cur->lsd_next = NULL; *buffer += sizeof (struct ldap_service_search_descriptor); *buflen -= sizeof (struct ldap_service_search_descriptor); return NSS_STATUS_SUCCESS; } static enum nss_status _nss_ldap_readconfig(struct ldap_config ** presult, char **buffer, size_t *buflen) { FILE *fp; char b[NSS_LDAP_CONFIG_BUFSIZ]; enum nss_status status = NSS_STATUS_SUCCESS; struct ldap_config *result; struct stat statbuf; if (bytesleft (*buffer, *buflen, struct ldap_config *) < sizeof (struct ldap_config)) { return NSS_STATUS_TRYAGAIN; } align (*buffer, *buflen, struct ldap_config *); result = *presult = (struct ldap_config *) *buffer; *buffer += sizeof (struct ldap_config); *buflen -= sizeof (struct ldap_config); status = _nss_ldap_init_config(result); if (status != NSS_STATUS_SUCCESS) { return NSS_STATUS_SUCCESS; } fp = fopen (NSS_LDAP_PATH_CONF, "r"); if (fp == NULL) { return NSS_STATUS_UNAVAIL; } if (fstat(fileno (fp), &statbuf) == 0) result->ldc_mtime = statbuf.st_mtime; else result->ldc_mtime = 0; while (fgets (b, sizeof (b), fp) != NULL) { char *k, *v; int len; char **t = NULL; if (*b == '\n' || *b == '\r' || *b == '#') continue; k = b; v = k; /* skip past all characters in keyword */ while (*v != '\0' && *v != ' ' && *v != '\t') v++; if (*v == '\0') continue; /* terminate keyword */ *(v++) = '\0'; /* skip empty lines with more than 3 spaces at the start of the line */ /* rds.oliver@samera.com.py 01-set-2004 */ if (*v == '\n') continue; /* skip all whitespaces between keyword and value */ /* Lars Oergel , 05.10.2000 */ while (*v == ' ' || *v == '\t') v++; /* kick off all whitespaces and newline at the end of value */ /* Bob Guo , 08.10.2001 */ /* Also remove \r (CR) to be able to handle files in DOS format (lines * terminated in CR LF). Alejandro Forero Cuervo * , 10-may-2005 */ len = strlen (v) - 1; while (v[len] == ' ' || v[len] == '\t' || v[len] == '\n' || v[len] == '\r') --len; v[++len] = '\0'; if (*buflen < (size_t) (len + 1)) { status = NSS_STATUS_TRYAGAIN; break; } if (!strcasecmp (k, NSS_LDAP_KEY_HOST)) { status = do_add_hosts (result, v, buffer, buflen); if (status != NSS_STATUS_SUCCESS) break; } else if (!strcasecmp (k, NSS_LDAP_KEY_URI)) { status = do_add_uris (result, v, buffer, buflen); if (status != NSS_STATUS_SUCCESS) break; } else if (!strcasecmp (k, NSS_LDAP_KEY_BASE)) { t = &result->ldc_base; } else if (!strcasecmp (k, NSS_LDAP_KEY_BINDDN)) { t = &result->ldc_binddn; } else if (!strcasecmp (k, NSS_LDAP_KEY_BINDPW)) { t = &result->ldc_bindpw; } else if (!strcasecmp (k, NSS_LDAP_KEY_USESASL)) { result->ldc_usesasl = (!strcasecmp (v, "on") || !strcasecmp (v, "yes") || !strcasecmp (v, "true")); } else if (!strcasecmp (k, NSS_LDAP_KEY_SASLID)) { t = &result->ldc_saslid; } else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTBINDDN)) { t = &result->ldc_rootbinddn; } else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTUSESASL)) { result->ldc_rootusesasl = (!strcasecmp (v, "on") || !strcasecmp (v, "yes") || !strcasecmp (v, "true")); } else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTSASLID)) { t = &result->ldc_rootsaslid; } else if (!strcasecmp (k, NSS_LDAP_KEY_SSLPATH)) { t = &result->ldc_sslpath; } else if (!strcasecmp (k, NSS_LDAP_KEY_SCOPE)) { if (!strcasecmp (v, "sub")) { result->ldc_scope = LDAP_SCOPE_SUBTREE; } else if (!strcasecmp (v, "one")) { result->ldc_scope = LDAP_SCOPE_ONELEVEL; } else if (!strcasecmp (v, "base")) { result->ldc_scope = LDAP_SCOPE_BASE; } } else if (!strcasecmp (k, NSS_LDAP_KEY_DEREF)) { if (!strcasecmp (v, "never")) { result->ldc_deref = LDAP_DEREF_NEVER; } else if (!strcasecmp (v, "searching")) { result->ldc_deref = LDAP_DEREF_SEARCHING; } else if (!strcasecmp (v, "finding")) { result->ldc_deref = LDAP_DEREF_FINDING; } else if (!strcasecmp (v, "always")) { result->ldc_deref = LDAP_DEREF_ALWAYS; } } else if (!strcasecmp (k, NSS_LDAP_KEY_PORT)) { result->ldc_port = atoi (v); } else if (!strcasecmp (k, NSS_LDAP_KEY_SSL)) { if (!strcasecmp (v, "on") || !strcasecmp (v, "yes") || !strcasecmp (v, "true")) { result->ldc_ssl_on = SSL_LDAPS; } else if (!strcasecmp (v, "start_tls")) { result->ldc_ssl_on = SSL_START_TLS; } } else if (!strcasecmp (k, NSS_LDAP_KEY_REFERRALS)) { result->ldc_referrals = (!strcasecmp (v, "on") || !strcasecmp (v, "yes") || !strcasecmp (v, "true")); } else if (!strcasecmp (k, NSS_LDAP_KEY_RESTART)) { result->ldc_restart = (!strcasecmp (v, "on") || !strcasecmp (v, "yes") || !strcasecmp (v, "true")); } else if (!strcasecmp (k, NSS_LDAP_KEY_LDAP_VERSION)) { result->ldc_version = atoi (v); } else if (!strcasecmp (k, NSS_LDAP_KEY_TIMELIMIT)) { result->ldc_timelimit = atoi (v); } else if (!strcasecmp (k, NSS_LDAP_KEY_BIND_TIMELIMIT)) { result->ldc_bind_timelimit = atoi (v); } else if (!strcasecmp (k, NSS_LDAP_KEY_IDLE_TIMELIMIT)) { result->ldc_idle_timelimit = atoi (v); } else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_POLICY)) { if (!strcasecmp (v, "hard") || !strcasecmp (v, "hard_open")) { result->ldc_reconnect_pol = LP_RECONNECT_HARD_OPEN; } else if (!strcasecmp (v, "hard_init")) { result->ldc_reconnect_pol = LP_RECONNECT_HARD_INIT; } else if (!strcasecmp (v, "soft")) { result->ldc_reconnect_pol = LP_RECONNECT_SOFT; } } else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_TRIES)) { result->ldc_reconnect_tries = atoi (v); } else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_SLEEPTIME)) { result->ldc_reconnect_sleeptime = atoi (v); } else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_MAXSLEEPTIME)) { result->ldc_reconnect_maxsleeptime = atoi (v); } else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_MAXCONNTRIES)) { result->ldc_reconnect_maxconntries = atoi (v); } else if (!strcasecmp (k, NSS_LDAP_KEY_SASL_SECPROPS)) { t = &result->ldc_sasl_secprops; } else if (!strcasecmp (k, NSS_LDAP_KEY_LOGDIR)) { t = &result->ldc_logdir; } else if (!strcasecmp (k, NSS_LDAP_KEY_DEBUG)) { result->ldc_debug = atoi (v); } else if (!strcasecmp (k, NSS_LDAP_KEY_PAGESIZE)) { result->ldc_pagesize = atoi (v); } #ifdef CONFIGURE_KRB5_CCNAME else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_CCNAME)) { t = &result->ldc_krb5_ccname; } #endif /* CONFIGURE_KRB5_CCNAME */ else if (!strcasecmp (k, "tls_checkpeer")) { if (!strcasecmp (v, "on") || !strcasecmp (v, "yes") || !strcasecmp (v, "true")) { result->ldc_tls_checkpeer = 1; } else if (!strcasecmp (v, "off") || !strcasecmp (v, "no") || !strcasecmp (v, "false")) { result->ldc_tls_checkpeer = 0; } } else if (!strcasecmp (k, "tls_cacertfile")) { t = &result->ldc_tls_cacertfile; } else if (!strcasecmp (k, "tls_cacertdir")) { t = &result->ldc_tls_cacertdir; } else if (!strcasecmp (k, "tls_ciphers")) { t = &result->ldc_tls_ciphers; } else if (!strcasecmp (k, "tls_cert")) { t = &result->ldc_tls_cert; } else if (!strcasecmp (k, "tls_key")) { t = &result->ldc_tls_key; } else if (!strcasecmp (k, "tls_randfile")) { t = &result->ldc_tls_randfile; } else if (!strncasecmp (k, NSS_LDAP_KEY_MAP_ATTRIBUTE, strlen (NSS_LDAP_KEY_MAP_ATTRIBUTE))) { do_parse_map_statement (result, v, MAP_ATTRIBUTE); } else if (!strncasecmp (k, NSS_LDAP_KEY_MAP_OBJECTCLASS, strlen (NSS_LDAP_KEY_MAP_OBJECTCLASS))) { do_parse_map_statement (result, v, MAP_OBJECTCLASS); } else if (!strncasecmp (k, NSS_LDAP_KEY_SET_OVERRIDE, strlen (NSS_LDAP_KEY_SET_OVERRIDE))) { do_parse_map_statement (result, v, MAP_OVERRIDE); } else if (!strncasecmp (k, NSS_LDAP_KEY_SET_DEFAULT, strlen (NSS_LDAP_KEY_SET_DEFAULT))) { do_parse_map_statement (result, v, MAP_DEFAULT); } else if (!strcasecmp (k, NSS_LDAP_KEY_INITGROUPS)) { if (!strcasecmp (v, "backlink")) { result->ldc_flags |= NSS_LDAP_FLAGS_INITGROUPS_BACKLINK; } else { result->ldc_flags &= ~(NSS_LDAP_FLAGS_INITGROUPS_BACKLINK); } } else if (!strcasecmp (k, NSS_LDAP_KEY_SCHEMA)) { if (!strcasecmp (v, "rfc2307bis")) { result->ldc_flags |= NSS_LDAP_FLAGS_RFC2307BIS; } else if (!strcasecmp (v, "rfc2307")) { result->ldc_flags &= ~(NSS_LDAP_FLAGS_RFC2307BIS); } } else if (!strcasecmp (k, NSS_LDAP_KEY_PAGED_RESULTS)) { if (!strcasecmp (v, "on") || !strcasecmp (v, "yes") || !strcasecmp (v, "true")) { result->ldc_flags |= NSS_LDAP_FLAGS_PAGED_RESULTS; } else { result->ldc_flags &= ~(NSS_LDAP_FLAGS_PAGED_RESULTS); } } else if (!strcasecmp (k, NSS_LDAP_KEY_INITGROUPS_IGNOREUSERS)) { status = do_parse_list (v, &result->ldc_initgroups_ignoreusers, buffer, buflen); if (status == NSS_STATUS_UNAVAIL) { break; } } else if (!strcasecmp (k, NSS_LDAP_KEY_CONNECT_POLICY)) { if (!strcasecmp (v, "oneshot")) { result->ldc_flags |= NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT; } else if (!strcasecmp (v, "persist")) { result->ldc_flags &= ~(NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT); } } else if (!strcasecmp (k, NSS_LDAP_KEY_SRV_DOMAIN)) { t = &result->ldc_srv_domain; } else { /* * check whether the key is a naming context key * if yes, parse; otherwise just return NSS_STATUS_SUCCESS * so we can ignore keys we don't understand. */ status = do_searchdescriptorconfig (k, v, len, result->ldc_sds, buffer, buflen); if (status == NSS_STATUS_UNAVAIL) { break; } } if (t != NULL) { strncpy (*buffer, v, len); (*buffer)[len] = '\0'; *t = *buffer; *buffer += len + 1; *buflen -= len + 1; } } fclose (fp); if (status != NSS_STATUS_SUCCESS) { return status; } if (result->ldc_rootbinddn != NULL) { fp = fopen (NSS_LDAP_PATH_ROOTPASSWD, "r"); if (fp) { if (fgets (b, sizeof (b), fp) != NULL) { int len; len = strlen (b); /* BUG#138: check for newline before removing */ if (len > 0 && b[len - 1] == '\n') len--; if (*buflen < (size_t) (len + 1)) { return NSS_STATUS_UNAVAIL; } strncpy (*buffer, b, len); (*buffer)[len] = '\0'; result->ldc_rootbindpw = *buffer; *buffer += len + 1; *buflen -= len + 1; } fclose (fp); } else if (!result->ldc_rootusesasl) { result->ldc_rootbinddn = NULL; } } if (result->ldc_port == 0) { if (result->ldc_ssl_on == SSL_LDAPS) { result->ldc_port = LDAPS_PORT; } else { result->ldc_port = LDAP_PORT; } } if (result->ldc_uris[0] == NULL) { status = NSS_STATUS_NOTFOUND; } return status; } int cfg_init(void) { static char configbuf[NSS_LDAP_CONFIG_BUFSIZ]; char *configbufp; size_t configbuflen; enum nss_status retv; if (nslcd_cfg==NULL) { configbufp=configbuf; configbuflen=sizeof(configbuf); retv=_nss_ldap_readconfig(&nslcd_cfg,&configbufp,&configbuflen); if (retv==NSS_STATUS_NOTFOUND) { /* config was read but no host information specified; try DNS */ retv=_nss_ldap_mergeconfigfromdns(nslcd_cfg,&configbufp,&configbuflen); } if (retv!=NSS_STATUS_SUCCESS) { log_log(LOG_DEBUG,"cfg_init() failed to read config"); return -1; } } return 0; } enum nss_status _nss_ldap_add_uri (struct ldap_config *result, const char *uri, char **buffer, size_t *buflen) { /* add a single URI to the list of URIs in the configuration */ int i; size_t uri_len; log_log(LOG_DEBUG,"==> _nss_ldap_add_uri"); for (i = 0; result->ldc_uris[i] != NULL; i++) ; if (i == NSS_LDAP_CONFIG_URI_MAX) { log_log(LOG_DEBUG,"<== _nss_ldap_add_uri: maximum number of URIs exceeded"); return NSS_STATUS_UNAVAIL; } assert (i < NSS_LDAP_CONFIG_URI_MAX); uri_len = strlen (uri); if (*buflen < uri_len + 1) return NSS_STATUS_TRYAGAIN; memcpy (*buffer, uri, uri_len + 1); result->ldc_uris[i] = *buffer; result->ldc_uris[i + 1] = NULL; *buffer += uri_len + 1; *buflen -= uri_len + 1; log_log(LOG_DEBUG,"<== _nss_ldap_add_uri: added URI %s", uri); return NSS_STATUS_SUCCESS; }