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 | |
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
-rw-r--r-- | nslcd/cfg.c | 1000 | ||||
-rw-r--r-- | nslcd/cfg.h | 12 | ||||
-rw-r--r-- | nslcd/group.c | 15 | ||||
-rw-r--r-- | nslcd/ldap-nss.c | 348 | ||||
-rw-r--r-- | nslcd/util.c | 1364 | ||||
-rw-r--r-- | nslcd/util.h | 43 |
6 files changed, 1348 insertions, 1434 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; +} diff --git a/nslcd/cfg.h b/nslcd/cfg.h index 5703701..71b552e 100644 --- a/nslcd/cfg.h +++ b/nslcd/cfg.h @@ -152,12 +152,18 @@ extern struct ldap_config *nslcd_cfg; * ** implemented */ -enum nss_status _nss_ldap_readconfig(struct ldap_config **result,char **buffer,size_t *buflen); -enum nss_status _nss_ldap_validateconfig(struct ldap_config *config); +/* + * Flags that are exposed via _nss_ldap_test_config_flag() + */ +#define NSS_LDAP_FLAGS_INITGROUPS_BACKLINK 0x0001 +#define NSS_LDAP_FLAGS_PAGED_RESULTS 0x0002 +#define NSS_LDAP_FLAGS_RFC2307BIS 0x0004 +#define NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT 0x0008 int _nss_ldap_test_config_flag(unsigned int flag); -int _nss_ldap_test_initgroups_ignoreuser(const char *user); int cfg_init(void); +enum nss_status _nss_ldap_add_uri (struct ldap_config *result, const char *uri,char **buffer, size_t *buflen); + #endif /* _CFG_H */ diff --git a/nslcd/group.c b/nslcd/group.c index 1c92987..5753932 100644 --- a/nslcd/group.c +++ b/nslcd/group.c @@ -48,6 +48,7 @@ #include "util.h" #include "common.h" #include "log.h" +#include "cfg.h" struct name_list { @@ -998,6 +999,20 @@ static enum nss_status ng_chase_backlink(const char ** membersOf, ldap_initgroup return stat; } +static int _nss_ldap_test_initgroups_ignoreuser(const char *user) +{ + char **p; + if (nslcd_cfg == NULL) + return 0; + if (nslcd_cfg->ldc_initgroups_ignoreusers == NULL) + return 0; + for (p = nslcd_cfg->ldc_initgroups_ignoreusers; *p != NULL; p++) + { + if (strcmp (*p, user) == 0) + return 1; + } + return 0; +} static enum nss_status group_bymember(const char *user, long int *start, long int *size, long int limit, diff --git a/nslcd/ldap-nss.c b/nslcd/ldap-nss.c index f5f6e4c..7423617 100644 --- a/nslcd/ldap-nss.c +++ b/nslcd/ldap-nss.c @@ -82,7 +82,6 @@ #include "ldap-nss.h" #include "util.h" -#include "dnsconfig.h" #include "pagectrl.h" #include "common.h" #include "log.h" @@ -148,14 +147,6 @@ static void do_close (void); static void do_set_sockopts (void); /* - * TLS routines: set global SSL session options. - */ -#if defined(HAVE_LDAP_START_TLS_S) || defined(HAVE_LDAP_START_TLS) || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) -static int do_ssl_options(struct ldap_config *cfg); -static int do_start_tls(struct ldap_session *session); -#endif - -/* * Function to be braced by reconnect harness. Used so we * can apply the reconnect code to both asynchronous and * synchronous searches. @@ -393,6 +384,72 @@ do_bind (LDAP * ld, int timelimit, const char *dn, const char *pw, return -1; } +#if defined(HAVE_LDAP_START_TLS_S) || defined(HAVE_LDAP_START_TLS) +static int do_start_tls (struct ldap_session * session) +{ + int rc; +#ifdef HAVE_LDAP_START_TLS + int msgid; + struct timeval tv,*timeout; + LDAPMessage *res=NULL; + + log_log(LOG_DEBUG,"==> do_start_tls"); + + rc=ldap_start_tls(session->ls_conn, NULL, NULL, &msgid); + if (rc != LDAP_SUCCESS) + { + log_log(LOG_DEBUG,"<== do_start_tls (ldap_start_tls failed: %s)",ldap_err2string(rc)); + return rc; + } + + if (session->ls_config->ldc_bind_timelimit==LDAP_NO_LIMIT) + { + timeout=NULL; + } + else + { + tv.tv_sec=session->ls_config->ldc_bind_timelimit; + tv.tv_usec=0; + timeout=&tv; + } + + rc=ldap_result(session->ls_conn,msgid,1,timeout,&res); + if (rc==-1) + { +#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) + if (ldap_get_option(session->ls_conn,LDAP_OPT_ERROR_NUMBER,&rc)!=LDAP_SUCCESS) + { + rc=LDAP_UNAVAILABLE; + } +#else + rc=ld->ld_errno; +#endif /* LDAP_OPT_ERROR_NUMBER */ + log_log(LOG_DEBUG,"<== do_start_tls (ldap_start_tls failed: %s)",ldap_err2string (rc)); + return rc; + } + + rc=ldap_result2error(session->ls_conn,res,1); + if (rc!=LDAP_SUCCESS) + { + log_log(LOG_DEBUG,"<== do_start_tls (ldap_result2error failed: %s)",ldap_err2string (rc)); + return rc; + } + + rc=ldap_install_tls(session->ls_conn); +#else + rc=ldap_start_tls_s(session->ls_conn,NULL,NULL); +#endif /* HAVE_LDAP_START_TLS */ + + if (rc != LDAP_SUCCESS) + { + log_log(LOG_DEBUG,"<== do_start_tls (start TLS failed: %s)",ldap_err2string(rc)); + return rc; + } + + return LDAP_SUCCESS; +} +#endif + /* * Rebind functions. */ @@ -860,70 +917,83 @@ _nss_ldap_init (void) return do_init (); } -#if defined(HAVE_LDAP_START_TLS_S) || defined(HAVE_LDAP_START_TLS) -static int -do_start_tls (struct ldap_session * session) +#if defined HAVE_LDAP_START_TLS_S || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) +static int do_ssl_options(void) { - int rc; -#ifdef HAVE_LDAP_START_TLS - int msgid; - struct timeval tv, *timeout; - LDAPMessage *res = NULL; - - log_log(LOG_DEBUG,"==> do_start_tls"); - - rc = ldap_start_tls (session->ls_conn, NULL, NULL, &msgid); - if (rc != LDAP_SUCCESS) - { - log_log(LOG_DEBUG,"<== do_start_tls (ldap_start_tls failed: %s)", ldap_err2string (rc)); - return rc; - } - - if (session->ls_config->ldc_bind_timelimit == LDAP_NO_LIMIT) + log_log(LOG_DEBUG,"==> do_ssl_options"); +#ifdef LDAP_OPT_X_TLS_RANDOM_FILE + if (nslcd_cfg->ldc_tls_randfile!=NULL) + { + /* rand file */ + if (ldap_set_option(NULL,LDAP_OPT_X_TLS_RANDOM_FILE, + nslcd_cfg->ldc_tls_randfile)!=LDAP_SUCCESS) { - timeout = NULL; + log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_RANDOM_FILE failed"); + return LDAP_OPERATIONS_ERROR; } - else + } +#endif /* LDAP_OPT_X_TLS_RANDOM_FILE */ + if (nslcd_cfg->ldc_tls_cacertfile!=NULL) + { + /* ca cert file */ + if (ldap_set_option(NULL,LDAP_OPT_X_TLS_CACERTFILE, + nslcd_cfg->ldc_tls_cacertfile)!=LDAP_SUCCESS) { - tv.tv_sec = session->ls_config->ldc_bind_timelimit; - tv.tv_usec = 0; - timeout = &tv; + log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_CACERTFILE failed"); + return LDAP_OPERATIONS_ERROR; } - - rc = ldap_result (session->ls_conn, msgid, 1, timeout, &res); - if (rc == -1) + } + if (nslcd_cfg->ldc_tls_cacertdir!=NULL) + { + /* ca cert directory */ + if (ldap_set_option(NULL,LDAP_OPT_X_TLS_CACERTDIR, + nslcd_cfg->ldc_tls_cacertdir)!=LDAP_SUCCESS) { -#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) - if (ldap_get_option (session->ls_conn, LDAP_OPT_ERROR_NUMBER, &rc) != LDAP_SUCCESS) - { - rc = LDAP_UNAVAILABLE; - } -#else - rc = ld->ld_errno; -#endif /* LDAP_OPT_ERROR_NUMBER */ - - log_log(LOG_DEBUG,"<== do_start_tls (ldap_start_tls failed: %s)", ldap_err2string (rc)); - return rc; + log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_CACERTDIR failed"); + return LDAP_OPERATIONS_ERROR; } - - rc = ldap_result2error (session->ls_conn, res, 1); - if (rc != LDAP_SUCCESS) + } + /* require cert? */ + if (nslcd_cfg->ldc_tls_checkpeer > -1) + { + if (ldap_set_option(NULL,LDAP_OPT_X_TLS_REQUIRE_CERT, + &nslcd_cfg->ldc_tls_checkpeer)!=LDAP_SUCCESS) { - log_log(LOG_DEBUG,"<== do_start_tls (ldap_result2error failed: %s)", ldap_err2string (rc)); - return rc; + log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_REQUIRE_CERT failed"); + return LDAP_OPERATIONS_ERROR; } + } - rc = ldap_install_tls (session->ls_conn); -#else - rc = ldap_start_tls_s (session->ls_conn, NULL, NULL); -#endif /* HAVE_LDAP_START_TLS */ - - if (rc != LDAP_SUCCESS) - { - log_log(LOG_DEBUG,"<== do_start_tls (start TLS failed: %s)", ldap_err2string(rc)); - return rc; - } + if (nslcd_cfg->ldc_tls_ciphers != NULL) + { + /* set cipher suite, certificate and private key: */ + if (ldap_set_option(NULL,LDAP_OPT_X_TLS_CIPHER_SUITE, + nslcd_cfg->ldc_tls_ciphers)!=LDAP_SUCCESS) + { + log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_CIPHER_SUITE failed"); + return LDAP_OPERATIONS_ERROR; + } + } + if (nslcd_cfg->ldc_tls_cert != NULL) + { + if (ldap_set_option(NULL,LDAP_OPT_X_TLS_CERTFILE, + nslcd_cfg->ldc_tls_cert)!=LDAP_SUCCESS) + { + log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_CERTFILE failed"); + return LDAP_OPERATIONS_ERROR; + } + } + if (nslcd_cfg->ldc_tls_key != NULL) + { + if (ldap_set_option(NULL,LDAP_OPT_X_TLS_KEYFILE, + nslcd_cfg->ldc_tls_key)!=LDAP_SUCCESS) + { + log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_KEYFILE failed"); + return LDAP_OPERATIONS_ERROR; + } + } + log_log(LOG_DEBUG,"<== do_ssl_options"); return LDAP_SUCCESS; } #endif @@ -939,7 +1009,6 @@ do_start_tls (struct ldap_session * session) static enum nss_status do_open (void) { - struct ldap_config *cfg; int usesasl; char *bindarg; enum nss_status stat; @@ -971,8 +1040,6 @@ do_open (void) return NSS_STATUS_SUCCESS; } - cfg = nslcd_cfg; - #if LDAP_SET_REBIND_PROC_ARGS == 3 ldap_set_rebind_proc (__session.ls_conn, do_rebind, NULL); #elif LDAP_SET_REBIND_PROC_ARGS == 2 @@ -980,12 +1047,12 @@ do_open (void) #endif ldap_set_option (__session.ls_conn, LDAP_OPT_PROTOCOL_VERSION, - &cfg->ldc_version); + &nslcd_cfg->ldc_version); - ldap_set_option (__session.ls_conn, LDAP_OPT_DEREF, &cfg->ldc_deref); + ldap_set_option (__session.ls_conn, LDAP_OPT_DEREF, &nslcd_cfg->ldc_deref); ldap_set_option (__session.ls_conn, LDAP_OPT_TIMELIMIT, - &cfg->ldc_timelimit); + &nslcd_cfg->ldc_timelimit); #ifdef LDAP_X_OPT_CONNECT_TIMEOUT /* @@ -993,28 +1060,28 @@ do_open (void) * the TCP connect timeout. For want of a better value, * we use the bind_timelimit to control this. */ - timeout = cfg->ldc_bind_timelimit * 1000; + timeout = nslcd_cfg->ldc_bind_timelimit * 1000; ldap_set_option (__session.ls_conn, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout); #endif /* LDAP_X_OPT_CONNECT_TIMEOUT */ #ifdef LDAP_OPT_NETWORK_TIMEOUT - tv.tv_sec = cfg->ldc_bind_timelimit; + tv.tv_sec = nslcd_cfg->ldc_bind_timelimit; tv.tv_usec = 0; ldap_set_option (__session.ls_conn, LDAP_OPT_NETWORK_TIMEOUT, &tv); #endif /* LDAP_OPT_NETWORK_TIMEOUT */ #ifdef LDAP_OPT_REFERRALS ldap_set_option (__session.ls_conn, LDAP_OPT_REFERRALS, - cfg->ldc_referrals ? LDAP_OPT_ON : LDAP_OPT_OFF); + nslcd_cfg->ldc_referrals ? LDAP_OPT_ON : LDAP_OPT_OFF); #endif /* LDAP_OPT_REFERRALS */ #ifdef LDAP_OPT_RESTART ldap_set_option (__session.ls_conn, LDAP_OPT_RESTART, - cfg->ldc_restart ? LDAP_OPT_ON : LDAP_OPT_OFF); + nslcd_cfg->ldc_restart ? LDAP_OPT_ON : LDAP_OPT_OFF); #endif /* LDAP_OPT_RESTART */ #if defined(HAVE_LDAP_START_TLS_S) || defined(HAVE_LDAP_START_TLS) - if (cfg->ldc_ssl_on == SSL_START_TLS) + if (nslcd_cfg->ldc_ssl_on == SSL_START_TLS) { int version; @@ -1031,7 +1098,7 @@ do_open (void) } /* set up SSL context */ - if (do_ssl_options (cfg) != LDAP_SUCCESS) + if (do_ssl_options()!=LDAP_SUCCESS) { do_close (); log_log(LOG_DEBUG,"<== do_open (SSL setup failed)"); @@ -1056,11 +1123,11 @@ do_open (void) /* * If SSL is desired, then enable it. */ - if (cfg->ldc_ssl_on == SSL_LDAPS) + if (nslcd_cfg->ldc_ssl_on == SSL_LDAPS) { #if defined(LDAP_OPT_X_TLS) int tls = LDAP_OPT_X_TLS_HARD; - if (ldap_set_option (__session.ls_conn, LDAP_OPT_X_TLS, &tls) != + if (ldap_set_option(__session.ls_conn, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) { do_close (); @@ -1069,7 +1136,7 @@ do_open (void) } /* set up SSL context */ - if (do_ssl_options (cfg) != LDAP_SUCCESS) + if (do_ssl_options()!=LDAP_SUCCESS) { do_close (); log_log(LOG_DEBUG,"<== do_open (SSL setup failed)"); @@ -1103,35 +1170,34 @@ do_open (void) * Thanks to Doug Nazar <nazard@dragoninc.on.ca> for this * patch. */ - if (geteuid() == 0 && cfg->ldc_rootbinddn != NULL) + if (geteuid() == 0 && nslcd_cfg->ldc_rootbinddn != NULL) { #if defined(HAVE_LDAP_SASL_INTERACTIVE_BIND_S) && (defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H)) - usesasl = cfg->ldc_rootusesasl; - bindarg = - cfg->ldc_rootusesasl ? cfg->ldc_rootsaslid : cfg->ldc_rootbindpw; + usesasl = nslcd_cfg->ldc_rootusesasl; + bindarg = nslcd_cfg->ldc_rootusesasl ? nslcd_cfg->ldc_rootsaslid : nslcd_cfg->ldc_rootbindpw; #else usesasl = 0; - bindarg = cfg->ldc_rootbindpw; + bindarg = nslcd_cfg->ldc_rootbindpw; #endif rc = do_bind (__session.ls_conn, - cfg->ldc_bind_timelimit, - cfg->ldc_rootbinddn, bindarg, usesasl); + nslcd_cfg->ldc_bind_timelimit, + nslcd_cfg->ldc_rootbinddn, bindarg, usesasl); } else { #if defined(HAVE_LDAP_SASL_INTERACTIVE_BIND_S) && (defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H)) - usesasl = cfg->ldc_usesasl; - bindarg = cfg->ldc_usesasl ? cfg->ldc_saslid : cfg->ldc_bindpw; + usesasl = nslcd_cfg->ldc_usesasl; + bindarg = nslcd_cfg->ldc_usesasl ? nslcd_cfg->ldc_saslid : nslcd_cfg->ldc_bindpw; #else usesasl = 0; - bindarg = cfg->ldc_bindpw; + bindarg = nslcd_cfg->ldc_bindpw; #endif rc = do_bind (__session.ls_conn, - cfg->ldc_bind_timelimit, - cfg->ldc_binddn, - cfg->ldc_bindpw, usesasl); + nslcd_cfg->ldc_bind_timelimit, + nslcd_cfg->ldc_binddn, + nslcd_cfg->ldc_bindpw, usesasl); } if (rc != LDAP_SUCCESS) @@ -1139,7 +1205,7 @@ do_open (void) /* log actual LDAP error code */ syslog (LOG_AUTHPRIV | LOG_INFO, "nss_ldap: failed to bind to LDAP server %s: %s", - cfg->ldc_uris[__session.ls_current_uri], + nslcd_cfg->ldc_uris[__session.ls_current_uri], ldap_err2string (rc)); stat = do_map_error (rc); do_close (); @@ -1157,102 +1223,6 @@ do_open (void) return stat; } -#if defined HAVE_LDAP_START_TLS_S || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) -static int -do_ssl_options (struct ldap_config * cfg) -{ - int rc; - - log_log(LOG_DEBUG,"==> do_ssl_options"); - -#ifdef LDAP_OPT_X_TLS_RANDOM_FILE - if (cfg->ldc_tls_randfile != NULL) - { - /* rand file */ - rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE, - cfg->ldc_tls_randfile); - if (rc != LDAP_SUCCESS) - { - log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_RANDOM_FILE failed"); - return LDAP_OPERATIONS_ERROR; - } - } -#endif /* LDAP_OPT_X_TLS_RANDOM_FILE */ - - if (cfg->ldc_tls_cacertfile != NULL) - { - /* ca cert file */ - rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, - cfg->ldc_tls_cacertfile); - if (rc != LDAP_SUCCESS) - { - log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_CACERTFILE failed"); - return LDAP_OPERATIONS_ERROR; - } - } - - if (cfg->ldc_tls_cacertdir != NULL) - { - /* ca cert directory */ - rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR, - cfg->ldc_tls_cacertdir); - if (rc != LDAP_SUCCESS) - { - log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_CACERTDIR failed"); - return LDAP_OPERATIONS_ERROR; - } - } - - /* require cert? */ - if (cfg->ldc_tls_checkpeer > -1) - { - rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, - &cfg->ldc_tls_checkpeer); - if (rc != LDAP_SUCCESS) - { - log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_REQUIRE_CERT failed"); - return LDAP_OPERATIONS_ERROR; - } - } - - if (cfg->ldc_tls_ciphers != NULL) - { - /* set cipher suite, certificate and private key: */ - rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, - cfg->ldc_tls_ciphers); - if (rc != LDAP_SUCCESS) - { - log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_CIPHER_SUITE failed"); - return LDAP_OPERATIONS_ERROR; - } - } - - if (cfg->ldc_tls_cert != NULL) - { - rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE, cfg->ldc_tls_cert); - if (rc != LDAP_SUCCESS) - { - log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_CERTFILE failed"); - return LDAP_OPERATIONS_ERROR; - } - } - - if (cfg->ldc_tls_key != NULL) - { - rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE, cfg->ldc_tls_key); - if (rc != LDAP_SUCCESS) - { - log_log(LOG_DEBUG,"<== do_ssl_options: Setting of LDAP_OPT_X_TLS_KEYFILE failed"); - return LDAP_OPERATIONS_ERROR; - } - } - - log_log(LOG_DEBUG,"<== do_ssl_options"); - - return LDAP_SUCCESS; -} -#endif - /* * This function initializes an enumeration context, acquiring * the global mutex. @@ -3165,12 +3135,12 @@ _nss_ldap_map_get (enum ldap_map_selector sel, NSS_LDAP_DATUM_ZERO (&val); - stat = _nss_ldap_db_get (map, NSS_LDAP_DB_NORMALIZE_CASE, &key, &val); + stat = dict_get (map, NSS_LDAP_DB_NORMALIZE_CASE, &key, &val); if (stat == NSS_STATUS_NOTFOUND && sel != LM_NONE) { map = nslcd_cfg->ldc_maps[LM_NONE][type]; assert (map != NULL); - stat = _nss_ldap_db_get (map, NSS_LDAP_DB_NORMALIZE_CASE, &key, &val); + stat = dict_get (map, NSS_LDAP_DB_NORMALIZE_CASE, &key, &val); } if (stat == NSS_STATUS_SUCCESS) diff --git a/nslcd/util.c b/nslcd/util.c index 182c822..f067160 100644 --- a/nslcd/util.c +++ b/nslcd/util.c @@ -56,91 +56,6 @@ #include "log.h" #include "cfg.h" -#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 ) - -/* - * 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 LDAP_PAGESIZE 1000 - - -static struct ldap_dictionary *do_alloc_dictionary(void); -static enum nss_status do_getrdnvalue (const char *dn, - const char *rdntype, - char **rval, char **buffer, - size_t * buflen); - -static enum nss_status do_parse_map_statement (struct ldap_config * cfg, - const char *statement, - enum ldap_map_type type); - -static enum nss_status do_searchdescriptorconfig (const char *key, - const char *value, - size_t valueLength, - struct ldap_service_search_descriptor - ** result, char **buffer, - size_t * buflen); static void *__cache = NULL; @@ -159,7 +74,7 @@ dn2uid_cache_put (const char *dn, const char *uid) if (__cache == NULL) { - __cache = (void *)do_alloc_dictionary(); + __cache = (void *)dict_new(); if (__cache == NULL) { cache_unlock (); @@ -172,7 +87,7 @@ dn2uid_cache_put (const char *dn, const char *uid) val.data = (void *) uid; val.size = strlen (uid); - status = _nss_ldap_db_put (__cache, 0, &key, &val); + status = dict_put (__cache, 0, &key, &val); cache_unlock (); @@ -196,7 +111,7 @@ dn2uid_cache_get (const char *dn, char **uid, char **buffer, size_t * buflen) key.data = (void *) dn; key.size = strlen (dn); - status = _nss_ldap_db_get (__cache, 0, &key, &val); + status = dict_get (__cache, 0, &key, &val); if (status != NSS_STATUS_SUCCESS) { cache_unlock (); @@ -268,131 +183,6 @@ _nss_ldap_dn2uid (const char *dn, char **uid, char **buffer, size_t * buflen, return status; } -enum nss_status -_nss_ldap_getrdnvalue (LDAPMessage * entry, - const char *rdntype, - char **rval, char **buffer, size_t * buflen) -{ - char *dn; - enum nss_status status; - - dn = _nss_ldap_get_dn (entry); - if (dn == NULL) - { - return NSS_STATUS_NOTFOUND; - } - - status = do_getrdnvalue (dn, rdntype, rval, buffer, buflen); -#ifdef HAVE_LDAP_MEMFREE - ldap_memfree (dn); -#else /* HAVE_LDAP_MEMFREE */ - free (dn); -#endif /* not HAVE_LDAP_MEMFREE */ - - /* - * If examining the DN failed, then pick the nominal first - * value of cn as the canonical name (recall that attributes - * are sets, not sequences) - */ - if (status == NSS_STATUS_NOTFOUND) - { - char **vals; - - vals = _nss_ldap_get_values (entry, rdntype); - - if (vals != NULL) - { - int rdnlen = strlen (*vals); - if (*buflen > rdnlen) - { - char *rdnvalue = *buffer; - strncpy (rdnvalue, *vals, rdnlen); - rdnvalue[rdnlen] = '\0'; - *buffer += rdnlen + 1; - *buflen -= rdnlen + 1; - *rval = rdnvalue; - status = NSS_STATUS_SUCCESS; - } - else - { - status = NSS_STATUS_TRYAGAIN; - } - ldap_value_free (vals); - } - } - - return status; -} - -int _nss_ldap_write_rndvalue(FILE *fp,LDAPMessage *entry,const char *rdntype) -{ - char *dn; - int status=456; - char **vals; - int32_t tmpint32; - char **exploded_dn; - char **exploded_rdn; - char rdnava[64]; - int rdnavalen; - int i; - /* log call */ - log_log(LOG_DEBUG,"_nss_ldap_write_rndvalue(%s)",rdntype); - /* get the dn from the entry */ - dn=_nss_ldap_get_dn(entry); - if (dn==NULL) - return NSLCD_RESULT_NOTFOUND; - /* append a `=' to the rdntype */ - snprintf(rdnava,sizeof(rdnava),"%s=",rdntype); - rdnavalen=strlen(rdnava); - /* explode dn */ - exploded_dn=ldap_explode_dn(dn,0); - if (exploded_dn!=NULL) - { - /* - * attempt to get the naming attribute's principal - * value by parsing the RDN. We need to support - * multivalued RDNs (as they're essentially mandated - * for services) - */ - exploded_rdn=ldap_explode_rdn(exploded_dn[0],0); - if (exploded_rdn!=NULL) - { - for (i=0;exploded_rdn[i]!=NULL;i++) - { - /* if the values begins with rndava */ - if (strncasecmp(exploded_rdn[i],rdnava,rdnavalen)==0) - { - /* FIXME: handle case where WRITE fails */ - WRITE_STRING(fp,exploded_rdn[i]+rdnavalen); - status=0; - break; - } - } - ldap_value_free(exploded_rdn); - } - ldap_value_free(exploded_dn); - } - ldap_memfree(dn); - /* - * If examining the DN failed, then pick the nominal first - * value of cn as the canonical name (recall that attributes - * are sets, not sequences) - */ - if (status==456) - { - vals=_nss_ldap_get_values(entry,rdntype); - if (vals!=NULL) - { - /* write the first entry */ - WRITE_STRING(fp,vals[0]); - status=NSS_STATUS_SUCCESS; - ldap_value_free(vals); - status=0; - } - } - return status; -} - static enum nss_status do_getrdnvalue (const char *dn, const char *rdntype, @@ -505,922 +295,128 @@ do_getrdnvalue (const char *dn, return NSS_STATUS_NOTFOUND; } -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 = _nss_ldap_db_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 = _nss_ldap_db_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; - - key = (char *) statement; - val = key; - while (*val != ' ' && *val != '\t') - val++; - *(val++) = '\0'; - - while (*val == ' ' || *val == '\t') - val++; - - { - char *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_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] = (void *)do_alloc_dictionary(); - if (result->ldc_maps[i][j] == NULL) - return NSS_STATUS_UNAVAIL; - } - } - - return NSS_STATUS_SUCCESS; -} - -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; -} - -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 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; -} - enum nss_status -_nss_ldap_readconfig (struct ldap_config ** presult, char **buffer, size_t *buflen) +_nss_ldap_getrdnvalue (LDAPMessage * entry, + const char *rdntype, + char **rval, 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; - } + char *dn; + enum nss_status status; - fp = fopen (NSS_LDAP_PATH_CONF, "r"); - if (fp == NULL) + dn = _nss_ldap_get_dn (entry); + if (dn == NULL) { - return NSS_STATUS_UNAVAIL; + return NSS_STATUS_NOTFOUND; } - if (fstat (fileno (fp), &statbuf) == 0) - result->ldc_mtime = statbuf.st_mtime; - else - result->ldc_mtime = 0; + status = do_getrdnvalue (dn, rdntype, rval, buffer, buflen); +#ifdef HAVE_LDAP_MEMFREE + ldap_memfree (dn); +#else /* HAVE_LDAP_MEMFREE */ + free (dn); +#endif /* not HAVE_LDAP_MEMFREE */ - while (fgets (b, sizeof (b), fp) != NULL) + /* + * If examining the DN failed, then pick the nominal first + * value of cn as the canonical name (recall that attributes + * are sets, not sequences) + */ + if (status == NSS_STATUS_NOTFOUND) { - 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'; + char **vals; - if (*buflen < (size_t) (len + 1)) - { - status = NSS_STATUS_TRYAGAIN; - break; - } + vals = _nss_ldap_get_values (entry, rdntype); - 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 (vals != NULL) { - if (!strcasecmp (v, "on") - || !strcasecmp (v, "yes") - || !strcasecmp (v, "true")) + int rdnlen = strlen (*vals); + if (*buflen > rdnlen) { - result->ldc_flags |= NSS_LDAP_FLAGS_PAGED_RESULTS; + char *rdnvalue = *buffer; + strncpy (rdnvalue, *vals, rdnlen); + rdnvalue[rdnlen] = '\0'; + *buffer += rdnlen + 1; + *buflen -= rdnlen + 1; + *rval = rdnvalue; + status = NSS_STATUS_SUCCESS; } 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; + status = NSS_STATUS_TRYAGAIN; } + ldap_value_free (vals); } - - 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; - } - } + return status; +} - if (result->ldc_port == 0) +int _nss_ldap_write_rndvalue(FILE *fp,LDAPMessage *entry,const char *rdntype) +{ + char *dn; + int status=456; + char **vals; + int32_t tmpint32; + char **exploded_dn; + char **exploded_rdn; + char rdnava[64]; + int rdnavalen; + int i; + /* log call */ + log_log(LOG_DEBUG,"_nss_ldap_write_rndvalue(%s)",rdntype); + /* get the dn from the entry */ + dn=_nss_ldap_get_dn(entry); + if (dn==NULL) + return NSLCD_RESULT_NOTFOUND; + /* append a `=' to the rdntype */ + snprintf(rdnava,sizeof(rdnava),"%s=",rdntype); + rdnavalen=strlen(rdnava); + /* explode dn */ + exploded_dn=ldap_explode_dn(dn,0); + if (exploded_dn!=NULL) + { + /* + * attempt to get the naming attribute's principal + * value by parsing the RDN. We need to support + * multivalued RDNs (as they're essentially mandated + * for services) + */ + exploded_rdn=ldap_explode_rdn(exploded_dn[0],0); + if (exploded_rdn!=NULL) { - if (result->ldc_ssl_on == SSL_LDAPS) - { - result->ldc_port = LDAPS_PORT; - } - else + for (i=0;exploded_rdn[i]!=NULL;i++) + { + /* if the values begins with rndava */ + if (strncasecmp(exploded_rdn[i],rdnava,rdnavalen)==0) { - result->ldc_port = LDAP_PORT; + /* FIXME: handle case where WRITE fails */ + WRITE_STRING(fp,exploded_rdn[i]+rdnavalen); + status=0; + break; } + } + ldap_value_free(exploded_rdn); } - - if (result->ldc_uris[0] == NULL) + ldap_value_free(exploded_dn); + } + ldap_memfree(dn); + /* + * If examining the DN failed, then pick the nominal first + * value of cn as the canonical name (recall that attributes + * are sets, not sequences) + */ + if (status==456) + { + vals=_nss_ldap_get_values(entry,rdntype); + if (vals!=NULL) { - status = NSS_STATUS_NOTFOUND; + /* write the first entry */ + WRITE_STRING(fp,vals[0]); + status=NSS_STATUS_SUCCESS; + ldap_value_free(vals); + status=0; } - + } return status; } @@ -1463,28 +459,17 @@ int _nss_ldap_escape_string(const char *src,char *buffer,size_t buflen) return 0; } -/* XXX just a linked list for now */ - -struct ldap_dictionary -{ - struct ldap_datum key; - struct ldap_datum value; - struct ldap_dictionary *next; -}; - -static struct ldap_dictionary *do_alloc_dictionary(void) +struct ldap_dictionary *dict_new(void) { struct ldap_dictionary *dict; - - dict = malloc (sizeof (*dict)); - if (dict == NULL) - { - return NULL; - } - NSS_LDAP_DATUM_ZERO (&dict->key); - NSS_LDAP_DATUM_ZERO (&dict->value); - dict->next = NULL; - + dict = malloc(sizeof(struct ldap_dictionary)); + if (dict==NULL) + { + return NULL; + } + NSS_LDAP_DATUM_ZERO(&dict->key); + NSS_LDAP_DATUM_ZERO(&dict->value); + dict->next=NULL; return dict; } @@ -1531,103 +516,74 @@ do_dup_datum (unsigned flags, struct ldap_datum * dst, const struct ldap_datum * return NSS_STATUS_SUCCESS; } -enum nss_status -_nss_ldap_db_get (void *db, - unsigned flags, - const struct ldap_datum * key, - struct ldap_datum * value) +enum nss_status dict_get( + struct ldap_dictionary *db, + unsigned flags, + const struct ldap_datum *key, + struct ldap_datum *value) { - struct ldap_dictionary *dict = (struct ldap_dictionary *) db; struct ldap_dictionary *p; - - for (p = dict; p != NULL; p = p->next) - { - int cmp; - - if (p->key.size != key->size) - continue; - - if (flags & NSS_LDAP_DB_NORMALIZE_CASE) - cmp = strncasecmp ((char *)p->key.data, (char *)key->data, key->size); - else - cmp = memcmp (p->key.data, key->data, key->size); - - if (cmp == 0) - { - value->data = p->value.data; - value->size = p->value.size; - - return NSS_STATUS_SUCCESS; - } + for (p=db;p!=NULL;p=p->next) + { + int cmp; + if (p->key.size != key->size) + continue; + if (flags & NSS_LDAP_DB_NORMALIZE_CASE) + cmp=strncasecmp((char *)p->key.data,(char *)key->data,key->size); + else + cmp=memcmp(p->key.data,key->data,key->size); + if (cmp==0) + { + value->data=p->value.data; + value->size=p->value.size; + return NSS_STATUS_SUCCESS; } - + } return NSS_STATUS_NOTFOUND; } -enum nss_status -_nss_ldap_db_put (void *db, - unsigned flags, - const struct ldap_datum * key, - const struct ldap_datum * value) +enum nss_status dict_put( + struct ldap_dictionary *db, + unsigned flags, + const struct ldap_datum *key, + const struct ldap_datum *value) { struct ldap_dictionary *dict = (struct ldap_dictionary *) db; struct ldap_dictionary *p, *q; - assert (key != NULL); - assert (key->data != NULL); + assert(key!=NULL); + assert(key->data!=NULL); - if (dict->key.data == NULL) - { - /* uninitialized */ - q = dict; - p = NULL; - } + if (dict->key.data==NULL) + { + /* uninitialized */ + q=dict; + p=NULL; + } else - { - p = do_find_last (dict); - assert (p != NULL); - assert (p->next == NULL); - q = do_alloc_dictionary(); - if (q == NULL) - return NSS_STATUS_TRYAGAIN; - } - - if (do_dup_datum (flags, &q->key, key) != NSS_STATUS_SUCCESS) - { - do_free_dictionary (q); - return NSS_STATUS_TRYAGAIN; - } - - if (do_dup_datum (flags, &q->value, value) != NSS_STATUS_SUCCESS) - { - do_free_dictionary (q); + { + p=do_find_last(dict); + assert(p!=NULL); + assert(p->next==NULL); + q=dict_new(); + if (q==NULL) return NSS_STATUS_TRYAGAIN; - } - - if (p != NULL) - p->next = q; - - return NSS_STATUS_SUCCESS; -} - -enum nss_status _nss_ldap_validateconfig (struct ldap_config *config) -{ - struct stat statbuf; + } - if (config == NULL) - { - return NSS_STATUS_UNAVAIL; - } + if (do_dup_datum(flags,&q->key,key)!=NSS_STATUS_SUCCESS) + { + do_free_dictionary(q); + return NSS_STATUS_TRYAGAIN; + } - if (config->ldc_mtime == 0) - { - return NSS_STATUS_SUCCESS; - } + if (do_dup_datum(flags,&q->value,value)!=NSS_STATUS_SUCCESS) + { + do_free_dictionary(q); + return NSS_STATUS_TRYAGAIN; + } - if (stat (NSS_LDAP_PATH_CONF, &statbuf) == 0) - { - return (statbuf.st_mtime > config->ldc_mtime) ? NSS_STATUS_TRYAGAIN : NSS_STATUS_SUCCESS; - } + if (p!=NULL) + p->next=q; return NSS_STATUS_SUCCESS; } diff --git a/nslcd/util.h b/nslcd/util.h index 44698d9..eacc7da 100644 --- a/nslcd/util.h +++ b/nslcd/util.h @@ -44,22 +44,14 @@ enum nss_status _nss_ldap_dn2uid (const char *dn, int *pIsNestedGroup, LDAPMessage ** pRes); -#define NSS_LDAP_CONFIG_BUFSIZ 4096 - -/* - * Flags that are exposed via _nss_ldap_test_config_flag() - */ -#define NSS_LDAP_FLAGS_INITGROUPS_BACKLINK 0x0001 -#define NSS_LDAP_FLAGS_PAGED_RESULTS 0x0002 -#define NSS_LDAP_FLAGS_RFC2307BIS 0x0004 -#define NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT 0x0008 - /* * Escape '*' in a string for use as a filter */ int _nss_ldap_escape_string(const char *str,char *buf,size_t buflen); +/* Dictionary functions. */ + struct ldap_datum { void *data; @@ -73,17 +65,24 @@ struct ldap_datum #define NSS_LDAP_DB_NORMALIZE_CASE 0x1 -enum nss_status _nss_ldap_db_put (void *db, - unsigned flags, - const struct ldap_datum * key, - const struct ldap_datum * value); -enum nss_status _nss_ldap_db_get (void *db, - unsigned flags, - const struct ldap_datum * key, - struct ldap_datum * value); - -enum nss_status -_nss_ldap_add_uri (struct ldap_config *result, const char *uri, - char **buffer, size_t *buflen); +struct ldap_dictionary +{ + struct ldap_datum key; + struct ldap_datum value; + struct ldap_dictionary *next; +}; + +struct ldap_dictionary *dict_new(void); +enum nss_status dict_put(struct ldap_dictionary *db, + unsigned flags, + const struct ldap_datum *key, + const struct ldap_datum *value); +enum nss_status dict_get(struct ldap_dictionary *db, + unsigned flags, + const struct ldap_datum *key, + struct ldap_datum *value); + + + #endif /* _LDAP_NSS_LDAP_UTIL_H */ |