lists.arthurdejong.org
RSS feed

nss-pam-ldapd commit: r1913 - in nss-pam-ldapd: nslcd tests

[Date Prev][Date Next] [Thread Prev][Thread Next]

nss-pam-ldapd commit: r1913 - in nss-pam-ldapd: nslcd tests



Author: arthur
Date: Sat Jan 12 23:36:00 2013
New Revision: 1913
URL: http://arthurdejong.org/viewvc/nss-pam-ldapd?revision=1913&view=revision

Log:
reorganise configuration file parsing code

Modified:
   nss-pam-ldapd/nslcd/cfg.c
   nss-pam-ldapd/tests/test_cfg.c

Modified: nss-pam-ldapd/nslcd/cfg.c
==============================================================================
--- nss-pam-ldapd/nslcd/cfg.c   Sat Jan 12 23:33:00 2013        (r1912)
+++ nss-pam-ldapd/nslcd/cfg.c   Sat Jan 12 23:36:00 2013        (r1913)
@@ -5,7 +5,7 @@
 
    Copyright (C) 1997-2005 Luke Howard
    Copyright (C) 2007 West Consulting
-   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Arthur de Jong
+   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Arthur de Jong
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -77,69 +77,6 @@
     exit(EXIT_FAILURE);                                                     \
   }
 
-/* prototype for parse_validnames_statement() because it is used in
-   cfg_defaults() */
-static void parse_validnames_statement(const char *filename, int lnr,
-                                       const char *keyword, char *line,
-                                       struct ldap_config *cfg);
-
-/* set the configuration information to the defaults */
-static void cfg_defaults(struct ldap_config *cfg)
-{
-  int i;
-  memset(cfg, 0, sizeof(struct ldap_config));
-  cfg->threads = 5;
-  cfg->uidname = NULL;
-  cfg->uid = NOUID;
-  cfg->gid = NOGID;
-  for (i = 0; i < (NSS_LDAP_CONFIG_MAX_URIS + 1); i++)
-  {
-    cfg->uris[i].uri = NULL;
-    cfg->uris[i].firstfail = 0;
-    cfg->uris[i].lastfail = 0;
-  }
-#ifdef LDAP_VERSION3
-  cfg->ldap_version = LDAP_VERSION3;
-#else /* LDAP_VERSION3 */
-  cfg->ldap_version = LDAP_VERSION2;
-#endif /* not LDAP_VERSION3 */
-  cfg->binddn = NULL;
-  cfg->bindpw = NULL;
-  cfg->rootpwmoddn = NULL;
-  cfg->rootpwmodpw = NULL;
-  cfg->sasl_mech = NULL;
-  cfg->sasl_realm = NULL;
-  cfg->sasl_authcid = NULL;
-  cfg->sasl_authzid = NULL;
-  cfg->sasl_secprops = NULL;
-#ifdef LDAP_OPT_X_SASL_NOCANON
-  cfg->sasl_canonicalize = -1;
-#endif /* LDAP_OPT_X_SASL_NOCANON */
-  for (i = 0; i < NSS_LDAP_CONFIG_MAX_BASES; i++)
-    cfg->bases[i] = NULL;
-  cfg->scope = LDAP_SCOPE_SUBTREE;
-  cfg->deref = LDAP_DEREF_NEVER;
-  cfg->referrals = 1;
-  cfg->bind_timelimit = 10;
-  cfg->timelimit = LDAP_NO_LIMIT;
-  cfg->idle_timelimit = 0;
-  cfg->reconnect_sleeptime = 1;
-  cfg->reconnect_retrytime = 10;
-#ifdef LDAP_OPT_X_TLS
-  cfg->ssl = SSL_OFF;
-#endif /* LDAP_OPT_X_TLS */
-  cfg->pagesize = 0;
-  cfg->nss_initgroups_ignoreusers = NULL;
-  cfg->nss_min_uid = 0;
-  parse_validnames_statement(__FILE__, __LINE__, "",
-                             "/^[a-z0-9._@$][a-z0-9._@$ 
\\~-]*[a-z0-9._@$~-]$/i",
-                             cfg);
-  cfg->ignorecase = 0;
-  for (i = 0; i < NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES; i++)
-    cfg->pam_authz_searches[i] = NULL;
-  cfg->pam_password_prohibit_message = NULL;
-}
-
 /* simple strdup wrapper */
 static char *xstrdup(const char *s)
 {
@@ -158,123 +95,15 @@
   return tmp;
 }
 
-/* add a single URI to the list of URIs in the configuration */
-static void add_uri(const char *filename, int lnr,
-                    struct ldap_config *cfg, const char *uri)
-{
-  int i;
-  log_log(LOG_DEBUG, "add_uri(%s)", uri);
-  /* find the place where to insert the URI */
-  for (i = 0; cfg->uris[i].uri != NULL; i++)
-    /* nothing */ ;
-  /* check for room */
-  if (i >= NSS_LDAP_CONFIG_MAX_URIS)
-  {
-    log_log(LOG_ERR, "%s:%d: maximum number of URIs exceeded",
-            filename, lnr);
-    exit(EXIT_FAILURE);
-  }
-  /* append URI to list */
-  cfg->uris[i].uri = xstrdup(uri);
-}
-
-#ifdef HAVE_LDAP_DOMAIN2HOSTLIST
-/* return the domain name of the current host
-   the returned string must be freed by caller */
-static const char *cfg_getdomainname(const char *filename, int lnr)
-{
-  const char *fqdn, *domain;
-  fqdn = getfqdn();
-  if ((fqdn != NULL) && ((domain = strchr(fqdn, '.')) != NULL) && (domain[1] 
!= '\0'))
-    return domain + 1;
-  log_log(LOG_ERR, "%s:%d: unable to determinate a domain name",
-          filename, lnr);
-  exit(EXIT_FAILURE);
-}
-
-/* add URIs by doing DNS queries for SRV records */
-static void add_uris_from_dns(const char *filename, int lnr,
-                              struct ldap_config *cfg, const char *domain)
-{
-  int rc;
-  char *hostlist = NULL, *nxt;
-  char buf[HOST_NAME_MAX + sizeof("ldap://";)];
-  log_log(LOG_DEBUG, "query %s for SRV records", domain);
-  rc = ldap_domain2hostlist(domain, &hostlist);
-  if (rc != LDAP_SUCCESS)
-  {
-    log_log(LOG_ERR, "%s:%d: no servers found in DNS zone %s: %s",
-            filename, lnr, domain, ldap_err2string(rc));
-    exit(EXIT_FAILURE);
-  }
-  if ((hostlist == NULL) || (*hostlist == '\0'))
-  {
-    log_log(LOG_ERR, "%s:%d: no servers found in DNS zone %s",
-            filename, lnr, domain);
-    exit(EXIT_FAILURE);
-  }
-  /* hostlist is a space-separated list of host names that we use to build
-     URIs */
-  while (hostlist != NULL)
-  {
-    /* find the next space and split the string there */
-    nxt = strchr(hostlist, ' ');
-    if (nxt != NULL)
-    {
-      *nxt = '\0';
-      nxt++;
-    }
-    /* if port is 636, use ldaps:// URI */
-    if ((strlen(hostlist) > 4) && (strcmp(hostlist + strlen(hostlist) - 4, 
":636") == 0))
-    {
-      hostlist[strlen(hostlist) - 4] = '\0';
-      mysnprintf(buf, sizeof(buf), "ldaps://%s", hostlist);
-    }
-    else
-    {
-      /* strip default port number */
-      if ((strlen(hostlist) > 4) && (strcmp(hostlist + strlen(hostlist) - 4, 
":389") == 0))
-        hostlist[strlen(hostlist) - 4] = '\0';
-      mysnprintf(buf, sizeof(buf), "ldap://%s";, hostlist);
-    }
-    log_log(LOG_DEBUG, "add_uris_from_dns(): found uri: %s", buf);
-    add_uri(filename, lnr, cfg, buf);
-    /* get next entry from list */
-    hostlist = nxt;
-  }
-}
-#endif /* HAVE_LDAP_DOMAIN2HOSTLIST */
-
-static int parse_boolean(const char *filename, int lnr, const char *value)
-{
-  if ((strcasecmp(value, "on") == 0) ||
-      (strcasecmp(value, "yes") == 0) ||
-      (strcasecmp(value, "true") == 0) || (strcasecmp(value, "1") == 0))
-    return 1;
-  else if ((strcasecmp(value, "off") == 0) ||
-           (strcasecmp(value, "no") == 0) ||
-           (strcasecmp(value, "false") == 0) || (strcasecmp(value, "0") == 0))
-    return 0;
-  else
-  {
-    log_log(LOG_ERR, "%s:%d: not a boolean argument: '%s'",
-            filename, lnr, value);
-    exit(EXIT_FAILURE);
-  }
-}
-
-static int parse_scope(const char *filename, int lnr, const char *value)
+/* check that the condition is true and otherwise log an error
+   and bail out */
+static inline void check_argumentcount(const char *filename, int lnr,
+                                       const char *keyword, int condition)
 {
-  if ((strcasecmp(value, "sub") == 0) || (strcasecmp(value, "subtree") == 0))
-    return LDAP_SCOPE_SUBTREE;
-  else if ((strcasecmp(value, "one") == 0) || (strcasecmp(value, "onelevel") 
== 0))
-    return LDAP_SCOPE_ONELEVEL;
-  else if (strcasecmp(value, "base") == 0)
-    return LDAP_SCOPE_BASE;
-  else
+  if (!condition)
   {
-    log_log(LOG_ERR, "%s:%d: not a scope argument: '%s'",
-            filename, lnr, value);
+    log_log(LOG_ERR, "%s:%d: %s: wrong number of arguments",
+            filename, lnr, keyword);
     exit(EXIT_FAILURE);
   }
 }
