Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I generate self-signed client certificates for a little Apache server hosted under my stairs. The script below was hacked together for this purpose - note it uses the 'mini-CA' x509 method, therefore recording nothing in an index.txt.

Now I need to revoke one such client certificate, which entails generating a CRL and adding it to Apache. CRL generation seems to require an index.txt however:

root@myserver:~# openssl ca -cert "ssl_ca/ca.crt" -keyfile "ssl_ca/ca.key" -revoke "ssl_badguy/badguy.p12"
./demoCA/index.txt: No such file or directory
unable to open './demoCA/index.txt'

Is there a 'standalone' CRL generation command, as per cert creation? I don't care about persistence of CAs or respecting proper SSL 'theory' (otherwise there'd be no self-signing for a start). Originally I just wanted to secure and control access to my server; now I just want to revoke some of that access.

When called as per ./clientcert.sh certname, the following script makes a new directory /root/ssl_certname/ with all the bumf (including PKCS12).

#! /bin/bash

echo 'When it asks for a key password (3 times), recommend you use the new key name'
echo 'When it asks for cert details, use "." (blank) for all, EXCEPT CN, which should'
echo 'also be the key name. All other passwords ("Export" etc.) are blank'

clientname="$1"
newdir="/root/ssl_$1"
caloc="/root/ssl_ca"
cert="$newdir/$1"

if [ -d "$newdir" ]; then
    echo "$newdir already exists!"
else
    mkdir "$newdir"
    cd "$caloc"

    openssl genrsa -des3 -out "$cert.key" 2048
    openssl rsa -in "$cert.key" -out "$cert.key.insecure"
    mv "$cert.key" "$cert.key.secure"
    mv "$cert.key.insecure" "$cert.key"

    openssl req -new -key "$cert.key" -out "$cert.csr"

    openssl x509 -req -days 365 -CA ca.crt -CAkey ca.key -CAcreateserial -in "$cert.csr" -out "$cert.crt"

    openssl pkcs12 -export -clcerts -in "$cert.crt" -inkey "$cert.key" -out "$cert.p12"
fi

EDIT: Technically doesn't solve the issue, but I've achieved the same thing by adding the following to my default-ssl vhost:

# Block badguy client cert
Rewritecond %{SSL:SSL_CLIENT_S_DN_CN} =badguy
RewriteRule (.*) /blocked [QSA,R,L]

- where /blocked doesn't actually exist (I guess I could put a holding page there).

share|improve this question
add comment

3 Answers

up vote 2 down vote accepted

First off, let's be clear: the client certificates are not self-signed. They are signed by a CA, and that CA's certificate is self-signed. This is important, because a self-signed certificate cannot be revoked at all, by definition: revocation is an information coming from the issuing CA; a self-signed certificate is its own CA.

A second important point is that a CRL is a list of revoked certificates so far. So if you revoke one certificate, then you have a CRL which designates that certificate; if you then revoke another one, then your next CRL must designate both certificates. If the next CRL only talks about the second certificate, then it "unrevokes" the first one. For revocation, Apache has no memory, or rather, the CRL is Apache's memory. Apache will use the latest CRL as the exclusive source of revocation information for all certificates.

This means that you really need to maintain a list of revoked certificates on the CA. The openssl command-line tool can maintain such a list for you: that's the index.txt file, as maintained by the openssl ca command-line option. If you don't use it, then you will have to maintain the information yourself, which is, at best, cumbersome. If you want to handle revocation at all, then the simplest way is to use the index.txt and let OpenSSL manage it.

Now if you have already done it, then it is of course possible to sign a CRL with the CA private key using the library, programmatically; but there is no command-line tool for that. This is said so in the documentation:

BUGS

Ideally it should be possible to create a CRL using appropriate options and files too.

And also there:

RESTRICTIONS

The text database index file is a critical part of the process and if corrupted it can be difficult to fix. It is theoretically possible to rebuild the index file from all the issued certificates and a current CRL: however there is no option to do this.

To produce a CRL with some code, I suggest that you have a look in the OpenSSL source code, in the apps/ca.c file; search for "X509_CRL_new". The functions are not well documented... But, I insist, if you begin to revoke certificates then you must maintain a list of all certificates revoked so far (at least the serial numbers, preferably with the revocation date for each of them), and this basically means making your own equivalent of the index.txt file of openssl ca.

