the djb way

secure socket solutions


example: https with publicfile

With ucspi-ssl, we are now free to put up SSL-enabled versions of our existing services. As a starting point, let's return to the publicfile web server, httpd.

We consider publicfile here primarily for the purposes of becoming familiar with ucspi-ssl. After all, publicfile is targeted for serving information that is intended to be public; it will rarely make sense to encrypt this server with SSL.

Then again, not everything we do has to make sense, either.

Anyway, to get started, we need to apply a small patch to publicfile, so that it will recognize "https://" requests. This patch, also by William Baxter, is available at http://www.superscript.com/patches/publicfile.sslserver. Download, apply the patch, and rebuild publicfile:

# cd /usr/local/djb/build/publicfile-0.52
# patch -p1 < /path/to/publicfile.sslserver
# make

Before installing the patched version, you will need to shut down any publicfile services already running:

# svc -d /service/httpd
# make setup check
# svc -u /service/httpd

Great, the patched httpd binary is installed. Now we need to make a "certificate" for our SSL-enabled server. We keep things simple, and create a self-signed certificate and unencrypted private key for our https service with a single command:

# cd /etc/ssl
# openssl req -new -x509 -nodes -days 730 \
> -newkey rsa:1024 \
> -keyout private/https.key \
> -out https.cert

When you run the command, you will be prompted with a dialogue to input values for the certificate, something like this (our input is in bold):

# openssl req -new -x509 -nodes -days 730 \
> -newkey rsa:1024 -keyout private/https.key -out https.cert
Generating a 1024 bit RSA private key
............................++++++
.....................++++++
writing new private key to 'private/https.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:UG
State or Province Name (full name) []:Uganda
Locality Name (eg, city) []:Kampala
Organization Name (eg, company) []:Example Org
Organizational Unit Name (eg, section) []:publishing
Common Name (eg, fully qualified host name) []:www.example.org
Email Address []:postmaster@example.org

Make whatever entries you find suitable for your service. However, for best results, the entry you make for "Common Name" should match the FQDN used by clients to access the service. In the example here, we will expect clients to reach the service by typing:

https://www.example.org/

into their browser. So we set the Common Name to "www.example.org".

The openssl command will generate two files we will use with the service:

We'll see these used in a moment. For now, just note a few particulars for ucspi-ssl:

Now for the publicfile-httpsd service. First create the local service directories:

# mkdir -p /var/svc.d/publicfile-httpsd/{log,env}

Copy this "run" script into /var/svc.d/publicfile-httpsd/run:


#!/bin/sh
# publicfile-httpsd/run
# daemontools service for publicfile httpd w/ ssl
# ===
CONLIMIT=71
HTTPS_ARCHIVE="/var/public/https"

exec 2>&1
echo "*** Starting publicfile-httpd (w/ ssl) on ${HTTPS_ARCHIVE}:"
exec envdir ./env envuidgid publicfile softlimit -o20 -d500000 \
  sslserver -vDRH -l0 -b50 \
  -c ${CONLIMIT}  \
  0 443 \
    /usr/local/publicfile/bin/httpd ${HTTPS_ARCHIVE}

### that's all, folks!

Make the file executable with chmod 755. Note that we recycle the unpriveleged user account "publicfile" to run this service with envuidgid. This script is almost identical to the one we installed for the original publicfile-httpd service, with these differences:

We use envdir to set the environmental variables used by sslserver to tell it where to find our keys and certificates. These are setup like so:

# cd /var/svc.d/publicfile-httpsd
# echo "/etc/ssl/https.cert" > env/CERTFILE
# echo "/etc/ssl/private/https.key" > env/KEYFILE

Also, if your build configuration entries in the conf-* files don't match the actual OpenSSL installation on your host, you should specify the actual locations now:

# echo "/etc/ssl/dh1024.pem" > env/DHFILE

Set up the multilog-er for the service as usual, with this run script in /var/svc.d/publicfile-httpsd/log/run:


#!/bin/sh
# publicfile-httpsd/log/run
# multilogger for publicfile-httpsd service
# ===
exec setuidgid multilog multilog t /var/multilog/httpsd


Make the script executable, chmod 755, then setup the log directory:

# mkdir /var/multilog/httpsd
# chown multilog /var/multilog/httpsd

The last thing to do before starting the service is to set up the document archive. Review the original instructions for publicfile-httpd for details. These commands may suffice to create the archive and install a test document:

# mkdir -p /var/public/https/0
# cd /var/public/https
# ln -s 0 www.example.org
# cd 0
# cat <<EOF > 0/index.html
<html>
<head>
<title>publicfile with ssl!</title>
</head>
<body>
<p>
This is publicfile, with ucspi-ssl!
</p>
</body>
</html>
EOF

At last, the big moment, starting the service:

# ln -s /var/svc.d/publicfile-httpsd /service/httpsd

Follow the log in another terminal, to make sure the service started correctly:

$ cd /var/multilog/httpsd
$ tail -f current | tai64nlocal

If you see any problems, you may need to do more than the usual trouble-shooting:

Otherwise, if the log looks okay, test the service with your browser, something like Mozilla or an SSL-enabled lynx. Mozilla will ask you some questions about trusting the self-signed certificate; just click your way through and your page will appear!

The ucspi-ssl package also has an https@ utility, the analogue of ucspi-tcp's http@ utility. For it to work properly, you will need to feed it the name of your server's certificate file as the certificate authority, with the -a option:

$ https@ www.example.org / 443 -a /etc/ssl/https.cert

If all goes well, you will see your test page.

Do note that the sslclient used in https@ is very picky. If the FQDN doesn't match the Common Name in the certificate, sslclient will refuse the connection.

When you get this service running, you've cleared a big hurdle. From here on out ucspi-ssl services will be child's play!


Copyright © 2004, Wayne Marshall.
All rights reserved.

Last edit 2004.02.06, wcm.