"Linux Gazette...making Linux just a little more lovable!"


Stronghold : Undocumented Fun

By James Shelburne, brammal@iamerica.net


Disclaimer: Secure Socket Layer technology is a pretty touchy legal matter. There's lots of money riding on it for a relatively small number of companies. Therefore keep in mind that what I say in this article may not be correct. If you plan to use Stronghold/Netscape (or any other SSL server/client pair) for inter-office communication get legal advice, or make sure you know what you're doing.
Also I won't go into some of the knowledge that I think you already have, like the basics of public key cryptography or the fact that SSl URLs are https:// instead of https://.

If you've looked for affordable ways to incorporate Secure Socket technology into your intranet you've probably run into Stronghold. Although Stronghold runs on platforms other than Linux it's a great, low resource intensive way, to use a spare Linux box for providing encrypted/authenticated document transfers over the Internet. This is perfect if you need to "network" separate offices over the Internet without worrying about prying eyes looking in on your document transfers.
The main problem you face when trying to use Stronghold for inter-office communication is the lack of good documentation. Stronghold is mainly intended for companies who want to receive credit card orders on-line. As such, the installation scripts and documentation don't go into much detail about setting up Certificate Authorities (more on this later) and the features that allow you to not only have server authentication, but also client authentication as well. To clarify things a bit I'll give you a short "tutorial" on Secure Socket features. Since Netscape is the only browser that currently has a decent Secure Socket Layer (or SSL from here on out) implementation, I'll use that.


Netscape Security

Start up Netscape (3.0) and select Options -> Security Preferences. Click on the tab that says Site Certificates. This dialog box contains information about what Certificate Authorities your browser currently recognizes and what level of trust you have assigned to each. To illustrate this, select United States Postal Service CA and click the button that says "Edit Certificate..."
Now you should see another dialog box pop up which contains various information on that particular certificate. Notice the two fields: "This certificate belongs to:" and "This certificate was issued by:". In both cases it contains the same information. This means that the certificate has been "self-signed" by the certificate owner.
A little further down in the dialog box you'll see a pair of "radio buttons" that allow you to either accept or deny connections from secured Web sites that have been certified with this key. In other words, if you allow connections from sites whose keys have been signed by the USPS you're telling Netscape that you trust the USPS enough to certify SSL-enabled Web servers and that no further proof of a server's identity is needed. In reality, the USPS doesn't publicly certify keys (at least that I know of), we're just using that as an example. The final check-box tells Netscape to warn you before a secure connection is established to a Web server that has been certified by this key. Click "Cancel" to exit this dialog box.
If you connect to a site that has not been certified by one of the CAs listed, all is not lost; you can still accept the individual site's key as an individual "Site Certificate."We won't worry about this method too much, but if you want to see which, if any, site certificates are installed in Netscape then select Site Certificates from the drop-down list above the "Site Certificate" list box. Note that, for some reason, Certificate Authority certificates are considered "Site Certificates."

What you've looked at here is enough for basic electronic commerce. In other words, if you want to send sensitive information to a Web site, all you really need to know is that the site is who it claims to be. The Certificate Authorities listed provide this level of security. If you want to use your Web server to distribute sensitive information to select individuals, Server Authentication doesn't do you much good. Client Authentication gives you the ability to authenticate the clients who connect to your SSL Web server.


Client Authentication

Client Authentication of one of the neatest features of Netscape. In the previous screen, select the tab that says Personal Certificates. If you installed any Client Certificates (doubtful) they'll be here. If a server requests Client Authentication, Netscape can perform one of three actions:

  1. Automatically decide which Client Certificate to send the server.
  2. Let the user decide which Client Certificate to send to the server.
  3. Send a particular Client Certificate to the server.

You can tell which action you want Netscape to perform by selecting the appropriate option from the drop-down list in the "Personal Certificates" dialog box.
Client certificates can be purchased from various Certificate Authorities. This can get to be expensive if you want to certify multiple client browsers, not to mention a hassle. Luckily Stronghold comes with the basic tools that will allow you to create your own small-time certificate authority that you can use to certify clients who connect to your server and even other servers on your intranet.


A look at the files

