1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-16 06:01:02 +03:00

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
This commit is contained in:
Peter Eisentraut
2021-04-07 15:11:41 +02:00
parent c1968426ba
commit 5c55dc8b47
5 changed files with 61 additions and 1 deletions

View File

@ -303,6 +303,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
"SSL-Revocation-List-Dir", "", 64,
offsetof(struct pg_conn, sslcrldir)},
{"sslsni", "PGSSLSNI", "1", NULL,
"SSL-SNI", "", 1,
offsetof(struct pg_conn, sslsni)},
{"requirepeer", "PGREQUIREPEER", NULL, NULL,
"Require-Peer", "", 10,
offsetof(struct pg_conn, requirepeer)},
@ -4095,6 +4099,8 @@ freePGconn(PGconn *conn)
free(conn->sslcrldir);
if (conn->sslcompression)
free(conn->sslcompression);
if (conn->sslsni)
free(conn->sslsni);
if (conn->requirepeer)
free(conn->requirepeer);
if (conn->ssl_min_protocol_version)

View File

@ -1082,6 +1082,28 @@ initialize_SSL(PGconn *conn)
SSL_CTX_free(SSL_context);
SSL_context = NULL;
/*
* Set Server Name Indication (SNI), if enabled by connection parameters.
* Per RFC 6066, do not set it if the host is a literal IP address (IPv4
* or IPv6).
*/
if (conn->sslsni && conn->sslsni[0] &&
!(strspn(conn->pghost, "0123456789.") == strlen(conn->pghost) ||
strchr(conn->pghost, ':')))
{
if (SSL_set_tlsext_host_name(conn->ssl, conn->pghost) != 1)
{
char *err = SSLerrmessage(ERR_get_error());
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set SSL Server Name Indication (SNI): %s\n"),
err);
SSLerrfree(err);
SSL_CTX_free(SSL_context);
return -1;
}
}
/*
* Read the SSL key. If a key is specified, treat it as an engine:key
* combination if there is colon present - we don't support files with

View File

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