Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-11-30 Thread Bruce Momjian
On Thu, Mar 21, 2013 at 01:42:55PM +0800, Craig Ringer wrote:
> On 03/19/2013 09:46 PM, Stephen Frost wrote:
> > * Craig Ringer (cr...@2ndquadrant.com) wrote:
> >> As far as I'm concerned that's the immediate problem fixed. It may be
> >> worth adding a warning on startup if we find non-self-signed certs in
> >> root.crt too, something like 'WARNING: Intermediate certificate found in
> >> root.crt. This does not do what you expect and your configuration may be
> >> insecure; see the Client Certificates chapter in the documentation.'
> >
> > I'm not sure that I follow this logic, unless you're proposing that
> > intermediate CAs only be allowed to be picked up from system-wide
> > configuration? That strikes me as overly constrained as I imagine there
> > are valid configurations today which have intermediate CAs listed, with
> > the intention that they be available for PG to build the chain from a
> > client cert that is presented back up to the root. Now, the client
> > might be able to provide such an intermediate CA cert too (one of the
> > fun things about SSL is that the client can send any 'missing' certs to
> > the server, if it has them available..), but it also might not.
> >
> 
> Drat, you're quite right. I've always included the full certificate
> chain in client certs but it's in no way required.
> 
> I guess that pretty much means mainaining the status quo and documenting
> it better.

I have developed the attached patch to document this behavior.  My goals
were:

* clarify that a cert can match a remote intermediate or root certificate
* clarify that the client cert must match a server root.crt
* clarify that the server cert much match a client root.crt
* clarify that the root certificate does not have to be specified
  in the client or server cert as long as the remote end has the chain
  to the root

Does it meet these goals?  Is it correct?

-- 
  Bruce Momjian  http://momjian.us
  EnterpriseDB http://enterprisedb.com

  + Everyone has their own god. +
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
new file mode 100644
index 955f248..ad54564
*** a/doc/src/sgml/libpq.sgml
--- b/doc/src/sgml/libpq.sgml
*** ldap://ldap.acme.com/cn=dbserver,cn=host
*** 7179,7193 
 intermediate certificate authority, rather than one that is
 directly trusted by the server.  To use such a certificate, append the
 certificate of the signing authority to the postgresql.crt
!file, then its parent authority's certificate, and so on up to a
!root authority that is trusted by the server.  The root
!certificate should be included in every case where
!postgresql.crt contains more than one certificate.

  

!Note that root.crt lists the top-level CAs that are
!considered trusted for signing server certificates.  In principle it need
 not list the CA that signed the client's certificate, though in most cases
 that CA would also be trusted for server certificates.

--- 7179,7193 
 intermediate certificate authority, rather than one that is
 directly trusted by the server.  To use such a certificate, append the
 certificate of the signing authority to the postgresql.crt
!file, then its parent authority's certificate, and so on up to a certificate
!authority, root or intermediate, that is trusted by
!the server, i.e. appears in the server's root.crt
!file.

  

!Note that the client's ~/.postgresql/root.crt lists the top-level CAs 
!that are considered trusted for signing server certificates.  In principle it need
 not list the CA that signed the client's certificate, though in most cases
 that CA would also be trusted for server certificates.

diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
new file mode 100644
index ab51782..fbed06f
*** a/doc/src/sgml/runtime.sgml
--- b/doc/src/sgml/runtime.sgml
*** pg_dumpall -p 5432 | psql -d postgres -p
*** 1986,1995 
 intermediate certificate authority, rather than one that is
 directly trusted by clients.  To use such a certificate, append the
 certificate of the signing authority to the server.crt file,
!then its parent authority's certificate, and so on up to a root
!authority that is trusted by the clients.  The root certificate should
!be included in every case where server.crt contains more than
!one certificate.

  

--- 1986,1995 
 intermediate certificate authority, rather than one that is
 directly trusted by clients.  To use such a certificate, append the
 certificate of the signing authority to the server.crt file,
!then its parent authority's certificate, and so on up to a certificate
!authority, root or intermediate, that is trusted by
!clients, i.e. appears in the clients' root.crt
!files.

  


-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes 

Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-20 Thread Craig Ringer

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 03/19/2013 09:46 PM, Stephen Frost wrote:
> * Craig Ringer (cr...@2ndquadrant.com) wrote:
>> As far as I'm concerned that's the immediate problem fixed. It may be
>> worth adding a warning on startup if we find non-self-signed certs in
>> root.crt too, something like 'WARNING: Intermediate certificate found in
>> root.crt. This does not do what you expect and your configuration may be
>> insecure; see the Client Certificates chapter in the documentation.'
>
> I'm not sure that I follow this logic, unless you're proposing that
> intermediate CAs only be allowed to be picked up from system-wide
> configuration? That strikes me as overly constrained as I imagine there
> are valid configurations today which have intermediate CAs listed, with
> the intention that they be available for PG to build the chain from a
> client cert that is presented back up to the root. Now, the client
> might be able to provide such an intermediate CA cert too (one of the
> fun things about SSL is that the client can send any 'missing' certs to
> the server, if it has them available..), but it also might not.
>

Drat, you're quite right. I've always included the full certificate
chain in client certs but it's in no way required.

I guess that pretty much means mainaining the status quo and documenting
it better.

- -- 
 Craig Ringer   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.13 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQEcBAEBAgAGBQJRSp3fAAoJELBXNkqjr+S2+JYH+wUo2mCMB2n3/mXo24l0rO5+