There are lots of relevant files that Stronghold works with. I'll list the main, non-HTTP-specific ones. I'll also assume you have installed the program in the default directory (preferred).

/usr/local/ssl/private/YOUR-SERVER.key This is your server's *private* key and should not be world-accessible at all. The way Stronghold installed the directory "private" is chmod 700 root.

/usr/local/ssl/certs/YOUR-SERVER.cert This is where your servers *public* key is located. This should be world-readable, and in fact your server won't work in secure mode if it is not.

/usr/local/ssl/CA/rootcerts.pem This file contains the public keys from the various CAs who issue Client Certificates. When your server wants to check that a Client Certificate is actually issued by a valid CA it looks in this file. This can be changed, but more on that later.

/usr/local/ssl/CA/cacert.pem When you start your own CA this file will contain your public key. Note: This is not your server's public key.

/usr/local/ssl/CA/private/cakey.pem The private key for your CA is stored here. As with all private keys, only root (or whatever username you administer your CA under) should be able to see or change it.

/usr/local/ssl/CA/ssleay.conf AND /usr/local/ssl/lib/ssleay.conf For one reason or another, Stronghold has two separate configuration files. There is only a slight difference between them and Stronghold seems to want to use them both so I'll describe the files as if they were one and point out the differences as we come to them.


The ssleay.conf file

ssleay.conf is the main configuration file for Stronghold's key processing tools. It's relatively complex but fairly well commented out so I won't go into the whole thing, just a general overview and extra explanation where I think it's necessary.

The thing that makes this configuration file different from what we've come to expect from Linux (and UN*X in general) is the way it's subdivided. If you've done much MS Windows programming you'll notice that it is divided into key=value pairs and most sections also have an "application name," for instance:

[ policy_match ]
countryName		= match
stateOrProvinceName	= match
organizationName	= match
organizationalUnitName	= optional
commonName		= supplied
emailAddress		= optional
In this section policy_match is the "application name" and the rest are standard key=value pairs. Here the whole section can be referenced by the label "policy_match"


Selected fields (from ssleay.conf):

