libpq should expose GSS-related parameters even when not implemented.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 20 Dec 2019 20:34:07 +0000 (15:34 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 20 Dec 2019 20:34:07 +0000 (15:34 -0500)
We realized years ago that it's better for libpq to accept all
connection parameters syntactically, even if some are ignored or
restricted due to lack of the feature in a particular build.
However, that lesson from the SSL support was for some reason never
applied to the GSSAPI support.  This is causing various buildfarm
members to have problems with a test case added by commit 6136e94dc,
and it's just a bad idea from a user-experience standpoint anyway,
so fix it.

While at it, fix some places where parameter-related infrastructure
was added with the aid of a dartboard, or perhaps with the aid of
the anti-pattern "add new stuff at the end".  It should be safe
to rearrange the contents of struct pg_conn even in released
branches, since that's private to libpq (and we'd have to move
some fields in some builds to fix this, anyway).

Back-patch to all supported branches.

Discussion: https://postgr.es/m/11297.1576868677@sss.pgh.pa.us

contrib/postgres_fdw/expected/postgres_fdw.out
contrib/postgres_fdw/sql/postgres_fdw.sql
doc/src/sgml/libpq.sgml
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/libpq-int.h

index 3d6e4eeea0c0bd0b9db1745aa42739d58a398276..ea67ae31d08a1d0bbaf4372873bd0ab922044ccb 100644 (file)
@@ -132,8 +132,8 @@ CREATE FOREIGN TABLE ft6 (
 -- ===================================================================
 -- tests for validator
 -- ===================================================================
--- requiressl, krbsrvname and gsslib are omitted because they depend on
--- configure options
+-- requiressl and some other parameters are omitted because
+-- valid values for them depend on configure options
 ALTER SERVER testserver1 OPTIONS (
    use_remote_estimate 'false',
    updatable 'true',
@@ -158,10 +158,10 @@ ALTER SERVER testserver1 OPTIONS (
    sslcert 'value',
    sslkey 'value',
    sslrootcert 'value',
-   sslcrl 'value'
+   sslcrl 'value',
    --requirepeer 'value',
-   -- krbsrvname 'value',
-   -- gsslib 'value',
+   krbsrvname 'value',
+   gsslib 'value'
    --replication 'value'
 );
 -- Error, invalid list syntax
@@ -8855,7 +8855,7 @@ DO $d$
     END;
 $d$;
 ERROR:  invalid option "password"
-HINT:  Valid options in this context are: service, passfile, channel_binding, connect_timeout, dbname, host, hostaddr, port, options, application_name, keepalives, keepalives_idle, keepalives_interval, keepalives_count, tcp_user_timeout, sslmode, sslcompression, sslcert, sslkey, sslrootcert, sslcrl, requirepeer, gssencmode, krbsrvname, target_session_attrs, use_remote_estimate, fdw_startup_cost, fdw_tuple_cost, extensions, updatable, fetch_size
+HINT:  Valid options in this context are: service, passfile, channel_binding, connect_timeout, dbname, host, hostaddr, port, options, application_name, keepalives, keepalives_idle, keepalives_interval, keepalives_count, tcp_user_timeout, sslmode, sslcompression, sslcert, sslkey, sslrootcert, sslcrl, requirepeer, gssencmode, krbsrvname, gsslib, target_session_attrs, use_remote_estimate, fdw_startup_cost, fdw_tuple_cost, extensions, updatable, fetch_size
 CONTEXT:  SQL statement "ALTER SERVER loopback_nopw OPTIONS (ADD password 'dummypw')"
 PL/pgSQL function inline_code_block line 3 at EXECUTE
 -- If we add a password for our user mapping instead, we should get a different
index 33307d67dafd35d220d9dc76dfa98b4c6b5b09dc..c525897a78a99e60a219bf1e238f093db37fab00 100644 (file)
@@ -145,8 +145,8 @@ CREATE FOREIGN TABLE ft6 (
 -- ===================================================================
 -- tests for validator
 -- ===================================================================
--- requiressl, krbsrvname and gsslib are omitted because they depend on
--- configure options
+-- requiressl and some other parameters are omitted because
+-- valid values for them depend on configure options
 ALTER SERVER testserver1 OPTIONS (
    use_remote_estimate 'false',
    updatable 'true',
@@ -171,10 +171,10 @@ ALTER SERVER testserver1 OPTIONS (
    sslcert 'value',
    sslkey 'value',
    sslrootcert 'value',
-   sslcrl 'value'
+   sslcrl 'value',
    --requirepeer 'value',
-   -- krbsrvname 'value',
-   -- gsslib 'value',
+   krbsrvname 'value',
+   gsslib 'value'
    --replication 'value'
 );
 
index 4325946cca3b07374df19e5e152da78017edc890..66b09da06f128c0d215b50be56c9edf660b8485f 100644 (file)
@@ -1747,8 +1747,10 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
       <term><literal>gsslib</literal></term>
       <listitem>
        <para>
-        GSS library to use for GSSAPI authentication. Only used on Windows.
-        Set to <literal>gssapi</literal> to force libpq to use the GSSAPI
+        GSS library to use for GSSAPI authentication.
+        Currently this is disregarded except on Windows builds that include
+        both GSSAPI and SSPI support.  In that case, set
+        this to <literal>gssapi</literal> to cause libpq to use the GSSAPI
         library for authentication instead of the default SSPI.
        </para>
       </listitem>
index 3ca7e0560cdd4e72990d3c70ec0cc313e8259be6..cb3c431e32843eb430b549a73405e201325ef20f 100644 (file)
@@ -304,6 +304,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
        "SSL-Client-Key", "", 64,
    offsetof(struct pg_conn, sslkey)},
 
+   {"sslpassword", NULL, NULL, NULL,
+       "SSL-Client-Key-Password", "*", 20,
+   offsetof(struct pg_conn, sslpassword)},
+
    {"sslrootcert", "PGSSLROOTCERT", NULL, NULL,
        "SSL-Root-Certificate", "", 64,
    offsetof(struct pg_conn, sslrootcert)},
@@ -317,30 +321,21 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
    offsetof(struct pg_conn, requirepeer)},
 
    /*
-    * Expose gssencmode similarly to sslmode - we can still handle "disable"
-    * and "prefer".
+    * As with SSL, all GSS options are exposed even in builds that don't have
+    * support.
     */
    {"gssencmode", "PGGSSENCMODE", DefaultGSSMode, NULL,
        "GSSENC-Mode", "", 7,   /* sizeof("disable") == 7 */
    offsetof(struct pg_conn, gssencmode)},
 
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
    /* Kerberos and GSSAPI authentication support specifying the service name */
    {"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
        "Kerberos-service-name", "", 20,
    offsetof(struct pg_conn, krbsrvname)},
-#endif
-
-#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
 
-   /*
-    * GSSAPI and SSPI both enabled, give a way to override which is used by
-    * default
-    */
    {"gsslib", "PGGSSLIB", NULL, NULL,
        "GSS-library", "", 7,   /* sizeof("gssapi") = 7 */
    offsetof(struct pg_conn, gsslib)},
-#endif
 
    {"replication", NULL, NULL, NULL,
        "Replication", "D", 5,
@@ -351,10 +346,6 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
        "Target-Session-Attrs", "", 11, /* sizeof("read-write") = 11 */
    offsetof(struct pg_conn, target_session_attrs)},
 
-   {"sslpassword", NULL, NULL, NULL,
-       "SSL-Client-Key-Password", "*", 20,
-   offsetof(struct pg_conn, sslpassword)},
-
    /* Terminating entry --- MUST BE LAST */
    {NULL, NULL, NULL, NULL,
    NULL, NULL, 0}
@@ -3983,6 +3974,8 @@ freePGconn(PGconn *conn)
        free(conn->sslcert);
    if (conn->sslkey)
        free(conn->sslkey);
+   if (conn->sslpassword)
+       free(conn->sslpassword);
    if (conn->sslrootcert)
        free(conn->sslrootcert);
    if (conn->sslcrl)
@@ -3991,14 +3984,14 @@ freePGconn(PGconn *conn)
        free(conn->sslcompression);
    if (conn->requirepeer)
        free(conn->requirepeer);
-   if (conn->connip)
-       free(conn->connip);
    if (conn->gssencmode)
        free(conn->gssencmode);
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
    if (conn->krbsrvname)
        free(conn->krbsrvname);
-#endif
+   if (conn->gsslib)
+       free(conn->gsslib);
+   if (conn->connip)
+       free(conn->connip);
 #ifdef ENABLE_GSS
    if (conn->gcred != GSS_C_NO_CREDENTIAL)
    {
@@ -4014,10 +4007,6 @@ freePGconn(PGconn *conn)
        gss_delete_sec_context(&minor, &conn->gctx, GSS_C_NO_BUFFER);
        conn->gctx = NULL;
    }
-#endif
-#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
-   if (conn->gsslib)
-       free(conn->gsslib);
 #endif
    /* Note that conn->Pfdebug is not ours to close or free */
    if (conn->last_query)
@@ -4034,8 +4023,6 @@ freePGconn(PGconn *conn)
        free(conn->target_session_attrs);
    termPQExpBuffer(&conn->errorMessage);
    termPQExpBuffer(&conn->workBuffer);
-   if (conn->sslpassword)
-       free(conn->sslpassword);
 
    free(conn);
 
index 7f5be7db7a1aa5da3036704fd1c81fd132617a08..e99cbf3739ed5170d115afa225dabea256c7ec30 100644 (file)
@@ -359,13 +359,14 @@ struct pg_conn
    char       *sslcompression; /* SSL compression (0 or 1) */
    char       *sslkey;         /* client key filename */
    char       *sslcert;        /* client certificate filename */
+   char       *sslpassword;    /* client key file password */
    char       *sslrootcert;    /* root certificate filename */
    char       *sslcrl;         /* certificate revocation list filename */
    char       *requirepeer;    /* required peer credentials for local sockets */
-
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
+   char       *gssencmode;     /* GSS mode (require,prefer,disable) */
    char       *krbsrvname;     /* Kerberos service name */
-#endif
+   char       *gsslib;         /* What GSS library to use ("gssapi" or
+                                * "sspi") */
 
    /* Type of connection to make.  Possible values: any, read-write. */
    char       *target_session_attrs;
@@ -484,7 +485,6 @@ struct pg_conn
 #endif                         /* USE_OPENSSL */
 #endif                         /* USE_SSL */
 
-   char       *gssencmode;     /* GSS mode (require,prefer,disable) */
 #ifdef ENABLE_GSS
    gss_ctx_id_t gctx;          /* GSS context */
    gss_name_t  gtarg_nam;      /* GSS target name */
@@ -496,10 +496,6 @@ struct pg_conn
 #endif
 
 #ifdef ENABLE_SSPI
-#ifdef ENABLE_GSS
-   char       *gsslib;         /* What GSS library to use ("gssapi" or
-                                * "sspi") */
-#endif
    CredHandle *sspicred;       /* SSPI credentials handle */
    CtxtHandle *sspictx;        /* SSPI context */
    char       *sspitarget;     /* SSPI target name */
@@ -512,8 +508,6 @@ struct pg_conn
 
    /* Buffer for receiving various parts of messages */
    PQExpBufferData workBuffer; /* expansible string */
-
-   char *sslpassword; /* client key file password */
 };
 
 /* PGcancel stores all data necessary to cancel a connection. A copy of this