@@ -311,173 +140,106 @@
   return buf;
 }
 
-static enum ldap_map_selector parse_map(const char *value)
-{
-  if ((strcasecmp(value, "alias") == 0) || (strcasecmp(value, "aliases") == 0))
-    return LM_ALIASES;
-  else if ((strcasecmp(value, "ether") == 0) || (strcasecmp(value, "ethers") 
== 0))
-    return LM_ETHERS;
-  else if (strcasecmp(value, "group") == 0)
-    return LM_GROUP;
-  else if ((strcasecmp(value, "host") == 0) || (strcasecmp(value, "hosts") == 
0))
-    return LM_HOSTS;
-  else if (strcasecmp(value, "netgroup") == 0)
-    return LM_NETGROUP;
-  else if ((strcasecmp(value, "network") == 0) || (strcasecmp(value, 
"networks") == 0))
-    return LM_NETWORKS;
-  else if (strcasecmp(value, "passwd") == 0)
-    return LM_PASSWD;
-  else if ((strcasecmp(value, "protocol") == 0) || (strcasecmp(value, 
"protocols") == 0))
-    return LM_PROTOCOLS;
-  else if (strcasecmp(value, "rpc") == 0)
-    return LM_RPC;
-  else if ((strcasecmp(value, "service") == 0) || (strcasecmp(value, 
"services") == 0))
-    return LM_SERVICES;
-  else if (strcasecmp(value, "shadow") == 0)
-    return LM_SHADOW;
-  else
-    return LM_NONE;
-}
-
-/* check to see if the line begins with a named map */
-static enum ldap_map_selector get_map(char **line)
+static char *get_strdup(const char *filename, int lnr,
+                        const char *keyword, char **line)
 {
-  char token[32];
-  char *old;
-  enum ldap_map_selector map;
-  /* get the token */
-  old = *line;
-  if (get_token(line, token, sizeof(token)) == NULL)
-    return LM_NONE;
-  /* find the map if any */
-  map = parse_map(token);
-  /* unknown map, return to the previous state */
-  if (map == LM_NONE)
-    *line = old;
-  return map;
+  char token[64];
+  check_argumentcount(filename, lnr, keyword,
+                      get_token(line, token, sizeof(token)) != NULL);
+  return xstrdup(token);
 }
 
-/* check that the condition is true and otherwise log an error
-   and bail out */
-static inline void check_argumentcount(const char *filename, int lnr,
-                                       const char *keyword, int condition)
+static char *get_linedup(const char *filename, int lnr,
+                         const char *keyword, char **line)
 {
-  if (!condition)
-  {
-    log_log(LOG_ERR, "%s:%d: %s: wrong number of arguments",
-            filename, lnr, keyword);
-    exit(EXIT_FAILURE);
-  }
+  char *var;
+  check_argumentcount(filename, lnr, keyword, (*line != NULL) && (**line != 
'\0'));
+  var = xstrdup(*line);
+  /* mark that we are at the end of the line */
+  *line = NULL;
+  return var;
 }
 
-/* check that the file is not world readable */
-static void check_permissions(const char *filename, const char *keyword)
+static void get_eol(const char *filename, int lnr,
+                    const char *keyword, char **line)
 {
-  struct stat sb;
-  /* get file status */
-  if (stat(filename, &sb))
-  {
-    log_log(LOG_ERR, "cannot stat() %s: %s", filename, strerror(errno));
-    exit(EXIT_FAILURE);
-  }
-  /* check permissions */
-  if ((sb.st_mode & 0007) != 0)
+  if ((line != NULL) && (*line != NULL) && (**line != '\0'))
   {
-    if (keyword != NULL)
-      log_log(LOG_ERR, "%s: file should not be world readable if %s is set",
-              filename, keyword);
-    else
-      log_log(LOG_ERR, "%s: file should not be world readable", filename);
+    log_log(LOG_ERR, "%s:%d: %s: too may arguments", filename, lnr, keyword);
     exit(EXIT_FAILURE);
   }
 }
 
-static void get_int(const char *filename, int lnr,
-                    const char *keyword, char **line, int *var)
+static int get_int(const char *filename, int lnr,
+                   const char *keyword, char **line)
 {
-  /* TODO: refactor to have less overhead */
   char token[32];
   check_argumentcount(filename, lnr, keyword,
                       get_token(line, token, sizeof(token)) != NULL);
   /* TODO: replace with correct numeric parse */
-  *var = atoi(token);
+  return atoi(token);
 }
 
-static void get_boolean(const char *filename, int lnr,
-                        const char *keyword, char **line, int *var)
+static int parse_boolean(const char *filename, int lnr, const char *value)
 {
-  /* TODO: refactor to have less overhead */
-  char token[32];
-  check_argumentcount(filename, lnr, keyword,
-                      get_token(line, token, sizeof(token)) != NULL);
-  *var = parse_boolean(filename, lnr, token);
+  if ((strcasecmp(value, "on") == 0) ||
+      (strcasecmp(value, "yes") == 0) ||
+      (strcasecmp(value, "true") == 0) || (strcasecmp(value, "1") == 0))
+    return 1;
+  else if ((strcasecmp(value, "off") == 0) ||
+           (strcasecmp(value, "no") == 0) ||
+           (strcasecmp(value, "false") == 0) || (strcasecmp(value, "0") == 0))
+    return 0;
+  else
+  {
+    log_log(LOG_ERR, "%s:%d: not a boolean argument: '%s'",
+            filename, lnr, value);
+    exit(EXIT_FAILURE);
+  }
 }
 
-static void get_strdup(const char *filename, int lnr,
-                       const char *keyword, char **line, char **var)
+static int get_boolean(const char *filename, int lnr,
+                       const char *keyword, char **line)
 {
-  /* TODO: refactor to have less overhead */
-  char token[64];
+  char token[32];
   check_argumentcount(filename, lnr, keyword,
                       get_token(line, token, sizeof(token)) != NULL);
-  /* Note: we have a memory leak here if a single variable is changed
-     multiple times in one config (deemed not a problem) */
-  *var = xstrdup(token);
+  return parse_boolean(filename, lnr, token);
 }
 
-static void get_restdup(const char *filename, int lnr,
-                        const char *keyword, char **line, char **var)
+static void handle_uid(const char *filename, int lnr,
+                       const char *keyword, char *line,
+                       struct ldap_config *cfg)
 {
-  check_argumentcount(filename, lnr, keyword, (*line != NULL) && (**line != 
'\0'));
-  /* Note: we have a memory leak here if a single mapping is changed
-     multiple times in one config (deemed not a problem) */
-  *var = xstrdup(*line);
-  /* mark that we are at the end of the line */
-  *line = NULL;
-}
-
-static void get_eol(const char *filename, int lnr,
-                    const char *keyword, char **line)
-{
-  if ((line != NULL) && (*line != NULL) && (**line != '\0'))
-  {
-    log_log(LOG_ERR, "%s:%d: %s: too may arguments", filename, lnr, keyword);
-    exit(EXIT_FAILURE);
-  }
-}
-
-static void get_uid(const char *filename, int lnr,
-                    const char *keyword, char **line,
-                    uid_t *var, gid_t *gid, char **str)
-{
-  /* TODO: refactor to have less overhead */
   char token[32];
   struct passwd *pwent;
   char *tmp;
   check_argumentcount(filename, lnr, keyword,
-                      get_token(line, token, sizeof(token)) != NULL);
+                      get_token(&line, token, sizeof(token)) != NULL);
+  get_eol(filename, lnr, keyword, &line);
   /* check if it is a valid numerical uid */
   errno = 0;
