Here is a patch to support RFC 2255 LDAP URLs in pg_hba.conf.  So,
instead of, say

host ... ldap ldapserver=ldap.example.net ldapbasedn="dc=example, dc=net" 
ldapsearchattribute=uid

you could write

host ... ldap lapurl="ldap://ldap.example.net/dc=example,dc=net?uid?sub";

Apache and probably other software uses the same format, and it's easier
to have a common format for all such configuration instead of having to
translate the information provided by the LDAP admin into each
software's particular configuration spellings.

I'm using the OpenLDAP-provided URL parsing routine, which means this
wouldn't be supported on Windows.  But we already support different
authentication settings on different platforms, so this didn't seem such
a big problem.
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index d053fce..ba6523b 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -1486,6 +1486,39 @@ <title>LDAP Authentication</title>
         </para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term><literal>ldapurl</literal></term>
+       <listitem>
+        <para>
+         You can write most of the LDAP options alternatively using an RFC 2255
+         LDAP URL.  The format is
+<synopsis>
+ldap://[<replaceable>user</replaceable>[:<replaceable>password</replaceable>]@]<replaceable>host</replaceable>[:<replaceable>port</replaceable>]/<replaceable>basedn</replaceable>[?[<replaceable>attribute</replaceable>][?[<replaceable>scope</replaceable>]]]
+</synopsis>
+         <replaceable>scope</replaceable> must be one
+         of <literal>base</literal>, <literal>one</literal>, <literal>sub</literal>,
+         typically the latter.  Only one attribute is used, and some other
+         components of standard LDAP URLs such as filters and extensions are
+         not supported.
+        </para>
+
+        <para>
+         If you want encrypted LDAP connections, you have to use
+         the <literal>ldaptls</literal> option in addition
+         to <literal>ldapurl</literal>.  The <literal>ldaps</literal> URL
+         scheme (direct SSL connection) is not supported.
+        </para>
+
+        <para>
+         Some other software that supports authentication against LDAP uses the
+         same URL format, so it will be easier to share the configuration.
+        </para>
+
+        <para>
+         LDAP URLs are currently only supported with OpenLDAP, not on Windows.
+        </para>
+       </listitem>
+      </varlistentry>
     </variablelist>
    </para>
 
@@ -1520,6 +1553,13 @@ <title>LDAP Authentication</title>
     If that second connection succeeds, the database access is granted.
    </para>
 
+   <para>
+    Here is the same search+bind configuration written as a URL:
+<programlisting>
+host ... ldap lapurl="ldap://ldap.example.net/dc=example,dc=net?uid?sub";
+</programlisting>
+   </para>
+
    <tip>
     <para>
      Since LDAP often uses commas and spaces to separate the different
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index ca470e1..cc1140d 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -2209,7 +2209,7 @@ static int pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
 
 		r = ldap_search_s(ldap,
 						  port->hba->ldapbasedn,
-						  LDAP_SCOPE_SUBTREE,
+						  port->hba->ldapscope,
 						  filter,
 						  attributes,
 						  0,
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 7502e82..ba630a7 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -37,6 +37,16 @@
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 
+#ifdef USE_LDAP
+#ifndef WIN32
+/* We use a deprecated function to keep the codepath the same as win32. */
+#define LDAP_DEPRECATED 1
+#include <ldap.h>
+#else
+#include <winldap.h>
+#endif
+#endif
+
 
 #define atooid(x)  ((Oid) strtoul((x), NULL, 10))
 #define atoxid(x)  ((TransactionId) strtoul((x), NULL, 10))
@@ -1336,7 +1346,7 @@ static bool parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
 			{
 				ereport(LOG,
 						(errcode(ERRCODE_CONFIG_FILE_ERROR),
-						 errmsg("cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, or ldapsearchattribute together with ldapprefix"),
+						 errmsg("cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, or ldapurl together with ldapprefix"),
 						 errcontext("line %d of configuration file \"%s\"",
 									line_num, HbaFileName)));
 				return NULL;
@@ -1378,6 +1388,8 @@ static bool parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
 static bool
 parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
 {
+	hbaline->ldapscope = LDAP_SCOPE_SUBTREE;
+
 	if (strcmp(name, "map") == 0)
 	{
 		if (hbaline->auth_method != uaIdent &&
@@ -1437,6 +1449,54 @@ static bool parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
 		REQUIRE_AUTH_OPTION(uaPAM, "pamservice", "pam");
 		hbaline->pamservice = pstrdup(val);
 	}
+	else if (strcmp(name, "ldapurl") == 0)
+	{
+		LDAPURLDesc *urldata;
+		int rc;
+
+		REQUIRE_AUTH_OPTION(uaLDAP, "ldapurl", "ldap");
+
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+		rc = ldap_url_parse(val, &urldata);
+		if (rc != LDAP_SUCCESS)
+		{
+			ereport(LOG,
+				 (errcode(ERRCODE_CONFIG_FILE_ERROR),
+				  errmsg("could not parse LDAP URL \"%s\": %s", val, ldap_err2string(rc))));
+			return false;
+		}
+
+		if (strcmp(urldata->lud_scheme, "ldap") != 0)
+		{
+			ereport(LOG,
+					(errcode(ERRCODE_CONFIG_FILE_ERROR),
+					 errmsg("unsupported LDAP URL scheme: %s", urldata->lud_scheme)));
+			ldap_free_urldesc(urldata);
+			return false;
+		}
+
+		hbaline->ldapserver = pstrdup(urldata->lud_host);
+		hbaline->ldapport = urldata->lud_port;
+		hbaline->ldapbasedn = pstrdup(urldata->lud_dn);
+
+		if (urldata->lud_attrs)
+			hbaline->ldapsearchattribute = pstrdup(urldata->lud_attrs[0]);  /* only use first one */
+		hbaline->ldapscope = urldata->lud_scope;
+		if (urldata->lud_filter)
+		{
+			ereport(LOG,
+					(errcode(ERRCODE_CONFIG_FILE_ERROR),
+					 errmsg("filters not supported in LDAP URLs")));
+			ldap_free_urldesc(urldata);
+			return false;
+		}
+		ldap_free_urldesc(urldata);
+#else /* not OpenLDAP */
+		ereport(LOG,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("LDAP URLs not supported on this platform")));
+#endif /* not OpenLDAP */
+	}
 	else if (strcmp(name, "ldaptls") == 0)
 	{
 		REQUIRE_AUTH_OPTION(uaLDAP, "ldaptls", "ldap");
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
index 408d262..79a5dc6 100644
--- a/src/include/libpq/hba.h
+++ b/src/include/libpq/hba.h
@@ -71,6 +71,7 @@ typedef struct HbaLine
 	char	   *ldapbindpasswd;
 	char	   *ldapsearchattribute;
 	char	   *ldapbasedn;
+	int			ldapscope;
 	char	   *ldapprefix;
 	char	   *ldapsuffix;
 	bool		clientcert;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to