mxS6d9uJNIZZErZX2I/NfY59kLX1ypUAeGhQnCSOZuxig6Xd91nXzRdkaQF/+WHa
9hEAXbOtl7bMgj8cEIfloQlSU94VXamH53i5YL5ZVLqkQG/7uknY05NbJs3IGM5g
ALrEgo3XOC8JyUz21hZzaQOb2vbdSh0F0O17EoJz1fLY6l5ScFnLWihKYurp5Oq0
em1bsN0GKckmSa7a9mJ37Hvowi92epbtF4XR1DyrQGOHQSCLq0NnCthA5MtdPXN0
+BJQWZfx0qcRcrHMILkFa0Uu7Bc9Ao0q06l55DNSyYXx1FWN0cBArGpXcoPb8Zs=
=BAYd
-END PGP SIGNATURE-



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


Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-19 Thread Stephen Frost
* Craig Ringer (cr...@2ndquadrant.com) wrote:
> As far as I'm concerned that's the immediate problem fixed. It may be
> worth adding a warning on startup if we find non-self-signed certs in
> root.crt too, something like 'WARNING: Intermediate certificate found in
> root.crt. This does not do what you expect and your configuration may be
> insecure; see the Client Certificates chapter in the documentation.'

I'm not sure that I follow this logic, unless you're proposing that
intermediate CAs only be allowed to be picked up from system-wide
configuration?  That strikes me as overly constrained as I imagine there
are valid configurations today which have intermediate CAs listed, with
the intention that they be available for PG to build the chain from a
client cert that is presented back up to the root.  Now, the client
might be able to provide such an intermediate CA cert too (one of the
fun things about SSL is that the client can send any 'missing' certs to
the server, if it has them available..), but it also might not.

> We could then look at using more flexible approaches to match PostgreSQL
> users to client certificates, like regexps or (preferably, IMO)
> DN-component based solutions to extract usernames from cert DNs, etc.
> Various ways to specify *authorization*.

Sure.

> It's looking more and more like the *authentication* side is basically
> "do you trust this CA root not to sign certs for fraudlent/fake
> SubjectDNs or issue intermediate certs that might do so? Trust: include
> it. No trust: Don't." That's what we have now, it just needs to be
> explained better in the docs.

I certainly agree that the docs could be improved in this area. :)

Thanks,

Stephen


signature.asc
Description: Digital signature


Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-19 Thread Craig Ringer

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 03/19/2013 08:39 PM, Stephen Frost wrote:
> Craig,
>
> * Craig Ringer (cr...@2ndquadrant.com) wrote:
>> Yep, in most applications I've seen you usually store a list of
>> authorized SubjectDNs or you just use your own self-signed root and
>> issue certs from it.
>
> Even with a self-signed root issuing certs, you need to map the
> individual cert to a PG user in some fashion.
>

The more I look a this, the more it looks like trying to use
intermediate CAs as authentication roots is largely wrong anyway. We
should document this with something like:

NOTE: Only self-signed root CA certificates should be added to
ssl_ca_file. If you add an intermediate CA certificate (one that's not
self-signed) then PostgreSQL will not be able to validate client
certificates against it because it will not have access to the full
certificate chain. You can't fix that by adding the full certificate
chain then PostgreSQL will then accept client certificates trusted by
any member of the chain, including the root, so the effect is the same
as placing only the root certificate in the file. It is not currently
possible to trust certificates signed by an intermediate CA but not the
parents in its certificate chain.

... plus some explanation that having a valid trusted cert doesn't mean
you're authorized for access, you still have to meet the requrements in
pg_hba.conf, have a valid username/password or match an authorized
certificate DN (depending on config), etc.

As far as I'm concerned that's the immediate problem fixed. It may be
worth adding a warning on startup if we find non-self-signed certs in
root.crt too, something like 'WARNING: Intermediate certificate found in
root.crt. This does not do what you expect and your configuration may be
insecure; see the Client Certificates chapter in the documentation.'



We could then look at using more flexible approaches to match PostgreSQL
users to client certificates, like regexps or (preferably, IMO)
DN-component based solutions to extract usernames from cert DNs, etc.
Various ways to specify *authorization*.

It's looking more and more like the *authentication* side is basically
"do you trust this CA root not to sign certs for fraudlent/fake
SubjectDNs or issue intermediate certs that might do so? Trust: include
it. No trust: Don't." That's what we have now, it just needs to be
explained better in the docs.

- -- 
 Craig Ringer   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.13 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQEcBAEBAgAGBQJRSGoOAAoJELBXNkqjr+S26esIALSmgX6/4lC+J7W3YPDpl1DE
UJsSGc46oBZbC/5xDwBELh2Tg+fqzIe+Kmx+EpsC20MaGinqEz9iwTb2M7vTFhxh
nvAkp1Em8MhR6lvCKITjPnDBCv7yQ7K3yTAfHO+LU2J1t3eVhStpXh71/73pRLoQ
p3SAUwO0EBnZFdY2HVLPABK7tpjuf5Mpn0QFR9T+KvsgcP9QXiV0UTFI0IxlQrpE
NRlJfPwkoYAweISTACrDwqJHJ3sL/qLdOQ8l4BCsiwtqynX7fPhxmDUuBXrOTqlS
dwW9ZkBJ9jvXjF3PPk1t0oujlMJGBC4Y7xgIb0Kd87Vyv/OTkWE4XKriDhIH6oQ=
=f3qr
-END PGP SIGNATURE-



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


Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-19 Thread Stephen Frost
Craig,

