Fix bogus behavior of PQsslAttribute(conn, "library").
authorTom Lane <[email protected]>
Thu, 29 Sep 2022 21:28:09 +0000 (17:28 -0400)
committerTom Lane <[email protected]>
Thu, 29 Sep 2022 21:28:09 +0000 (17:28 -0400)
Commit ebc8b7d44 intended to change the behavior of
PQsslAttribute(NULL, "library"), but accidentally also changed
what happens with a non-NULL conn pointer.  Undo that so that
only the intended behavior change happens.  Clarify some
associated documentation.

Per bug #17625 from Heath Lord.  Back-patch to v15.

Discussion: https://postgr.es/m/17625-fc47c78b7d71b534@postgresql.org

doc/src/sgml/libpq.sgml
src/interfaces/libpq/fe-secure-openssl.c

index 57bfc8fc714d59f9be7918744b81071d449a1d1d..8908f775df3155fdc70f857faabcf1ccd898772c 100644 (file)
@@ -2514,8 +2514,9 @@ const char *PQsslAttribute(const PGconn *conn, const char *attribute_name);
 
       <para>
        The list of available attributes varies depending on the SSL library
-       being used, and the type of connection. If an attribute is not
-       available, returns NULL.
+       being used and the type of connection.  Returns NULL if the connection
+       does not use SSL or the specified attribute name is not defined for the
+       library in use.
       </para>
 
       <para>
@@ -2574,12 +2575,15 @@ const char *PQsslAttribute(const PGconn *conn, const char *attribute_name);
 
       <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.
+       queried without a connection by passing NULL as
+       the <literal>conn</literal> argument.  The result will be the default
+       SSL library name, or NULL if <application>libpq</application> was
+       compiled without any SSL support.  (Prior
+       to <productname>PostgreSQL</productname> version 15, passing NULL as
+       the <literal>conn</literal> argument always resulted in NULL.
+       Client programs needing to differentiate between the newer and older
+       implementations of this case may check the
+       <literal>LIBPQ_HAS_SSL_LIBRARY_DETECTION</literal> feature macro.)
       </para>
      </listitem>
     </varlistentry>
@@ -2588,7 +2592,8 @@ const char *PQsslAttribute(const PGconn *conn, const char *attribute_name);
      <term><function>PQsslAttributeNames</function><indexterm><primary>PQsslAttributeNames</primary></indexterm></term>
      <listitem>
       <para>
-       Return an array of SSL attribute names available. The array is terminated by a NULL pointer.
+       Returns an array of SSL attribute names available.
+       The array is terminated by a NULL pointer.
 <synopsis>
 const char * const * PQsslAttributeNames(const PGconn *conn);
 </synopsis>
@@ -2600,8 +2605,10 @@ const char * const * PQsslAttributeNames(const PGconn *conn);
      <term><function>PQsslStruct</function><indexterm><primary>PQsslStruct</primary></indexterm></term>
      <listitem>
       <para>
-       Return a pointer to an SSL-implementation-specific object describing
-       the connection.
+       Returns a pointer to an SSL-implementation-specific object describing
+       the connection.  Returns NULL if the connection is not encrypted
+       or the requested type of object is not available from the connection's
+       SSL implementation.
 <synopsis>
 void *PQsslStruct(const PGconn *conn, const char *struct_name);
 </synopsis>
@@ -2609,8 +2616,9 @@ void *PQsslStruct(const PGconn *conn, const char *struct_name);
       <para>
        The struct(s) available depend on the SSL implementation in use.
        For <productname>OpenSSL</productname>, there is one struct,
-       available under the name "OpenSSL", and it returns a pointer to the
-       <productname>OpenSSL</productname> <literal>SSL</literal> struct.
+       available under the name <literal>OpenSSL</literal>,
+       and it returns a pointer to
+       <productname>OpenSSL</productname>'s <literal>SSL</literal> struct.
        To use this function, code along the following lines could be used:
 <programlisting><![CDATA[
 #include <libpq-fe.h>
@@ -2643,7 +2651,7 @@ void *PQsslStruct(const PGconn *conn, const char *struct_name);
      <listitem>
       <para>
        <indexterm><primary>SSL</primary><secondary sortas="libpq">in libpq</secondary></indexterm>
-       Returns the SSL structure used in the connection, or null
+       Returns the SSL structure used in the connection, or NULL
        if SSL is not in use.
 
 <synopsis>
index aea4661736cb83d25427beefbefd1b3b9e97de9b..74b5c5987a68edb5f6c6c101560cbe0f89955ae1 100644 (file)
@@ -1745,14 +1745,21 @@ PQsslAttributeNames(PGconn *conn)
 const char *
 PQsslAttribute(PGconn *conn, const char *attribute_name)
 {
-   if (strcmp(attribute_name, "library") == 0)
-       return "OpenSSL";
-
    if (!conn)
+   {
+       /* PQsslAttribute(NULL, "library") reports the default SSL library */
+       if (strcmp(attribute_name, "library") == 0)
+           return "OpenSSL";
        return NULL;
+   }
+
+   /* All attributes read as NULL for a non-encrypted connection */
    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];