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
Views: Raw Message | Whole Thread | Download mbox | Resend email
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 Content-Type Size
postgresql-backend-send-client-trusted-roots-v1.diff text/x-patch 956 bytes

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Joshua Tolley 2010-05-22 23:45:48 Re: psql or pgbouncer bug?
Previous Message Tom Molesworth 2010-05-22 14:24:49 Re: psql or pgbouncer bug?