-  *var = strtouid(token, &tmp, 10);
+  cfg->uid = strtouid(token, &tmp, 10);
   if ((*token != '\0') && (*tmp == '\0') && (errno == 0) && (strchr(token, 
'-') == NULL))
   {
     /* get the name and gid from the passwd database */
-    pwent = getpwuid(*var);
-    if ((gid != NULL) && (*gid != NOGID))
-      *gid = pwent->pw_gid;
-    if (str != NULL)
-      *str = strdup(pwent->pw_name);
-    return;
+    pwent = getpwuid(cfg->uid);
+    if (pwent != NULL)
+    {
+      if (cfg->gid == NOGID)
+        cfg->gid = pwent->pw_gid;
+      cfg->uidname = strdup(pwent->pw_name);
+      return;
+    }
   }
   /* find by name */
   pwent = getpwnam(token);
   if (pwent != NULL)
   {
-    *var = pwent->pw_uid;
-    if ((gid != NULL) && (*gid != NOGID))
-      *gid = pwent->pw_gid;
-    if (str != NULL)
-      *str = strdup(token);
+    cfg->uid = pwent->pw_uid;
+    if (cfg->gid == NOGID)
+      cfg->gid = pwent->pw_gid;
+    cfg->uidname = strdup(token);
     return;
   }
   /* log an error */
@@ -486,25 +248,26 @@
   exit(EXIT_FAILURE);
 }
 
-static void get_gid(const char *filename, int lnr,
-                    const char *keyword, char **line, gid_t *var)
+static void handle_gid(const char *filename, int lnr,
+                       const char *keyword, char *line,
+                       gid_t *gid)
 {
-  /* TODO: refactor to have less overhead */
   char token[32];
   struct group *grent;
   char *tmp;
   check_argumentcount(filename, lnr, keyword,
-                      get_token(line, token, sizeof(token)) != NULL);
+                      get_token(&line, token, sizeof(token)) != NULL);
+  get_eol(filename, lnr, keyword, &line);
   /* check if it is a valid numerical gid */
   errno = 0;
-  *var = strtogid(token, &tmp, 10);
+  *gid = strtogid(token, &tmp, 10);
   if ((*token != '\0') && (*tmp == '\0') && (errno == 0) && (strchr(token, 
'-') == NULL))
     return;
   /* find by name */
   grent = getgrnam(token);
   if (grent != NULL)
   {
-    *var = grent->gr_gid;
+    *gid = grent->gr_gid;
     return;
   }
   /* log an error */
@@ -513,37 +276,94 @@
   exit(EXIT_FAILURE);
 }
 
-#ifdef LDAP_OPT_X_TLS
-static void get_reqcert(const char *filename, int lnr,
-                        const char *keyword, char **line, int *var)
+/* add a single URI to the list of URIs in the configuration */
+static void add_uri(const char *filename, int lnr,
+                    struct ldap_config *cfg, const char *uri)
 {
-  char token[16];
-  /* get token */
-  check_argumentcount(filename, lnr, keyword,
-                      get_token(line, token, sizeof(token)) != NULL);
-  /* check if it is a valid value for tls_reqcert option */
-  if ((strcasecmp(token, "never") == 0) || (strcasecmp(token, "no") == 0))
-    *var = LDAP_OPT_X_TLS_NEVER;
-  else if (strcasecmp(token, "allow") == 0)
-    *var = LDAP_OPT_X_TLS_ALLOW;
-  else if (strcasecmp(token, "try") == 0)
-    *var = LDAP_OPT_X_TLS_TRY;
-  else if ((strcasecmp(token, "demand") == 0) ||
-           (strcasecmp(token, "yes") == 0))
-    *var = LDAP_OPT_X_TLS_DEMAND;
-  else if (strcasecmp(token, "hard") == 0)
-    *var = LDAP_OPT_X_TLS_HARD;
-  else
+  int i;
+  /* find the place where to insert the URI */
+  for (i = 0; cfg->uris[i].uri != NULL; i++)
+    /* nothing */ ;
+  /* check for room */
+  if (i >= NSS_LDAP_CONFIG_MAX_URIS)
   {
-    log_log(LOG_ERR, "%s:%d: %s: invalid argument: '%s'",
-            filename, lnr, keyword, token);
+    log_log(LOG_ERR, "%s:%d: maximum number of URIs exceeded",
+            filename, lnr);
     exit(EXIT_FAILURE);
   }
+  /* append URI to list */
+  cfg->uris[i].uri = xstrdup(uri);
 }
-#endif /* LDAP_OPT_X_TLS */
 
-static void parse_krb5_ccname_statement(const char *filename, int lnr,
-                                        const char *keyword, char *line)
+#ifdef HAVE_LDAP_DOMAIN2HOSTLIST
+/* return the domain name of the current host
+   the returned string must be freed by caller */
+static const char *cfg_getdomainname(const char *filename, int lnr)
+{
+  const char *fqdn, *domain;
+  fqdn = getfqdn();
+  if ((fqdn != NULL) && ((domain = strchr(fqdn, '.')) != NULL) && (domain[1] 
!= '\0'))
+    return domain + 1;
+  log_log(LOG_ERR, "%s:%d: unable to determinate a domain name",
+          filename, lnr);
+  exit(EXIT_FAILURE);
+}
+
+/* add URIs by doing DNS queries for SRV records */
+static void add_uris_from_dns(const char *filename, int lnr,
+                              struct ldap_config *cfg, const char *domain)
+{
+  int rc;
+  char *hostlist = NULL, *nxt;
+  char buf[HOST_NAME_MAX + sizeof("ldap://";)];
+  log_log(LOG_DEBUG, "query %s for SRV records", domain);
+  rc = ldap_domain2hostlist(domain, &hostlist);
+  if (rc != LDAP_SUCCESS)
+  {
+    log_log(LOG_ERR, "%s:%d: no servers found in DNS zone %s: %s",
+            filename, lnr, domain, ldap_err2string(rc));
+    exit(EXIT_FAILURE);
+  }
+  if ((hostlist == NULL) || (*hostlist == '\0'))
+  {
+    log_log(LOG_ERR, "%s:%d: no servers found in DNS zone %s",
+            filename, lnr, domain);
+    exit(EXIT_FAILURE);
+  }
+  /* hostlist is a space-separated list of host names that we use to build
+     URIs */
+  while (hostlist != NULL)
+  {
+    /* find the next space and split the string there */
+    nxt = strchr(hostlist, ' ');
+    if (nxt != NULL)
+    {
+      *nxt = '\0';
+      nxt++;
+    }
+    /* if port is 636, use ldaps:// URI */
+    if ((strlen(hostlist) > 4) && (strcmp(hostlist + strlen(hostlist) - 4, 
":636") == 0))
+    {
+      hostlist[strlen(hostlist) - 4] = '\0';
+      mysnprintf(buf, sizeof(buf), "ldaps://%s", hostlist);
+    }
+    else
+    {
+      /* strip default port number */
+      if ((strlen(hostlist) > 4) && (strcmp(hostlist + strlen(hostlist) - 4, 
":389") == 0))
+        hostlist[strlen(hostlist) - 4] = '\0';
+      mysnprintf(buf, sizeof(buf), "ldap://%s";, hostlist);
+    }
+    log_log(LOG_DEBUG, "add_uris_from_dns(): found uri: %s", buf);
+    add_uri(filename, lnr, cfg, buf);
+    /* get next entry from list */
+    hostlist = nxt;
+  }
+}
+#endif /* HAVE_LDAP_DOMAIN2HOSTLIST */
+
+static void handle_krb5_ccname(const char *filename, int lnr,
+                               const char *keyword, char *line)
 {
   char token[80];
   const char *ccname;
@@ -555,8 +375,8 @@
 #endif /* HAVE_GSS_KRB5_CCACHE_NAME */
   /* get token */
   check_argumentcount(filename, lnr, keyword,
-                      (get_token(&line, token, sizeof(token)) != NULL) &&
-                      (*line == '\0'));
+                      (get_token(&line, token, sizeof(token)) != NULL));
+  get_eol(filename, lnr, keyword, &line);
   /* set default kerberos ticket cache for SASL-GSSAPI */
   ccname = token;
   /* check that cache exists and is readable if it is a file */