* Craig Ringer (cr...@2ndquadrant.com) wrote:
> Yep, in most applications I've seen you usually store a list of
> authorized SubjectDNs or you just use your own self-signed root and
> issue certs from it.

Even with a self-signed root issuing certs, you need to map the
individual cert to a PG user in some fashion.

> I'm pretty sure I've seen tools match on part of the DN, like the
> organisation field, but since I can't remember *where* I'm not sure
> that's all that useful.

Looking at what other tools do and how they handle this question would
certainly be a good idea.

> I don't know about "very rare" but it's certainly not common outside
> very large orgs. I tried to find a CA that'd let me issue intermediate
> client certs for 2ndQuadrant but found nobody that'd do it for
> certificate volumes less than several thousand new certs a month. I'd
> been using intermediate CAs based on my own self-signed CA root quite
> heavily in infrastructure elsewhere I was rather surprised that the same
> sort of thing wasn't easily available for public CAs.

It's pretty simple, really- issuing certs is how the public CAs make
their money.  If they give you a CA cert that can issue certs, they're
cut out of the loop.

> I get the impression it's fairly common in internal infrastructure,
> especially with the cert management tools offered by Microsoft Active
> Directory servers, but have no strong information to substantiate this.
> Nor do I know whether we need to support this mode of operation.

In general, CAs view intermediate certs as a way to provide automated
systems while having their self-signed root private key highly
protected.  The intermediate CAs therefore have a shorter life-span and
end up changing much more frequently than the root certs (though root
certs certainly also do change, but it's much more painful).  That's one
of the reasons that they're bad to use as part of the authentication
criteria.

The problem with trying to use intermediate CAs as a way of dividing up
organizational responsibility is simply that there's very few systems
out there which will support that kind of configuration, from what I've
seen.  Wrt Active Directory this problem is actually very well solved
through use of Kerberos, where you have multiple realms, directional
trust between the realms, and most tools (including PG) understand that
a principal is the combination of username@REALM and let you authorize
based on that.

> BTW, This discussion has made me realise that I know less about SSL/TLS
> and X.509 certificate extensions than I'd like to when dealing with this
> topic. In particular, I don't know whether a CA can issue an
> intermediate CA with extensions that restrict it to validly signing only
> host certificates for hosts under a particular domain or
> user-identifying client certs with CNs under a particular organisation -
> and whether, if such extensions exist, applications actually check them
> when verifying the certificate trust chain.

You can set flags on certificates but I've not seen the kind of complex
restrictions that you're describing.  Remember that anything that the CA
sets for an intermediate CA cert would have to be checked by whatever
software is doing the certificate validation, meaning that you'd have to
make sure all your certificate-based software is updated to do that kind
of validation (and do it in a consistent way, or you'd get all kinds of
fun failures).

> Ugh, that's not something I've ever had the ... privilege ... to deal
> with before.

I worked for the company that built the original federal bridge
software. :)  I wasn't directly involved in that project, but I
certainly gained some understanding of the complexities through working
with the folks who were.

> Only for using intermediate certs as authorization roots, and it may be
> reasonable to say "we don't support that, use an authorized DN list". Or
> come up with a better solution like checking attributes of the SubjectDN
> for authorization purposes after validating the signature chain to prove
> authenticity.

I think it'd be valuable to distinguish "trusted CAs" from "intermediate
CAs" in PG explicitly (as I recall, you can already do this by simply
ensuring that your OpenSSL config is set up correctly for the system
wide defaults).  That's what most serious SSL users will be familiar
with anyway.  I'm on the fence about if only supporting a list of
"trusted CAs" (through the cert files that we currently have) rises to
the level of being a security issue, but we should at least update the
documentation to reflect that all CAs listed in the file are fully
trusted and plan to provide an intermediate CA list option.  To be
honest, our entire SSL support mechanism could really use some work and
it'd be great if we had some folks looking into it seriously.  One of
the problems we've long had is the dependency on OpenSSL (yes, it's a
problem) and it'd be good to consider, if we're changing the SSL
configuration, how 

Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-19 Thread Bruce Momjian
On Tue, Mar 19, 2013 at 01:46:32AM -0400, Stephen Frost wrote:
> > I guess that suggests we should be calling this something like
> > 'ssl_authorized_client_roots'.
> 
> I'm no longer convinced that this really makes sense and I'm a bit
> worried about the simple authentication issue which I thought was at the
> heart of this concern.  Is there anything there that you see as being an
> issue with what we're doing currently..?

I too am worried that make SSL even more flexible will make simple setups
more complex to setup.

-- 
  Bruce Momjian  http://momjian.us
  EnterpriseDB http://enterprisedb.com

  + It's impossible for everything to be true. +


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


Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-18 Thread Craig Ringer

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 03/19/2013 01:46 PM, Stephen Frost wrote:
> If you're using a public CA as your
> root, then you need to make sure you know how to ensure only the right
> people have access, typically be storing in the mapping table the unique
> ID issued by the CA for your users.
Yep, in most applications I've seen you usually store a list of
authorized SubjectDNs or you just use your own self-signed root and
issue certs from it.