default_crl_days: This "CRL" stumped me for a while. Apparently it has to do with Certificate Revocation Lists, a feature that is not really implemented in the SSleay toolkit (the package that was used to give Stronghold it's SSL capabilities). Actually that's not completely true, the CRL capability is there but CRL handling utilities aren't.

policy: The "policy" field lets you select which policy you want to sign keys under. You probably won't need to mess with this since, in most cases, you will check and sign keys by hand. If you want to use a specific policy (check the Stronghold docs, what there is of them ;) ) change this field to "policy_match" and edit the policy_match section below to reflect your chosen policy. The two possible values: policy_match and policy_anything are "application names" of the sections of the configuration file that define who you will and will not sign keys for, or your "policy."

distinguished_name: There is only one difference between the two different configuration files that Stronghold's key management tools use, and this is it. This key=value pair will point to one of two different "application names": req_distinguished_name or makeca_distinguished_name. The only time it will point to makeca_distinguished_name is when you are creating your own Certificate Authority, the rest of the time it will point to req_distinguished_name.

[makeca_distinguished_name]: This and the next entry are not key=value pairs, but rather "application names" that define particular groups of information.
The makeca_distinguished_name section of the file is only really referenced when you first create your CA. Also you do not need all of the fields that are included under this heading. For instance, when I made my CA key pair I removed both "organizationalUnitName" and "commonName." Because we aren't dealing with slick commercial software, it may object if you start altering this configuration file heavily.

[req_distinguished_name]: This section of the config file is where information on machines to certify is kept. When you create a key-pair/signing request for your SSl server with genkey, default information is looked up here. Feel free to change some of the fields if you don't want this much info in your keyfile. Beware, some commercial key signers (i.e. RSA or whoever) may object to altered request formats. As before, your CA may choke if it gets a request that has been highly altered. One field to especial watch out for is "commonName," this is where Netscape looks to see if a web server is using an appropriate keyfile for it's domain name. For example, if Netscape tries to make a secure connection to www.insecure.org and the keyfile that the server sends says it belongs to www.secure.org, you'll get a little dialog box warning you about a possible security problem. If no "commonName" is supplied, Netscape fails to connect and gives an error-message.


The programs

genkey:Genkey is the program that is used to generate an initial key-pair for your secure server and send out a signing request certificate to your chosen CA. Before you run genkey make sure and create backup of both your private and public keys for your Web server. After you make backups, delete the original keys as genkey won't operate if it finds that a key-pair already exists. Run the program like this:

genkey YOUR_SERVER_NAME

This will create a key-pair for your server and send out a Certificate Signing Request (or CSR). Since we are going to create our own CA and sign the key for the Web server with that, make sure that the CSR is sent to your own e-mail address and not Verisign. Now you have generated an initial key-pair and CSR. Get the CSR from your e-mail and save it for later.
Also note that the defaults for genkey are had from the req_distinguished_name section of /usr/local/ssl/lib/ssleay.conf, if there are fields you don't want included in your keyfile remove them from this section.

makeca: Makeca is the program that is used to actually create your Certificate Authority. This program gets it's default information from the file /usr/local/ssl/CA/ssleay.conf in the makeca_distinguished_name section (assuming you have installed everything in the default locations).
Makeca is executed without any arguments and is actually pretty intuitive. As before, if there are entries that you don't want in your CA's keyfile just remove their entries from the makeca_distinguished_name section of the relevant configuration file.

ca: Ca is the actual program that you will use to perform Certificate Authority functions. This includes signing other Web server keys and Netscape's client keys. Assuming that you have been following along up till now I'll assume that you have already used genkey to create a key for your Web server and that you have mailed the CSR to yourself. To sign your Web server's CSR save it as /tmp/csr and type the following:

ca -config /usr/local/ssl/lib/ssleay.conf -in /tmp/csr

ca will check the indicated configuration file to see what, if any, policy has been defined for signing keys and ask you for your CA password. After the key is signed it is stored in /usr/local/ssl/CA/new_cert/. New certificates are not stored by name but by serial number, with the newest cert having the highest number.
The cert is stored in PEM (Privacy Enhanced Mail) format and as such, can be included in e-mail as is.

getca: Once you have a signed certificate for your Web server you are ready to install it. Getca is the program for this and is called with:

getca YOUR_SERVER_NAME < /tmp/cert

We are assuming that /tmp/cert is your signed keyfile in PEM format.
One of the odd things about getca is that the input file must be "piped" into the program.
If this went correctly your Web server should now have a public key signed by your CA. Now for the tricky part...


Making Everything Work

Even though you now have a signed key certificate for your Web server you still can't use it. This is because Netscape isn't aware of your CA, this is to say that your CA isn't in the list of Site Certificates that we looked at earlier. To add your CA to that list follow these steps:

  1. Since the only (easy) way to install a key certificate in Netscape is through a Web server you'll have to add a new MIME type. I added mine to the mime.types file by adding a line like this:
    application/x-x509-ca-cacert       cacert
    
    There are other ways to add MIME types that don't involve messing with config files but I like the direct approach. Adding this MIME type tells Stronghold that every file that ends with a .cacert extension should be sent as a Certificate Authority's public key.

  2. The public key for your Certificate Authority is located in /usr/local/ssl/CA/cacert.pem. The only problem here is that it in in PEM format and Netscape expects CA keys to be in DER format. Luckily changing the format is pretty painless, simply move into the same directory as cacert.pem and type the following:
    x509 -outform DER < cacert.pem > cert.cacert
    
    Like getca, x509 requires input and output to be "piped." In any event your key is now in proper format and can be moved into one of your Web server's document directories.

  3. Now point Netscape at your freshly converted CA certificate (cert.cacert). Since you've added the appropriate MIME type Netscape will know that it is accepting a CA certificate and will lead you though the process of installing it.

With that out of the way you should now see your CA's key when you look in Netscape's Site Certificates dialog box. Now, when you connect with your Web server, Netscape will find the CA who signed the server's key and try to locate it in it's database of CA certificates. Since we've just installed your CA's certificate, Netscape should accept encrypted connections from any site that has been signed by your CA.


Client Certificates

Creating Client Certificates for Netscape is a pretty complex task, and one of the least documented features of SSL. All of Netscape's Client Certificate functions work through a WWW interface, and as such you'll need two special files: a HTML and a CGI, here are both:

key_req.cgi---------------------------------------------------------

#!/usr/bin/perl
read(STDIN,$input,$ENV{'CONTENT_LENGTH'});
open(TEST, ">/tmp/client_csr");
$input =~ s/\+/ /g;
$input =~ s/&/\n/g;
$input =~ s/%2B/\+/g;
$input =~ s/%2F/\//g;
$input =~ s/%3D/=/g;
$input =~ s/%0A//g;
print TEST ("$input");
print("Content-type: text/html\n\n$input\n");
--------------------------------------------------------------------

keygen.html---------------------------------------------------------
<HTML><HEAD>
<TITLE>Make akey</TITLE></HEAD><BODY>
<FORM ACTION="/cgi-bin/key_req.cgi" METHOD=POST>
E-mail: <br>
<INPUT TYPE="TEXT" NAME="Email" MAXLENGTH=40SIZE=40><br>
Common Name: <br>
<INPUT TYPE="TEXT" NAME="CN" MAXLENGTH=64 SIZE=64><br>
Organization Name:  <br><INPUT TYPE="TEXT" NAME="O"><br>
Organization Unit:  <br><INPUT TYPE="TEXT" NAME="OU"><br>
Locality:           <br><INPUT TYPE="TEXT" NAME="L"><br>
State or Province:  <br><INPUT TYPE="TEXT" NAME="SP"><br>
Country (2 letter): <br>
<INPUT TYPE="TEXT" NAME="C" MAXLENGTH="2" SIZE="2"><br>
<KEYGEN NAME="SPKAC" CHALLENGE="testkeygen"><br>
<INPUT TYPE="submit" VALUE="Generate Key"></FORM>
</BODY></HTML>
--------------------------------------------------------------------
These files may need a little modification to work on your system, but they should work like this:

keygen.html This is the actual HTML that Netscape needs to process a key request. Like many things in Stronghold's SSL key management utilities, you can omit just about whatever fields you want. For instance you might want to only create keys that have an e-mail address and a name, for this you would just remove everything except those two fields. This HTML was snagged from the SSL user mailing list archive at https://remus.prakinf.tu-ilmenau.de/ssl-users/

key_req.cgi This is the CGI program that will take Netscape's key request and format it into something that your CA can understand and sign. The script outputs two copies of the key request, the first goes to /tmp/client_csr and the second is echoed back to Netscape as text.


Making A Signed Client Certificate

To create a Client Certificate signed by your CA follow these steps:

  1. Assuming you have correctly installed both the CGI and HTML, load the HTML form into Netscape. From the drop-down list select the key-size that you want. If you are using the export version of Netscape you won't be able to choose a key size any larger than 512 bits. Fill in the fields with the desired information and select Generate Key. Netscape will lead you through the steps of creating your key. When you see the text of the client_csr echoed to the screen, you'll know that the script has been completed.

  2. Go into your CA directory and type:
    ca -spkac /tmp/client_csr -out /tmp/clientcert.der
    
    You'll be asked for your CA password and, if all goes well, a signed Client Cert will be output into /tmp/clientcert.der.

  3. As with installing CA certificates Netscape needs a special MIME type telling it that a particular file is a Client Certificate. Install this MIME type just like you installed the previous one:
    application/x-x509-user-cert              der
    
    This will tell Stronghold to use this MIME type for every file that ends in the .der extension.
    Whenever you change the configuration files you will have to restart the server so that the changes will take effect. Stronghold comes with a script called reload that does this for you.

  4. Move clientcert.der into a directory of your Web server and point your copy of Netscape at it. Netscape will then guide you through installing your new Client Certificate.
    As you do this keep in mind that you won't be able to make a key with one copy of Netscape and install the signed certificate in another. This is because every time Netscape makes a key it keeps various information in a database file. Because it is in a file you don't have to worry about creating the key and installing it in one session. You can even shut down Netscape and install the key the next day without running into any problems.

After the certificate is installed select Options -> Security Preferences and click the Personal Certificates tab. Your new Client Certificate should appear in the listbox.
If you're not the only person who has access to your machine, or even if you *think* that you are. It's a good idea to password protect your Client Certificate, this way someone won't be able to masquerade as you by simply having access to your computer. In Options -> Security Preferences, selecting the Passwords tab will bring up a dialog box that will allow you to password protect your copy of Netscape. If you set a password here it will will be used to actually encrypt your Client Certificate(s). Loose this password and you're out of luck.


Client Authentication

Unfortunately client authentication isn't very advanced with any SSL Web server package as of yet. In the future this will change so we might as well get comfortable with SSL technology now, even though parts can get pretty bumpy.
First we'll go through the steps to enable reliable Client Authentication with Stronghold:

  1. Open Stronghold's SSL configuration file in a text editor (httpsd.conf).

  2. Enable SSLFakeBasicAuth. This will allow Stronghold to make limited decisions about who should be allowed access to the server from the information it gets from Client Certificates.

  3. Set SSLVerifyClient to 2. This tells Stronghold that it must always verify clients who want to connect to the server. If this isn't set then SSLFakeBasicAuth is pretty much useless.

  4. The SSLCACertificateFile directive tells Stronghold where to look for valid CA certificates for checking signed client keys. Normally this points to the file rootcerts.pem which contains public keys for a number of CAs that sign Client Certificates. It's very important to point this to your own CA's public key file, in this case cacert.pem. Doing this will only allow SSL connections from clients who have had their keys signed by your CA, if you are using this for inter-office work, you will want to do it this way.

Stronghold handles users in a different and more limited way than what most webmasters are used to. For instance, in my Client Certificate I've only included my Name and e-mail address. This way, Stronghold identifies me with a string like this:

/CN=James Shelburne/Email=brammal@iamerica.net

If you will look at the source for the HTML form above you'll notice that the "keys" are the same (i.e. CN for CommonName, Email for e-mail address etc.). If I had included other fields in my certificate, Stronghold would identify me by a larger list of "keys and values."


Using SSLFakeBasicAuth

To test out SSLFakeBasicAuth insert a line like this in Stronghold's SSL configuration file (Note: this only works in the SSL config file. SSLFakeBasicAuth doesn't work with unencrypted HTTP transfers)