@@ -593,141 +413,140 @@
 #endif /* HAVE_GSS_KRB5_CCACHE_NAME */
 }
 
-/* assigns the base to the specified variable doing domain expansion
-   and a simple check to avoid overwriting duplicate values */
-static void set_base(const char *filename, int lnr,
-                     const char *value, const char **var)
+/* check to see if the line begins with a named map */
+static enum ldap_map_selector get_map(char **line)
+{
+  char token[32];
+  char *old;
+  /* get the token */
+  old = *line;
+  if (get_token(line, token, sizeof(token)) == NULL)
+    return LM_NONE;
+  /* see if we found a map */
+  if ((strcasecmp(token, "alias") == 0) || (strcasecmp(token, "aliases") == 0))
+    return LM_ALIASES;
+  else if ((strcasecmp(token, "ether") == 0) || (strcasecmp(token, "ethers") 
== 0))
+    return LM_ETHERS;
+  else if (strcasecmp(token, "group") == 0)
+    return LM_GROUP;
+  else if ((strcasecmp(token, "host") == 0) || (strcasecmp(token, "hosts") == 
0))
+    return LM_HOSTS;
+  else if (strcasecmp(token, "netgroup") == 0)
+    return LM_NETGROUP;
+  else if ((strcasecmp(token, "network") == 0) || (strcasecmp(token, 
"networks") == 0))
+    return LM_NETWORKS;
+  else if (strcasecmp(token, "passwd") == 0)
+    return LM_PASSWD;
+  else if ((strcasecmp(token, "protocol") == 0) || (strcasecmp(token, 
"protocols") == 0))
+    return LM_PROTOCOLS;
+  else if (strcasecmp(token, "rpc") == 0)
+    return LM_RPC;
+  else if ((strcasecmp(token, "service") == 0) || (strcasecmp(token, 
"services") == 0))
+    return LM_SERVICES;
+  else if (strcasecmp(token, "shadow") == 0)
+    return LM_SHADOW;
+  /* unknown map, return to the previous state */
+  *line = old;
+  return LM_NONE;
+}
+
+static void handle_base(const char *filename, int lnr,
+                        const char *keyword, char *line,
+                        struct ldap_config *cfg)
 {
+  const char **bases;
+  int i;
+  char *value;
 #ifdef HAVE_LDAP_DOMAIN2DN
   const char *domain = NULL;
   char *domaindn = NULL;
 #endif /* HAVE_LDAP_DOMAIN2DN */
+  /* get the list of bases to update */
+  bases = base_get_var(get_map(&line));
+  if (bases == NULL)
+    bases = cfg->bases;
+  /* rest of the line is the value */
+  value = get_linedup(filename, lnr, keyword, &line);
   /* if the base is "DOMAIN" use the domain name */
   if (strcasecmp(value, "domain") == 0)
   {
 #ifdef HAVE_LDAP_DOMAIN2DN
+    free(value);
     domain = cfg_getdomainname(filename, lnr);
     ldap_domain2dn(domain, &domaindn);
     log_log(LOG_DEBUG, "set_base(): setting base to %s from domain",
             domaindn);
-    value = domaindn;
+    value = xstrdup(domaindn);
 #else /* not HAVE_LDAP_DOMAIN2DN */
     log_log(LOG_ERR, "%s:%d: value %s not supported on platform",
             filename, lnr, value);
     exit(EXIT_FAILURE);
 #endif /* not HAVE_LDAP_DOMAIN2DN */
   }
-  /* set the new value */
-  *var = xstrdup(value);
-}
-
-/* parse the validnames statement */
-static void parse_validnames_statement(const char *filename, int lnr,
-                                       const char *keyword, char *line,
-                                       struct ldap_config *cfg)
-{
-  char *value;
-  int i, l;
-  int flags = REG_EXTENDED | REG_NOSUB;
-  /* the rest of the line should be a regular expression */
-  get_restdup(filename, lnr, keyword, &line, &value);
-  /* check formatting and update flags */
-  if (value[0] != '/')
-  {
-    log_log(LOG_ERR, "%s:%d: regular expression incorrectly delimited",
-            filename, lnr);
-    exit(EXIT_FAILURE);
-  }
-  l = strlen(value);
-  if (value[l - 1] == 'i')
-  {
-    value[l - 1] = '\0';
-    l--;
-    flags |= REG_ICASE;
-  }
-  if (value[l - 1] != '/')
-  {
-    log_log(LOG_ERR, "%s:%d: regular expression incorrectly delimited",
-            filename, lnr);
-    exit(EXIT_FAILURE);
-  }
-  value[l - 1] = '\0';
-  /* compile the regular expression */
-  if ((i = regcomp(&cfg->validnames, value + 1, flags)) != 0)
-  {
-    /* get the error message */
-    l = regerror(i, &cfg->validnames, NULL, 0);
-    value = malloc(l);
-    if (value == NULL)
-      log_log(LOG_ERR, "%s:%d: invalid regular expression", filename, lnr);
-    else
-    {
-      regerror(i, &cfg->validnames, value, l);
-      log_log(LOG_ERR, "%s:%d: invalid regular expression: %s",
-              filename, lnr, value);
-    }
-    exit(EXIT_FAILURE);
-  }
-}
-
-static void parse_pam_password_prohibit_message_statement(
-                const char *filename, int lnr, const char *keyword,
-                char *line, struct ldap_config *cfg)
-{
-  char *value;
-  int l;
-  /* the rest of the line should be a message */
-  get_restdup(filename, lnr, keyword, &line, &value);
-  /* strip quotes if they are present */
-  l = strlen(value);
-  if ((value[0] == '\"') && (value[l - 1] == '\"'))
-  {
-    value[l - 1] = '\0';
-    value++;
-  }
-  cfg->pam_password_prohibit_message = value;
-}
-
-static void parse_base_statement(const char *filename, int lnr,
-                                 const char *keyword, char *line,
-                                 struct ldap_config *cfg)
-{
-  const char **bases;
-  int i;
-  /* get the list of bases to update */
-  bases = base_get_var(get_map(&line));
-  if (bases == NULL)
-    bases = cfg->bases;
   /* find the spot in the list of bases */
   for (i = 0; i < NSS_LDAP_CONFIG_MAX_BASES; i++)
-  {
     if (bases[i] == NULL)
     {
-      check_argumentcount(filename, lnr, keyword, (line != NULL) && (*line != 
'\0'));
-      set_base(filename, lnr, line, &bases[i]);
+      bases[i] = value;
       return;
     }
-  }
   /* no free spot found */
   log_log(LOG_ERR, "%s:%d: maximum number of base options per map (%d) 
exceeded",
           filename, lnr, NSS_LDAP_CONFIG_MAX_BASES);
   exit(EXIT_FAILURE);
 }
 
-static void parse_scope_statement(const char *filename, int lnr,
-                                  const char *keyword, char *line,
-                                  struct ldap_config *cfg)
+static void handle_scope(const char *filename, int lnr,
+                         const char *keyword, char *line,
+                         struct ldap_config *cfg)
 {
+  char token[32];
   int *var;
   var = scope_get_var(get_map(&line));
+  check_argumentcount(filename, lnr, keyword,
+                      get_token(&line, token, sizeof(token)) != NULL);
+  get_eol(filename, lnr, keyword, &line);
   if (var == NULL)
     var = &cfg->scope;
-  check_argumentcount(filename, lnr, keyword, (line != NULL) && (*line != 
'\0'));
-  *var = parse_scope(filename, lnr, line);
+  if ((strcasecmp(token, "sub") == 0) || (strcasecmp(token, "subtree") == 0))
+    *var = LDAP_SCOPE_SUBTREE;
+  else if ((strcasecmp(token, "one") == 0) || (strcasecmp(token, "onelevel") 
== 0))
+    *var = LDAP_SCOPE_ONELEVEL;
+  else if (strcasecmp(token, "base") == 0)
+    *var = LDAP_SCOPE_BASE;
+  else
+  {
+    log_log(LOG_ERR, "%s:%d: not a scope argument: '%s'",
+            filename, lnr, token);
+    exit(EXIT_FAILURE);
+  }
+}
+
+static void handle_deref(const char *filename, int lnr,
+                         const char *keyword, char *line,
+                         struct ldap_config *cfg)
+{
+  char token[32];
+  check_argumentcount(filename, lnr, keyword,
+                      get_token(&line, token, sizeof(token)) != NULL);
+  get_eol(filename, lnr, keyword, &line);
+  if (strcasecmp(token, "never") == 0)
+    cfg->deref = LDAP_DEREF_NEVER;
+  else if (strcasecmp(token, "searching") == 0)
+    cfg->deref = LDAP_DEREF_SEARCHING;
+  else if (strcasecmp(token, "finding") == 0)
+    cfg->deref = LDAP_DEREF_FINDING;
+  else if (strcasecmp(token, "always") == 0)
+    cfg->deref = LDAP_DEREF_ALWAYS;
+  else
+  {
+    log_log(LOG_ERR, "%s:%d: wrong argument: '%s'", filename, lnr, token);
+    exit(EXIT_FAILURE);
+  }
 }
 
