On Fri, 2022-03-25 at 15:32 -0400, Robert Haas wrote:
> On Mon, Feb 28, 2022 at 3:21 PM Jacob Champion <pchamp...@vmware.com> wrote:
> > v3 rebases over Andres' changes and actually adds the Perl driver that
> > I missed the git-add for.
> 
> This seems totally reasonable. However, I think it should update the
> documentation somehow.

Done in v4.

Do I need to merge my tiny test program into the libpq_pipeline tests?
I'm not sure what the roadmap is for those.

Thanks!
--Jacob
commit 53fca988682c80a99bbb19eeb3d7959533fc3b83
Author: Jacob Champion <pchamp...@vmware.com>
Date:   Fri Mar 25 14:16:47 2022 -0700

    squash! Enable SSL library detection via PQsslAttribute()
    
    Add docs.

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 3998b1781b..82f3092715 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -2538,6 +2538,17 @@ const char *PQsslAttribute(const PGconn *conn, const 
char *attribute_name);
             Name of the SSL implementation in use. (Currently, only
             <literal>"OpenSSL"</literal> is implemented)
            </para>
+           <note>
+            <para>
+             As a special case, the <literal>library</literal> attribute may be
+             queried without an existing connection by passing NULL as the
+             <literal>conn</literal> argument. The historical behavior was to
+             return NULL for any attribute when a NULL <literal>conn</literal>
+             was provided; client programs needing to differentiate between the
+             newer and older implementations may check the
+             <literal>LIBPQ_HAS_SSL_LIBRARY_DETECTION</literal> feature macro.
+            </para>
+           </note>
           </listitem>
          </varlistentry>
         <varlistentry>
From 1ec54121dc0eeae7e48b9e38b829980e6a11e31c Mon Sep 17 00:00:00 2001
From: Jacob Champion <pchamp...@vmware.com>
Date: Mon, 29 Nov 2021 14:36:38 -0800
Subject: [PATCH v4] Enable SSL library detection via PQsslAttribute()

Currently, libpq client code must have a connection handle before it can
query the "library" SSL attribute. This poses problems if the client
needs to know what SSL library is in use before constructing a
connection string. (For example, with the NSS proposal, a client would
have to decide whether to use the "ssldatabase" connection setting
rather than "sslcert" et al.)

Allow PQsslAttribute(NULL, "library") to return the library in use --
currently, just "OpenSSL" or NULL. The new behavior is announced with
the LIBPQ_HAS_SSL_LIBRARY_DETECTION feature macro, allowing clients to
differentiate between a libpq that was compiled without SSL support and
a libpq that's just too old to tell.
---
 doc/src/sgml/libpq.sgml                  | 11 +++++++
 src/interfaces/libpq/Makefile            |  1 +
 src/interfaces/libpq/fe-secure-openssl.c |  6 ++--
 src/interfaces/libpq/libpq-fe.h          |  2 ++
 src/interfaces/libpq/t/002_api.pl        | 23 +++++++++++++++
 src/interfaces/libpq/test/.gitignore     |  1 +
 src/interfaces/libpq/test/Makefile       |  2 +-
 src/interfaces/libpq/test/testclient.c   | 37 ++++++++++++++++++++++++
 8 files changed, 79 insertions(+), 4 deletions(-)
 create mode 100644 src/interfaces/libpq/t/002_api.pl
 create mode 100644 src/interfaces/libpq/test/testclient.c

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 3998b1781b..82f3092715 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -2538,6 +2538,17 @@ const char *PQsslAttribute(const PGconn *conn, const char *attribute_name);
             Name of the SSL implementation in use. (Currently, only
             <literal>"OpenSSL"</literal> is implemented)
            </para>
