Re: Serverside SNI support in libpq
Jacob Champion <jacob.champion@enterprisedb.com>
From: Jacob Champion <jacob.champion@enterprisedb.com>
To: Daniel Gustafsson <daniel@yesql.se>
Cc: Jelte Fennema-Nio <postgres@jeltef.nl>,
Heikki Linnakangas <hlinnaka@iki.fi>, Dewei Dai <daidewei1970@163.com>, "li.evan.chao" <li.evan.chao@gmail.com>, Michael Paquier <michael@paquier.xyz>, Andres Freund <andres@anarazel.de>, Pgsql Hackers <pgsql-hackers@lists.postgresql.org>
Date: 2026-01-16T23:44:55Z
Lists: pgsql-hackers
[skipping right to the weird part, will circle back to the other questions later] On Tue, Jan 13, 2026 at 1:57 AM Daniel Gustafsson <daniel@yesql.se> wrote: > I think the attached is pretty clear improvement over the previous version so > thanks for the review suggestions. That being said, the test which was > reported to still fail upstream is failing here as well (it does the right > thing with the connection, but terminates the handshake in a different place). > In an attempt to fix that I moved to using the ClientHello callback which > OpenSSL document to be the right one (yet they use the servername callback > themselves), but it renders the same result. I hope that your eagle eyes (or > someone elses) can figure out either what is wrong, or if this is a different > form of right. The same failing test is added to 0001 to run it in a strictly > non-SNI config as well. I hadn't realized that this also regressed without SNI! That helped a lot. With 0001, the bug is this diff, which runs the verify_cb regardless of the ssl_ca setting: > - SSL_CTX_set_verify(context, > - (SSL_VERIFY_PEER | > - SSL_VERIFY_CLIENT_ONCE), > - verify_cb); > } > > + /* > + * Always ask for SSL client cert, but don't fail if it's not presented. > + * We might fail such connections later, depending on what we find in > + * pg_hba.conf. > + */ > + SSL_CTX_set_verify(context, > + (SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE), > + verify_cb); 0002 undid that but reintroduced it in be_tls_open_server(): > /* enable ALPN */ > SSL_CTX_set_alpn_select_cb(SSL_context, alpn_cb, port); > > + SSL_CTX_set_verify(SSL_context, > + (SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE), > + verify_cb); If I remove that diff, the regression goes away. But then we start failing SNI tests: > [14:24:05.901](0.000s) not ok 72 - host: 'example.com', ca: 'root+client_ca.crt': connect with sslcert, client certificate sent: no stderr > [14:24:05.902](0.000s) # Failed test 'host: 'example.com', ca: 'root+client_ca.crt': connect with sslcert, client certificate sent: no stderr' > # at src/test/ssl/t/004_sni.pl line 314. > [14:24:05.902](0.000s) # got: 'psql: error: connection to server at "127.0.0.1", port 15428 failed: FATAL: connection requires a valid client certificate' > # expected: '' > [14:24:05.917](0.000s) not ok 76 - host: 'example.net', ca: 'root+server_ca.crt': connect with sslcert, client certificate sent: matches > [14:24:05.917](0.000s) # Failed test 'host: 'example.net', ca: 'root+server_ca.crt': connect with sslcert, client certificate sent: matches' > # at ssl/t/004_sni.pl line 327. > [14:24:05.917](0.000s) # 'psql: error: connection to server at "127.0.0.1", port 15428 failed: FATAL: connection requires a valid client certificate' > # doesn't match '(?^:unknown ca)' I think the root problem probably comes back to SSL_set_SSL_CTX [1]. That copies the certificate over from the new SSL_CTX, but it doesn't really seem to care about much else, and there are a _lot_ of settings copied into the SSL pointer during initial connection [2] that are ignored there. The verify mode and callback are two such settings. So is the password callback (which may mean that the new per-host-line logic for openssl_tls_init_hook won't work correctly either). So unless Matt Caswell knows of an existing API that does this right, I think I'm coming back to the idea that we should keep a single SSL_CTX, and then use the selected HostsLine to override individual connection settings during the clienthello/servername callback. Do we give anything up with that approach? --Jacob [1] https://postgr.es/m/CAOYmi%2Bk%3DVF-2BCqfR49A92tx%3D_QNuL%3D3iT3w6FysOffKw9cxDQ%40mail.gmail.com [2] https://github.com/openssl/openssl/blob/5d401004a0/ssl/ssl_lib.c#L731
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Declare load_hosts() as returning HostsFileLoadResult.
- 93da29736649 19 (unreleased) landed
-
ssl: Skip passphrase reload tests in EXEC_BACKEND builds
- e87ab5049deb 19 (unreleased) landed
-
ssl: Serverside SNI support for libpq
- 4f433025f666 19 (unreleased) landed
-
ssl: Add tests for client CA
- 25e568ba7ce7 19 (unreleased) landed