libpq should expose GSS-related parameters even when not implemented.

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
This commit is contained in:
Tom Lane 2019-12-20 15:34:07 -05:00
parent 77f416af6e
commit e60b480d39
5 changed files with 31 additions and 48 deletions

View 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

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

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

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

View 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