I'm pretty sure I've seen tools match on part of the DN, like the
organisation field, but since I can't remember *where* I'm not sure
that's all that useful.
> It's very rare, from what I've
> seen, for public CAs to issue intermediate CAs to organizations to
> generate their own certs off of, so I'm a bit confused about how we got
> to this point.
I don't know about "very rare" but it's certainly not common outside
very large orgs. I tried to find a CA that'd let me issue intermediate
client certs for 2ndQuadrant but found nobody that'd do it for
certificate volumes less than several thousand new certs a month. I'd
been using intermediate CAs based on my own self-signed CA root quite
heavily in infrastructure elsewhere I was rather surprised that the same
sort of thing wasn't easily available for public CAs.

I get the impression it's fairly common in internal infrastructure,
especially with the cert management tools offered by Microsoft Active
Directory servers, but have no strong information to substantiate this.
Nor do I know whether we need to support this mode of operation.

BTW, This discussion has made me realise that I know less about SSL/TLS
and X.509 certificate extensions than I'd like to when dealing with this
topic. In particular, I don't know whether a CA can issue an
intermediate CA with extensions that restrict it to validly signing only
host certificates for hosts under a particular domain or
user-identifying client certs with CNs under a particular organisation -
and whether, if such extensions exist, applications actually check them
when verifying the certificate trust chain.


> What I *have* seen is cross-root-cert trusts (known as the Federal
> Bridge in the US government), but that's quite a different thing as you
> have multiple self-signed root CAs involved and need to know how to
> properly traverse between them based on the trusts which have been
> built.
Ugh, that's not something I've ever had the ... privilege ... to deal
with before.
>
> I'm no longer convinced that this really makes sense and I'm a bit
> worried about the simple authentication issue which I thought was at the
> heart of this concern. Is there anything there that you see as being an
> issue with what we're doing currently..?
Only for using intermediate certs as authorization roots, and it may be
reasonable to say "we don't support that, use an authorized DN list". Or
come up with a better solution like checking attributes of the SubjectDN
for authorization purposes after validating the signature chain to prove
authenticity.
> I do think we want to figure out a way to improve our mapping table to
> be able to use more than just the CN, since that can be repeated in
> multiple certs issued from a root CA, particularly when there are
> intermediary CAs. One option might be to provide a way to map against a
> specific issuing CA, or to a CA in the chain, but there's a lot of risk
> to that due to CA churn (in large setups, you're going to have lots of
> users who have certs issued from a bunch of different CAs, and those
> user certs will roll to new CAs as new badges are issued, for
> example..). It can get to be a real nightmare to try and keep up with
> all of the changes at that level.
Certificate fingerprint? Easily obtained via most client UIs and via
openssl x509 -in cert.crt -fingerprint, eg:

SHA1 Fingerprint=DA:03:9B:FB:81:69:AB:48:64:3D:35:B4:90:56:CF:F1:24:FE:89:B0

However, if I was managing a group large enough to want cert auth I'd
want to be able to specify something like:

SubjectDNMatches: C=*, ST=*, L=*, O=MyCompany, CN=*

... in which case there'd no longer be a need to restrict trust to
intermediate CAs, you'd just trust the root and restrict the authorized
SubjectDNs. If you don't trust your own root CA not to issue certs in
your company's name to 3rd parties you shouldn't be using it. (Whether
it's actually sane to trust a CA is another argument).

- -- 
 Craig Ringer   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.13 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQEcBAEBAgAGBQJRSAJZAAoJELBXNkqjr+S2JrcIALZebfEW4FbfFI6WOs6qDutr
tz486SlnPV+cf29ex242evSUgNQTz38uFKMIs9EIRfe7sVKz3whn0MARmQY9dKph
CusbXNqcPIBbZIZM1hObaKOnMvNnGk5sxnRh4iKjzcMjqCULG5LVX7bXAXn3PcjA
u3lYlNWONWdmz708QOCgvpui4wEv5+bVuik/CnRdPu+BWAcndJHUMuxZMxkUC/rs
4OjLlEg6BPiXRgIKTFBNsa0vvCyVBUd5ri0RCtxUr5T/L/ORWdM+Ic0nqCEPTqyI
EOtDKu

Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-18 Thread Stephen Frost
Craig,

* Craig Ringer (cr...@2ndquadrant.com) wrote:
> They are intermediary, but we're dealing with the case where trust and
> authorization are not the same thing. Trust stems from the trusted root
> in the SSL CA model, but that's a chain of trust for *identity*
> (authentication), not *authorization*.

Oh, I see.

> The usual SSL terminology doesn't consider this, because it's a simple
> back and white trust model where authenticated = authorized.

That's not entirely accurate on a couple of levels.  First, basic SSL is
only concerned with authentication, authorization has historically been
left up to the application.  The more typical approach with the
situation you're describing is to have an organization-level root CA
which you only issue certs against.  If you're using a public CA as your
root, then you need to make sure you know how to ensure only the right
people have access, typically be storing in the mapping table the unique
ID issued by the CA for your users.  It's very rare, from what I've
seen, for public CAs to issue intermediate CAs to organizations to
generate their own certs off of, so I'm a bit confused about how we got
to this point.

What I *have* seen is cross-root-cert trusts (known as the Federal
Bridge in the US government), but that's quite a different thing as you
have multiple self-signed root CAs involved and need to know how to
properly traverse between them based on the trusts which have been
built.

Regarding cross-CAS authorization, there are extended attributes which
are listed in the certificates that applications are expected to look
at when considering authorization for the client.  It's been taken
further than that however, where inter-CA trusts have been defined
with actual mappings between these extended attributes, including
'null' mappings (indicating that CA 'A' doesn't trust attribute 'q'
from CA 'B').

> I guess that suggests we should be calling this something like
> 'ssl_authorized_client_roots'.

I'm no longer convinced that this really makes sense and I'm a bit
worried about the simple authentication issue which I thought was at the
heart of this concern.  Is there anything there that you see as being an
issue with what we're doing currently..?

I do think we want to figure out a way to improve our mapping table to
be able to use more than just the CN, since that can be repeated in
multiple certs issued from a root CA, particularly when there are
intermediary CAs.  One option might be to provide a way to map against a
specific issuing CA, or to a CA in the chain, but there's a lot of risk
to that due to CA churn (in large setups, you're going to have lots of
users who have certs issued from a bunch of different CAs, and those
user certs will roll to new CAs as new badges are issued, for
example..).  It can get to be a real nightmare to try and keep up with
all of the changes at that level.

Thanks,

Stephen


signature.asc
Description: Digital signature


Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-18 Thread Craig Ringer

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 03/18/2013 08:55 PM, Stephen Frost wrote:
> Makes sense to me. I'm not particular about the names, but isn't this
> set of CAs generally considered intermediary? Eg: 'trusted', '
> intermediate', etc?
They are intermediary, but we're dealing with the case where trust and
authorization are not the same thing. Trust stems from the trusted root
in the SSL CA model, but that's a chain of trust for *identity*
(authentication), not *authorization*.

Bob J. Criminal might well have a client certificate from a trusted
authority proving that he's who he says he is (he's authenticated) but
we sure as hell don't want to authorize his access to anything.

