Re: [HACKERS] libpq should not be using SSL_CTX_set_client_cert_cb

2010-05-26 Thread Garick Hamlin
On Tue, May 25, 2010 at 10:29:07PM -0400, Tom Lane wrote:
 I've been experimenting with SSL setups involving chains of CA
 certificates, ie, where the server or client cert itself is signed by
 an intermediate CA rather than a trusted root CA.  This appears to work
 well enough on the server side if you configure the server correctly
 (see discussion of bug #5468).  However, libpq is not able to work with
 a client certificate unless that cert is directly signed by a CA that
 the server trusts (ie, one listed directly in the server's root.crt file).
 This is because there is no good way to feed back any intermediate CA
 certs to the server.  The man page for SSL_CTX_set_client_cert_cb says
 in so many words that the client_cert_cb API is maldesigned:

I don't understand the problem (I don't know the code).  

However, requiring intermediate certs be prepopulated in a trust store will 
effectively make use cases like Bridged PKI not practical.  (and think that 
use cases like that will be very interesting as things like various PIV 
Cards projects are implemented).  

InCommon is also rolling out personal and machine certificates soon and 
there are some potentially similar use cases there for educational 
communities.  Their offering is not a bridge (although some users could
join a bridge), but there will likely be many different intermediate CA
created and likely created on a regular basis so the same issue exists.

Ideally, I think the client code should be able to compute a path to an
offered Trust Anchor and present it.  The server should not have to store 
and keep up-to-date the entire bridge's repository to authenticate any user. 
This would be the right way, IMO.

It should be easy for the client to build a path: they have the Trust Anchor 
in their store along with whatever intermediate certs they need otherwise
their cert would be less than useful.  They just need to send that chain.

I am guessing the problem is that validating the presented chain is hard?  
or am I misunderstanding the reason to want to nail down all the 
intermediates ahead of time.  

Again, I am not very familiar with what that code does currently

Garick

 
   BUGS
 
   The client_cert_cb() cannot return a complete certificate chain,
   it can only return one client certificate. If the chain only has
   a length of 2, the root CA certificate may be omitted according
   to the TLS standard and thus a standard conforming answer can be
   sent to the server. For a longer chain, the client must send the
   complete chain (with the option to leave out the root CA
   certificate). This can only be accomplished by either adding the
   intermediate CA certificates into the trusted certificate store
   for the SSL_CTX object (resulting in having to add CA
   certificates that otherwise maybe would not be trusted), or by
   adding the chain certificates using the
   SSL_CTX_add_extra_chain_cert(3) function, which is only
   available for the SSL_CTX object as a whole and that therefore
   probably can only apply for one client certificate, making the
   concept of the callback function (to allow the choice from
   several certificates) questionable.
 
 It strikes me that we could not only fix this case, but make the libpq
 code simpler and more like the backend case, if we got rid of
 client_cert_cb and instead preloaded the ~/.postgresql/postgresql.crt
 file using SSL_CTX_use_certificate_chain_file().  Then, using an
 indirectly signed client cert would only require including the full cert
 chain in that file.
 
 So I'm wondering if there was any specific reason behind using the
 callback API to start with.  Anybody remember?
 
   regards, tom lane
 
 -- 
 Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
 To make changes to your subscription:
 http://www.postgresql.org/mailpref/pgsql-hackers

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] libpq should not be using SSL_CTX_set_client_cert_cb

2010-05-26 Thread Tom Lane
Garick Hamlin gham...@isc.upenn.edu writes:
 I am guessing the problem is that validating the presented chain is hard?  

No, the problem is that the current libpq code fails to present the
chain at all.  It will only load and send the first cert in the
postgresql.crt file.  This works only when the client's cert is signed
directly by one of the CAs trusted by the server.

regards, tom lane

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] libpq should not be using SSL_CTX_set_client_cert_cb

2010-05-26 Thread Garick Hamlin
On Wed, May 26, 2010 at 10:54:42AM -0400, Tom Lane wrote:
 Garick Hamlin gham...@isc.upenn.edu writes:
  I am guessing the problem is that validating the presented chain is hard?  
 
 No, the problem is that the current libpq code fails to present the
 chain at all.  It will only load and send the first cert in the
 postgresql.crt file.  This works only when the client's cert is signed
 directly by one of the CAs trusted by the server.

Sorry, I just re-read your original message.  You were clear, but I read
it wrong.

This is much less limiting than what I thought was being suggested.  Having 
a user's credentials work with only one trust anchor isn't that bad.  I am 
not familiar enough with openssl to know if there is a specific pitfall to
the change you suggested (which I think was what you were asking)..

One could make it work with multiple TAs in a similar fashion if it also 
checked for the existence of a directory (like: ~/.postgresql/client_ta ) to 
store chains to each supported TA by fingerprint.  

That might not be worth the effort at this point...

Garick

 
   regards, tom lane

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] libpq should not be using SSL_CTX_set_client_cert_cb

2010-05-26 Thread Tom Lane
Garick Hamlin gham...@isc.upenn.edu writes:
 One could make it work with multiple TAs in a similar fashion if it also 
 checked for the existence of a directory (like: ~/.postgresql/client_ta ) to 
 store chains to each supported TA by fingerprint.  

 That might not be worth the effort at this point...

