-
Notifications
You must be signed in to change notification settings - Fork 389
Description
Motivation and situation
OpenSSL 1.1.1 as used in pg13-14 is unsupported since Sep. 2023. 3.0 is the current LTS supported till Sep. 2026. It is still uncertain if 3.3 or 3.4 will be the next LTS. We use 3.0 in pg15-16 and 3.3 in pg17.
With the update to 3.0 we can support pg13 till EOL and update pg14 together with 15-16/17 to the next LTS in autumn 2026.
Our build of OpenSSL is used for PostgreSQL itself (client and server), the pgcrypto
extension and since the pg16 bundle also for GDAL. We do not ship the openssl
binaries, only the libraries.
Migration issues
All components are compatible with OpenSSL 3 like they were with 1.1.1 but the algorithms supported differ between them. Many older ones are now 'legacy' and not enabled by default. Postgres.app users may depend on them with their pg13-14 setup (not >= pg15 as we always shipped these with OpenSSL 3 and legacy disabled) Possible uses include:
pgcrypto
:- digest like
md4
- ciphers like DES:
3des
or Blowfishbf
for PGP or raw encryption
- digest like
libpq
when connecting to an remote server using legacy ciphers- Postgres
- even in the default configuration of GUC ssl_ciphers DES is included
To ensure a smooth migration for existing users, I'd like to enable the Legacy provider by default for OpenSSL 3 in pg13-14 so the bundle behaves most similar to the bundle with OpenSSL 1.1.1.
Problem
OpenSSL providers cannot be defined at compile time but only activated at runtime. The providers activated by default are configured in a config file openssl.cnf
which is read from OpenSSL's OPENSSLDIR, the same directory the bundle of CA-Certs cert.pem
is loaded from. While alle three can be modified by environment variables OPENSSLDIR
, OPENSSL_CONF
and SSL_CERT_FILE
, only the OPENSSLDIR
can be set at compile time. We would like to use the cert.pem
from the OS but activate the legacy provider in openssl.cnf
.
Possible solutions
use system OPENSSLDIR and instruct user
Build with --openssldir=/private/etc/ssl
and simply instruct the user to prepend some config to /etc/ssl/openssl.cnf
(root required). This would however have an influence on the behaviour of non-Postgres.app openssl
3 and effectively break openssl
<3 incl. the system provided 0.9.8 / LibreSSL due to its different syntax. For this reason, we should probably rethink the approach of 6f20a05 in general!
openssl_conf = openssl_init
[openssl_init]
providers = providers
[providers]
default = provider_default
legacy = provider_legacy
[provider_default]
activate = 1
[provider_legacy]
activate = 1
use system OPENSSLDIR, alter default OPENSSL_CONF filename, instruct user
Build with --openssldir=/private/etc/ssl
and patch ./include/internal/cryptlib.h
to use a different filename like openssl-3.cnf
for OPENSSL_CONF
. Then instruct the user to copy a prepared file to /etc/ssl
(root required).
use system OPENSSLDIR, load OPENSSL_CONF from the bundle
Build with --openssldir=/private/etc/ssl
, patch /crypto/conf/conf_mod.c
's CONF_get1_default_config_file
to load OPENSSL_CONF
from a fix directory in $(PREFIX)
and place a openssl.cnf
like above in that directory, potentially with a .include /etc/ssl/openss.cnf
.
have a local OPENSSLDIR and symlink SSL_CERT_FILE
Compile with --openssldir=$(PREFIX)/share/ssl
(is share
a good fit?) and place a openssl.cnf
like above in that directory, potentially with a .include /etc/ssl/openss.cnf
. To support sslrootcert=system
(>= pg16), add a symlink to /private/etc/cert.pem
in that directory.
This does not work when Postgres.app is relocated: legacy provider and system certificates would be unavailable or taken from the bundle at the default location.
have a local OPENSSLDIR and alter default SSL_CERT_FILE path
Like above but patch ./include/internal/cryptlib.h
to use a hardcoded value for X509_CERT_FILE
instead of OPENSSLDIR "/cert.pem"
replaceing the symlink.
Discussion
All solutions found so far have pros and cons. If relocatibilty of Postgres.app is concern, further investigations are necessary to ensure OpenSSL finds its ENGINESDIR
and MODULESDIR
within the correct bundle. I'm not sure how common / supported it is to place certificates used with PostgreSQL in /etc/ssl/certs
.
While the branch openssl-3
currently implements the "have a local OPENSSLDIR and symlink SSL_CERT_FILE" approach, I tend to like the "use system OPENSSLDIR, load OPENSSL_CONF from the bundle" approach better.
Validation
- Show default directories:
/Applications/Postgres.app/Contents/Versions/14/bin/openssl version -a
- List active providers:
/Applications/Postgres.app/Contents/Versions/14/bin/openssl list -providers
- Test a legacy digest:
echo "content" | /Applications/Postgres.app/Contents/Versions/14/bin/openssl dgst -md4
- Test
pgcrypto
with a legacy digest (runCREATE EXTENSION pgcrypto;
before):
/Applications/Postgres.app/Contents/Versions/14/bin/psql -c "SELECT digest('content', 'md4');"
- Test
pgcrypto
with a legacy cipher:
SELECT encrypt('content', 'secret', 'bf');