From aa2fec0a18e4d23272c78916ef318078c920611a Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 3 Dec 2012 23:29:56 -0500 Subject: [PATCH] Add support for LDAP URLs Allow specifying LDAP authentication parameters as RFC 4516 LDAP URLs. --- doc/src/sgml/client-auth.sgml | 37 ++++++++++++++++++++++ src/backend/libpq/auth.c | 2 +- src/backend/libpq/hba.c | 59 ++++++++++++++++++++++++++++++++++- 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 d053fcebfd..909c81bd40 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -1486,6 +1486,34 @@ omicron bryanh guest1 + + ldapurl + + + 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 + +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. + + + + To use encrypted LDAP connections, the ldaptls + option has to be used in addition to ldapurl. + The ldaps URL scheme (direct SSL connection) is not + supported. + + + + LDAP URLs are currently only supported with OpenLDAP, not on Windows. + + + @@ -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. + + Here is the same search+bind configuration written as a URL: + +host ... ldap lapurl="ldap://ldap.example.net/dc=example,dc=net?uid?sub" + + Some other software that supports authentication against LDAP uses the + same URL format, so it will be easier to share the configuration. + + 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 ca470e1883..cc1140d9bc 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 7502e82860..2bb661cf12 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 +#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 408d26263a..79a5dc608c 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; -- 2.40.0