I'm inclined to think not.  You can instruct libpq to send a non-default
certificate file by setting its sslcert/sslkey parameters, and I think
what people would typically do is just treat those as known properties
of each server connection they have to deal with.  Implementing cert
selection logic inside libpq would simplify such cases, but I can't see
that anybody is likely to get around to that anytime soon.

Chained certs, on the other hand, definitely are in use in the real
world, so we'd better fix libpq to handle that case.

regards, tom lane

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] libpq should not be using SSL_CTX_set_client_cert_cb

2010-05-26 Thread Tom Lane
I wrote:
 It strikes me that we could not only fix this case, but make the libpq
 code simpler and more like the backend case, if we got rid of
 client_cert_cb and instead preloaded the ~/.postgresql/postgresql.crt
 file using SSL_CTX_use_certificate_chain_file().

Just for the archives: I've applied a patch along that line, but it made
me realize afresh what an ugly kluge OpenSSL's API is.  Unless I've
missed something basic, it's only possible to load additional certs for
a cert chain into an SSL_CTX object, not an SSL object.  (This is
reflected in the fact that SSL_CTX_use_certificate_chain_file doesn't
have an SSL-object equivalent, and even more fundamentally that
SSL_CTX_add_extra_chain_cert doesn't either.)  Basically, certificate
stores are managed at the SSL_CTX level not as part of SSL objects.

This is a problem for libpq because it tries to maintain only one
SSL_CTX object per client-side process: if you have multiple PG
connections in a single client process, either concurrently or one 
after another, they all share the same SSL_CTX.  Now that doesn't
matter so long as all the connections use the same
sslcert/sslkey/sslrootcert/sslcrl settings, but what if they don't?

What will happen as things stand is that all the certs get loaded
into a common pool.  That's not too horrible as long as there are
not actual conflicts, but it could mean that for example some
connections trust CA certs that the app programmer expected to only
be trusted for other connections.  I did arrange (and test) that the
client cert and key are local to each connection, but leakage of
trusted root certs is a different story.

We could avoid this problem if we were willing to set up a separate
SSL_context for each connection, but I'm not sure if it's worth that.
The scenario where a single application process is managing multiple
distinct sets of trusted certs seems a bit far-fetched anyway.

Comments?

regards, tom lane

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] libpq should not be using SSL_CTX_set_client_cert_cb

2010-05-26 Thread Craig Ringer

On 27/05/10 10:21, Tom Lane wrote:


What will happen as things stand is that all the certs get loaded
into a common pool.  That's not too horrible as long as there are
not actual conflicts, but it could mean that for example some
connections trust CA certs that the app programmer expected to only
be trusted for other connections.  I did arrange (and test) that the
client cert and key are local to each connection, but leakage of
trusted root certs is a different story.



We could avoid this problem if we were willing to set up a separate
SSL_context for each connection, but I'm not sure if it's worth that.
The scenario where a single application process is managing multiple
distinct sets of trusted certs seems a bit far-fetched anyway.


OpenSSL really doesn't seem to be designed for multiple truly 
independent SSL contexts. The SSL context stuff has clearly been hacked 
on after the fact to a library that started out having only one global 
state, and it's pretty incomplete. I'm honestly not sure it's worth 
trying to allow per-connection trust going, especially as (AFAIK) 
there's no evidence that anybody _wants_ per-client-connection SSL trust 
anyway.


If I really needed that sort of thing, I'd try to abstract the OpenSSL 
stuff away a layer, so it could be replaced by Mozilla NSS (or GnuTLS, 
or whatever) if an application needed it. This would make it easier to 
use libpq in apps that already have their own SSL/TLS environment based 
on a different library, and would make it possible for apps to use more 
flexible libraries if they needed to do complex things with SSL/TLS.


Really, though, is it necessary? What's the use case for trusting one 
cert for one connection, and another cert for another connection, beyond 
what's already provided by 'verify-full' in terms of hostname/ip 
checking? It *is* possible in more sophisticated APIs (Java, NSS too I 
think) but it's hard to imagine client-side reasons to use it.


(Or have I misunderstood what you're describing?)

--
Craig Ringer

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] libpq should not be using SSL_CTX_set_client_cert_cb

2010-05-26 Thread Tom Lane
Craig Ringer cr...@postnewspapers.com.au writes:
 On 27/05/10 10:21, Tom Lane wrote:
 What will happen as things stand is that all the certs get loaded
 into a common pool.  That's not too horrible as long as there are
 not actual conflicts, but it could mean that for example some
 connections trust CA certs that the app programmer expected to only
 be trusted for other connections.  I did arrange (and test) that the
 client cert and key are local to each connection, but leakage of
 trusted root certs is a different story.

 We could avoid this problem if we were willing to set up a separate
 SSL_context for each connection, but I'm not sure if it's worth that.
 The scenario where a single application process is managing multiple
 distinct sets of trusted certs seems a bit far-fetched anyway.

 OpenSSL really doesn't seem to be designed for multiple truly 
 independent SSL contexts. The SSL context stuff has clearly been hacked 
 on after the fact to a library that started out having only one global 
 state, and it's pretty incomplete. I'm honestly not sure it's worth 
 trying to allow per-connection trust going, especially as (AFAIK) 
 there's no evidence that anybody _wants_ per-client-connection SSL trust 
 anyway.

Precisely.  I'm not excited about doing anything about this in the near
term, or even the not-so-near term.  I just wanted to get the
information into the PG archives in case it ever does become
significant.

regards, tom lane

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers