Enable SSL library detection via PQsslAttribute()
authorDaniel Gustafsson <dgustafsson@postgresql.org>
Tue, 29 Mar 2022 12:02:45 +0000 (14:02 +0200)
committerDaniel Gustafsson <dgustafsson@postgresql.org>
Tue, 29 Mar 2022 12:02:45 +0000 (14:02 +0200)
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.

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.

Author: Jacob Champion <pchampion@vmware.com>
Reviewed-by: Robert Haas <robertmhaas@gmail.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/4c8b76ef434a96627170a31c3acd33cbfd6e41f1.camel@vmware.com

doc/src/sgml/libpq.sgml
src/interfaces/libpq/Makefile
src/interfaces/libpq/fe-secure-openssl.c
src/interfaces/libpq/libpq-fe.h
src/interfaces/libpq/t/002_api.pl [new file with mode: 0644]
src/interfaces/libpq/test/.gitignore
src/interfaces/libpq/test/Makefile
src/interfaces/libpq/test/testclient.c [new file with mode: 0644]

index 70233aa872e71733f106cfa411e85148f3fc2cc9..eac5dee9f76ec7747c551c40406f2214785af05c 100644 (file)
@@ -2581,6 +2581,16 @@ const char *PQsslAttribute(const PGconn *conn, const char *attribute_name);
          </varlistentry>
        </variablelist>
       </para>
+
+      <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>
      </listitem>
     </varlistentry>
 
index 3c53393fa4102dac12e54b144568d2becae98ad8..89bf5e0126008e1e5a18e522798f1892af4c008c 100644 (file)
@@ -13,6 +13,7 @@ subdir = src/interfaces/libpq
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
+export with_ssl
 
 PGFILEDESC = "PostgreSQL Access Library"
 
index d81218a4ccdec9ebe6be629d6e71d6c0c2b493b5..d3bf57b850a868add1ffe8d83915eff3c8d0cd39 100644 (file)
@@ -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];
index 20eb855abc107b68e2b5dbf2b108bbc0f068aa14..7986445f1a9e07cb43fcb9d53dd45f92ffde5786 100644 (file)
@@ -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 (file)
index 0000000..7c6c578
--- /dev/null
@@ -0,0 +1,20 @@
+# 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();
index 5e803d8816a84ed80ffc90b1589ef29e2f8ccb3c..4b17210483d18935441e7bfd6787d5a84d3854d2 100644 (file)
@@ -1 +1,2 @@
+/testclient
 /uri-regress
index 54212159065e92e5be0398efd406276f06025ebd..1d45be0c375ddf6e3a1781d1153b2a07d062960e 100644 (file)
@@ -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 (file)
index 0000000..2c730d8
--- /dev/null
@@ -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;
+}