]> granicus.if.org Git - postgresql/commitdiff
Add support for LDAP URLs
authorPeter Eisentraut <peter_e@gmx.net>
Tue, 4 Dec 2012 04:29:56 +0000 (23:29 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Tue, 4 Dec 2012 04:31:02 +0000 (23:31 -0500)
Allow specifying LDAP authentication parameters as RFC 4516 LDAP URLs.

doc/src/sgml/client-auth.sgml
src/backend/libpq/auth.c
src/backend/libpq/hba.c
src/include/libpq/hba.h

index d053fcebfd0dae357e42f4176f88290f0e9c02e5..909c81bd4087d1cab2c4b003662b357c267efe51 100644 (file)
@@ -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
index ca470e18835b531817673d656ae5b5fe8c293f3d..cc1140d9bce941a1952287a590ad10c7224802a0 100644 (file)
@@ -2209,7 +2209,7 @@ CheckLDAPAuth(Port *port)
 
                r = ldap_search_s(ldap,
                                                  port->hba->ldapbasedn,
-                                                 LDAP_SCOPE_SUBTREE,
+                                                 port->hba->ldapscope,
                                                  filter,
                                                  attributes,
                                                  0,
index 7502e82860d53e5a9530f0ee42d69b3585dcd15c..2bb661cf122bd15725f3cc766134499158842a86 100644 (file)
 #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");
index 408d26263a9544ac82c14f4f8b7448b4457c9a2e..79a5dc608c8d1798d8c4d9c9a212c895418cd08d 100644 (file)
@@ -71,6 +71,7 @@ typedef struct HbaLine
        char       *ldapbindpasswd;
        char       *ldapsearchattribute;
        char       *ldapbasedn;
+       int                     ldapscope;
        char       *ldapprefix;
        char       *ldapsuffix;
        bool            clientcert;