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 @@
LDAP Authentication
+
+ ldapurl
+
+
+ You can write most of the LDAP options alternatively using an RFC 2255
+ LDAP URL. The format is
+
+ldap://[user[:password]@]host[:port]/basedn[?[attribute][?[scope]]]
+
+ scope must be one
+ of base, one, sub,
+ typically the latter. Only one attribute is used, and some other
+ components of standard LDAP URLs such as filters and extensions are
+ not supported.
+
+
+
+ If you want encrypted LDAP connections, you have to use
+ the ldaptls option in addition
+ to ldapurl. The ldaps URL
+ scheme (direct SSL connection) is not supported.
+
+
+
+ Some other software that supports authentication against LDAP uses the
+ same URL format, so it will be easier to share the configuration.
+
+
+
+ LDAP URLs are currently only supported with OpenLDAP, not on Windows.
+
+
+
@@ -1520,6 +1553,13 @@ LDAP Authentication
If that second connection succeeds, the database access is granted.
+
+ Here is the same search+bind configuration written as a URL:
+
+host ... ldap lapurl="ldap://ldap.example.net/dc=example,dc=net?uid?sub"
+
+
+
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
+#else
+#include
+#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;