old-www/LDP/LG/issue14/stronghold.html

552 lines
27 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head><title>Stronghold: Undocumented fun</title></head>
<body bgcolor=#ffffff>
<H4>
&quot;Linux Gazette...<I>making Linux just a little more lovable!</I>&quot;
<IMG ALIGN=MIDDLE SRC="../gx/heart.gif"> </H4>
<P> <HR> <P>
<!--===================================================================-->
<center><font size=7 color=#ff0000>Stronghold</font>
<font size=7>: Undocumented Fun</font></center><p>
<center>
<H4>By James Shelburne,
<a href="mailto:brammal@iamerica.net">brammal@iamerica.net</a></H4>
</center>
<P> <HR> <P>
<font size=2>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.<br>
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 http://.</font><p>
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
&quotnetwork&quot; separate offices over the Internet without worrying about
prying eyes looking in on your document transfers.<br>
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
&quot;tutorial&quot; 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.<p>
<hr><font size=5>Netscape Security</font><p>
Start up Netscape (3.0) and select <b>Options -&gt; Security
Preferences</b>. Click on the tab that says <b>Site Certificates</b>. 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 <b>United States Postal Service CA</b> and
click the button that says &quot;Edit Certificate...&quot;<br>
Now you should see another dialog box pop up which contains various
information on that particular certificate. Notice the two fields:
&quot;This certificate belongs to:&quot; and &quot;This certificate was
issued by:&quot;. In both cases it contains the same information. This means
that the certificate has been &quot;self-signed&quot; by the certificate
owner.<br>
A little further down in the dialog box you'll see a pair of &quot;radio
buttons&quot; 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 &quot;Cancel&quot; to exit
this dialog box.<br>
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 &quot;Site Certificate.&quot;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 <b>Site Certificates</b> from the drop-down
list above the &quot;Site Certificate&quot; list box. Note that, for some
reason, Certificate Authority certificates are considered
&quot;Site Certificates.&quot;<p>
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.<p>
<hr><font size=5>Client Authentication</font><p>
Client Authentication of one of the neatest features of Netscape. In the
previous screen, select the tab that says <b>Personal Certificates</b>. If
you installed any Client Certificates (doubtful) they'll be here. If a
server requests Client Authentication, Netscape can perform one of three
actions:<p>
<ol>
<li>Automatically decide which Client Certificate to send the server.
<li>Let the user decide which Client Certificate to send to the server.
<li>Send a particular Client Certificate to the server.
</ol><p>
You can tell which action you want Netscape to perform by selecting the
appropriate option from the drop-down list in the &quot;Personal
Certificates&quot; dialog box.<br>
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.<p>
<hr><font size=5>A look at the files</font><p>
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).<p>
<b>/usr/local/ssl/private/YOUR-SERVER.key</b> This is your server's
*private* key and should not be world-accessible at all. The way Stronghold
installed the directory &quot;private&quot; is chmod 700 root.<p>
<b>/usr/local/ssl/certs/YOUR-SERVER.cert</b> 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.<p>
<b>/usr/local/ssl/CA/rootcerts.pem</b> 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.<p>
<b>/usr/local/ssl/CA/cacert.pem</b> When you start your own CA this file
will contain your public key. Note: This is not your server's public key.<p>
<b>/usr/local/ssl/CA/private/cakey.pem </b> 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.<p>
<b>/usr/local/ssl/CA/ssleay.conf AND /usr/local/ssl/lib/ssleay.conf </b>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.<p>
<hr><font size=5>The ssleay.conf file</font><p>
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.<p>
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 <b>key=value</b> pairs and most sections also have an
&quot;application name,&quot; for instance:
<pre>
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
</pre>
In this section <b>policy_match</b> is the &quot;application name&quot; and
the rest are standard <b>key=value</b> pairs. Here the whole section can be
referenced by the label &quot;policy_match&quot;<p>
<hr><font size=5>Selected fields (from ssleay.conf):</font><p>
<b>default_crl_days:</b> This &quot;CRL&quot; 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.<p>
<b>policy:</b> The &quot;policy&quot; 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 &quot;policy_match&quot; and edit the policy_match
section below to reflect your chosen policy. The two possible values:
<b>policy_match</b> and <b>policy_anything</b> are
&quot;application names&quot; of the sections of the configuration file that
define who you will and will not sign keys for, or your &quot;policy.&quot;<p>
<b>distinguished_name:</b> There is only one difference between the two
different configuration files that Stronghold's key management tools use,
and this is it. This <b>key=value</b> pair will point to one of two
different &quot;application names&quot;: <b>req_distinguished_name</b> or
<b>makeca_distinguished_name</b>. The only time it will point to
<b>makeca_distinguished_name</b> is when you are creating your own Certificate
Authority, the rest of the time it will point to
<b>req_distinguished_name</b>.<p>
<b>[makeca_distinguished_name]:</b> This and the next entry are not
<b>key=value</b> pairs, but rather &quot;application names&quot; that define
particular groups of information.<br>
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
&quot;organizationalUnitName&quot; and &quot;commonName.&quot; Because we
aren't dealing with slick commercial software, it may object if you start
altering this configuration file heavily.<p>
<b>[req_distinguished_name]:</b> 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 <b>genkey,</b> 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
&quot;commonName,&quot; 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
&quot;commonName&quot; is supplied, Netscape fails to connect and gives an
error-message.<p>
<hr><font size=5>The programs</font><p>
<b>genkey:</b>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:<p>
genkey YOUR_SERVER_NAME<p>
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.<br>
Also note that the defaults for genkey are had from the
<b>req_distinguished_name</b> 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.<p>
<b>makeca:</b> 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 <b>makeca_distinguished_name</b>
section (assuming you have installed everything in the default locations).<br>
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 <b>makeca_distinguished_name</b> section
of the relevant configuration file.<p>
<b>ca:</b> 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 <b>genkey</b> 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:<p>
ca -config /usr/local/ssl/lib/ssleay.conf -in /tmp/csr<p>
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.<br>
The cert is stored in PEM (Privacy Enhanced Mail) format and as such, can be
included in e-mail as is.<p>
<b>getca:</b> 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:<p>
getca YOUR_SERVER_NAME &lt; /tmp/cert<p>
We are assuming that /tmp/cert is your signed keyfile in PEM format.<br>
One of the odd things about <b>getca</b> is that the input file must be
&quot;piped&quot; into the program.<br>
If this went correctly your Web server should now have a public key signed
by your CA. Now for the tricky part...<p>
<hr><font size=5>Making Everything Work</font><p>
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 <b>Site Certificates</b> that we
looked at earlier. To add your CA to that list follow these steps:<p>
<ol>
<li> 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:<br>
<pre>
application/x-x509-ca-cacert cacert
</pre>
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 <b>.cacert</b> extension should
be sent as a Certificate Authority's public key.<p>
<li> The public key for your Certificate Authority is located in
<b>/usr/local/ssl/CA/cacert.pem.</b> 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:<br>
<pre>
x509 -outform DER < cacert.pem > cert.cacert
</pre>
Like getca, x509 requires input and output to be &quot;piped.&quot; In any
event your key is now in proper format and can be moved into one of your
Web server's document directories.<p>
<li> 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.<p>
</ol>
With that out of the way you should now see your CA's key when you look in
Netscape's <b>Site Certificates</b> 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.<p>
<hr><font size=5>Client Certificates</font><p>
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:<p>
<pre>
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---------------------------------------------------------
&lt;HTML&gt;&lt;HEAD&gt;
&lt;TITLE&gt;Make akey&lt;/TITLE&gt;&lt;/HEAD&gt;&lt;BODY&gt;
&lt;FORM ACTION="/cgi-bin/key_req.cgi" METHOD=POST&gt;
E-mail: &lt;br&gt;
&lt;INPUT TYPE="TEXT" NAME="Email" MAXLENGTH=40SIZE=40&gt;&lt;br&gt;
Common Name: &lt;br&gt;
&lt;INPUT TYPE="TEXT" NAME="CN" MAXLENGTH=64 SIZE=64&gt;&lt;br&gt;
Organization Name: &lt;br&gt;&ltINPUT TYPE="TEXT" NAME="O"&gt;&lt;br&gt;
Organization Unit: &lt;br&gt;&lt;INPUT TYPE="TEXT" NAME="OU"&gt;&lt;br&gt;
Locality: &lt;br&gt;&lt;INPUT TYPE="TEXT" NAME="L"&gt;&lt;br&gt;
State or Province: &lt;br&gt;&lt;INPUT TYPE="TEXT" NAME="SP"&gt;&lt;br&gt;
Country (2 letter): &lt;br&gt;
&lt;INPUT TYPE="TEXT" NAME="C" MAXLENGTH="2" SIZE="2"&gt;&lt;br&gt;
&lt;KEYGEN NAME="SPKAC" CHALLENGE="testkeygen"&gt;&lt;br&gt;
&lt;INPUT TYPE="submit" VALUE="Generate Key"&gt;&lt;/FORM&gt;
&lt;/BODY&gt;&lt;/HTML&gt;
--------------------------------------------------------------------
</pre>
These files may need a little modification to work on your system, but they
should work like this:<p>
<b>keygen.html</b> 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
<a href="http://remus.prakinf.tu-ilmenau.de/ssl-users/">
http://remus.prakinf.tu-ilmenau.de/ssl-users/</a><p>
<b>key_req.cgi</b> 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.<p>
<hr><font size=5>Making A Signed Client Certificate</font><p>
To create a Client Certificate signed by your CA follow these steps:<p>
<ol>
<li> 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 <b>Generate Key</b>. 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.<p>
<li> Go into your CA directory and type:<br>
<pre>
ca -spkac /tmp/client_csr -out /tmp/clientcert.der
</pre>
You'll be asked for your CA password and, if all goes well, a signed Client
Cert will be output into /tmp/clientcert.der.<p>
<li> 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:
<pre>
application/x-x509-user-cert der
</pre>
This will tell Stronghold to use this MIME type for every file that ends in
the <b>.der</b> extension.<br> 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 <b>reload</b> that does this for you.<p>
<li> Move <b>clientcert.de</b>r 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.<br>
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.
</ol><p>
After the certificate is installed select <b>Options -&gt; Security
Preferences</b> and click the <b>Personal Certificates</b> tab. Your new
Client Certificate should appear in the listbox.<br>
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 <b>Options -&gt; Security
Preferences</b>, selecting the <b>Passwords</b> 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.<p>
<hr><font size=5>Client Authentication</font><p>
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.<br>
First we'll go through the steps to enable reliable Client Authentication
with Stronghold:<p>
<ol>
<li> Open Stronghold's SSL configuration file in a text editor (httpsd.conf).
<p>
<li> 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.<p>
<li> 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.<p>
<li> The SSLCACertificateFile directive tells Stronghold where to look for
valid CA certificates for checking signed client keys. Normally this points
to the file <b>rootcerts.pem</b> 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 <b>cacert.pem</b>. 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.<p>
</ol>
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:<p>
/CN=James Shelburne/Email=brammal@iamerica.net<p>
If you will look at the source for the HTML form above you'll notice that
the &quot;keys&quot; 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 &quot;keys and
values.&quot;<p>
<hr><font size=5>Using SSLFakeBasicAuth</font><p>
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)<p>
<pre>
&lt;Location /TEST_DIR&gt;
AuthType Basic
AuthName Secret_Stuff
AuthUserFile /usr/local/apache/conf/ssl_user_file
&lt;Limit GET POST&gt;
require valid-user
&lt;/Limit&gt;
&lt;/Location&gt;
</pre><p>
The file <b>/usr/local/apache/conf/ssl_user_file</b> (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 <b>ssl_user_file</b> would be:<p>
/CN=James Shelburne/Email=brammal@iamerica.net<p>
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.<p>
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.<p>
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
<b>SSL_CLIENT_DN</b>. Here's a short CGI script that when accessed through
SSL will display the user's identifying string:<p>
<pre>
CLIENT_DN displayer--------------------------------------------------
#!/usr/bin/perl
print &lt&ltEOF
Content-type: text/html
&lthtml&gt&lt;head&gt;
&lt;title&gt;Your SSL_CLIENT_DN string&lt;/title&gt;&lt;/head&gt
&lt;h3&gt;Your SSL_CLIENT_DN string is:&lt;br&gt;&lt;/h3&gt;
&lth4&gt;$ENV{'SSL_CLIENT_DN'}&lt;/h4&gt;
&lt/html&gt;
EOF
---------------------------------------------------------------------
</pre><p>
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.<p>
<!--===================================================================-->
<P> <hr> <P>
<center><H5>Copyright &copy; 1997, James Shelburne <BR>
Published in Issue 14 of the Linux Gazette</H5></center>
<!--===================================================================-->
<P> <hr> <P>
<A HREF="./index.html"><IMG ALIGN=BOTTOM SRC="../gx/indexnew.gif"
ALT="[ TABLE OF CONTENTS ]"></A>
<A HREF="../index.html"><IMG ALIGN=BOTTOM SRC="../gx/homenew.gif"
ALT="[ FRONT PAGE ]"></A>
<A HREF="./pilot.html"><IMG SRC="../gx/back2.gif"
ALT=" Back "></A>
<A HREF="./usenix.html"><IMG SRC="../gx/fwd.gif" ALT=" Next "></A>
<P> <hr> <P>
</BODY>
</HTML>