After the LDAP code was switched to use ldap_initialize() as part of the
ldaps support, ldapi (LDAP over Unix-domain sockets) also works.  I
noticed an old bug report (#13625) that asked for it.  So I suggest this
patch to document this and add some tests.

One flaw is that this only works when using the URL syntax.  Providing a
separate option would require coding URL escaping, since ultimately an
URL must be composed and passed to ldap_initialize().  But since
OpenLDAP apparently now considers URLs to be the preferred form for
connection parameters, I'm comfortable just sticking to that format.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 4b24fa8aaf68327f773327269b23b6b129df858c Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pete...@gmx.net>
Date: Thu, 8 Feb 2018 10:21:43 -0500
Subject: [PATCH] Document support for LDAP over Unix-domain sockets (ldapi)

After the LDAP code was switched to use ldap_initialize() as part of the
ldaps support, ldapi also works, so we might as well document it and add
some tests.

Bug: #13625
---
 doc/src/sgml/client-auth.sgml | 10 ++++++++++
 src/test/ldap/t/001_auth.pl   | 25 +++++++++++++++++++++++--
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 53832d08e2..8ed95bef4e 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -1618,6 +1618,7 @@ <title>LDAP Authentication</title>
          other LDAP options in a more compact and standard form.  The format is
 <synopsis>
 
ldap[s]://<replaceable>host</replaceable>[:<replaceable>port</replaceable>]/<replaceable>basedn</replaceable>[?[<replaceable>attribute</replaceable>][?[<replaceable>scope</replaceable>][?[<replaceable>filter</replaceable>]]]]
+ldapi://<replaceable>path</replaceable>/<replaceable>basedn</replaceable>[?[<replaceable>attribute</replaceable>][?[<replaceable>scope</replaceable>][?[<replaceable>filter</replaceable>]]]]
 </synopsis>
          <replaceable>scope</replaceable> must be one
          of <literal>base</literal>, <literal>one</literal>, 
<literal>sub</literal>,
@@ -1640,6 +1641,15 @@ <title>LDAP Authentication</title>
          <literal>ldapurl</literal>.
         </para>
 
+        <para>
+         The URL scheme <literal>ldapi</literal> makes the LDAP connection
+         over a Unix-domain socket.  The <replaceable>path</replaceable> must
+         be URL-encoded, for example
+         <literal>ldapi://%2Fusr%2Flocal%2Fvar%2Fldapi</literal>.  This
+         connection method can only specified as a URL, not via separate
+         options.
+        </para>
+
         <para>
          For non-anonymous binds, <literal>ldapbinddn</literal>
          and <literal>ldapbindpasswd</literal> must be specified as separate
diff --git a/src/test/ldap/t/001_auth.pl b/src/test/ldap/t/001_auth.pl
index 5508da459f..71045a5866 100644
--- a/src/test/ldap/t/001_auth.pl
+++ b/src/test/ldap/t/001_auth.pl
@@ -2,7 +2,7 @@
 use warnings;
 use TestLib;
 use PostgresNode;
-use Test::More tests => 19;
+use Test::More tests => 20;
 
 my ($slapd, $ldap_bin_dir, $ldap_schema_dir);
 
@@ -32,6 +32,16 @@
 
 $ENV{PATH} = "$ldap_bin_dir:$ENV{PATH}" if $ldap_bin_dir;
 
+sub url_encode {
+       my $string = shift;
+       $string =~ s/([^a-zA-Z0-9\-_.!~*'()])/sprintf("%%%02X", ord($1))/ge;
+       $string =~ tr/ /+/;
+       return $string;
+}
+
+# for Unix-domain socket
+my $tempdir_short = TestLib::tempdir_short;
+
 my $ldap_datadir = "${TestLib::tmp_check}/openldap-data";
 my $slapd_certs = "${TestLib::tmp_check}/slapd-certs";
 my $slapd_conf = "${TestLib::tmp_check}/slapd.conf";
@@ -41,7 +51,9 @@
 my $ldap_server = 'localhost';
 my $ldap_port = int(rand() * 16384) + 49152;
 my $ldaps_port = $ldap_port + 1;
+my $ldapi_socket = "$tempdir_short/ldapi";
 my $ldap_url = "ldap://$ldap_server:$ldap_port";;
+my $ldapi_url = "ldapi://" . url_encode($ldapi_socket);
 my $ldaps_url = "ldaps://$ldap_server:$ldaps_port";
 my $ldap_basedn = 'dc=example,dc=net';
 my $ldap_rootdn = 'cn=Manager,dc=example,dc=net';
@@ -86,7 +98,7 @@
 system_or_bail "openssl", "req", "-new", "-nodes", "-keyout", 
"$slapd_certs/server.key", "-out", "$slapd_certs/server.csr", "-subj", 
"/cn=server";
 system_or_bail "openssl", "x509", "-req", "-in", "$slapd_certs/server.csr", 
"-CA", "$slapd_certs/ca.crt", "-CAkey", "$slapd_certs/ca.key", 
"-CAcreateserial", "-out", "$slapd_certs/server.crt";
 
-system_or_bail $slapd, '-f', $slapd_conf, '-h', "$ldap_url $ldaps_url";
+system_or_bail $slapd, '-f', $slapd_conf, '-h', "$ldap_url $ldapi_url 
$ldaps_url";
 
 END
 {
@@ -162,6 +174,15 @@ sub test_access
 $ENV{"PGPASSWORD"} = 'secret1';
 test_access($node, 'test1', 0, 'search+bind with LDAP URL authentication 
succeeds');
 
+note "ldapi";
+
+unlink($node->data_dir . '/pg_hba.conf');
+$node->append_conf('pg_hba.conf', qq{local all all ldap 
ldapurl="$ldapi_url/$ldap_basedn?uid?sub"});
+$node->reload;
+
+$ENV{"PGPASSWORD"} = 'secret1';
+test_access($node, 'test1', 0, 'authentication using ldapi URL succeeds');
+
 note "search filters";
 
 unlink($node->data_dir . '/pg_hba.conf');

base-commit: b3a101eff0fd3747bebf547b1769e28f820f4515
-- 
2.16.1

Reply via email to