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;