1

Is it possible to configure Apache (or any other SSL-aware server) to only accept connections from clients presenting a certificate from a pre-defined list? These certificates may be signed by any CA (and may be self-signed).

A while back I tried to get client certificate validation working in the EPP system of the domain registry I work for. The EPP protocol spec mandates use of "mutual strong client-server authentication". In practice, this means that both the client and the server must validate the certificate of the other peer in the session.

We created a private certificate authority and asked registrars to submit CSRs, which we then signed. This seemed to us to be the simplest solution, but many of our registrars objected: they were used to obtaining a client certificate from a CA, and submitting that certificate to the registry. So we had to scrap the system. I have been trying to find a way of implementing this system in our server, which is based on the mod_epp module for Apache.

Gavin Brown
  • 103
  • 1
  • 9

2 Answers2

3

It may be possible to do with just the core mod_ssl, using SSLRequire. Im not sure the exact SSL variable you would want, but something like this should work:

SSLRequire %{SSL_CLIENT_S_DN_UID} in { file("/tmp/list") }

Alternatively, you can map some certificate attribute to the user name that usually comes from HTTP Authentication (.htaccess type restrictions):

.htaccess:

SSLOptions +FakeBasicAuth SSLUserName SSL_CLIENT_S_DN_CN AuthGroupFile /tmp/SSL_Groups Require group my-users

/tmp/SSL_Groups:

my-users: uid=bob,dc=site,dc=com uid=jane,dc=site,dc=com

Again, I'm not 100% on what SSL_CLIENT_S_DN_CN looks like, but you get the point.

Jeff Warnica
  • 474
  • 2
  • 8
  • I have a further question about the SSLRequire directive: I am having trouble getting the file() function to work. Doing this works fine with a test certificate: SSLRequire %{SSL_CLIENT_M_SERIAL} in { "[hex code]" } as does this, but only if /tmp/list contains only a single serial number, without a terminating newline: SSLRequire %{SSL_CLIENT_S_DN} in { file("/tmp/list") } What format should the file be in? I've tried separating entries with newlines and commas with no joy. – Gavin Brown Apr 26 '10 at 12:23
  • Further to my earlier comment: the file() function is extremely limited, and won't work in the way you've described: it is interpreted purely as a string, so you can't put multiple DNs in a file and have Apache grep the file. – Gavin Brown May 04 '10 at 16:59
  • Well, I think the +FakeBasicAuth should work as described. – Jeff Warnica May 05 '10 at 15:45
2

You should be able to setup a directory with all the CA certificates you trust and then point at that with the SSLCACertificatePath directive so you can authenticated based on any certificate. Then as Jeff mentioned use SSLRequire to limit access to the set of certificates you want to permit.

If your system doesn't already have a set of common CAs certs installed then you could copy them from somewhere else. The Debian the ca-certificates package may be a good starting point.

Zoredache
  • 130,897
  • 41
  • 276
  • 420
  • interesting but it sounds like the client would still needs to accept the 3rd party certs and install them into their own cert store right? – djangofan Jun 17 '10 at 19:38
  • @djangofan, Yes, to authenticate with a client certificate the end-user must get the certificate from somewhere and install it into the certificate store used by their browser. – Zoredache Jun 17 '10 at 20:36