<Location /TEST_DIR>
AuthType Basic
AuthName Secret_Stuff
AuthUserFile /usr/local/apache/conf/ssl_user_file
<Limit GET POST>
require valid-user
</Limit>
</Location>

The file /usr/local/apache/conf/ssl_user_file (or whatever file you choose to use) should contain the SSL identifier strings for each person that you want to be able to access your SSL server. If I wanted to set up my server so that I was the only one who would be able to access it, then the only line in my ssl_user_file would be:

/CN=James Shelburne/Email=brammal@iamerica.net

When I try to make a secure connection to the server, Netscape will send the Client Certificate made earlier. Stronghold will see that SSLFakeBasicAuth is enabled and if I try and access /TEST_DIR, it will check the users in the AuthUserFile to see if I'm there. If I'm in the file I'll be granted access, if not, then access will be refused.

If you want to control access for a number of different user groups, feel free to have multiple ssl_user_files each containing the identifying strings for the people in that group. You might have ssl_accounting, ssl_sales and etc.

How do you find the strings that each user is identified by? When SSLVerifyClient is set to 2 and a person tries to access a directory on the server that is protected by SSLFakeBasicAuth the user string comes up in the file /usr/local/apache/logs/ssl/access_log. However, a better way to get the same information is through the use of CGI environment variables, in particular SSL_CLIENT_DN. Here's a short CGI script that when accessed through SSL will display the user's identifying string:

CLIENT_DN displayer--------------------------------------------------
#!/usr/bin/perl
print <<EOF
Content-type: text/html

<html><head>
<title>Your SSL_CLIENT_DN string</title></head>
<h3>Your SSL_CLIENT_DN string is:<br></h3>
<h4>$ENV{'SSL_CLIENT_DN'}</h4>
</html>
EOF
---------------------------------------------------------------------

There are other CGI environment variables but SSL_CLEINT_DN is the most useful. If you know your way around CGI programming you can automate your site on the basis of the SSL_CLIENT_DN variable.


Copyright © 1997, James Shelburne
Published in Issue 14 of the Linux Gazette


[ TABLE OF CONTENTS ] [ FRONT PAGE ]  Back  Next