That's where the intermediate certs come in. We might say "Only users
with certificates issued by our corporate HR team are authorized to
connect to our servers". This is a root of trust, but this time it's a
root of trust to *authorize*, not just to authenticate.

The usual SSL terminology doesn't consider this, because it's a simple
back and white trust model where authenticated = authorized.

I guess that suggests we should be calling this something like
'ssl_authorized_client_roots'.

- -- 
 Craig Ringer   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.13 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQEcBAEBAgAGBQJRR/dqAAoJELBXNkqjr+S2TV4H/3f9Hnf9JhSuGhWblh2adgTJ
Rkdx/9RbByJDMJP0s0c8C1sXaWZGJmKmLhJoes4IIvOVW85SVUa9WoT+UBJPdx9P
esUNsSLFokLqom3TxNRZOHaloyZ+OZafSUnKCwMOIvD0hIehrS3Wcg70QMSj06tX
h22BVhA8bzO1Wdg9UdD98jcuWdEbLgWzVtvIXjICcMJ1azgiF1VY4zwUUbBJBfLG
UIA7+2TtVaXQuge6qWgId0RTKKrb6cLHXCSQ/rigy0mRH9m/G5jKmqENvLAnafI4
4lSBPyDzNj2fBfP9YgIiAe/EGjnJMWQfBBghQI3QrK2kjOZXtzZoOb4XEjfn3FI=
=u+2j
-END PGP SIGNATURE-



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


Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-18 Thread Ian Pilcher
On 03/18/2013 02:01 AM, Craig Ringer wrote:
> This appears to match Ian's description of having a validation-only cert
> list and a separate list of certs used to verify clients. I'd like to
> follow Apache's model:

Ready for some more good news?

It's possible that I'm missing something, but Apache (mod_ssl) appears
to exhibit the exact same behavior.

Tested on Fedora 18, with the following packages:

  httpd-2.4.3-15.fc18.x86_64
  mod_ssl-2.4.3-15.fc18.x86_64
  openssl-1.0.1e-3.fc18.x86_64

I have set the following in /etc/httpd/conf.d/ssl.conf:

  Listen 3 https
  
  ServerName postgres.example.com
  SSLCertificateFile /etc/pki/tls/certs/postgres.crt
  SSLCertificateKeyFile /etc/pki/tls/private/postgres.key
  SSLCACertificateFile /etc/pki/tls/certs/client-ca.chain
  SSLCADNRequestFile /etc/pki/tls/certs/client-ca.crt
  SSLVerifyClient require
  SSLVerifyDepth  10

Notes:

  * The port is set to 3, because that's hard-coded into the
(attached) test client.
  * I am using the certificates that I previously sent.
  * ServerName is set to postgres.example.com to match its certificate.
  * postgres.crt contains its entire chain (postgres.crt + server-ca.crt
+ root-ca.crt), so that I don't have to specify a
SSLCertificateChainFile.
  * client-ca.chain is client-ca.crt + root-ca.crt.  As with PostgreSQL,
I found that I have to provide the root CA certificate in order for
any client to connect.

With this configuration, the test client is able to connect with the
"good" client certificate, but it is also able to connect with the "bad"
client certificate when it presents a certificate chain that includes
the server CA certificate.

-- 

Ian Pilcher arequip...@gmail.com
Sometimes there's nothing left to do but crash and burn...or die trying.

#include 
#include 
#include 

#include 
#include 
#include 

#include 
#include 