share|improve this answer
    
Thanks again for your informative answer. –  benxyzzy Oct 14 '13 at 22:58
add comment

Now I find that I must add another answer, at another level.

You are trying to use certificates for authorization. Don't. It does not work well in the long term.

Certificates are for authentication. A certificate tells you: this guy owns that public key. Revocation is a way to cancel that, and is meant to be used when the key ownership is no longer maintained: e.g. the private key was stolen, so the guy no longer "owns" the public key. In your case, the key ownership is still valid: though the guy is declared unwelcome, he still owns the public key from his certificate. In that sense, revocation is not the proper tool.

In technical terms, it all boils down to the facts that certificate distribution is expensive, and certificate revocation is asynchronous. The "right" way to do things is to use certificates for authentication (the client proves his identity), but to handle authorization elsewhere: authorization is the process by which you determine what actions are allowed for a given identity. Trying to push authorization bits into the certificate is a path which leads to sorrow (a classic mistake which everybody involved in PKI does at some point, but still a mistake).

The mod_authz_user module might help you maintain authorization information (e.g. the list of allowed or denied users) in handy files (I have not tried).

share|improve this answer
    
Helpful advice, but what other motivation is there for proving identities, except to control access? Your description fits server certs, but we're talking client certs here. I've only ever seen people care about the identity of their clients, when they want to restrict access for some of them. Isn't this the whole basis of SSL usage in OpenVPN, for example? I would happily use any 'authorization' method based on browser-communicated files rather than user-entered credentials. –  benxyzzy Oct 9 '13 at 15:12
    
The point is that certificates are not good at doing authorization stuff. "Proving an identity" is not the same as "controlling access": to prove the identity is the first step, but there is a second step which is called "authorization" ("ok, we now know this is Bob; what is Bob allowed to read or write ?") and certificates are not appropriate for that. There are simplified scenarios where access is all-or-nothing, and in these case one can see the authentication step as being sufficient, but that's not really true; it leads to problems (e.g. your problem with revocation). –  Tom Leek Oct 9 '13 at 15:28
    
Isn't this semantics? I guess you could say I am using the client certs to prove identity; the second 'what is allowed' step happens via my Rewriterules based on CN (similar to the OP). Alternatively, it happens when the client cert doesn't correspond to Apache's ca.crt, or no client cert is provided. If client cert support was meant only for identification purposes, why does Apache need to know the CA? Why would it matter? (Sorry for my persistence, this is purely interest rather than disagreement) –  benxyzzy Oct 9 '13 at 15:38
    
Apache uses the CA to verify the signature on the certificate sent by the client. What happens is that the client shows his certificate and demonstrates his mastery of the corresponding private key by producing a signature (this is part of the SSL handshake). The server (Apache) verifies that signature with regards to the public key in the certificate, and verifies the signature on the certificate with regards to the CA public key (which is in the ca.crt file). All of this shows that the client is really the one whose name is in the certificate. –  Tom Leek Oct 9 '13 at 15:51
    
So knowing the CA is important for the authentication process to take place: it allows Apache to decide whether the client certificate is genuine or not. But once the client is authenticated (Apache knows who the guy is), the server must still decide whether this client is to be granted access, and, more generically, what parts of the site it may read. This decision is authorization and takes place after authentication. By using the certificate for authorization, you run into your present problem: you know who the client is, and yet you do not want to grant him access. –  Tom Leek Oct 9 '13 at 15:54
add comment

The index.txt file is used to keep track of the generated certificates and some properties, like the revocation date. This file is used to generate the CRL.

-gencrl

    this option generates a CRL based on information in the index file.

You can change the default file in the openssl.conf file if needed, or use your own like in : http://stackoverflow.com/a/7770075, or as the next answer suggests it, try to do the job manually using x509 commands: http://stackoverflow.com/a/13047670.

The latter uses -CAoptions to circumvent the default options of openss.conf. Please be advise that the index.txt file is an important part of the openssl CA setting and should not be dismissed in a production environment.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.