-static void parse_filter_statement(const char *filename, int lnr,
-                                   const char *keyword, char *line)
+static void handle_filter(const char *filename, int lnr,
+                          const char *keyword, char *line)
 {
   const char **var;
   const char *map = line;
@@ -748,8 +567,8 @@
 }
 
 /* this function modifies the statement argument passed */
-static void parse_map_statement(const char *filename, int lnr,
-                                const char *keyword, char *line)
+static void handle_map(const char *filename, int lnr,
+                       const char *keyword, char *line)
 {
   enum ldap_map_selector map;
   const char **var;
@@ -776,16 +595,49 @@
   }
   if (attmap_set_mapping(var, newatt) == NULL)
   {
-    log_log(LOG_ERR, "%s:%d: attribute %s cannot be an expression",
-            filename, lnr, oldatt);
+    log_log(LOG_ERR, "%s:%d: attribute %s cannot be an expression",
+            filename, lnr, oldatt);
+    exit(EXIT_FAILURE);
+  }
+}
+
+#ifdef LDAP_OPT_X_TLS
+static void handle_tls_reqcert(const char *filename, int lnr,
+                               const char *keyword, char *line)
+{
+  char token[16];
+  int value, rc;
+  /* get token */
+  check_argumentcount(filename, lnr, keyword,
+                      get_token(&line, token, sizeof(token)) != NULL);
+  get_eol(filename, lnr, keyword, &line);
+  /* check if it is a valid value for tls_reqcert option */
+  if ((strcasecmp(token, "never") == 0) || (strcasecmp(token, "no") == 0))
+    value = LDAP_OPT_X_TLS_NEVER;
+  else if (strcasecmp(token, "allow") == 0)
+    value = LDAP_OPT_X_TLS_ALLOW;
+  else if (strcasecmp(token, "try") == 0)
+    value = LDAP_OPT_X_TLS_TRY;
+  else if ((strcasecmp(token, "demand") == 0) ||
+           (strcasecmp(token, "yes") == 0))
+    value = LDAP_OPT_X_TLS_DEMAND;
+  else if (strcasecmp(token, "hard") == 0)
+    value = LDAP_OPT_X_TLS_HARD;
+  else
+  {
+    log_log(LOG_ERR, "%s:%d: %s: invalid argument: '%s'",
+            filename, lnr, keyword, token);
     exit(EXIT_FAILURE);
   }
+  log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT,%s)", token);
+  LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &value);
 }
+#endif /* LDAP_OPT_X_TLS */
 
-/* this function modifies the statement argument passed */
-static void parse_nss_initgroups_ignoreusers_statement(
-                const char *filename, int lnr, const char *keyword,
-                char *line, struct ldap_config *cfg)
+/* this function modifies the line argument passed */
+static void handle_nss_initgroups_ignoreusers(
+                const char *filename, int lnr,
+                const char *keyword, char *line, struct ldap_config *cfg)
 {
   char token[MAX_LINE_LENGTH];
   char *username, *next;
@@ -828,17 +680,64 @@
   }
 }
 