int main(int argc, char *argv[])
{
SSL_CTX *ctx;
SSL *ssl;
struct sockaddr_in server_addr;
int sock_fd;

if (argc != 3) {
	fprintf(stderr, "USAGE: %s  \n", argv[0]);
	exit(__LINE__);
}

SSL_load_error_strings();
SSL_library_init();

if ((ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
}

if (SSL_CTX_use_certificate_chain_file(ctx, argv[1]) != 1) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
}

if (SSL_CTX_use_PrivateKey_file(ctx, argv[2], SSL_FILETYPE_PEM) != 1) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
}

if (SSL_CTX_check_private_key(ctx) != 1) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
}

memset(&server_addr, 0, sizeof server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(3);
server_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
	perror("socket");
	exit(__LINE__);
}

if (connect(sock_fd, (struct sockaddr *)&server_addr,
		sizeof server_addr) == -1) {
	perror("connect");
	exit(__LINE__);
}

puts("Connected.  Starting SSL handshake.");

if ((ssl = SSL_new(ctx)) == NULL) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
}

if (SSL_set_fd(ssl, sock_fd) == 0) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
}

if (SSL_connect(ssl) != 1) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
}

puts("SSL handshake successful.  Shutting down.");

return 0;
}

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


Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-18 Thread Stephen Frost
Craig, all,

* Craig Ringer (cr...@2ndquadrant.com) wrote:
> PROBLEM VERIFIED

Let me just say "ugh".  I've long wondered why we have things set up in
such a way that the whole chain has to be in one file, but it didn't
occur to me that it'd actually end up causing this issue.  In some ways,
I really wonder about this being OpenSSL's fault as much as ours, but I
doubt they'd see it that way. :)

> What we need to happen instead is for root.crt to contain only the
> trusted certificates and have a *separate* file or directory for
> intermediate certificates that OpenSSL can look up to get the
> intermediates it needs to validate client certs, like
> `ssl_ca_chain_file` or `ssl_ca_chain_path` if we want to support
> OpenSSL's hashed certificate directories.

Makes sense to me.  I'm not particular about the names, but isn't this
set of CAs generally considered intermediary?  Eg: 'trusted', '
intermediate', etc?

Thanks,

Stephen


signature.asc
Description: Digital signature


Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-18 Thread Craig Ringer
On 03/18/2013 02:27 PM, Ian Pilcher wrote:
> On 03/18/2013 12:07 AM, Craig Ringer wrote:
>> So this problem is verified.

> * Trusted certificates - What currently goes in the (unfortunately
>   named) root.crt file.

Well, a little unfortunate. It contains roots of *client authentication*
trust, which is fair enough, they just aren't necessarily self-signed
certificates that are roots of *certificate validity* trust (root CA certs).

This list is set by SSL_CTX_set_client_CA_list . The examples section of
its man page contains:

  Scan all certificates in CAfile and list them as acceptable CAs:

   SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));

> * Validation-only certificates - CA certificates that are used only to
>   complete the chain from a trusted certificate to a self-signed root.
>   I haven't been able to come up with a particularly good name for a
>   file containing this type of certificate(s) -- validate.crt?

We should probably take advantage of the fact that 9.2 made these
filenames configurable to deprecate root.crt and choose two descriptive
filenames, something like trusted_cert_roots.crt and
trusted_client_cert_signers.crt .

> This is conceptually simple, and I've been fiddling with it for the last
> week or so.  Unfortunately, the OpenSSL documentation has made this far
> more challenging that it should be.  Simple things like reading multiple
> certificates from a file, checking whether an X509_STORE contains a
> particular certificate, etc. are all proving to be unexpectedly
> difficult.  (I never thought that I'd miss the Java SSL API!)

Apache's sources are useful there. When working with OpenSSL sometimes
the sanest option is to find something you know already does it right,
work out how, *understand why it works* and then apply that approach to
your code. Blindly copying their approach is stupid and guaranteed to
lead to security holes, but others' code remains some of the best
documentation for OpenSSL if used for hints rather than blindly copied.

-- 
 Craig Ringer   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services


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


Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-18 Thread Craig Ringer
On 03/18/2013 01:07 PM, Craig Ringer wrote:
> System wide installation of the root may allow OpenSSL to discover it
> and use it for verification back to the root without having to trust it
> to sign clients. I'll do some more checking to see if this is possible
> with how Pg uses OpenSSL but I'm inclined to doubt it.
It looks like we aren't reading the system-wide certs or looking them up
when certs aren't resolved in the files Pg explicitly passes to OpenSSL,
so a system-wide install doesn't look like it'll work.

I've had a look at how Apache handles this and it took me a while to
work out what's going on. Apache uses SSLCACertificateFile (concatenated
certs) / SSLCACertificatePath (hashed dir) to look up trusted
certificate signers. It According to the docs it doesn't appear to make
any provision there for trusting intermediate certificates but not their
parents as signers of client certificates, but it looks like support is
there, the docs just don't explain it well.

Apache has SSLCADNRequestFile / SSLCADNRequestPath which are described
as controlling the acceptable certificate names sent to clients in a
client cert request. The docs don't make it clear if Apache will trust
only client certs with these certs in their chains or whether this only
controls the list of certificate DNs presented to the client rather than
what's accepted in response. The code suggests that they control trust
not just the cert list presented.

In Apache's modules/ssl/ssl_engine_init.c it calls
SSL_CTX_load_verify_locations on the SSLCACertificateFile and
SSLCACertificatePath.

