From 6e7e878f3e7ebf7aa66b82b1857bfdb8325f1288 Mon Sep 17 00:00:00 2001
From: Arthur de Jong <arthur@arthurdejong.org>
Date: Fri, 19 Nov 2021 12:11:15 +0100
Subject: Support DNSLDAPS in uri

This supports both `uri DNSLDAPS` and `uri DNSLDAPS:some.domain`
variants alongside the pre-existing `uri DNS` that was already supported
generating ldaps URIs for all SRV records found.
---
 man/nslcd.conf.5.xml | 11 +++++++----
 nslcd/cfg.c          | 32 ++++++++++++++++++++++++++------
 2 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/man/nslcd.conf.5.xml b/man/nslcd.conf.5.xml
index c8f98b6..aafb700 100644
--- a/man/nslcd.conf.5.xml
+++ b/man/nslcd.conf.5.xml
@@ -157,17 +157,20 @@
        <acronym>SRV</acronym> records. <!-- since 0.5 -->
        By default the current domain is used but another domain can
        be queried by using the
-       <literal>DNS:</literal><replaceable>DOMAIN</replaceable> syntax.
+       <literal>DNS:DOMAIN</literal> syntax.
        <!-- since 0.8.4 -->
+       To convert <acronym>SRV</acronym> records for port 389 into an
+       <literal>ldaps://</literal> <acronym>URI</acronym>, <literal>DNSLDAPS</literal>
+       can be used. <!-- since 0.9.12 -->
       </para>
       <para>
-       When using the ldapi scheme, %2f should be used to escape slashes
-       (e.g. ldapi://%2fvar%2frun%2fslapd%2fldapi/), although most of the
+       When using the <literal>ldapi</literal> scheme, <literal>%2f</literal> should be used to escape slashes
+       (e.g. <literal>ldapi://%2fvar%2frun%2fslapd%2fldapi/</literal>), although most of the
        time this should not be needed.
       </para>
       <para>
        This option may be specified multiple times and/or with more
-       URIs on the line, separated by space. Normally, only the first
+       URIs on the line, separated by spaces. Normally, only the first
        server will be used with the following servers as fall-back (see
        <option>bind_timelimit</option> below).
       </para>
diff --git a/nslcd/cfg.c b/nslcd/cfg.c
index 772f0f6..86917d5 100644
--- a/nslcd/cfg.c
+++ b/nslcd/cfg.c
@@ -421,11 +421,12 @@ static const char *cfg_getdomainname(const char *filename, int lnr)
 
 /* 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)
+                              struct ldap_config *cfg, const char *domain,
+                              int force_ldaps)
 {
   int rc;
   char *hostlist = NULL, *nxt;
-  char buf[BUFLEN_HOSTNAME + sizeof("ldap://")];
+  char buf[BUFLEN_HOSTNAME + sizeof("ldaps://")];
   log_log(LOG_DEBUG, "query %s for SRV records", domain);
   rc = ldap_domain2hostlist(domain, &hostlist);
   if (rc != LDAP_SUCCESS)
@@ -467,7 +468,7 @@ static void add_uris_from_dns(const char *filename, int lnr,
       /* strip default port number */
       if ((strlen(hostlist) > 4) && (strcmp(hostlist + strlen(hostlist) - 4, ":389") == 0))
         hostlist[strlen(hostlist) - 4] = '\0';
-      if (mysnprintf(buf, sizeof(buf), "ldap://%s", hostlist))
+      if (mysnprintf(buf, sizeof(buf), "ldap%s://%s", force_ldaps ? "s" : "", hostlist))
       {
         log_log(LOG_ERR, "add_uris_from_dns(): buf buffer too small (%lu required)",
                 (unsigned long) strlen(hostlist) + 7);
@@ -1389,8 +1390,7 @@ static void cfg_read(const char *filename, struct ldap_config *cfg)
         if (strcasecmp(token, "dns") == 0)
         {
 #ifdef HAVE_LDAP_DOMAIN2HOSTLIST
-          add_uris_from_dns(filename, lnr, cfg,
-                            cfg_getdomainname(filename, lnr));
+          add_uris_from_dns(filename, lnr, cfg, cfg_getdomainname(filename, lnr), 0);
 #else /* not HAVE_LDAP_DOMAIN2HOSTLIST */
           log_log(LOG_ERR, "%s:%d: value %s not supported on platform",
                   filename, lnr, token);
@@ -1400,7 +1400,27 @@ static void cfg_read(const char *filename, struct ldap_config *cfg)
         else if (strncasecmp(token, "dns:", 4) == 0)
         {
 #ifdef HAVE_LDAP_DOMAIN2HOSTLIST
-          add_uris_from_dns(filename, lnr, cfg, strdup(token + 4));
+          add_uris_from_dns(filename, lnr, cfg, strdup(token + 4), 0);
+#else /* not HAVE_LDAP_DOMAIN2HOSTLIST */
+          log_log(LOG_ERR, "%s:%d: value %s not supported on platform",
+                  filename, lnr, token);
+          exit(EXIT_FAILURE);
+#endif /* not HAVE_LDAP_DOMAIN2HOSTLIST */
+        }
+        else if (strcasecmp(token, "dnsldaps") == 0)
+        {
+#ifdef HAVE_LDAP_DOMAIN2HOSTLIST
+          add_uris_from_dns(filename, lnr, cfg, cfg_getdomainname(filename, lnr), 1);
+#else /* not HAVE_LDAP_DOMAIN2HOSTLIST */
+          log_log(LOG_ERR, "%s:%d: value %s not supported on platform",
+                  filename, lnr, token);
+          exit(EXIT_FAILURE);
+#endif /* not HAVE_LDAP_DOMAIN2HOSTLIST */
+        }
+        else if (strncasecmp(token, "dnsldaps:", 9) == 0)
+        {
+#ifdef HAVE_LDAP_DOMAIN2HOSTLIST
+          add_uris_from_dns(filename, lnr, cfg, strdup(token + 9), 1);
 #else /* not HAVE_LDAP_DOMAIN2HOSTLIST */
           log_log(LOG_ERR, "%s:%d: value %s not supported on platform",
                   filename, lnr, token);
-- 
cgit v1.2.3