4

I have a CA hierarchy like this:

               Root-CA
          ________|_____________
         |                      |
      TEST-CA             PRODUCTION-CA
    _____|_____             ____|____
   |           |           |         |
TEST-SRV   TEST-CLI    PROD-SRV   PROD-CLI

From the perspective of the production server identified by the PROD-SRV server certificate, how would I setup Apache mod_ssl to require the PROD-CLI client certificate signed by the PRODUCTION-CA and not allow a client with the TEST-CLI certificate signed by the TEST-CA?


Currently I have:

SSLCertificateFile      prod_srv.crt
SSLCertificateKeyFile   prod_srv.pem
SSLCADNRequestFile      prod_ca.crt
SSLCACertificateFile    root_ca.crt

This looks like it is working because the server asks the browser for the PROD CLI certificate but if I provide TEST CLI certificate a valid certificate path is constructed and a test client is accepted onto the production system.

moosaka
  • 143
  • 1
  • 5

2 Answers2

2

Look into the SSLRequire directive - the following rule should look at the Issuer field (i.e. the CA certificate) of the certificate presented, pick out the CN, and match it against the name of your PRODUCTION-CA certificate.

SSLRequire %{SSL_CLIENT_I_DN_CN} == "PRODUCTION-CA"
meulop
  • 726
  • 5
  • 10
  • Thanks meulop! This solution works when `SSLVerifyClient` is set to `optional`. I was hoping there would be a way to implement this simply through defining trust, making the chain validation fail without explicitly checking parts of the certificates. If nobody provides such a solution I shall accept yours in a few days. I appreciate your help! – moosaka Mar 06 '12 at 12:24
  • Is this solution vulnerable to implicit trust attacks? (i.e. if someone manages to obtain a CA certificate you trust, with the name `PRODUCTION-CA`.) Can you check against a specific public key here, or maybe there is some other way to tell Apache "only trust certificates issued by this specific CA certificate"? – mpontillo Jun 12 '12 at 01:02
  • Never mind. Looks like you'd do it with [SSLCACertificateFile](http://httpd.apache.org/docs/2.0/mod/mod_ssl.html#sslcacertificatefile) set to `PRODUCTION-CA`. And in your case this might be fine because you have `root_ca.crt` (your own) specified in the configuration. I was worried about implicit trust from a public CA. I guess from a general security perspective it's better to trust *less*, so why not use the production CA and just exclude everything else? – mpontillo Jun 12 '12 at 01:07
2

I wanted to authenticate clients with certs issued by sub-CAs of an intermediate CA, i.e. like the following:

               Root-CA
                  |
            Intermediate-CA
          ________|_____________
         |                      |
      SUB-CA 1               SUB-CA 2
    _____|_____             ____|____
   |           |           |         |
TEST-SRV   TEST-CLI    PROD-SRV   PROD-CLI

You can use the SSL_CLIENT_CERT_CHAIN_n variable to inspect the chain, and e.g. do the following:

SSLRequireSSL
SSLVerifyClient require
SSLCACertificateFile ".../root-ca.cert.pem"
Require expr %{SSL_CLIENT_CERT_CHAIN_1} == file(".../intermediate.cert.pem")

or even multiple first-level intermediate CAs:

Require expr %{SSL_CLIENT_CERT_CHAIN_1} in { file(`".../intermediate.cert.pem"), file(".../intermediate2.cert.pem") }
Marcel Klehr
  • 121
  • 2