It then  calls ssl_init_FindCAList with the
SSLCADNRequestFile/SSLCADNRequestPath if they're specified in the
configuration, otherwise it calls it with the
SSLCACertificateFile/SSLCACertificatePath . That calls
ssl_init_PushCAList on all of the certs it finds in the File and Path
variants. For each cert file that calls SSL_load_client_CA_file and for
each cert within each file pushes the cert onto a STACK_OF(X509_NAME) if
a cert with the same DN isn't already in the stack. It passes the stack
to OpenSSL's SSL_CTX_set_client_CA_list .

So what Apache does appears to boil down to:

SSL_CTX_load_verify_locations(ca_file,ca_path);
if (ca_dn_file || ca_dn_path) {
SSL_CTX_set_client_CA_list( ... STACK_OF unique certs on ca_dn_file
and ca_dn_path ... );
} else {
SSL_CTX_set_client_CA_list( ... STACK_OF unique certs on ca_file and
ca_path );
}

This appears to match Ian's description of having a validation-only cert
list and a separate list of certs used to verify clients. I'd like to
follow Apache's model:

in postgresql.conf, if ssl_ca_file is set then pass it to
SSL_CTX_load_verify_locations . If the proposed new parameter
ssl_ca_valid_client_signers_file is set then pass the certs in that to
SSL_CTX_set_client_CA_list ; otherwise pass the certs in ssl_ca_file to
SSL_CTX_set_client_CA_list and thus retain the current behaviour.
Hopefully we can avoid the ugly read-and-deduplicate stuff Apache has to
do because we currently only support a certfile anyway, we don't read
certdirs, so I'll look for helper functions that wrap
SSL_CTX_set_client_CA_list.

-- 
 Craig Ringer   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services



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


Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-17 Thread Ian Pilcher
On 03/18/2013 12:07 AM, Craig Ringer wrote:
> So this problem is verified.

Thanks for taking the time to look into this.  Good to know I'm not
crazy.

> What we need to happen instead is for root.crt to contain only the
> trusted certificates and have a *separate* file or directory for
> intermediate certificates that OpenSSL can look up to get the
> intermediates it needs to validate client certs, like
> `ssl_ca_chain_file` or `ssl_ca_chain_path` if we want to support
> OpenSSL's hashed certificate directories.

I did a fair bit of searching and asked about this subject on the
openssl-users list.  The consensus seems to be that doing this with
OpenSSL will require 2 separate sets of certificates and a validation
callback.

The two sets of certificates are:

* Trusted certificates - What currently goes in the (unfortunately
  named) root.crt file.

* Validation-only certificates - CA certificates that are used only to
  complete the chain from a trusted certificate to a self-signed root.
  I haven't been able to come up with a particularly good name for a
  file containing this type of certificate(s) -- validate.crt?

All of the certificates in both sets get added to the SSL_CTX, so that
OpenSSL can do its normal validation -- all the way to a root CA.  The
trusted certificates also need to be maintained as a separate set
(X509_STORE?).

Once OpenSSL has built the complete certificate chain, the validation
callback can refuse the connection if the chain does not contain at
least one of the *trusted* certificates.

This is conceptually simple, and I've been fiddling with it for the last
week or so.  Unfortunately, the OpenSSL documentation has made this far
more challenging that it should be.  Simple things like reading multiple
certificates from a file, checking whether an X509_STORE contains a
particular certificate, etc. are all proving to be unexpectedly
difficult.  (I never thought that I'd miss the Java SSL API!)

> System wide installation of the root may allow OpenSSL to discover it
> and use it for verification back to the root without having to trust it
> to sign clients. I'll do some more checking to see if this is possible
> with how Pg uses OpenSSL but I'm inclined to doubt it.

Me too.  I think that OpenSSL's behavior embodies the idea that a
certificate can only be validated if a chain can be formed to a self-
signed root CA.  (And there's probably a pretty good argument to be
made for this position, particularly when CRLs are added to the mix.)

> I thought you might be able to add the common root to the server.crt
> certificate chain to let OpenSSL discover it that way, but it looks like
> OpenSSL won't use certs it's seen in server.crt when verifying client
> cert trust paths.

Nope.  It's pretty obvious from be-secure.c that only the certificates
in root.crt will be used.

-- 

Ian Pilcher arequip...@gmail.com
Sometimes there's nothing left to do but crash and burn...or die trying.



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


Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-17 Thread Craig Ringer
On 03/09/2013 04:52 PM, Ian Pilcher wrote:
> After looking at be-secure.c and investigating the way that OpenSSL
> validates certificates, I do not believe that there is any way of
> achieving the desired behavior with the current codebase.

Test process:

SET UP SERVER VERIFIED SSL (NO CLIENT CERTS)
--

Edited postgresql.conf and set:

ssl=on
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'
ssl_ca_file='root.crt'

Copied your samples:

# cp $CERTS/postgres.crt server.crt
# cp $CERTS/postgres.key server.key
# cp $CERTS/client-ca.crt root.crt
# chown postgres:postgres root.crt server.crt server.key
# chmod 0600 server.crt server.key root.crt
# systemctl restart  postgresql-9.2.service

$ psql "postgresql://localhost/?sslmode=require"
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)

