Skip site navigation (1) Skip section navigation (2)

Re: BUG #5468: Pg doesn't send accepted root CA list to client during SSL client cert request

From: Craig Ringer <craig(at)postnewspapers(dot)com(dot)au>
To: pgsql-bugs <pgsql-bugs(at)postgresql(dot)org>
Subject: Re: BUG #5468: Pg doesn't send accepted root CA list to client during SSL client cert request
Date: 2010-05-22 14:50:03
Message-ID: 4BF7EF1B.5010704@postnewspapers.com.au (view raw or flat)
Thread:
Lists: pgsql-bugs
On 22/05/10 12:01, Craig Ringer wrote:
> On 21/05/2010 10:35 PM, Magnus Hagander wrote:
 >>
>> Unfortunately, I don't think this is something we can fix as a bugfix
>> - it'll be a pretty clear change of behaviour, so I think it's
>> something we will need to push back for a full release, which would
>> mean 9.1.
>
> Urk. I think you're right, but I don't like it :S
>
> I'm working on testing a patch that gets Pg to present all trusted roots
> to the client now, and will send it in as a starting point once I've
> tested it with the clients I have on hand - PgJDBC, libpq, etc.

I've attached the patch. As you can see it's trivial, but this being 
OpenSSL a small change doesn't necessarily have a small effect. While it 
was produced against 8.4, it should apply fine against HEAD. I'm pulling 
a shallow clone now just to make sure.

In this case though, it's a call that has _absolutely_ no effect if 
'root.crt' isn't present in the data dir to tell the server to request a 
client certificate during SSL negotiations. It's never run.

If 'root.crt' _is_ present, there are no new steps in the negotiation 
behaviour, nor any new requirements of the client or server. All that 
happens is that the client is given some more information which it may 
choose to use to select an appropriate client certificate to present.

Clients that already worked didn't use this information - after all, it 
was absent from the CertificateRequest sent by the server so they 
couldn't use it if they wanted to. This includes libpq+openssl clients 
(psql, PgAdmin III, etc). It also includes Java/JDBC clients with a 
custom SSLSocketFactory that uses a custom X509KeyManager that 
unconditionally presents a single client certificate - as this was the 
only way to make client certificate authentication work in Java/PgJDBC 
without this change.

I've verified that psql (8.4.3) and PgAdmin III (1.10.2) using libpq 
8.4.3 are happy with this change, and behave no differently. See below.

I've also tested and made sure that a Java app with a 
X509KeyManager/SSLSocketFactory that unconditionally present a client 
certificate work fine (and unchanged) before and after the change. 
Though after the change the app doesn't need the custom SSLSocketFactory 
it works fine with it. I'll post an executable .jar and source .zip once 
I tidy it up a little, as it'll serve as a useful example for how to use 
libpq with client certificates - and how you *don't* need a custom 
SSLSocketFactory if Pg sends the cert list.

psqlODBC uses psql with OpenSSL so it should behave just like psql, but 
I can't find any documentation on how to use client certificates with it 
anyway.

There are a lot of other interfaces here:

   http://www.postgresql.org/download/products/2

... most of which I should be able to test given time. The problem is 
that half the time they fail to document whether they support client 
certificates at all, or how to use them, suggesting that it's likely 
nobody uses that feature with them anyway. Furthermore, many client 
interfaces are based on libpq and will inherit its client certificate 
support.



For libpq-based clients:

==== libpq NO CLIENT CERT PRESENT ====
For these, nothing is in .postgresql/ so the clients can't present a 
cert when requested.

- If no client cert is present locally but the server demands one ( 
root.crt is present and clientcert=1 is present on the matching line of 
pg_hba.conf), they successfully negotiate an SSL connection without 
presenting a client cert and are then disconnected by the server with a 
message saying a client cert is required - as expected. No change.

- If the server requests a client cert but doesn't require it ( root.crt 
is present, but clientcert=1 is not present on the matching line of 
pg_hba.conf ) they successfully negotiate SSL without presenting a 
client certificate and establish a successful connection. No change.

==== libpq CORRECT CLIENT CERT PRESENT ====
For these, a cert and key signed by a trusted root in root.crt is 
present on the client at .postgresql/postgresql.{crt,key}

- If the server demands a client cert (root.crt is present and 
clientcert=1) they present that client cert to the server, are verified, 
and connect successfully. No change.

- If the server demands a client cert (root.crt is present and 
clientcert=1) they present that client cert to the server, are verified, 
and connect successfully. No change.

==== libpq WRONG CLIENT CERT PRESENT ====
For these, a client cert and key are present in
.postgresql/postgresql.{crt,key} but they're signed by a CA not in the 
server's trusted CA list (root.crt) so they can't be verified.

- If the server demands a client cert, negotiation fails with "psql: SSL 
error: tlsv1 alert unknown ca". No change.

- If the server requests but does not demand a client cert, negotiation 
fails with "psql: SSL error: tlsv1 alert unknown ca". No change.



Once I have the Java test app and have tried the clients I can from the 
client list, I'll send this patch in properly. I'd really like it to be 
considered for 9.0, but I can see it can't really be included in 8.4 
(helpful as that'd be).

--
Craig Ringer

Attachment: postgresql-backend-send-client-trusted-roots-v1.diff
Description: text/x-patch (956 bytes)

In response to

Responses

pgsql-bugs by date

Next:From: Joshua TolleyDate: 2010-05-22 23:45:48
Subject: Re: psql or pgbouncer bug?
Previous:From: Tom MolesworthDate: 2010-05-22 14:24:49
Subject: Re: psql or pgbouncer bug?

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group