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.

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
This commit is contained in:
Daniel Gustafsson 2022-03-29 14:02:45 +02:00
parent 8cd7627c7b
commit ebc8b7d441
8 changed files with 75 additions and 4 deletions

View 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>

View File

@ -13,6 +13,7 @@ subdir = src/interfaces/libpq
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
export with_ssl
PGFILEDESC = "PostgreSQL Access Library"

View 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];

View 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

View File

@ -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();

View File

@ -1 +1,2 @@
/testclient
/uri-regress

View 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)

View File

@ -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;
}