9

I'm using apache2 (2.2.3) to serve a site where I'd like to have clients authenticate with certificates. Since I only need to verify that a user presenting a particular certificate is the same user who has presented that certificate in the past, the CA signing the certificate is irrelevant. It seems, though, that using SSLVerifyClient require requires SSLCACertificateFile ... (or SSLCACertificatePath ...), and then apache will only accept certificates signed by a CA in that file/path. Is there a way to get apache to accept any client certificate, regardless of the issuing/singing CA? (i.e. verify that the client has the corresponding private key to the presented public key, but not bother verifying the issuing/signing CA)

6
  • How do you plan on tracking which certificates have authenticated? Apr 21, 2012 at 20:29
  • @ShaneMadden: Something like a table mapping certificates to internal user IDs. The mechanics of the public-key cryptography would take the place of a password exchange.
    – Isaac
    Apr 21, 2012 at 20:34
  • 2
    Right - what I'm getting at is that Apache doesn't do a table mapping certificates to internal user IDs. If you're going to have users authenticate with client certificates, why not give the users certificates that you sign? As you've mentioned, there are OpenID providers who do exactly that. Apache's mod_ssl was designed to authenticate users based on a certificate signing relationship; if you'd prefer to disregard that for some reason then you'll need to implement the certificate authentication in your own code that's also handling your certificate-to-user mapping. Apr 21, 2012 at 20:43
  • @ShaneMadden: I was hoping to avoid issuing certificates and if I only accept certificates that I issued, then smartcard-based certificates are out. No matter what I do, some part of the system is going to take place at the application level, but since there's all the mod_ssl machinery there, I was hoping that it could take care of some of the work for me.
    – Isaac
    Apr 21, 2012 at 20:47
  • 1
    @ShaneMadden One advantage of optional_no_ca is that it can be better for the UI, since you can display an HTTP error message if something is wrong with the certificate (you couldn't otherwise, since a bad client cert would stop the connection before the HTTP layer). It's also useful if you want to try alternative ways of verifying a cert (e.g. WebID). You're right you'd want something to do the verification though, and that would only really work when the request is handled by code (e.g. within PHP/CGI/Java), not so much with files.
    – Bruno
    Apr 22, 2012 at 17:43

2 Answers 2

11

As you've found, you can disable the certificate verification at the SSL/TLS handshake level within Apache Httpd by using SSLVerifyCLient optional_no_ca.

The second problem you're going to face with what you're trying to do is to get the client to send the certificate. Since your certificate are not intended to be within a PKI, they could be self-signed and have various issuers.

When requesting a client-certificate, the server sends a CertificateRequest TLS message to the client during the handhsake. This message contains the certificate_authorities list:

A list of the distinguished names of acceptable certificate authorities. These distinguished names may specify a desired distinguished name for a root CA or for a subordinate CA; thus, this message can be used to describe both known roots and a desired authorization space. If the certificate_authorities list is empty then the client MAY send any certificate of the appropriate ClientCertificateType, unless there is some external arrangement to the contrary.

Browsers use this to choose which client certificate to send (if any).

(Note that the part about the empty list is only in the specification from TLS 1.1 onwards. SSL 3.0 and TLS 1.0 are silent on this, and in practice, it will also work.)

You get two options for this.

  • If the client certificates you expect are going to be self-signed, they will all have different issuers. Because you won't know what to expect, the server will need to send an empty list. To do this, use the SSLCADNRequestFile directive and point it to a file that contains just an empty line (if I remember well, it doesn't work with a completely empty file).

  • The second (less clean) option. Is to agree on an Issuer DN common to all the client certificates you expect, whether or not they have indeed been issued by that CA certificate (or whether or not that CA even exists). By doing so, you'd be breaking the PKI model considerably (more).

    If you agree on an Issuer DN like CN=Dummy CA (for example). Anyone can build a self-signed certificate using CN=Dummy CA as Subject DN (and Issuer DN), possibly with different keys. Although the SSLCADNRequestFile directive expects to be configured with certificates to build the list, these are not used to verify the client-certificate at all, it's just a complicated (but natural in the context of the other directives) way of configuring the certificate_authorities list. If you, as a service, puts a self-signed cert with these names in SSLCADNRequestFile, this will make the CertificateRequest TLS message use CN=Dummy CA in the certificate_authorities list (these are just names, not certs at this stage). The client will then be able to pick up its own certificate with Issuer DN CN=Dummy CA, whether or not its signature could be verified by that certificate (same keys) or not, since no signature verification is involved in these steps anyway.

This being said, remember that with SSLVerifyCLient optional_no_ca, no real certificate verification is made (I suppose you could check the SSL_CLIENT_VERIFY variable if your manual verification is just a fallback solution to a PKI you have configured anyway). All you'll know at that stage is that the client has the private key for the public key certificate it has presented (guaranteed by the TLS CertificateVerify message): you will need to perform some form of verification if you want there to be authentication of some sort. (You can't trust any of the content of the certificate, that is any of the binding between its public key and the names/attributes it contains.)

This won't work well for files, but you can do this for an application (e.g. PHP/CGI/... even Java if you pass the certificate to the proxied Java server). One basic way would be to have a pre-known list of public keys, or you could look at the ideas in FOAF+SSL/WebID.

2

Using SSLVerifyCLient optional_no_ca (instead of require) causes apache to not check the issuing CA (and thus not need a CA certificate file or path). It does permit the client/user to not submit a certificate, so checking that a certificate was used at all has to be done separately.

(Apparently, I just failed to thoroughly read the mod_ssl documentation.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .