Update LDAP Protocol in fe-connect.c to v3

Started by Andrew Jackson10 months ago16 messages
#1Andrew Jackson
andrewjackson947@gmail.com

Currently the LDAP usage in fe-connect.c does not explicitly set the
protocol version to v3. This causes issues with many LDAP servers as they
will often require clients to use the v3 protocol and disallow any use of
the v2 protocol. Further the other usage of LDAP in postgres (in
`backend/libpq/auth.c`) uses the v3 protocol.

This patch changes fe-connect.c so that it uses the v3 protocol similar to
`backend/libpq/auth.c`.

One further note is that I do not currently see any test coverage over the
LDAP functionality in `fe-connect.c`. I am happy to add that to this patch
if needed.

#2Andrew Jackson
andrewjackson947@gmail.com
In reply to: Andrew Jackson (#1)
1 attachment(s)
Re: Update LDAP Protocol in fe-connect.c to v3

Apologies, forgot to attach the patch in the prior email.

On Sat, Mar 22, 2025 at 4:10 PM Andrew Jackson <andrewjackson947@gmail.com>
wrote:

Show quoted text

Currently the LDAP usage in fe-connect.c does not explicitly set the
protocol version to v3. This causes issues with many LDAP servers as they
will often require clients to use the v3 protocol and disallow any use of
the v2 protocol. Further the other usage of LDAP in postgres (in
`backend/libpq/auth.c`) uses the v3 protocol.

This patch changes fe-connect.c so that it uses the v3 protocol similar to
`backend/libpq/auth.c`.

One further note is that I do not currently see any test coverage over the
LDAP functionality in `fe-connect.c`. I am happy to add that to this patch
if needed.

Attachments:

v1-0001-Set-version-3-protocol.patchtext/x-patch; charset=US-ASCII; name=v1-0001-Set-version-3-protocol.patchDownload
From f93256a5f80bde1d5de79941bd7313a014085f2b Mon Sep 17 00:00:00 2001
From: CommanderKeynes <andrewjackson947@gmail.coma>
Date: Sat, 22 Mar 2025 15:34:42 -0500
Subject: [PATCH v1] Set version 3 protocol

---
 src/interfaces/libpq/fe-connect.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index d5051f5e820..40d7d176cf0 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -5413,6 +5413,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
 			   *entry;
 	struct berval **values;
 	LDAP_TIMEVAL time = {PGLDAP_TIMEOUT, 0};
+	int         ldapversion = LDAP_VERSION3;
 
 	if ((url = strdup(purl)) == NULL)
 	{
@@ -5544,6 +5545,13 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
 		return 3;
 	}
 
+    if ((ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
+    {
+		free(url);
+        ldap_unbind(ld);
+        return 2;
+    }
+
 	/*
 	 * Perform an explicit anonymous bind.
 	 *
-- 
2.47.2

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Jackson (#1)
Re: Update LDAP Protocol in fe-connect.c to v3

Andrew Jackson <andrewjackson947@gmail.com> writes:

Currently the LDAP usage in fe-connect.c does not explicitly set the
protocol version to v3. This causes issues with many LDAP servers as they
will often require clients to use the v3 protocol and disallow any use of
the v2 protocol.

This is the first complaint I can recall hearing about that, so
exactly which ones are "many"? Also, are we really sufficiently
compliant with v3 that just adding this bit is enough?

One further note is that I do not currently see any test coverage over the
LDAP functionality in `fe-connect.c`. I am happy to add that to this patch
if needed.

src/test/ldap/ doesn't do it for you?

regards, tom lane

#4Andrew Jackson
andrewjackson947@gmail.com
In reply to: Tom Lane (#3)
Re: Update LDAP Protocol in fe-connect.c to v3

This is the first complaint I can recall hearing about that, so

exactly which ones are "many"?

I've tested a 2 before figuring out about the v3 issue. lldap[0]https://github.com/lldap/lldap and the
docker image osixia/docker-openldap[1]https://github.com/osixia/docker-openldap.
- lldap gives the following error message when I attempt to connect
without the patch "Service Error: while handling incoming messages: while
receiving LDAP op: Bind request version is not equal to 3. This is a
serious client bug.". With the attached patch this error message does not
appear
- osixia/docker-openlap gives the following error message without the
patch "67df745e conn=1001 op=0 RESULT tag=97 err=2 text=historical protocol
version requested, use LDAPv3 instead".
"

Also, are we really sufficiently compliant with v3 that just adding this

bit is enough?

I believe that this bit is all that is needed. Per the man page for
ldap_set_option [2]https://linux.die.net/man/3/ldap: "The protocol version used by the library defaults to
LDAPv2 (now historic), which corresponds to the LDAP_VERSION2 macro.
Application developers are encouraged to explicitly set
LDAP_OPT_PROTOCOL_VERSION to LDAPv3, using the LDAP_VERSION3 macro, or to
allow users to select the protocol version."

src/test/ldap/ doesn't do it for you?

Looking through the tests here it seems like they are all tests for the
serverside auth functionality that is configurable in pg_hba.conf. I don't
see any tests that test the client side "LDAP Lookup of Connection
Parameters" described in [3]https://www.postgresql.org/docs/current/libpq-ldap.html

[0]: https://github.com/lldap/lldap
[1]: https://github.com/osixia/docker-openldap
[2]: https://linux.die.net/man/3/ldap
[3]: https://www.postgresql.org/docs/current/libpq-ldap.html

On Sat, Mar 22, 2025 at 6:10 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Show quoted text

Andrew Jackson <andrewjackson947@gmail.com> writes:

Currently the LDAP usage in fe-connect.c does not explicitly set the
protocol version to v3. This causes issues with many LDAP servers as they
will often require clients to use the v3 protocol and disallow any use of
the v2 protocol.

This is the first complaint I can recall hearing about that, so
exactly which ones are "many"? Also, are we really sufficiently
compliant with v3 that just adding this bit is enough?

One further note is that I do not currently see any test coverage over

the

LDAP functionality in `fe-connect.c`. I am happy to add that to this

patch

if needed.

src/test/ldap/ doesn't do it for you?

regards, tom lane

#5Peter Eisentraut
peter@eisentraut.org
In reply to: Andrew Jackson (#4)
Re: Update LDAP Protocol in fe-connect.c to v3

On 23.03.25 04:05, Andrew Jackson wrote:

This is the first complaint I can recall hearing about that, so

exactly which ones are "many"?

I've tested a 2 before figuring out about the v3 issue. lldap[0] and the
docker image osixia/docker-openldap[1].
- lldap  gives the following error message when I attempt to connect
without the patch "Service Error: while handling incoming messages:
while receiving LDAP op: Bind request version is not equal to 3. This is
a serious client bug.". With the attached patch this error message does
not appear
-  osixia/docker-openlap gives the following error message without the
patch "67df745e conn=1001 op=0 RESULT tag=97 err=2 text=historical
protocol version requested, use LDAPv3 instead".
"

Also, are we really sufficiently compliant with v3 that just adding

this bit is enough?

I believe that this bit is all that is needed. Per the man page for
ldap_set_option [2]: "The protocol version used by the library defaults
to LDAPv2 (now historic), which corresponds to the LDAP_VERSION2 macro.
Application developers are encouraged to explicitly set
LDAP_OPT_PROTOCOL_VERSION to LDAPv3, using the LDAP_VERSION3 macro, or
to allow users to select the protocol version."

src/test/ldap/ doesn't do it for you?

Looking through the tests here it seems like they are all tests for the
serverside auth functionality that is configurable in pg_hba.conf. I
don't see any tests that test the client side "LDAP Lookup of Connection
Parameters" described in [3]

Ah yes. There are two independent pieces of LDAP functionality. One is
the client authentication support in the backend, the other is the
connection parameter lookup in libpq. The former does set the LDAP
protocol version, the latter does not. This was clearly just forgotten.
Your patch makes sense.

#6Andrew Jackson
andrewjackson947@gmail.com
In reply to: Peter Eisentraut (#5)
1 attachment(s)
Re: Update LDAP Protocol in fe-connect.c to v3

Hi,

Added some tests for the LDAP connection parameters lookup functionality
with the attached patch. It is based off of the tests that were added
recently that cover the connection service file libpq functionality as well
as the existing ldap test framework.

Thanks,
Andrew Jackson

On Wed, Mar 26, 2025, 1:41 AM Peter Eisentraut <peter@eisentraut.org> wrote:

Show quoted text

On 23.03.25 04:05, Andrew Jackson wrote:

This is the first complaint I can recall hearing about that, so

exactly which ones are "many"?

I've tested a 2 before figuring out about the v3 issue. lldap[0] and the
docker image osixia/docker-openldap[1].
- lldap gives the following error message when I attempt to connect
without the patch "Service Error: while handling incoming messages:
while receiving LDAP op: Bind request version is not equal to 3. This is
a serious client bug.". With the attached patch this error message does
not appear
- osixia/docker-openlap gives the following error message without the
patch "67df745e conn=1001 op=0 RESULT tag=97 err=2 text=historical
protocol version requested, use LDAPv3 instead".
"

Also, are we really sufficiently compliant with v3 that just adding

this bit is enough?

I believe that this bit is all that is needed. Per the man page for
ldap_set_option [2]: "The protocol version used by the library defaults
to LDAPv2 (now historic), which corresponds to the LDAP_VERSION2 macro.
Application developers are encouraged to explicitly set
LDAP_OPT_PROTOCOL_VERSION to LDAPv3, using the LDAP_VERSION3 macro, or
to allow users to select the protocol version."

src/test/ldap/ doesn't do it for you?

Looking through the tests here it seems like they are all tests for the
serverside auth functionality that is configurable in pg_hba.conf. I
don't see any tests that test the client side "LDAP Lookup of Connection
Parameters" described in [3]

Ah yes. There are two independent pieces of LDAP functionality. One is
the client authentication support in the backend, the other is the
connection parameter lookup in libpq. The former does set the LDAP
protocol version, the latter does not. This was clearly just forgotten.
Your patch makes sense.

Attachments:

v1-0001-Add-TAP-tests-for-LDAP-connection-parameter-lookup.patchtext/x-diff; charset=US-ASCII; name=v1-0001-Add-TAP-tests-for-LDAP-connection-parameter-lookup.patchDownload
From 53210d9ba583a2159e4847b4adda20b9a4f652f7 Mon Sep 17 00:00:00 2001
From: CommanderKeynes <andrewjackson947@gmail.coma>
Date: Mon, 31 Mar 2025 22:47:19 -0500
Subject: [PATCH] Add TAP tests for LDAP connection parameter lookup

This commit adds regressions tests that tests the LDAP Lookup
of Connection Parameters functionality. Prior to this commit
LDAP test coverage only existed for the serverside auth
functionality and for connection service file with parameters
directly specified in the file. This tests included with this PR
tests a pg_service.conf that contains a link to an LDAP system which
contains all of the connection parameters.

Author: Andrew Jackson <andrewjackson947@gmail.com>
Discussion: https://www.postgresql.org/message-id/CAKK5BkHixcivSCA9pfd_eUp7wkLRhvQ6OtGLAYrWC%3Dk7E76LDQ%40mail.gmail.com
---
 .../t/003_ldap_connection_param_lookup.pl     | 202 ++++++++++++++++++
 1 file changed, 202 insertions(+)
 create mode 100644 src/test/ldap/t/003_ldap_connection_param_lookup.pl

diff --git a/src/test/ldap/t/003_ldap_connection_param_lookup.pl b/src/test/ldap/t/003_ldap_connection_param_lookup.pl
new file mode 100644
index 00000000000..a531cb783c8
--- /dev/null
+++ b/src/test/ldap/t/003_ldap_connection_param_lookup.pl
@@ -0,0 +1,202 @@
+# Copyright (c) 2025, PostgreSQL Global Development Group
+use strict;
+use warnings FATAL => 'all';
+use File::Copy;
+use PostgreSQL::Test::Utils;
+use PostgreSQL::Test::Cluster;
+use Test::More;
+use FindBin;
+use lib "$FindBin::RealBin/..";
+use LdapServer;
+
+if ($ENV{with_ldap} ne 'yes')
+{
+	plan skip_all => 'LDAP not supported by this build';
+}
+elsif (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\bldap\b/)
+{
+	plan skip_all =>
+	  'Potentially unsafe test LDAP not enabled in PG_TEST_EXTRA';
+}
+elsif (!$LdapServer::setup)
+{
+	plan skip_all => $LdapServer::setup_error;
+}
+#
+# This tests scenarios related to the service name and the service file,
+# for the connection options and their environment variables.
+my $dummy_node = PostgreSQL::Test::Cluster->new('dummy_node');
+$dummy_node->init;
+
+my $node = PostgreSQL::Test::Cluster->new('node');
+$node->init;
+$node->start;
+
+note "setting up LDAP server";
+
+my $ldap_rootpw = 'secret';
+my $ldap = LdapServer->new($ldap_rootpw, 'anonymous');    # use anonymous auth
+$ldap->ldapadd_file('authdata.ldif');
+$ldap->ldapsetpw('uid=test1,dc=example,dc=net', 'secret1');
+$ldap->ldapsetpw('uid=test2,dc=example,dc=net', 'secret2');
+#
+# Windows vs non-Windows: CRLF vs LF for the file's newline, relying on
+# the fact that libpq uses fgets() when reading the lines of a service file.
+my $newline = $windows_os ? "\r\n" : "\n";
+
+my $td = PostgreSQL::Test::Utils::tempdir;
+
+# TODO create ldap file based on postgres connection info
+my $ldif_valid = "$td/connection_params.ldif";
+append_to_file($ldif_valid, "version:1");
+append_to_file($ldif_valid, $newline);
+append_to_file($ldif_valid, "dn:cn=mydatabase,dc=example,dc=net");
+append_to_file($ldif_valid, $newline);
+append_to_file($ldif_valid, "changetype:add");
+append_to_file($ldif_valid, $newline);
+append_to_file($ldif_valid, "objectclass:top");
+append_to_file($ldif_valid, $newline);
+append_to_file($ldif_valid, "objectclass:device");
+append_to_file($ldif_valid, $newline);
+append_to_file($ldif_valid, "cn:mydatabase");
+append_to_file($ldif_valid, $newline);
+append_to_file($ldif_valid, "description:host=");
+append_to_file($ldif_valid, $node->host);
+append_to_file($ldif_valid, $newline);
+append_to_file($ldif_valid, "description:port=");
+append_to_file($ldif_valid, $node->port);
+
+$ldap->ldapadd_file($ldif_valid);
+
+my ($ldap_server, $ldap_port, $ldaps_port, $ldap_url,
+	$ldaps_url, $ldap_basedn, $ldap_rootdn
+) = $ldap->prop(qw(server port s_port url s_url basedn rootdn));
+
+# don't bother to check the server's cert (though perhaps we should)
+$ENV{'LDAPTLS_REQCERT'} = "never";
+
+note "setting up PostgreSQL instance";
+
+# Create the set of service files used in the tests.
+# File that includes a valid service name, that uses a decomposed connection
+# string for its contents, split on spaces.
+my $srvfile_valid = "$td/pg_service_valid.conf";
+append_to_file($srvfile_valid, "[my_srv]");
+append_to_file($srvfile_valid, $newline);
+append_to_file($srvfile_valid, "ldap://localhost:");
+append_to_file($srvfile_valid, $ldap_port);
+append_to_file($srvfile_valid, "/dc=example,dc=net?description?one?(cn=mydatabase)");
+
+# File defined with no contents, used as default value for PGSERVICEFILE,
+# so as no lookup is attempted in the user's home directory.
+my $srvfile_empty = "$td/pg_service_empty.conf";
+append_to_file($srvfile_empty, '');
+
+# Default service file in PGSYSCONFDIR.
+my $srvfile_default = "$td/pg_service.conf";
+
+# Missing service file.
+my $srvfile_missing = "$td/pg_service_missing.conf";
+
+# Set the fallback directory lookup of the service file to the temporary
+# directory of this test.  PGSYSCONFDIR is used if the service file
+# defined in PGSERVICEFILE cannot be found, or when a service file is
+# found but not the service name.
+local $ENV{PGSYSCONFDIR} = $td;
+# Force PGSERVICEFILE to a default location, so as this test never
+# tries to look at a home directory.  This value needs to remain
+# at the top of this script before running any tests, and should never
+# be changed.
+local $ENV{PGSERVICEFILE} = "$srvfile_empty";
+
+# Checks combinations of service name and a valid service file.
+{
+	local $ENV{PGSERVICEFILE} = $srvfile_valid;
+	$dummy_node->connect_ok(
+		'service=my_srv',
+		'connection with correct "service" string and PGSERVICEFILE',
+		sql => "SELECT 'connect1_1'",
+		expected_stdout => qr/connect1_1/);
+
+	$dummy_node->connect_ok(
+		'postgres://?service=my_srv',
+		'connection with correct "service" URI and PGSERVICEFILE',
+		sql => "SELECT 'connect1_2'",
+		expected_stdout => qr/connect1_2/);
+
+	$dummy_node->connect_fails(
+		'service=undefined-service',
+		'connection with incorrect "service" string and PGSERVICEFILE',
+		expected_stderr =>
+		  qr/definition of service "undefined-service" not found/);
+
+	local $ENV{PGSERVICE} = 'my_srv';
+	$dummy_node->connect_ok(
+		'',
+		'connection with correct PGSERVICE and PGSERVICEFILE',
+		sql => "SELECT 'connect1_3'",
+		expected_stdout => qr/connect1_3/);
+
+	local $ENV{PGSERVICE} = 'undefined-service';
+	$dummy_node->connect_fails(
+		'',
+		'connection with incorrect PGSERVICE and PGSERVICEFILE',
+		expected_stdout =>
+		  qr/definition of service "undefined-service" not found/);
+}
+
+# Checks case of incorrect service file.
+{
+	local $ENV{PGSERVICEFILE} = $srvfile_missing;
+	$dummy_node->connect_fails(
+		'service=my_srv',
+		'connection with correct "service" string and incorrect PGSERVICEFILE',
+		expected_stderr =>
+		  qr/service file ".*pg_service_missing.conf" not found/);
+}
+
+# Checks case of service file named "pg_service.conf" in PGSYSCONFDIR.
+{
+	# Create copy of valid file
+	my $srvfile_default = "$td/pg_service.conf";
+	copy($srvfile_valid, $srvfile_default);
+
+	$dummy_node->connect_ok(
+		'service=my_srv',
+		'connection with correct "service" string and pg_service.conf',
+		sql => "SELECT 'connect2_1'",
+		expected_stdout => qr/connect2_1/);
+
+	$dummy_node->connect_ok(
+		'postgres://?service=my_srv',
+		'connection with correct "service" URI and default pg_service.conf',
+		sql => "SELECT 'connect2_2'",
+		expected_stdout => qr/connect2_2/);
+
+	$dummy_node->connect_fails(
+		'service=undefined-service',
+		'connection with incorrect "service" string and default pg_service.conf',
+		expected_stderr =>
+		  qr/definition of service "undefined-service" not found/);
+
+	local $ENV{PGSERVICE} = 'my_srv';
+	$dummy_node->connect_ok(
+		'',
+		'connection with correct PGSERVICE and default pg_service.conf',
+		sql => "SELECT 'connect2_3'",
+		expected_stdout => qr/connect2_3/);
+
+	local $ENV{PGSERVICE} = 'undefined-service';
+	$dummy_node->connect_fails(
+		'',
+		'connection with incorrect PGSERVICE and default pg_service.conf',
+		expected_stdout =>
+		  qr/definition of service "undefined-service" not found/);
+
+	# Remove default pg_service.conf.
+	unlink($srvfile_default);
+}
+
+$node->teardown_node;
+
+done_testing();
--
2.43.5

#7Peter Eisentraut
peter@eisentraut.org
In reply to: Andrew Jackson (#2)
1 attachment(s)
Re: Update LDAP Protocol in fe-connect.c to v3

On 22.03.25 22:22, Andrew Jackson wrote:

Apologies, forgot to attach the patch in the prior email.

On Sat, Mar 22, 2025 at 4:10 PM Andrew Jackson
<andrewjackson947@gmail.com <mailto:andrewjackson947@gmail.com>> wrote:

Currently the LDAP usage in fe-connect.c does not explicitly set the
protocol version to v3. This causes issues with many LDAP servers as
they will often require clients to use the v3 protocol and disallow
any use of the v2 protocol. Further the other usage of LDAP in
postgres (in `backend/libpq/auth.c`) uses the v3 protocol.

This patch changes fe-connect.c so that it uses the v3 protocol
similar to `backend/libpq/auth.c`.

One further note is that I do not currently see any test coverage
over the LDAP functionality in `fe-connect.c`. I am happy to add
that to this patch if needed.

Here is a slightly polished version of this patch. I added an error
message, and changed the return code, but it's a bit confusing which one
might be the right one.

I also looked over the test file that you sent in a separate message.
That also looks generally ok, but I'm not so deep into LDAP right now
that I can give a detailed review.

My hunch right now is that we should probably take the patch that sets
the version option and consider it for backpatching. The patch with the
tests can be held for detailed review later.

Attachments:

v2-0001-libpq-Set-LDAP-protocol-version-3.patchtext/plain; charset=UTF-8; name=v2-0001-libpq-Set-LDAP-protocol-version-3.patchDownload
From c1e85711e1b0c7efcd1fa55cc46db959e12d6cfb Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 3 Apr 2025 15:06:13 +0200
Subject: [PATCH v2] libpq: Set LDAP protocol version 3

Some LDAP servers reject the default version 2 protocol.  So set
version 3 before starting the connection.  This matches how the
backend LDAP code has worked all along.

Co-authored-by: Andrew Jackson <andrewjackson947@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAKK5BkHixcivSCA9pfd_eUp7wkLRhvQ6OtGLAYrWC%3Dk7E76LDQ%40mail.gmail.com
---
 src/interfaces/libpq/fe-connect.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 715b5d5aff4..d45fd6bdcf9 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -5475,6 +5475,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
 			   *entry;
 	struct berval **values;
 	LDAP_TIMEVAL time = {PGLDAP_TIMEOUT, 0};
+	const int	ldapversion = LDAP_VERSION3;
 
 	if ((url = strdup(purl)) == NULL)
 	{
@@ -5606,6 +5607,15 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
 		return 3;
 	}
 
+	if ((rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
+	{
+		libpq_append_error(errorMessage, "could not set LDAP protocol version: %s",
+						   ldap_err2string(rc));
+		free(url);
+		ldap_unbind(ld);
+		return 3;
+	}
+
 	/*
 	 * Perform an explicit anonymous bind.
 	 *
-- 
2.49.0

#8Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#7)
Re: Update LDAP Protocol in fe-connect.c to v3

Peter Eisentraut <peter@eisentraut.org> writes:

Here is a slightly polished version of this patch. I added an error
message, and changed the return code, but it's a bit confusing which one
might be the right one.

I'm kind of -0.5 on declaring the variable as "const", because none of
our existing calls of ldap_set_option do that. I do see that the
Linux man page for ldap_set_option claims that that argument can be
const, but I think you're risking a portability gotcha for no large
gain. LGTM otherwise.

My hunch right now is that we should probably take the patch that sets
the version option and consider it for backpatching. The patch with the
tests can be held for detailed review later.

+1 for that plan.

regards, tom lane

#9Andrew Jackson
andrewjackson947@gmail.com
In reply to: Tom Lane (#8)
1 attachment(s)
Re: Update LDAP Protocol in fe-connect.c to v3

Here is the same patch as v2 but with "const" removed in case you want to
move forward with that change. Tested locally against the tests I wrote in
the other patch to sanity check the change.

On Thu, Apr 3, 2025 at 8:42 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Show quoted text

Peter Eisentraut <peter@eisentraut.org> writes:

Here is a slightly polished version of this patch. I added an error
message, and changed the return code, but it's a bit confusing which one
might be the right one.

I'm kind of -0.5 on declaring the variable as "const", because none of
our existing calls of ldap_set_option do that. I do see that the
Linux man page for ldap_set_option claims that that argument can be
const, but I think you're risking a portability gotcha for no large
gain. LGTM otherwise.

My hunch right now is that we should probably take the patch that sets
the version option and consider it for backpatching. The patch with the
tests can be held for detailed review later.

+1 for that plan.

regards, tom lane

Attachments:

v3-0001-libpq-Set-LDAP-protocol-version-3.patchtext/x-patch; charset=US-ASCII; name=v3-0001-libpq-Set-LDAP-protocol-version-3.patchDownload
From 4684d5cd1bc5c5150f6435bf2be1be9f957a4429 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 3 Apr 2025 15:06:13 +0200
Subject: [PATCH] libpq: Set LDAP protocol version 3

Some LDAP servers reject the default version 2 protocol.  So set
version 3 before starting the connection.  This matches how the
backend LDAP code has worked all along.

Co-authored-by: Andrew Jackson <andrewjackson947@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAKK5BkHixcivSCA9pfd_eUp7wkLRhvQ6OtGLAYrWC%3Dk7E76LDQ%40mail.gmail.com
---
 src/interfaces/libpq/fe-connect.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index ddcc7b60ab0..d9d064174de 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -5069,6 +5069,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
 			   *entry;
 	struct berval **values;
 	LDAP_TIMEVAL time = {PGLDAP_TIMEOUT, 0};
+	int	ldapversion = LDAP_VERSION3;
 
 	if ((url = strdup(purl)) == NULL)
 	{
@@ -5200,6 +5201,15 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
 		return 3;
 	}
 
+	if ((rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
+	{
+		libpq_append_error(errorMessage, "could not set LDAP protocol version: %s",
+						   ldap_err2string(rc));
+		free(url);
+		ldap_unbind(ld);
+		return 3;
+	}
+
 	/*
 	 * Perform an explicit anonymous bind.
 	 *
-- 
2.47.2

#10Pavel Seleznev
pavel.seleznev@gmail.com
In reply to: Andrew Jackson (#9)
Re: Update LDAP Protocol in fe-connect.c to v3

I applied your patch. I ran extended application tests relative to vanilla ones, which include various scenarios of working with LDAP and I think that we can safely apply the patch in the PG18.

I did not see the need for additional LDAP tests, since compatibility is provided by the LDAP library itself, and not by the Postgres code. Also protocol version 3 has been published for quite a long time (more than 20 years) and real use by clients is through version 3

#11Peter Eisentraut
peter@eisentraut.org
In reply to: Pavel Seleznev (#10)
Re: Update LDAP Protocol in fe-connect.c to v3

On 15.05.25 14:54, Pavel Seleznev wrote:

I applied your patch. I ran extended application tests relative to vanilla ones, which include various scenarios of working with LDAP and I think that we can safely apply the patch in the PG18.

I did not see the need for additional LDAP tests, since compatibility is provided by the LDAP library itself, and not by the Postgres code. Also protocol version 3 has been published for quite a long time (more than 20 years) and real use by clients is through version 3

FWIW, I'm prepared to commit this, but not for PG 18 at this point.

#12Peter Eisentraut
peter@eisentraut.org
In reply to: Peter Eisentraut (#11)
Re: Update LDAP Protocol in fe-connect.c to v3

On 23.05.25 13:51, Peter Eisentraut wrote:

On 15.05.25 14:54, Pavel Seleznev wrote:

I applied your patch. I ran extended application tests relative to
vanilla ones, which include various scenarios of working with LDAP and
I think that we can safely apply the patch in the PG18.

I did not see the need for additional LDAP tests, since compatibility
is provided by the LDAP library itself,  and not by the Postgres code.
Also  protocol version 3 has been published for quite a long time
(more than 20 years) and real use by clients is through version 3

FWIW, I'm prepared to commit this, but not for PG 18 at this point.

I have looked at this patch again. There is a CI failure on Windows,
and I was also able to reproduce this in my own CI runs, so it's not
just a fluke.

https://cirrus-ci.com/task/6576976439279616?logs=build#L1271

The whole thing is puzzling, since we use the same code in the backend,
without any Windows-specific guards. No clue.

#13Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Peter Eisentraut (#12)
Re: Update LDAP Protocol in fe-connect.c to v3

On Tue, Aug 12, 2025 at 8:37 AM Peter Eisentraut <peter@eisentraut.org> wrote:

The whole thing is puzzling, since we use the same code in the backend,
without any Windows-specific guards. No clue.

I think it's a CI-wide failure, or at least the cfbot is showing a red
column at the moment.

--Jacob

#14Andres Freund
andres@anarazel.de
In reply to: Jacob Champion (#13)
Re: Update LDAP Protocol in fe-connect.c to v3

Hi,

On 2025-08-12 08:46:00 -0700, Jacob Champion wrote:

On Tue, Aug 12, 2025 at 8:37 AM Peter Eisentraut <peter@eisentraut.org> wrote:

The whole thing is puzzling, since we use the same code in the backend,
without any Windows-specific guards. No clue.

I think it's a CI-wide failure, or at least the cfbot is showing a red
column at the moment.

See /messages/by-id/CAN55FZ1RuBhJmPWs3Oi=9UoezDfrtO-VaU67db5+0_uy19uF+A@mail.gmail.com

Greetings,

Andres Freund

#15Peter Eisentraut
peter@eisentraut.org
In reply to: Jacob Champion (#13)
Re: Update LDAP Protocol in fe-connect.c to v3

On 12.08.25 17:46, Jacob Champion wrote:

On Tue, Aug 12, 2025 at 8:37 AM Peter Eisentraut <peter@eisentraut.org> wrote:

The whole thing is puzzling, since we use the same code in the backend,
without any Windows-specific guards. No clue.

I think it's a CI-wide failure, or at least the cfbot is showing a red
column at the moment.

Ok, then I'm going to be wild and commit it anyway. Done.

#16Peter Eisentraut
peter@eisentraut.org
In reply to: Andrew Jackson (#6)
Re: Update LDAP Protocol in fe-connect.c to v3

On 01.04.25 16:19, Andrew Jackson wrote:

Added some tests for the LDAP connection parameters lookup functionality
with the attached patch. It is based off of the tests that were added
recently that cover the connection service file libpq functionality as
well as the existing ldap test framework.

I have committed this additional test file. Thanks.