diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2007-01-17 16:03:11 +0000 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2007-01-17 16:03:11 +0000 |
commit | d2296ccd7c8bfdfffe4dc99c4c4db32eaae4c60b (patch) | |
tree | e35d6b53cc0b53c7425f8bf8f3923c28fc34562d /nslcd/cfg.c | |
parent | c026629eedf04f9d3579180980bb6bfa6759d15b (diff) |
move most config code into cfg.c, clean up dictornary stuff in util.c and do some more smaller restructuring
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-ldapd@223 ef36b2f9-881f-0410-afb5-c4e39611909c
Diffstat (limited to 'nslcd/cfg.c')
-rw-r--r-- | nslcd/cfg.c | 1000 |
1 files changed, 984 insertions, 16 deletions
diff --git a/nslcd/cfg.c b/nslcd/cfg.c index 37f7d8c..ba5e875 100644 --- a/nslcd/cfg.c +++ b/nslcd/cfg.c @@ -26,6 +26,12 @@ #include "config.h" #include <string.h> +#include <stdio.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdlib.h> #include "ldap-nss.h" #include "util.h" @@ -34,28 +40,951 @@ struct ldap_config *nslcd_cfg=NULL; -int _nss_ldap_test_config_flag (unsigned int flag) +#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); } -int _nss_ldap_test_initgroups_ignoreuser(const char *user) +static enum nss_status _nss_ldap_init_config(struct ldap_config *result) { - char **p; - if (nslcd_cfg == NULL) - return 0; + int i, j; - if (nslcd_cfg->ldc_initgroups_ignoreusers == NULL) - return 0; + memset (result, 0, sizeof (*result)); - for (p = nslcd_cfg->ldc_initgroups_ignoreusers; *p != NULL; p++) + 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++) { - if (strcmp (*p, user) == 0) - return 1; + result->ldc_maps[i][j]=(void *)dict_new(); + if (result->ldc_maps[i][j] == NULL) + return NSS_STATUS_UNAVAIL; } + } - return 0; + 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) +{ + struct ldap_datum key, val; + void **map; + enum nss_status retv; + + switch (type) + { + case MAP_ATTRIBUTE: + /* special handling for attribute mapping */ if (strcmp + (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 (strcmp (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; + } + break; + case MAP_OBJECTCLASS: + case MAP_OVERRIDE: + case MAP_DEFAULT: + break; + default: + return NSS_STATUS_NOTFOUND; + break; + } + + assert (sel <= LM_NONE); + map = &config->ldc_maps[sel][type]; + assert (*map != NULL); + + NSS_LDAP_DATUM_ZERO (&key); + key.data = (void *) from; + key.size = strlen (from) + 1; + + NSS_LDAP_DATUM_ZERO (&val); + val.data = (void *) to; + val.size = strlen (to) + 1; + + retv = dict_put (*map, NSS_LDAP_DB_NORMALIZE_CASE, &key, &val); + if (retv == NSS_STATUS_SUCCESS && + (type == MAP_ATTRIBUTE || type == MAP_OBJECTCLASS)) + { + type = (type == MAP_ATTRIBUTE) ? MAP_ATTRIBUTE_REVERSE : MAP_OBJECTCLASS_REVERSE; + map = &config->ldc_maps[sel][type]; + + retv = dict_put (*map, NSS_LDAP_DB_NORMALIZE_CASE, &val, &key); + } + + return retv; +} + +static enum nss_status do_parse_map_statement( + struct ldap_config *cfg,const 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 */ + int 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 <lars.oergel@innominate.de>, 05.10.2000 */ + while (*v == ' ' || *v == '\t') + v++; + + /* kick off all whitespaces and newline at the end of value */ + /* Bob Guo <bob@mail.ied.ac.cn>, 08.10.2001 */ + + /* Also remove \r (CR) to be able to handle files in DOS format (lines + * terminated in CR LF). Alejandro Forero Cuervo + * <azul@freaks-unidos.net>, 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) @@ -63,18 +992,18 @@ int cfg_init(void) static char configbuf[NSS_LDAP_CONFIG_BUFSIZ]; char *configbufp; size_t configbuflen; - enum nss_status stat; + enum nss_status retv; if (nslcd_cfg==NULL) { configbufp=configbuf; configbuflen=sizeof(configbuf); - stat=_nss_ldap_readconfig(&nslcd_cfg,&configbufp,&configbuflen); - if (stat==NSS_STATUS_NOTFOUND) + retv=_nss_ldap_readconfig(&nslcd_cfg,&configbufp,&configbuflen); + if (retv==NSS_STATUS_NOTFOUND) { /* config was read but no host information specified; try DNS */ - stat=_nss_ldap_mergeconfigfromdns(nslcd_cfg,&configbufp,&configbuflen); + retv=_nss_ldap_mergeconfigfromdns(nslcd_cfg,&configbufp,&configbuflen); } - if (stat != NSS_STATUS_SUCCESS) + if (retv!=NSS_STATUS_SUCCESS) { log_log(LOG_DEBUG,"cfg_init() failed to read config"); return -1; @@ -82,3 +1011,42 @@ int cfg_init(void) } 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; +} |