+           <note>
+            <para>
+             As a special case, the <literal>library</literal> attribute may be
+             queried without an existing connection by passing NULL as the
+             <literal>conn</literal> argument. The historical behavior was to
+             return NULL for any attribute when a NULL <literal>conn</literal>
+             was provided; client programs needing to differentiate between the
+             newer and older implementations may check the
+             <literal>LIBPQ_HAS_SSL_LIBRARY_DETECTION</literal> feature macro.
+            </para>
+           </note>
           </listitem>
          </varlistentry>
         <varlistentry>
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index 3c53393fa4..89bf5e0126 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -13,6 +13,7 @@ subdir = src/interfaces/libpq
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
+export with_ssl
 
 PGFILEDESC = "PostgreSQL Access Library"
 
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index d81218a4cc..d3bf57b850 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1631,14 +1631,14 @@ PQsslAttributeNames(PGconn *conn)
 const char *
 PQsslAttribute(PGconn *conn, const char *attribute_name)
 {
+	if (strcmp(attribute_name, "library") == 0)
+		return "OpenSSL";
+
 	if (!conn)
 		return NULL;
 	if (conn->ssl == NULL)
 		return NULL;
 
-	if (strcmp(attribute_name, "library") == 0)
-		return "OpenSSL";
-
 	if (strcmp(attribute_name, "key_bits") == 0)
 	{
 		static char sslbits_str[12];
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 20eb855abc..7986445f1a 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -36,6 +36,8 @@ extern "C"
 #define LIBPQ_HAS_PIPELINING 1
 /* Indicates presence of PQsetTraceFlags; also new PQtrace output format */
 #define LIBPQ_HAS_TRACE_FLAGS 1
+/* Indicates that PQsslAttribute(NULL, "library") is useful */
+#define LIBPQ_HAS_SSL_LIBRARY_DETECTION 1
 
 /*
  * Option flags for PQcopyResult
diff --git a/src/interfaces/libpq/t/002_api.pl b/src/interfaces/libpq/t/002_api.pl
new file mode 100644
index 0000000000..bcf91bc558
--- /dev/null
+++ b/src/interfaces/libpq/t/002_api.pl
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+
+# Copyright (c) 2022, PostgreSQL Global Development Group
+
+use strict;
+use warnings;
+
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+# Test PQsslAttribute(NULL, "library")
+my ($out, $err) = run_command(['testclient', '--ssl']);
+
+if ($ENV{with_ssl} eq 'openssl')
+{
+	is($out, 'OpenSSL', 'PQsslAttribute(NULL, "library") returns "OpenSSL"');
+}
+else
+{
+	is($err, 'SSL is not enabled', 'PQsslAttribute(NULL, "library") returns NULL');
+}
+
+done_testing();
diff --git a/src/interfaces/libpq/test/.gitignore b/src/interfaces/libpq/test/.gitignore
index 5e803d8816..4b17210483 100644
--- a/src/interfaces/libpq/test/.gitignore
+++ b/src/interfaces/libpq/test/.gitignore
@@ -1 +1,2 @@
+/testclient
 /uri-regress
diff --git a/src/interfaces/libpq/test/Makefile b/src/interfaces/libpq/test/Makefile
index 5421215906..1d45be0c37 100644
--- a/src/interfaces/libpq/test/Makefile
+++ b/src/interfaces/libpq/test/Makefile
@@ -11,7 +11,7 @@ endif
 override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
 LDFLAGS_INTERNAL += $(libpq_pgport)
 
-PROGS = uri-regress
+PROGS = testclient uri-regress
 
 all: $(PROGS)
 
diff --git a/src/interfaces/libpq/test/testclient.c b/src/interfaces/libpq/test/testclient.c
new file mode 100644
index 0000000000..2c730d83fa
--- /dev/null
+++ b/src/interfaces/libpq/test/testclient.c
@@ -0,0 +1,37 @@
+/*
+ * testclient.c
+ *		A test program for the libpq public API
+ *
+ * Copyright (c) 2022, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		src/interfaces/libpq/test/testclient.c
+ */
+
+#include "postgres_fe.h"
+
+#include "libpq-fe.h"
+
+static void
+print_ssl_library()
+{
+	const char *lib = PQsslAttribute(NULL, "library");
+
+	if (!lib)
+		fprintf(stderr, "SSL is not enabled\n");
+	else
+		printf("%s\n", lib);
+}
+
+int
+main(int argc, char *argv[])
+{
+	if ((argc > 1) && !strcmp(argv[1], "--ssl"))
+	{
+		print_ssl_library();
+		return 0;
+	}
+
+	printf("currently only --ssl is supported\n");
+	return 1;
+}
-- 
2.25.1

Reply via email to