(Last modified: 07/15/01)

 

Introduction

This document demonstrates how Apache can be used to control access based on a web client's digital certificate. Three machines are used in this example:

 

  • A Certificate Authority (CA), running OpenBSD, which validates and signs the client keys,
  • A web server, running OpenBSD and Apache + mod_ssl, which only allows users with certificates signed by the CA to view its protected pages, and
  • The client, running Windows 2000 and IE 5.5, which requests a key with openssl.exe, and attempts to view the pages protected by the web server.

    Note that in a production environment, the CA should be a separate machine and disconnected from the network.

     

    Create the Certificate Authority (CA)

    On the machine used for the CA, create a directory for its keys:

     

    mkdir -p /etc/ssl/ca/private
    chown -R root:wheel /etc/ssl/ca
    chmod 700 /etc/ssl/ca/private
    

    Next, generate a private key and a certificate request, and then self-sign the certificate.

     

    openssl genrsa -out ca.key 1024
    openssl req -new -key ca.key -out ca.csr
    openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
    

     

    Setup the Web Server Certificate

    On the web server, create a self-signed certificate for SSL requests:

     

    openssl genrsa -out server.key 1024
    openssl req -new -key server.key -out server.csr
    openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
    

    Make sure the path(s) to the server certificate are correct in /var/www/conf/httpd.conf.

     

    Install the CA Certificate on the Web Server

    Copy the CA certificate (via floppy) to /var/www/conf/ssl.crt/ca.crt, on the web server.

    Tell the web server (Apache) where it can find the CA certificate, in httpd.conf:

     

    <VirtualHost _default_:443>
    ... 
    SSLCACertificateFile /var/www/conf/ssl.crt/ca.crt
    ...
    </VirtualHost>
    

     

    Require a Certificate for Access

    Tell Apache which URL (in this case /cert) to require authentication for. httpd.conf:

     

    <VirtualHost _default_:443>
    ...
    <Location /cert>
       SSLRequireSSL
       SSLVerifyClient require
       SSLVerifyDepth 10
    </Location>
    ...
    </VirtualHost>
    

    Shutdown and Restart httpd:

     

    apachectl stop
    /usr/sbin/httpd -DSSL
    

    Have the Client Request a Certificate

    On the client, generate a private key and certificate request:

     

    openssl genrsa -out client.key 1024
    openssl req -new -key client.key -out client.csr -config openssl.cnf
    
    OpenSSL for Win32 can be downloaded here.

    Note that OpenSSL won't be able to obtain a nice pseudo-random sample for its key generation, and will complain. However, it will allow you to specify a document for added entropy with the -rand switch. In testing, I created a file on the OpenBSD machine with dd if=/dev/srandom of=output.txt bs=4096 count=1, copied that file to Windows, and generated a key with openssl genrsa -rand output.txt -out client.key 1024.

     

    Have the Authority Sign the Certificate

    Copy the client request to the CA (via floppy), and sign the client request with the CA's private key:

     

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

    Copy the signed certificate (client.crt) back to the client.

     

    Import the Client Certificate

    Create a PKCS#12 document from the client private key and the signed certificate:

     

    openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12
    
    Double click client.p12 to import, and select the default values.

    Finally, attempt to access the protected server pages (e.g. http://www.server.com/cert/).

    Known Issues

    The example generates 1024-bit keys. I tried 4096-bits for each key without success. Please drop me a note if you've solved this dilema.
  • No labels