From c0966084b91818bdf3d35e87666399c7e59298d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Renaud=20M=C3=A9trich?= Date: Mon, 15 Jun 2026 08:15:50 +0200 Subject: [PATCH v2 4/8] Load alternate certificates only for the default host context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The global ssl_alt_cert_file/ssl_alt_key_file GUCs were being loaded into every host context, including per-host SNI entries from pg_hosts.conf. This caused unintended behavior: if an SNI host used a different key type, the alt cert was added as an alternative; if the same type, it silently replaced the host cert. Add an is_default parameter to init_host_context() and only load the alternate certificate for the default host context (postgresql.conf), not for per-host SNI entries. Author: Renaud Métrich --- src/backend/libpq/be-secure-openssl.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index fa9f551e22a..6964830c5af 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -98,7 +98,7 @@ static bool initialize_dh(SSL_CTX *context, bool isServerStart); static bool initialize_ecdh(SSL_CTX *context, bool isServerStart); static const char *SSLerrmessageExt(unsigned long ecode, const char *replacement); static const char *SSLerrmessage(unsigned long ecode); -static bool init_host_context(HostsLine *host, bool isServerStart); +static bool init_host_context(HostsLine *host, bool isServerStart, bool is_default); static void host_context_cleanup_cb(void *arg); #ifdef HAVE_SSL_CTX_SET_CLIENT_HELLO_CB static int sni_clienthello_cb(SSL *ssl, int *al, void *arg); @@ -251,7 +251,7 @@ be_tls_init(bool isServerStart) { HostsLine *host = lfirst(line); - if (!init_host_context(host, isServerStart)) + if (!init_host_context(host, isServerStart, false)) goto error; /* @@ -346,7 +346,7 @@ be_tls_init(bool isServerStart) pgconf->ssl_passphrase_cmd = ssl_passphrase_command; pgconf->ssl_passphrase_reload = ssl_passphrase_command_supports_reload; - if (!init_host_context(pgconf, isServerStart)) + if (!init_host_context(pgconf, isServerStart, true)) goto error; /* @@ -655,7 +655,7 @@ host_context_cleanup_cb(void *arg) } static bool -init_host_context(HostsLine *host, bool isServerStart) +init_host_context(HostsLine *host, bool isServerStart, bool is_default) { SSL_CTX *ctx = SSL_CTX_new(SSLv23_method()); static bool init_warned = false; @@ -784,23 +784,25 @@ init_host_context(HostsLine *host, bool isServerStart) /* * Load alternate certificate (e.g. ECDSA alongside RSA) into the same * context. OpenSSL supports one certificate per key type and selects - * the appropriate one during the TLS handshake. + * the appropriate one during the TLS handshake. Only load for the + * default host context (postgresql.conf), not for per-host SNI entries + * from pg_hosts.conf. */ - if (ssl_alt_cert_file[0] && !ssl_alt_key_file[0]) + if (is_default && ssl_alt_cert_file[0] && !ssl_alt_key_file[0]) { ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("ssl_alt_cert_file is set but ssl_alt_key_file is not"))); goto error; } - if (!ssl_alt_cert_file[0] && ssl_alt_key_file[0]) + if (is_default && !ssl_alt_cert_file[0] && ssl_alt_key_file[0]) { ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("ssl_alt_key_file is set but ssl_alt_cert_file is not"))); goto error; } - if (ssl_alt_cert_file[0] && ssl_alt_key_file[0]) + if (is_default && ssl_alt_cert_file[0] && ssl_alt_key_file[0]) { if (SSL_CTX_use_certificate_chain_file(ctx, ssl_alt_cert_file) != 1) { -- 2.52.0