-static void parse_pam_authz_search_statement(
-                const char *filename, int lnr, const char *keyword,
-                char *line, struct ldap_config *cfg)
+static void handle_validnames(const char *filename, int lnr,
+                              const char *keyword, char *line,
+                              struct ldap_config *cfg)
+{
+  char *value;
+  int i, l;
+  int flags = REG_EXTENDED | REG_NOSUB;
+  /* the rest of the line should be a regular expression */
+  value = get_linedup(filename, lnr, keyword, &line);
+  /* check formatting and update flags */
+  if (value[0] != '/')
+  {
+    log_log(LOG_ERR, "%s:%d: regular expression incorrectly delimited",
+            filename, lnr);
+    exit(EXIT_FAILURE);
+  }
+  l = strlen(value);
+  if (value[l - 1] == 'i')
+  {
+    value[l - 1] = '\0';
+    l--;
+    flags |= REG_ICASE;
+  }
+  if (value[l - 1] != '/')
+  {
+    log_log(LOG_ERR, "%s:%d: regular expression incorrectly delimited",
+            filename, lnr);
+    exit(EXIT_FAILURE);
+  }
+  value[l - 1] = '\0';
+  /* compile the regular expression */
+  if ((i = regcomp(&cfg->validnames, value + 1, flags)) != 0)
+  {
+    /* get the error message */
+    l = regerror(i, &cfg->validnames, NULL, 0);
+    value = malloc(l);
+    if (value == NULL)
+      log_log(LOG_ERR, "%s:%d: invalid regular expression", filename, lnr);
+    else
+    {
+      regerror(i, &cfg->validnames, value, l);
+      log_log(LOG_ERR, "%s:%d: invalid regular expression: %s",
+              filename, lnr, value);
+    }
+    exit(EXIT_FAILURE);
+  }
+}
+
+static void handle_pam_authz_search(
+                const char *filename, int lnr,
+                const char *keyword, char *line, struct ldap_config *cfg)
 {
   SET *set;
   const char **list;
   int i;
   check_argumentcount(filename, lnr, keyword, (line != NULL) && (*line != 
'\0'));
   /* find free spot for search filter */
-  for (i = 0;
-       (i < NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES) && (cfg->pam_authz_searches[i] 
!= NULL);
+  for (i = 0; (i < NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES) && 
(cfg->pam_authz_searches[i] != NULL);
        i++)
     /* nothing */ ;
   if (i >= NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES)
@@ -876,6 +775,155 @@
   free(list);
 }
 
+static void handle_pam_password_prohibit_message(
+                const char *filename, int lnr,
+                const char *keyword, char *line, struct ldap_config *cfg)
+{
+  char *value;
+  int l;
+  /* the rest of the line should be a message */
+  value = get_linedup(filename, lnr, keyword, &line);
+  /* strip quotes if they are present */
+  l = strlen(value);
+  if ((value[0] == '\"') && (value[l - 1] == '\"'))
+  {
+    value[l - 1] = '\0';
+    value++;
+  }
+  cfg->pam_password_prohibit_message = value;
+}
+
+/* This function tries to get the LDAP search base from the LDAP server.
+   Note that this returns a string that has been allocated with strdup().
+   For this to work the myldap module needs enough configuration information
+   to make an LDAP connection. */
+static MUST_USE char *get_base_from_rootdse(void)
+{
+  MYLDAP_SESSION *session;
+  MYLDAP_SEARCH *search;
+  MYLDAP_ENTRY *entry;
+  const char *attrs[] = { "+", NULL };
+  int i;
+  int rc;
+  const char **values;
+  char *base = NULL;
+  /* initialize session */
+  session = myldap_create_session();
+  assert(session != NULL);
+  /* perform search */
+  search = myldap_search(session, "", LDAP_SCOPE_BASE, "(objectClass=*)",
+                         attrs, NULL);
+  if (search == NULL)
+  {
+    myldap_session_close(session);
+    return NULL;
+  }
+  /* go over results */
+  for (i = 0; (entry = myldap_get_entry(search, &rc)) != NULL; i++)
+  {
+    /* get defaultNamingContext */
+    values = myldap_get_values(entry, "defaultNamingContext");
+    if ((values != NULL) && (values[0] != NULL))
+    {
+      base = xstrdup(values[0]);
+      log_log(LOG_DEBUG, "get_basedn_from_rootdse(): found attribute 
defaultNamingContext with value %s",
+              values[0]);
+      break;
+    }
+    /* get namingContexts */
+    values = myldap_get_values(entry, "namingContexts");
+    if ((values != NULL) && (values[0] != NULL))
+    {
+      base = xstrdup(values[0]);
+      log_log(LOG_DEBUG, "get_basedn_from_rootdse(): found attribute 
namingContexts with value %s",
+              values[0]);
+      break;
+    }
+  }
+  /* clean up */
+  myldap_session_close(session);
+  return base;
+}
+
+/* check that the file is not world readable */
+static void check_permissions(const char *filename, const char *keyword)
+{
+  struct stat sb;
+  /* get file status */
+  if (stat(filename, &sb))
+  {
+    log_log(LOG_ERR, "cannot stat() %s: %s", filename, strerror(errno));
+    exit(EXIT_FAILURE);
+  }
+  /* check permissions */
+  if ((sb.st_mode & 0007) != 0)
+  {
+    if (keyword != NULL)
+      log_log(LOG_ERR, "%s: file should not be world readable if %s is set",
+              filename, keyword);
+    else
+      log_log(LOG_ERR, "%s: file should not be world readable", filename);
+    exit(EXIT_FAILURE);
+  }
+}
+
+/* set the configuration information to the defaults */
+static void cfg_defaults(struct ldap_config *cfg)
+{
+  int i;
+  memset(cfg, 0, sizeof(struct ldap_config));
+  cfg->threads = 5;
+  cfg->uidname = NULL;
+  cfg->uid = NOUID;
+  cfg->gid = NOGID;
+  for (i = 0; i < (NSS_LDAP_CONFIG_MAX_URIS + 1); i++)
+  {
+    cfg->uris[i].uri = NULL;
+    cfg->uris[i].firstfail = 0;
+    cfg->uris[i].lastfail = 0;
+  }
+#ifdef LDAP_VERSION3
+  cfg->ldap_version = LDAP_VERSION3;
+#else /* LDAP_VERSION3 */
+  cfg->ldap_version = LDAP_VERSION2;
+#endif /* not LDAP_VERSION3 */
+  cfg->binddn = NULL;
+  cfg->bindpw = NULL;
+  cfg->rootpwmoddn = NULL;
+  cfg->rootpwmodpw = NULL;
+  cfg->sasl_mech = NULL;
+  cfg->sasl_realm = NULL;
+  cfg->sasl_authcid = NULL;
+  cfg->sasl_authzid = NULL;
+  cfg->sasl_secprops = NULL;
+#ifdef LDAP_OPT_X_SASL_NOCANON
+  cfg->sasl_canonicalize = -1;
+#endif /* LDAP_OPT_X_SASL_NOCANON */
+  for (i = 0; i < NSS_LDAP_CONFIG_MAX_BASES; i++)
+    cfg->bases[i] = NULL;
+  cfg->scope = LDAP_SCOPE_SUBTREE;
+  cfg->deref = LDAP_DEREF_NEVER;
+  cfg->referrals = 1;
+  cfg->bind_timelimit = 10;
+  cfg->timelimit = LDAP_NO_LIMIT;
+  cfg->idle_timelimit = 0;
+  cfg->reconnect_sleeptime = 1;
+  cfg->reconnect_retrytime = 10;
+#ifdef LDAP_OPT_X_TLS
+  cfg->ssl = SSL_OFF;
+#endif /* LDAP_OPT_X_TLS */
+  cfg->pagesize = 0;
+  cfg->nss_initgroups_ignoreusers = NULL;
+  cfg->nss_min_uid = 0;
+  handle_validnames(__FILE__, __LINE__, "",
+                    "/^[a-z0-9._@$][a-z0-9._@$ \\~-]*[a-z0-9._@$~-]$/i",
+                    cfg);
+  cfg->ignorecase = 0;
+  for (i = 0; i < NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES; i++)
+    cfg->pam_authz_searches[i] = NULL;
+  cfg->pam_password_prohibit_message = NULL;
+}
+
 static void cfg_read(const char *filename, struct ldap_config *cfg)
 {
   FILE *fp;
@@ -922,18 +970,16 @@
     /* runtime options */
     if (strcasecmp(keyword, "threads") == 0)
     {
-      get_int(filename, lnr, keyword, &line, &cfg->threads);
+      cfg->threads = get_int(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "uid") == 0)
     {
-      get_uid(filename, lnr, keyword, &line, &cfg->uid, &cfg->gid, 
&cfg->uidname);
-      get_eol(filename, lnr, keyword, &line);
+      handle_uid(filename, lnr, keyword, line, cfg);
     }
     else if (strcasecmp(keyword, "gid") == 0)
     {
-      get_gid(filename, lnr, keyword, &line, &cfg->gid);
-      get_eol(filename, lnr, keyword, &line);
+      handle_gid(filename, lnr, keyword, line, &cfg->gid);
     }
     /* general connection options */
     else if (strcasecmp(keyword, "uri") == 0)
@@ -955,8 +1001,7 @@
         else if (strncasecmp(token, "dns:", 4) == 0)
         {
 #ifdef HAVE_LDAP_DOMAIN2HOSTLIST
-          add_uris_from_dns(filename, lnr, cfg,
-                            strdup(token + sizeof("dns")));
+          add_uris_from_dns(filename, lnr, cfg, strdup(token + 4));
 #else /* not HAVE_LDAP_DOMAIN2HOSTLIST */
           log_log(LOG_ERR, "%s:%d: value %s not supported on platform",
                   filename, lnr, token);
@@ -969,51 +1014,51 @@
     }
     else if (strcasecmp(keyword, "ldap_version") == 0)
     {
-      get_int(filename, lnr, keyword, &line, &cfg->ldap_version);
+      cfg->ldap_version = get_int(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "binddn") == 0)
     {
-      get_restdup(filename, lnr, keyword, &line, &cfg->binddn);
+      cfg->binddn = get_linedup(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "bindpw") == 0)
     {
       check_permissions(filename, keyword);
-      get_restdup(filename, lnr, keyword, &line, &cfg->bindpw);
+      cfg->bindpw = get_linedup(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "rootpwmoddn") == 0)
     {
-      get_restdup(filename, lnr, keyword, &line, &cfg->rootpwmoddn);
+      cfg->rootpwmoddn = get_linedup(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "rootpwmodpw") == 0)
     {
       check_permissions(filename, keyword);
-      get_restdup(filename, lnr, keyword, &line, &cfg->rootpwmodpw);
+      cfg->rootpwmodpw = get_linedup(filename, lnr, keyword, &line);
     }
     /* SASL authentication options */
     else if (strcasecmp(keyword, "sasl_mech") == 0)
     {
-      get_strdup(filename, lnr, keyword, &line, &cfg->sasl_mech);
+      cfg->sasl_mech = get_strdup(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "sasl_realm") == 0)
     {
-      get_strdup(filename, lnr, keyword, &line, &cfg->sasl_realm);
+      cfg->sasl_realm = get_strdup(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "sasl_authcid") == 0)
     {
-      get_strdup(filename, lnr, keyword, &line, &cfg->sasl_authcid);
+      cfg->sasl_authcid = get_strdup(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "sasl_authzid") == 0)
     {
-      get_strdup(filename, lnr, keyword, &line, &cfg->sasl_authzid);
+      cfg->sasl_authzid = get_strdup(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "sasl_secprops") == 0)
     {
-      get_strdup(filename, lnr, keyword, &line, &cfg->sasl_secprops);
+      cfg->sasl_secprops = get_strdup(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
 #ifdef LDAP_OPT_X_SASL_NOCANON
@@ -1022,12 +1067,12 @@
              (strcasecmp(keyword, "ldap_sasl_canonicalize") == 0) ||
              (strcasecmp(keyword, "sasl_canon") == 0))
     {
-      get_boolean(filename, lnr, keyword, &line, &cfg->sasl_canonicalize);
+      cfg->sasl_canonicalize = get_boolean(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "sasl_nocanon") == 0)
     {
-      get_boolean(filename, lnr, keyword, &line, &cfg->sasl_canonicalize);
+      cfg->sasl_canonicalize = get_boolean(filename, lnr, keyword, &line);
       cfg->sasl_canonicalize = !cfg->sasl_canonicalize;
       get_eol(filename, lnr, keyword, &line);
     }
@@ -1035,73 +1080,58 @@
     /* Kerberos authentication options */
     else if (strcasecmp(keyword, "krb5_ccname") == 0)
     {
-      parse_krb5_ccname_statement(filename, lnr, keyword, line);
+      handle_krb5_ccname(filename, lnr, keyword, line);
     }
     /* search/mapping options */
     else if (strcasecmp(keyword, "base") == 0)
     {
-      parse_base_statement(filename, lnr, keyword, line, cfg);
+      handle_base(filename, lnr, keyword, line, cfg);
     }
     else if (strcasecmp(keyword, "scope") == 0)
     {
-      parse_scope_statement(filename, lnr, keyword, line, cfg);
+      handle_scope(filename, lnr, keyword, line, cfg);
     }
     else if (strcasecmp(keyword, "deref") == 0)
     {
-      check_argumentcount(filename, lnr, keyword,
-                          (get_token(&line, token, sizeof(token)) != NULL));
-      if (strcasecmp(token, "never") == 0)
-        cfg->deref = LDAP_DEREF_NEVER;
-      else if (strcasecmp(token, "searching") == 0)
-        cfg->deref = LDAP_DEREF_SEARCHING;
-      else if (strcasecmp(token, "finding") == 0)
-        cfg->deref = LDAP_DEREF_FINDING;
-      else if (strcasecmp(token, "always") == 0)
-        cfg->deref = LDAP_DEREF_ALWAYS;
-      else
-      {
-        log_log(LOG_ERR, "%s:%d: wrong argument: '%s'", filename, lnr, token);
-        exit(EXIT_FAILURE);
-      }
-      get_eol(filename, lnr, keyword, &line);
+      handle_deref(filename, lnr, keyword, line, cfg);
     }
     else if (strcasecmp(keyword, "referrals") == 0)
     {
-      get_boolean(filename, lnr, keyword, &line, &cfg->referrals);
+      cfg->referrals = get_boolean(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "filter") == 0)
     {
-      parse_filter_statement(filename, lnr, keyword, line);
+      handle_filter(filename, lnr, keyword, line);
     }
     else if (strcasecmp(keyword, "map") == 0)
     {
-      parse_map_statement(filename, lnr, keyword, line);
+      handle_map(filename, lnr, keyword, line);
     }
     /* timing/reconnect options */
     else if (strcasecmp(keyword, "bind_timelimit") == 0)
     {
-      get_int(filename, lnr, keyword, &line, &cfg->bind_timelimit);
+      cfg->bind_timelimit = get_int(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "timelimit") == 0)
     {
-      get_int(filename, lnr, keyword, &line, &cfg->timelimit);
+      cfg->timelimit = get_int(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "idle_timelimit") == 0)
     {
-      get_int(filename, lnr, keyword, &line, &cfg->idle_timelimit);
+      cfg->idle_timelimit = get_int(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (!strcasecmp(keyword, "reconnect_sleeptime"))
     {
-      get_int(filename, lnr, keyword, &line, &cfg->reconnect_sleeptime);
+      cfg->reconnect_sleeptime = get_int(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "reconnect_retrytime") == 0)
     {
-      get_int(filename, lnr, keyword, &line, &cfg->reconnect_retrytime);
+      cfg->reconnect_retrytime = get_int(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
 #ifdef LDAP_OPT_X_TLS
@@ -1119,14 +1149,11 @@
     }
     else if (strcasecmp(keyword, "tls_reqcert") == 0)
     {
-      get_reqcert(filename, lnr, keyword, &line, &i);
-      get_eol(filename, lnr, keyword, &line);
-      log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT,%d)", i);
-      LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i);
+      handle_tls_reqcert(filename, lnr, keyword, line);
     }
     else if (strcasecmp(keyword, "tls_cacertdir") == 0)
     {
-      get_strdup(filename, lnr, keyword, &line, &value);
+      value = get_strdup(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
       /* TODO: check that the path is valid */
       log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CACERTDIR,\"%s\")",
@@ -1137,7 +1164,7 @@
     else if ((strcasecmp(keyword, "tls_cacertfile") == 0) ||
              (strcasecmp(keyword, "tls_cacert") == 0))
     {
-      get_strdup(filename, lnr, keyword, &line, &value);
+      value = get_strdup(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
       /* TODO: check that the path is valid */
       log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CACERTFILE,\"%s\")",
@@ -1147,7 +1174,7 @@
     }
     else if (strcasecmp(keyword, "tls_randfile") == 0)
     {
-      get_strdup(filename, lnr, keyword, &line, &value);
+      value = get_strdup(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
       /* TODO: check that the path is valid */
       log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_RANDOM_FILE,\"%s\")",
@@ -1157,7 +1184,7 @@
     }
     else if (strcasecmp(keyword, "tls_ciphers") == 0)
     {
-      get_restdup(filename, lnr, keyword, &line, &value);
+      value = get_linedup(filename, lnr, keyword, &line);
       log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CIPHER_SUITE,\"%s\")",
               value);
       LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, value);
@@ -1165,7 +1192,7 @@
     }
     else if (strcasecmp(keyword, "tls_cert") == 0)
     {
-      get_strdup(filename, lnr, keyword, &line, &value);
+      value = get_strdup(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
       /* TODO: check that the path is valid */
       log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CERTFILE,\"%s\")",
@@ -1175,7 +1202,7 @@
     }
     else if (strcasecmp(keyword, "tls_key") == 0)
     {
-      get_strdup(filename, lnr, keyword, &line, &value);
+      value = get_strdup(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
       /* TODO: check that the path is valid */
       log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_KEYFILE,\"%s\")",
@@ -1187,36 +1214,35 @@
     /* other options */
     else if (strcasecmp(keyword, "pagesize") == 0)
     {
-      get_int(filename, lnr, keyword, &line, &cfg->pagesize);
+      cfg->pagesize = get_int(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "nss_initgroups_ignoreusers") == 0)
     {
-      parse_nss_initgroups_ignoreusers_statement(filename, lnr, keyword, line,
+      handle_nss_initgroups_ignoreusers(filename, lnr, keyword, line,
                                                  cfg);
     }
     else if (strcasecmp(keyword, "nss_min_uid") == 0)
     {
-      get_uid(filename, lnr, keyword, &line, &cfg->nss_min_uid, NULL, NULL);
+      cfg->nss_min_uid = get_int(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "validnames") == 0)
     {
-      parse_validnames_statement(filename, lnr, keyword, line, cfg);
+      handle_validnames(filename, lnr, keyword, line, cfg);
     }
     else if (strcasecmp(keyword, "ignorecase") == 0)
     {
-      get_boolean(filename, lnr, keyword, &line, &cfg->ignorecase);
+      cfg->ignorecase = get_boolean(filename, lnr, keyword, &line);
       get_eol(filename, lnr, keyword, &line);
     }
     else if (strcasecmp(keyword, "pam_authz_search") == 0)
     {
-      parse_pam_authz_search_statement(filename, lnr, keyword, line, cfg);
+      handle_pam_authz_search(filename, lnr, keyword, line, cfg);
     }
     else if (strcasecmp(keyword, "pam_password_prohibit_message") == 0)
     {
-      parse_pam_password_prohibit_message_statement(filename, lnr, keyword,
-                                                    line, cfg);
+      handle_pam_password_prohibit_message(filename, lnr, keyword, line, cfg);
     }
 #ifdef ENABLE_CONFIGFILE_CHECKING
     /* fallthrough */
@@ -1286,58 +1312,6 @@
 }
 #endif /* NSLCD_BINDPW_PATH */
 
-/* This function tries to get the LDAP search base from the LDAP server.
-   Note that this returns a string that has been allocated with strdup().
-   For this to work the myldap module needs enough configuration information
-   to make an LDAP connection. */
-static MUST_USE char *get_base_from_rootdse(void)
-{
-  MYLDAP_SESSION *session;
-  MYLDAP_SEARCH *search;
-  MYLDAP_ENTRY *entry;
-  const char *attrs[] = { "+", NULL };
-  int i;
-  int rc;
-  const char **values;
-  char *base = NULL;
-  /* initialize session */
-  session = myldap_create_session();
-  assert(session != NULL);
-  /* perform search */
-  search = myldap_search(session, "", LDAP_SCOPE_BASE, "(objectClass=*)",
-                         attrs, NULL);
-  if (search == NULL)
-  {
-    myldap_session_close(session);
-    return NULL;
-  }
-  /* go over results */
-  for (i = 0; (entry = myldap_get_entry(search, &rc)) != NULL; i++)
-  {
-    /* get defaultNamingContext */
-    values = myldap_get_values(entry, "defaultNamingContext");
-    if ((values != NULL) && (values[0] != NULL))
-    {
-      base = xstrdup(values[0]);
-      log_log(LOG_DEBUG, "get_basedn_from_rootdse(): found attribute 
defaultNamingContext with value %s",
-              values[0]);
-      break;
-    }
-    /* get namingContexts */
-    values = myldap_get_values(entry, "namingContexts");
-    if ((values != NULL) && (values[0] != NULL))
-    {
-      base = xstrdup(values[0]);
-      log_log(LOG_DEBUG, "get_basedn_from_rootdse(): found attribute 
namingContexts with value %s",
-              values[0]);
-      break;
-    }
-  }
-  /* clean up */
-  myldap_session_close(session);
-  return base;
-}
-
 void cfg_init(const char *fname)
 {
 #ifdef LDAP_OPT_X_TLS

Modified: nss-pam-ldapd/tests/test_cfg.c
==============================================================================
--- nss-pam-ldapd/tests/test_cfg.c      Sat Jan 12 23:33:00 2013        (r1912)
+++ nss-pam-ldapd/tests/test_cfg.c      Sat Jan 12 23:36:00 2013        (r1913)
@@ -2,7 +2,7 @@
    test_cfg.c - simple test for the cfg module
    This file is part of the nss-pam-ldapd library.
 
-   Copyright (C) 2007, 2009, 2011, 2012 Arthur de Jong
+   Copyright (C) 2007, 2009, 2011, 2012, 2013 Arthur de Jong
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -85,18 +85,26 @@
 
 static void test_parse_scope(void)
 {
-  assert(parse_scope(__FILE__, __LINE__, "sUb") == LDAP_SCOPE_SUBTREE);
-  assert(parse_scope(__FILE__, __LINE__, "subtree") == LDAP_SCOPE_SUBTREE);
-  assert(parse_scope(__FILE__, __LINE__, "ONE") == LDAP_SCOPE_ONELEVEL);
-  assert(parse_scope(__FILE__, __LINE__, "oneLevel") == LDAP_SCOPE_ONELEVEL);
-  assert(parse_scope(__FILE__, __LINE__, "base") == LDAP_SCOPE_BASE);
-  assert(parse_scope(__FILE__, __LINE__, "bASe") == LDAP_SCOPE_BASE);
+  struct ldap_config cfg;
+  handle_scope(__FILE__, __LINE__, "scope", "sUb", &cfg);
+  assert(cfg.scope == LDAP_SCOPE_SUBTREE);
+  handle_scope(__FILE__, __LINE__, "scope", "subtree", &cfg);
+  assert(cfg.scope == LDAP_SCOPE_SUBTREE);
+  handle_scope(__FILE__, __LINE__, "scope", "ONE", &cfg);
+  assert(cfg.scope == LDAP_SCOPE_ONELEVEL);
+  handle_scope(__FILE__, __LINE__, "scope", "oneLevel", &cfg);
+  assert(cfg.scope == LDAP_SCOPE_ONELEVEL);
+  handle_scope(__FILE__, __LINE__, "scope", "base", &cfg);
+  assert(cfg.scope == LDAP_SCOPE_BASE);
+  handle_scope(__FILE__, __LINE__, "scope", "bASe", &cfg);
+  assert(cfg.scope == LDAP_SCOPE_BASE);
   /* most other values should call exit():
-     assert(parse_scope(__FILE__, __LINE__, "BSAE") == LDAP_SCOPE_BASE); */
+     handle_scope(__FILE__, __LINE__, "scope", "BSAE", &cfg); */
 }
 
 static void test_parse_map(void)
 {
+  char *line;
   /* some general assertions */
   assert((LM_ALIASES != LM_ETHERS) && (LM_ALIASES != LM_GROUP) &&
          (LM_ALIASES != LM_HOSTS) && (LM_ALIASES != LM_NETGROUP) &&
@@ -129,30 +137,25 @@
   assert((LM_RPC != LM_SERVICES) && (LM_RPC != LM_SHADOW));
   assert((LM_SERVICES != LM_SHADOW));
   /* test supported names */
-  assert(parse_map("alIas") == LM_ALIASES);
-  assert(parse_map("AliasES") == LM_ALIASES);
-  assert(parse_map("ether") == LM_ETHERS);
-  assert(parse_map("ethers") == LM_ETHERS);
-  assert(parse_map("group") == LM_GROUP);
-  /* assert(parse_map("groups") == LM_GROUP); */
-  assert(parse_map("host") == LM_HOSTS);
-  assert(parse_map("hosts") == LM_HOSTS);
-  assert(parse_map("netgroup") == LM_NETGROUP);
-  /* assert(parse_map("netgroups") == LM_NETGROUP); */
-  assert(parse_map("network") == LM_NETWORKS);
-  assert(parse_map("networks") == LM_NETWORKS);
-  assert(parse_map("passwd") == LM_PASSWD);
-  /* assert(parse_map("passwds") == LM_PASSWD); */
-  assert(parse_map("protocol") == LM_PROTOCOLS);
-  assert(parse_map("protocols") == LM_PROTOCOLS);
-  assert(parse_map("rpc") == LM_RPC);
-  /* assert(parse_map("rpcs") == LM_RPC); */
-  assert(parse_map("service") == LM_SERVICES);
-  assert(parse_map("services") == LM_SERVICES);
-  assert(parse_map("shadow") == LM_SHADOW);
-  /* assert(parse_map("shadows") == LM_SHADOW); */
-  /* most other values should call exit():
-     assert(parse_map("publickey") == LM_SERVICES); */
+  line = "alIas"; assert(get_map(&line) == LM_ALIASES);
+  line = "AliasES"; assert(get_map(&line) == LM_ALIASES);
+  line = "ether"; assert(get_map(&line) == LM_ETHERS);
+  line = "ethers"; assert(get_map(&line) == LM_ETHERS);
+  line = "group"; assert(get_map(&line) == LM_GROUP);
+  line = "host"; assert(get_map(&line) == LM_HOSTS);
+  line = "hosts"; assert(get_map(&line) == LM_HOSTS);
+  line = "netgroup"; assert(get_map(&line) == LM_NETGROUP);
+  line = "network"; assert(get_map(&line) == LM_NETWORKS);
+  line = "networks"; assert(get_map(&line) == LM_NETWORKS);
+  line = "passwd"; assert(get_map(&line) == LM_PASSWD);
+  line = "protocol"; assert(get_map(&line) == LM_PROTOCOLS);
+  line = "protocols"; assert(get_map(&line) == LM_PROTOCOLS);
+  line = "rpc"; assert(get_map(&line) == LM_RPC);
+  line = "service"; assert(get_map(&line) == LM_SERVICES);
+  line = "services"; assert(get_map(&line) == LM_SERVICES);
+  line = "shadow"; assert(get_map(&line) == LM_SHADOW);
+  line = "unknown"; assert(get_map(&line) == LM_NONE);
+  line = "x"; assert(get_map(&line) == LM_NONE);
 }
 
 static void test_parse_map_statement(void)
@@ -163,19 +166,20 @@
 static void test_tokenize(void)
 {
   /* this leaks memory all over the place */
-  char *line = strdup("yes this is 1 simple line");
+  char *line = strdup("yes  this is 1 simple line");
   char *str;
   int i;
-  get_boolean(__FILE__, __LINE__, __PRETTY_FUNCTION__, &line, &i);
+  i = get_boolean(__FILE__, __LINE__, __PRETTY_FUNCTION__, &line);
   assert(i == 1);
-  get_strdup(__FILE__, __LINE__, __PRETTY_FUNCTION__, &line, &str);
+  str = get_strdup(__FILE__, __LINE__, __PRETTY_FUNCTION__, &line);
   assertstreq(str, "this");
-  get_strdup(__FILE__, __LINE__, __PRETTY_FUNCTION__, &line, &str);
+  str = get_strdup(__FILE__, __LINE__, __PRETTY_FUNCTION__, &line);
   assertstreq(str, "is");
-  get_int(__FILE__, __LINE__, __PRETTY_FUNCTION__, &line, &i);
+  i = get_int(__FILE__, __LINE__, __PRETTY_FUNCTION__, &line);
   assert(i == 1);
-  get_restdup(__FILE__, __LINE__, __PRETTY_FUNCTION__, &line, &str);
+  str = get_linedup(__FILE__, __LINE__, __PRETTY_FUNCTION__, &line);
   assertstreq(str, "simple line");
+  get_eol(__FILE__, __LINE__, __PRETTY_FUNCTION__, &line);
 }
 
 extern const char *passwd_bases[];
-- 
To unsubscribe send an email to
nss-pam-ldapd-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/nss-pam-ldapd-commits/