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.
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 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:
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.
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.
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 = optionalIn 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"
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.
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...
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:
application/x-x509-ca-cacert cacertThere 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.
x509 -outform DER < cacert.pem > cert.cacertLike 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.
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.
To create a Client Certificate signed by your CA follow these steps:
ca -spkac /tmp/client_csr -out /tmp/clientcert.derYou'll be asked for your CA password and, if all goes well, a signed Client Cert will be output into /tmp/clientcert.der.
application/x-x509-user-cert derThis will tell Stronghold to use this MIME type for every file that ends in the .der extension.
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.
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:
/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."
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.