Skip to content

Commit 5c55dc8

Browse files
committed
libpq: Set Server Name Indication (SNI) for SSL connections
By default, have libpq set the TLS extension "Server Name Indication" (SNI). This allows an SNI-aware SSL proxy to route connections. (This requires a proxy that is aware of the PostgreSQL protocol, not just any SSL proxy.) In the future, this could also allow the server to use different SSL certificates for different host specifications. (That would require new server functionality. This would be the client-side functionality for that.) Since SNI makes the host name appear in cleartext in the network traffic, this might be undesirable in some cases. Therefore, also add a libpq connection option "sslsni" to turn it off. Discussion: https://www.postgresql.org/message-id/flat/7289d5eb-62a5-a732-c3b9-438cee2cb709%40enterprisedb.com
1 parent c196842 commit 5c55dc8

File tree

5 files changed

+61
-1
lines changed

5 files changed

+61
-1
lines changed

contrib/postgres_fdw/expected/postgres_fdw.out

+1-1
Original file line numberDiff line numberDiff line change
@@ -8917,7 +8917,7 @@ DO $d$
89178917
END;
89188918
$d$;
89198919
ERROR: invalid option "password"
8920-
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, sslcrldir, requirepeer, ssl_min_protocol_version, ssl_max_protocol_version, gssencmode, krbsrvname, gsslib, target_session_attrs, use_remote_estimate, fdw_startup_cost, fdw_tuple_cost, extensions, updatable, fetch_size, batch_size, async_capable, keep_connections
8920+
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, sslcrldir, sslsni, requirepeer, ssl_min_protocol_version, ssl_max_protocol_version, gssencmode, krbsrvname, gsslib, target_session_attrs, use_remote_estimate, fdw_startup_cost, fdw_tuple_cost, extensions, updatable, fetch_size, batch_size, async_capable, keep_connections
89218921
CONTEXT: SQL statement "ALTER SERVER loopback_nopw OPTIONS (ADD password 'dummypw')"
89228922
PL/pgSQL function inline_code_block line 3 at EXECUTE
89238923
-- If we add a password for our user mapping instead, we should get a different

doc/src/sgml/libpq.sgml

+31
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,27 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
17771777
</listitem>
17781778
</varlistentry>
17791779

1780+
<varlistentry id="libpq-connect-sslsni" xreflabel="sslsni">
1781+
<term><literal>sslsni</literal><indexterm><primary>Server Name Indication</primary></indexterm></term>
1782+
<listitem>
1783+
<para>
1784+
By default, libpq sets the TLS extension <quote>Server Name
1785+
Indication</quote> (SNI) on SSL-enabled connections. See <ulink
1786+
url="https://tools.ietf.org/html/rfc6066#section-3">RFC 6066</ulink>
1787+
for details. By setting this parameter to 0, this is turned off.
1788+
</para>
1789+
1790+
<para>
1791+
The Server Name Indication can be used by SSL-aware proxies to route
1792+
connections without having to decrypt the SSL stream. (Note that this
1793+
requires a proxy that is aware of the PostgreSQL protocol handshake,
1794+
not just any SSL proxy.) However, SNI makes the destination host name
1795+
appear in cleartext in the network traffic, so it might be undesirable
1796+
in some cases.
1797+
</para>
1798+
</listitem>
1799+
</varlistentry>
1800+
17801801
<varlistentry id="libpq-connect-requirepeer" xreflabel="requirepeer">
17811802
<term><literal>requirepeer</literal></term>
17821803
<listitem>
@@ -7797,6 +7818,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
77977818
</para>
77987819
</listitem>
77997820

7821+
<listitem>
7822+
<para>
7823+
<indexterm>
7824+
<primary><envar>PGSSLSNI</envar></primary>
7825+
</indexterm>
7826+
<envar>PGSSLSNI</envar> behaves the same as the <xref
7827+
linkend="libpq-connect-sslsni"/> connection parameter.
7828+
</para>
7829+
</listitem>
7830+
78007831
<listitem>
78017832
<para>
78027833
<indexterm>

src/interfaces/libpq/fe-connect.c

+6
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
303303
"SSL-Revocation-List-Dir", "", 64,
304304
offsetof(struct pg_conn, sslcrldir)},
305305

306+
{"sslsni", "PGSSLSNI", "1", NULL,
307+
"SSL-SNI", "", 1,
308+
offsetof(struct pg_conn, sslsni)},
309+
306310
{"requirepeer", "PGREQUIREPEER", NULL, NULL,
307311
"Require-Peer", "", 10,
308312
offsetof(struct pg_conn, requirepeer)},
@@ -4095,6 +4099,8 @@ freePGconn(PGconn *conn)
40954099
free(conn->sslcrldir);
40964100
if (conn->sslcompression)
40974101
free(conn->sslcompression);
4102+
if (conn->sslsni)
4103+
free(conn->sslsni);
40984104
if (conn->requirepeer)
40994105
free(conn->requirepeer);
41004106
if (conn->ssl_min_protocol_version)

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

+22
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,28 @@ initialize_SSL(PGconn *conn)
10821082
SSL_CTX_free(SSL_context);
10831083
SSL_context = NULL;
10841084

1085+
/*
1086+
* Set Server Name Indication (SNI), if enabled by connection parameters.
1087+
* Per RFC 6066, do not set it if the host is a literal IP address (IPv4
1088+
* or IPv6).
1089+
*/
1090+
if (conn->sslsni && conn->sslsni[0] &&
1091+
!(strspn(conn->pghost, "0123456789.") == strlen(conn->pghost) ||
1092+
strchr(conn->pghost, ':')))
1093+
{
1094+
if (SSL_set_tlsext_host_name(conn->ssl, conn->pghost) != 1)
1095+
{
1096+
char *err = SSLerrmessage(ERR_get_error());
1097+
1098+
appendPQExpBuffer(&conn->errorMessage,
1099+
libpq_gettext("could not set SSL Server Name Indication (SNI): %s\n"),
1100+
err);
1101+
SSLerrfree(err);
1102+
SSL_CTX_free(SSL_context);
1103+
return -1;
1104+
}
1105+
}
1106+
10851107
/*
10861108
* Read the SSL key. If a key is specified, treat it as an engine:key
10871109
* combination if there is colon present - we don't support files with

src/interfaces/libpq/libpq-int.h

+1
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ struct pg_conn
383383
char *sslrootcert; /* root certificate filename */
384384
char *sslcrl; /* certificate revocation list filename */
385385
char *sslcrldir; /* certificate revocation list directory name */
386+
char *sslsni; /* use SSL SNI extension (0 or 1) */
386387
char *requirepeer; /* required peer credentials for local sockets */
387388
char *gssencmode; /* GSS mode (require,prefer,disable) */
388389
char *krbsrvname; /* Kerberos service name */

0 commit comments

Comments
 (0)