(connects OK; expected since we aren't requiring client certs yet and we
aren't validating the server cert).

$ psql "postgresql://localhost/?sslmode=verify-ca"
psql: root certificate file "/home/craig/.postgresql/root.crt" does not
exist
Either provide the file or change sslmode to disable server certificate
verification.

Again expected, though we really should be using the system SSL cert
database. Anyway:

$ mkdir .postgresql
$ cp $CERTS/root-ca.crt ~/.postgresql/root.crt

(This should be the trusted root, not server-ca or client-ca since we
shouldn't have to keep copies of either to verify server trust). Now,
test we can verify the server's identity:

$ psql "postgresql://localhost/?sslmode=require"
psql: SSL error: certificate verify failed

Plonk, we can't. The reason for this is that the server has sent us its
cert and we have the root cert, but we don't have the intermediate
server-ca.crt . Append that to server.crt:

# cat $CERTS/postgres.crt $CERTS/server-ca.crt > server.crt
# systemctl restart  postgresql-9.2.service

$ psql "postgresql://localhost/?sslmode=require"
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)

OK, we're good now, the server is sending us the intermediate cert we
require. Regular non-client-cert verified SSL is fine.  Examination of
the protocol chat shows that the server is sending a Server Hello with a
Certificate message containing the server and intermdediate certificate DNs:

  id-at-commonName=postgres.example.com,id-at-organizationName=Ian
Pilcher,id-at-localityName=Carrollton,id-at-stateOrProvinceName=Texas,id-at-countryName=US
  id-at-commonName=Server CA,id-at-organizationName=Ian
Pilcher,id-at-localityName=Carrollton,id-at-stateOrProvinceName=Texas,id-at-countryName=US

as expected.


ENABLE CLIENT CERTIFICATE VERIFICATION
-

Now lets install our client certificates in the client.

$ cp $CERTS/good-client.key ~/.postgresql/postgresql.key
$ # Note that the order is important here, the client cert must appear
first, followed by the chain cert(s)
$ cat $CERTS/good-client.crt $CERTS/client-ca.crt >
~/.postgresql/postgresql.crt
$ chmod 0600 .postgresql/postgresql.key

$ psql "postgresql://localhost/?sslmode=verify-ca"
psql: SSL error: tlsv1 alert unknown ca


Examination of the handshake shows that the server is sending a request
for client certificates signed by:

  Distinguished Name: (id-at-commonName=Client
CA,id-at-organizationName=Ian
Pilcher,id-at-localityName=Carrollton,id-at-stateOrProvinceName=Texas,id-at-countryName=US)

and the client is sending in response:

  Certificate (id-at-commonName=Good Client,id-at-organizationName=Ian
Pilcher,id-at-localityName=Carrollton,id-at-stateOrProvinceName=Texas,id-at-countryName=US)
  Certificate (id-at-commonName=Client CA,id-at-organizationName=Ian
Pilcher,id-at-localityName=Carrollton,id-at-stateOrProvinceName=Texas,id-at-countryName=US)

as expected, and good-client.crt is indeed signed by client-ca.crt .
Again the issue appears to be that Pg can't find the root of trust,
which is fair enough given that it is not present in Pg's root.crt or
server.crt and it isn't installed system-wide either. We could add it to
the server's root.crt but that'd cause the issues that started this thread:

# cat $CERTS/client-ca.crt $CERTS/root-ca.crt > root.crt
# systemctl restart  postgresql-9.2.service

the good client cert works now:

$ psql "postgresql://localhost/?sslmode=verify-ca"
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)

PROBLEM VERIFIED
--

... but so does the one we don't want to trust, as per the problem report:

$ cat $CERTS/bad-client.crt $CERTS/server-ca.crt > postgresql.crt
$ cp $CERTS/bad-client.key postgresql.key
$ chmod 600 postgresql.key
$ psql "postgresql://localhost/?sslmode=verify-ca"
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)

So this problem is verified.


THE SOLUTION


What we need to happen instead is for root.crt to contain only the
trusted certificates and have a *separate* file or directory for
intermediate certificates 

Re: [GENERAL] [HACKERS] Trust intermediate CA for client certificates

2013-03-17 Thread Craig Ringer
On 03/09/2013 04:52 PM, Ian Pilcher wrote:
> 3. Once the root CA certificate is trusted, however, the "bad" client
>can also connect by using a certificate chain that includes the
>Server CA certificate --"cat bad-client.crt server-ca.crt >
>~/.postgresql/postgresql.crt".
>
> After looking at be-secure.c and investigating the way that OpenSSL
> validates certificates, I do not believe that there is any way of
> achieving the desired behavior with the current codebase.
I'm testing this and looking into it now.

At first glance this looks like a genuine problem. We need to be storing
the certs used for validating client cert auth separately from the
certificate chain that links those certs to trusted self-signed CA
roots. I was under the strong impression that OpenSSL would do this if
the client validation certs were in root.crt and the certificate chain
was in OpenSSL's certificate search path and am testing that now. Even
if that's the case we need to at least document this issue and
preferably detect the case where root.crt contains a certificate chain.

If this tests out as expected you need to consider the effects it'd have
on people who're not using self-signed CAs, but are instead using certs
signed by big CAs. *Any other customer of the same CA could potentially
connect to your server with a genuine, valid client cert issued to them
by the CA*. Ouch.

I'm going through and reproducing the problem now and will also test
OpenSSL certificate chain lookup path configurations to see if there's a
way to set things up correctly with the current backend code. I'll
report back shortly.

-- 
 Craig Ringer   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services



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