Hello 


I would like to share a patch that adds a feature to libpq to automatically 
select the best client certificate to send to the server (if it requests one). 
This feature is inspired by this email discussion years ago: 
https://www.postgresql.org/message-id/200905081539.n48Fdl2Y003286%40no.baka.org.
 This feature is useful if libpq client needs to communicate with multiple 
TLS-enabled PostgreSQL servers with different TLS certificate setups. Instead 
of letting the application to figure out the right certificate for the right 
server, the patch allows libpq library itself to pick the most ideal client 
certificate to send to the server.



Currently, we rely on options “sslcert” and “sslkey” parameters on the client 
side to select a client certificate + private key to send to the server, the 
patch adds 2 new options. “sslcertdir” and “sslkeydir” to specify directories 
where all possible certificate and private key files are stored. The new 
options cannot be used with “sslcert” and “sslkey” at the same time.



The most ideal certificate selection is based on the trusted CA names sent by 
the server in “Certificate Request” handshake message; obtained by the client 
making a call to “SSL_get0_peer_CA_list()” function. This list of trusted CA 
names tells the client the list of “issuers” that this server can trust. Inside 
“sslcertdir”, If a client certificate candidate’s issuer name equals to one of 
the trusted CA names, then that is the certificate to use. Once a candidate 
certificate is identified, the patch will then look for a matching private key 
in “sslkeydir”. These actions are performed in certificate callback function 
(cert_cb), which gets called when server requests a client certificate during 
TLS handshake.



This patch requires OpenSSL version 1.1.1 or later to work. The feature will be 
disabled with older OpenSSL versions. Attached is a POC patch containing the 
described feature.



Limitations:



One limitation of this feature is that it does not quite support the case where 
multiple private key files inside “sslkeydir” are encrypted with different 
passwords. When the client wants to find a matching private key from 
“sslkeydir”, it will always use the same password supplied by the client (via 
“sslpassword” option) to decrypt the private key it tries to access.





Also, no tap tests have been added to the patch to test this feature yet. So, 
to test this feature, we will need to prepare the environment manually:



1. generate 2 root CA certificates (ca1 and ca2), which sign 2 sets of client 
and server certificates.

2. configure the server to use a server certificate signed by either ca1 or ca2.

3. put all client certificates and private keys (signed by both ca1 and ca2) 
into a directory (we will point"sslcertdir" and "sslkeydir" to this directory)

4. based on the root CA certificate configured at the server side, the client 
will pick the certificate that the server can trust from specified "sslcertdir" 
and "sslkeydir" directories



Please let me know what you think. Any comments / feedback are greatly 
appreciated.



Best regards



================
Cary Huang

Highgo Software (Canada)

www.highgo.ca

Attachment: v1-0001-multiple_client_certificate_selection_support.patch
Description: Binary data

Reply via email to