diff options
-rw-r--r-- | doc/src/sgml/client-auth.sgml | 37 | ||||
-rw-r--r-- | src/backend/libpq/auth.c | 2 | ||||
-rw-r--r-- | src/backend/libpq/hba.c | 59 | ||||
-rw-r--r-- | src/include/libpq/hba.h | 1 |
4 files changed, 97 insertions, 2 deletions
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index d053fcebfd0..909c81bd408 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -1486,6 +1486,34 @@ omicron bryanh guest1 </para> </listitem> </varlistentry> + <varlistentry> + <term><literal>ldapurl</literal></term> + <listitem> + <para> + An RFC 4516 LDAP URL. This is an alternative way to write most of the + other LDAP options in a more compact and standard form. 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> + To use encrypted LDAP connections, the <literal>ldaptls</literal> + option has to be used in addition to <literal>ldapurl</literal>. + The <literal>ldaps</literal> URL scheme (direct SSL connection) is not + supported. + </para> + + <para> + LDAP URLs are currently only supported with OpenLDAP, not on Windows. + </para> + </listitem> + </varlistentry> </variablelist> </para> @@ -1520,6 +1548,15 @@ host ... ldap ldapserver=ldap.example.net ldapbasedn="dc=example, dc=net" ldapse 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> + Some other software that supports authentication against LDAP uses the + same URL format, so it will be easier to share the configuration. + </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 ca470e18835..cc1140d9bce 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -2209,7 +2209,7 @@ CheckLDAPAuth(Port *port) 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 7502e82860d..2bb661cf122 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -37,6 +37,13 @@ #include "utils/lsyscache.h" #include "utils/memutils.h" +#ifdef USE_LDAP +#ifndef WIN32 +#include <ldap.h> +#endif +/* currently no Windows LDAP needed in this file */ +#endif + #define atooid(x) ((Oid) strtoul((x), NULL, 10)) #define atoxid(x) ((TransactionId) strtoul((x), NULL, 10)) @@ -1336,7 +1343,7 @@ parse_hba_line(List *line, int line_num) { 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 +1385,8 @@ parse_hba_line(List *line, int line_num) 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 +1446,54 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num) 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 408d26263a9..79a5dc608c8 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; |