## $Id: README,v 1.8 92/11/03 13:34:49 genek Exp $
##
## README for Tripwire
##
## Gene Kim  & Gene Spafford
## The COAST Project
## Department of Computer Sciences
## Purdue University
##

##  All files in the distribution of Tripwire are Copyright 1992 by the
##  Purdue Research Foundation of Purdue University.  All rights
##  reserved.  Some individual files in this distribution may be covered
##  by other copyrights, as noted in their embedded comments.
##  
##  Redistribution and use in source and binary forms are permitted
##  provided that this entire copyright notice is duplicated in all such
##  copies, and that any documentation, announcements, and other
##  materials related to such distribution and use acknowledge that the
##  software was developed at Purdue University, W. Lafayette, IN by
##  Gene Kim and Eugene Spafford.  No charge, other than an "at-cost"
##  distribution fee, may be charged for copies, derivations, or
##  distributions of this material without the express written consent
##  of the copyright holder.  Neither the name of the University nor the
##  names of the authors may be used to endorse or promote products
##  derived from this material without specific prior written
##  permission.  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
##  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
##  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR
##  PURPOSE.

    This README file serves as a quick-and-dirty primer on Tripwire.
A paper that fully describes the design and rationale was not
completed in time to be included in this first Tripwire release.  The
design document will be released later as a technical report, and
possibly as a conference or journal paper.  It will also be included
in later releases of Tripwire.  This document will be referenced
throughout the Tripwire distribution as the Tripwire design document
or the comprehensive Tripwire paper.

    This README file contains information needed to build, test,
and run Tripwire.  A table of contents follow:


	    1.0.  Background
	    1.1.  Goals of Tripwire
	    2.0.  How to build Tripwire
	    2.1.  Common Tripwire compilation problems
	    2.2.  The sigfetch utility
	    3.0.  Getting Tripwire up and running
	    3.1.  Creating your tw.config file
	    3.2.  A caveat about your Tripwire database
	    3.2.  Running Tripwire as an integrity checker
	    3.3.  Keeping your database up-to-date
	    3.4.  A quick-checking mode
	    4.0.  Some Tripwire scaling hints for using Tripwire 
		    in large sites
	    4.1.  The tw.config grammar
	    4.2.  How you might use these directives
	    5.0.  Notes on signature routines
	    5.1.  Performance vs. security
	    6.0.  Signature routines
	    6.1.  MD5
	    6.2.  Snefru
	    6.3.  CRC-32
	    6.4.  CRC-16
	    6.5.  MD4
	    6.6.  MD2
	    6.7.  null signature
	    7.0.  Feedback and bug-reports
	    8.0.  User contributions
	    9.0.  Acknowledgements


1.0.  Background
================

    With the advent of increasingly sophisticated and subtle
account break-ins on Unix systems, the need for tools to aid in
the detection of unauthorized modification of files becomes
clear.  Tripwire is a tool that aids system administrators and
users in monitoring a designated set of files for any changes.
Used with system files on a regular (e.g., daily) basis, Tripwire
can notify system administrators of corrupted or tampered files,
so damage control measures can be taken in a timely manner.

1.1.  Goals of Tripwire
=======================

    Tripwire is a file integrity checker, a utility that compares
a designated set of files against information stored in a
previously generated database.  Any differences are flagged and
logged, and optionally, a user is notified through mail.  When
run against system files on a regular basis, any changes in
critical system files will be spotted -- and appropriate damage
control measures can be taken immediately.  With Tripwire, system
administrators can conclude with a high degree of certainty that
a given set of files remain free of unauthorized
modifications if Tripwire reports no changes.


2.0.  How to build Tripwire
===========================

    As of this writing, Tripwire has run successfully on (at least)
BSD, OSF/1, Mach, and late System V variants of Unix.  Tripwire was
built and tested on a wide variety of Unix variants.

    The file 'Ported' contains a list of platforms and operating
systems where Tripwire has already been successfully ported during
the six-week beta test period.  If you find your system in the
list, note the system settings that were used to build Tripwire.

    Second, look through the Makefile and make sure that the C
compiler and all flag settings are reasonable for your
configuration.  Most of the potentially tricky system settings
should be listed in the
'Ported' file.

    Next, look in the './configs' directory to find a predefined
'conf-<os>.h' file that matches closest to your operating system.
Note this file, because you will be inserting this filename in
the './include/config.h' file.  If no such file exists, pick one
"near" your system type and modify appropriately (then mail it back to
us for a future release).

    Now that you have chosen your operating system header file, edit
the './include/config.h' file to tailor Tripwire to your system.
Include the name of the predefined header file closest to your system
at the appropriate line in config.h

    Paths and names of Tripwire configuration files are also set
in the config.h file.  Make sure you note the locations that
Tripwire looks for its configuration and database files; change them
for your system, as appropriate.

    NOTE: We *strongly* urge you to locate the Tripwire
configuration files on a disk that can be made read-only with a
hardware setting.  This will prevent the files from being altered
by an attacker.  The run-time version of Tripwire should be
located in the same place.  If you are unable to mark a disk (or
diskette) as read-only, you might also consider putting it on a
remote partition of a more secure machine, and import it
read-only.  See the design document for the rationale behind this
note if the concept is not obvious.

    Last, look in the './configs' directory again to find a tw.config
file that matches your operating system.  These files were
custom-tailored to match the file layouts of various vendor supplied
operating system.  If no file in this subdirectory matches your
system, choose the one that is closest in nature (e.g., BSD4.3 or
SysV.4).  Edit this file to include additional files you want to
monitor (e.g., local bins and critical databases), to correct paths if
you have moved things or if they are mounted from a remote location
(check them only on the server!), and to exclude locally-active files
from the check.  You should probably add the Tripwire binary itself to
this file.  See the next section for further details.

    After you have customized your tw.config file, copy it to the
location that you specified in your config.h file.

    Next, simply type 'make' at the top level.  Note that all
Makefiles in the subdirectories are driven by the top-level Makefile.
(i.e., typing 'make' in the ./src directory will probably not work.)

2.1.  Common Tripwire compilation problems
==========================================

    If no file in this subdirectory matches your system, choose
the one that is closest in nature (e.g., BSD4.3 or SysV.4).  Edit
this file to include additional files you want to monitor (e.g.,
local bins and critical databases), to correct paths if you have
moved things or if they are mounted from a remote location (check
them only on the server!), and to exclude locally-active files
from the check.  You should probably add the Tripwire binary
itself to this file.  See the next section for further details.

    After you have customized your tw.config file, copy it to the
location that you specified in your config.h file.

    Next, simply type 'make' at the top level.  Note that all
Makefiles in the subdirectories are driven by the top-level
Makefile.  (i.e., typing 'make' in the ./src directory will not
work.)

2.1.  Common Tripwire compilation problems
==========================================

    Tripwire was originally written using ANSI C.  However,
Tripwire now compiles with K&R, too.  All of the prototypes
remain embedded between "#ifdef __STDC__" directives.  Sadly,
compiling under ANSI is sometimes noisier than with K&R.
Therefore, go ahead and compile with K&R unless religion dictates
ANSI.  (The code lints completely clean, excepting the malloc()
and exit() return values.)

    Common compilation trouble-spots are the dirent(S5)/direct(BSD) 
funkiness and #defines that changed for POSIX compliance.

2.2.  The sigfetch utility
==========================

    The sigfetch utility is provided so users can get signatures
of files without having to run Tripwire.  The syntax of sigfetch
is simple.  

	sigfetch [-0123456789aqv] [ file ... ]

    By default, sigfetch prints out all ten signatures.  However,
the signatures can be printed selectively by specifying the
signature number on the command line.

3.0.  Getting Tripwire up and running
=====================================

    Tripwire runs in either of two modes: Database Generation
mode or Integrity Checking mode.  In order to run Integrity
Checking, Tripwire must have a database to compare against.  To
do that, you must first specify the set of files for Tripwire to
monitor.  This list is stored in 'tw.config'.

3.1.  Creating your tw.config file
==================================

    Edit your 'tw.config' file, or whatever filename you defined for
the Tripwire config file, and add all the directories that contain
files that you want monitored.  The format of the config file is
described in its header and in the man page.  Pay especially close
attention to the ignore-flags and omit-lists, which can significantly
reduce the amount of uninteresting output generated by Tripwire.  For
example, you will probably want to omit files like mount tables that
are constantly changed by the operating system.

    Next, run Tripwire with 'tripwire -initialize'.  This will create
a file called 'tw.db_[hostname]' in the directory you specified to
hold your databases (where [hostname] will be replaced with your
machine hostname).

3.2.  A caveat about your Tripwire database
===========================================

    NOTE: Tripwire will detect changes made to files from this
point on.  You *must* be certain that the system on which you
generate the initial database is clean, however --- Tripwire
cannot detect unauthorized modifications that have already been
made.  One way to do this would be to take the machine to
single-user mode, reinstall all system binaries, and run Tripwire
in initialization mode before returning to multi-user operation.

    This database must be moved someplace where it cannot be
modified.  Because data from Tripwire is only as trustworthy as
its database, choose this with care.  We recommend placing all
the system databases on a read-only  disk, or exporting it
via read-only NFS from a "secure-server."  (This pathname is
hardcoded into Tripwire.  Any time you change the pathname to the
database repository, you must recompile Tripwire.  This prevents
a malicious intruder from spoofing Tripwire into giving a false
"okay" message.)

    We also recommend that you make a hardcopy printout of the
database contents right away.  In the event that you become
suspicious of the integrity of the database, you will be able to
manually compare information against this hardcopy.  We have yet
to hear of a way for  "crackers" to alter an old piece of
printout made before they penetrated the system!

3.3.  Testing Tripwire
======================

    Tripwire includes a script-driven test suite that checks the
top-level build directory against the distribution package.  

    In the ./tests directory, there is a Tripwire database of the
entire Tripwire source distribution and a tw.config file.  The
test script automatically converts the pathnames in these
Tripwire files to match those of your system.  After converting
the files, it then runs Tripwire in Integrity Checking mode.

    To run the test, simply type 'make test' at the top level.
This will invoke the script, and if all goes well, the output of
Tripwire matches the expected values that the script provides.


3.4.  Running Tripwire as an integrity checker
==============================================

    Once you have your database set up, you can run Tripwire
in Integrity Checking mode by 'tripwire'.  

3.5.  Keeping your database up-to-date
======================================

    A common setup for running Tripwire would mail the system
administrator any output that it generates.  However, some files on
your system may change during normal operation, and this necessitates
update of the Tripwire database.

    Tripwire supports incremental updates of its database on a
per-file/directory or tw.config entry basis.  Tripwire stores
information in the database so it can associate any file in the
database with the tw.config entry that generated it when the
database was created.

    Therefore, if a single file has changed, you can:

	tripwire -update /etc/newly.installed.file

    Or, if an entire set of files that made up an entry in
the tw.config file changed, you can:

	tripwire -update /usr/local/bin/Local_Package_Dir

    In either case, Tripwire regenerates the database entries
for every specified file.  A backup of the old database is
created in the ./databases directory.

3.6.  A quick-checking mode
===========================

    Tripwire allows you to selectively skip certain signatures at
run-time through a command-line option.  For example, if you wish
to run Tripwire on an hourly basis, even performing only MD5
checks might be computationally prohibitive.  For this
application, checking only the CRC32 signature might be
desirable.  To do this, assuming that only MD5, Snefru, and CRC32
were used when the database was initialized, you would type:

	tripwire -i 1 -i 2

   This tells tripwire to ignore signature 1 and signature 2.
Furthermore, for daily Tripwire runs, you could specify using
only MD5 and CRC32.  Finally, for weekly runs, you could run
Tripwire with all three signatures.


4.0.  Some Tripwire scaling hints for using Tripwire in large sites
===================================================================

    The tw.config.5 manual page describes in detail the syntax
supported by the tw.config file.  Tripwire includes features that
offer similar functionality to the C-preprocessor, and offer other
directives that assist in the use of Tripwire at sites consisting of
hundreds of workstations with local disk.

4.1.  The tw.config grammar
===========================

    These commands are briefly described below:

	@@define VAR VALUE
	@@undef VAR

	@@ifhost HOSTNAME
	@@ifnhost HOSTNAME
	@@ifdef VAR
	@@ifndef VAR
	@@else
	@@endif

	@@include FILENAME

    Furthermore, the tw.config grammar also supports logical
expressions.  For example, you could have something like this
in your tw.config file:

	@@ifhost spam.cc.purdue.edu || weiner.cc.purdue.edu
	...entries...
	@@endif

    Besides the obvious cpp-like functionality, you can use
@@define to create strings that are interpreted at run-time.
For example:

	@@ifhost mentor.cc.purdue.edu
	@@ define TEMPLATE_S	+pinug-cas0123456789
	@@else
	@@ define TEMPLATE_S	+pinug012-cas3456789
	@@endif

	/etc/tw.loginfo		@@TEMPLATE_S

4.2.  How you might use these directives
========================================

    Because Tripwire allows run-time interpretation of the
tw.config file, it becomes possible for many different hosts to
share the same tw.config file.  This allows the maintenance of
Tripwire configuration files to still be manageable in a large,
heterogeneous environment.  Although each host must still have
different database file, this has few consequences except for
disk space.

5.0.  Notes on signature routines
=================================

    The RSA Data Security, Inc. MD5, MD4, and MD2 Message
Digesting Algorithm, and Snefru, the Xerox Secure Hash Function,
code have been changed to eliminate big-endian and little-endian
specific routines.  These changes have been sent back to the
authors, but we are not aware of any buy-backs yet.  Until then,
there will remain some differences between the code in this
package and their respective virgin distributions.

5.1.  Performance vs. security
==============================

    Normally, only one checksum per file would be enough to
detect changes.  For purposes of speed, an easy to calculate
checksum would be preferred.  However, most easy-to-calculate
signatures are also easy to defeat if a determined attacker
wished to do so (see the chart in the design document to see how
easy this is to do with random comparisons).

    Tripwire includes four very difficult-to-forge signature
algorithms, as well as two more conventional CRC routines.  Using
the default setup of recording two signatures (MD5 and Snefru)
for each database entry gives very, very strong assurance that a
file has not been tampered with.  For tampering to have
succeeded, the attacker would have had to have changed the file
and added appropriate padding characters to recreate *both*
checksums without also altering the size of the file.  To do this
at random might not even be possible with the MD5 and Snefru
checksums used.  Those two algorithms have not been exhaustively
analyzed, but both are known to be fairly strong.  It is possible
that there exists no pair of inputs that give the same output for
both algorithms at once.

    This added assurance is at a heavy price, however.  The two
algorithms, and snefru in particular, are expensive to
calculate.  To run the MD5 and Snefru algorithms against every
file is likely to be overkill for almost all systems (unless you
have cpu cycles to spare!).  Both checksums should be run over
only the most critical files...like the Tripwire database and
program, and perhaps each setuid and setgid file on your system.
All other files can be checked with MD5 alone for much faster
operation and a high level of assurance. The task of altering a
file and recreating the original MD5 checksum is also very
difficult, and it is unlikely that any but the most determined,
sophisticated, and well-equipped attacker would be able to do it
in finite time.

    To decrease the execution run-times of Tripwire, consider
modifying your tripwire.config entries to ignore the Snefru
(signature 2) attribute on files that do not need such stringent
monitoring.  This will skip the computationally-expensive Snefru
signature collection entirely.  Balancing this equation of
security vs.  speed is a decision best made by the administrator,
most closely tailored to his/her site needs.

    For the extremely paranoid, Tripwire includes the MD2 and MD4
signature algorithms, as well as the 16 and 32-bit CRC algorithms
in its arsenal.  Be forewarned, however, that MD2 is an order 
of magnitude slower than even Snefru, and probably guarantees no 
greater integrity checking.  We include all these routines, however,
so you can pick what you feel to be most appropriate for your site.

    You may wish to add other routines as checksum/signature
generators.  For instance, if you have a fast DES implementation
(including chip-based generation), you might wish to encrypt the file
using CBC mode and some fixed key, saving the final 128 bits of output
as the signature.  The configuration file routines have several
signature flags that are currently bound to a null function, so there
is room for this expansion if you wish.

    Clearly, with six different signature algorithms at your
disposal, Tripwire offers considerable flexibility in ensuring
data security.  Tripwire makes maintaining a trivial CRC
database equally easy to administer and check as a full (but
perhaps less practical) six-signature database.

    The following section describes each of the six signature
algorithms.

6.0.  Signature routines
========================

    Tripwire ships with seven signature routines.  This section
briefly describes each signature routine.  This is by no means an
authoratative list, but it does attempt to give some background
on each of the signature routines provided:

    MD5, Snefru, MD4, and MD2 are all examples of cryptographic
checksum algorithms (also known as message digesting algorithms,
one-way hash functions, fingerprinting routines, or manipulation
detection codes).  They employ cryptographic techniques to ensure
that any small change in the input stream results in immediate
and widely diverging output.  This way, even a small change in
the input results in large change in the output.  Therefore, any
unauthorized, malicious, or accidental change will be evident.
Furthermore, because these algorithms use a 128-bit signature,
using a brute-force attack to introduce a deliberate change in
the file while trying to keep the same signature becomes a
computationally infeasible task.

    The CRC algorithms, on the other hand, use simple polynomial
division to generate the checksums.  While this technique is very
fast, the mathematics of this technique is well-understood.
Additionally, since the signature space is so small (usually 16
or 32 bits), a brute-force search for a CRC collision is well
within the capabilities of most workstations.  There are
currently several programs in the public domain that can, for any
given input file, provide a different output file with the same
CRC signature in 30 seconds or less.

    All observed timing measures provided for the signature
routines were performed on a Sequent Symmetry with ten 16 Mhz
80386 processors.  The numbers provided are simply an informal
gauge of throughput, rather than any authoratative metric.

6.1.  MD5
=========

    MD5 is the RSA Data Security Inc. Message-Digest Algorithm, a
proposed data authentication standard.  The Internet Draft
submission can be found as Internet Working Draft RFC 1321,
available via anonymous FTP from NIC.DDN.MIL or from RSA.COM as
~/pub/md5.doc.

    MD5 attempts to address potential security risks found in the
speedier, but less secure MD4, also by RSA Data Security Inc.
MD5 was designed as a more conservative algorithm that backs
"away from the edge" in terms of risks from successful
cryptanalytic attack.

    MD5 generates a 128-bit signature, and uses four rounds to
ensure pseudo-random output.  Observed throughput is about 70
Kbytes/second.

    Currently, MD5 is considered by many to be the
state-of-the-art signature algorithm.

6.2.  Snefru
============

    Snefru, the Xerox Secure Hash Function, was developed by
Ralph Merkle at Xerox PARC.  As an incentive to find a Snefru
crack, there is a $1000 cash prize promised to anyone who can
find two sets of input that map to the same signature.

    This reward has remained unclaimed since April 1990, when the
2-pass version of Snefru was broken by Eli Biham, a Ph.D. student
of Adi Shamir.  Currently, Ralph Merkle recommends using only the
4-pass version of Snefru, if not the 8-pass version.  The Snefru
README states, "Further study of the security of Snefru is
required before production use is advisable."

    As shipped with Tripwire, Snefru is configured to run in
4-passes.  Version 2.5 is the latest version available, and is
the version included with Tripwire.

    Snefru is slower than MD5, but is recommended as a backup for
MD5 as a primary signature.  As configured, Snefru runs at about
31 Kbytes/second.

    Snefru can be obtained via anonymous FTP from arisia.xerox.com 
in directory /pub/hash.

6.3.  CRC-32
============

    Cyclic Redundancy Checks have been the long been the de facto
error detection algorithm standard.  These algorithms are fast,
robust, and provides reliable detection of errors associated with
data transmission.  It has been shown that CRC-32 has a minimum
distance of 5 for block lengths of less than 4K.  However, this
decreases as the size of the blocks increases.

    Therefore, using CRC-32 on long files is certainly a
misapplication of this signature algorithm.  However, CRC-32 is
provided as a fast and speedy alternative to the slower
cryptographic checksumming algorithms.

    The version of CRC-32 included with Tripwire was written by 
Gary S. Brown XXX
    This CRC-32 implementation runs at about 111 Kbytes/second.

6.4.  CRC-16
============

    CRC-16 is the predecessor to CRC-32, using only 16 bits to
store to the remainder of the data and the generator polynomial.
CRC-16 is typically at the link level, usually done in hardware
to detect transmission errors.

    This CRC-16 implementation runs at abut 131 Kbytes/second.


6.5.  MD4
=========

    MD4, the RSA Data Security Inc. Message-Digest Algorithm, is
the predecessor to MD5 described above.  It was also sumbitted as
a standard data authentication algorithm, and is described in the
Internet Working Draft 1320.

    The MD4 algorithm was designed to exploit 32-bit RISC
architectures to maximize throughput.  On a Sun SparcStation,
throughput rates of over 1.4 Mbytes/second are achieved.

    MD4 can be obtained via anonymous FTP from RSA.COM in ~/pub.

    On a Sequent, MD4 throughput is about 332 Kbytes/second.


6.6.  MD2
==========

    The RSA Data Security, Inc. MD2 Message-Digest Algorithm was
created as part of the Privacy Enhanced Mail package -- a package
designed to authenticate and increase the security of electronic
mail.  Like the other algorithms by RSA Data Security, Inc
presented here, MD2 generates a 128-bit signature.

    The MD2 algorithm is quite slow.  On a 16 Mhz 80386, expect
only 3 Kbytes/second.  It is not clear that using this slower
algorithm instead of MD5 brings any comparative advantage.

6.7.  (null)
============

    Well, sig_null_get() is not really a signature algorithm.
Instead, it is a place holder for unused slots in the signature
array.  It will always return a single character, ``0''.


7.0.  Feedback and bug-reports
==============================

    Please send any bug-reports, questions, feedback, or any comments
to both genek@mentor.cc.purdue.edu and spaf@cs.purdue.edu.  One or
both Genes will try to answer questions as expeditiously as possible.


8.0.  User contributions
========================

    The ./contrib directory contains several programs contributed
by users during the beta-test period.  Each program is accompanied 
by a README file written by the program author.

    Both Genes are willing to serve as clearinghouses for
utilities that augment the Tripwire package.  If you have a
something that you would like included in the Tripwire package,
please contact either Gene Kim or Gene Spafford at the email
addresses listed in the previous section.


9.0  Acknowledgements
=====================

    Dan Farmer of Sun Microsystems, Inc. for providing answers to
questions of taste, and providing some impetus to finish this
project during the summer of 1992.  (dfarmer@corp.sun.com).

    Shabbir Safdar for actually running early versions of
Tripwire that popped up on an hourly basis.  We also thank him
for trying this on a few of the more exotic architectures around
Purdue.  (shabby@mentor.cc.purdue.edu)

    Steve Weeber of Lawrence Livermore National Laboratory for
insight into what sort of tools the Dept. of Energy has developed
for in-house use, and comparisons of their functionality with
Tripwire.  (weeber@llnl.gov).

    Ralph Merkle of Xerox PARC for information on the Snefru
one-way hash function.  (merkle@parc.xerox.com).

    One of the directory printing routine in utils.c comes from
the COPS package.  It was from crc_check.c by Jon Zeeff
(zeeff@b-tech.ann-arbor.mi.us).

    The 125 helpful beta testers that stuck with us during the
six-week testing period.  They put up with bugs, ever-changing
interfaces and database file formats, and in one case, a flurry
of conflicting patches in a thirty-minute period while GeneK and
Spaf took turns saying, "Uh, oh."

    We appreciate the heroic effort of the Tripwire beta testers who
suggested functional additions to Tripwire, found and hunted down
bugs, and refined Tripwire beyond the authors' expectations.  Special
thanks go to:

    Walker Aumann, Lance R. Bailey, David Barr, Greg Black, Adrian P.
    van Bloois, J. Dean Brock, Kurt Cockrum, John Cristy, Jim Duncan,
    David S. Goldberg, Johannes Gronvall, Tom Gutnick, Michaela
    Harlander, Andreas Haug, Bill Henderson, Jim Hendrick, Norman
    Hill, Paul Joslin, Poul-Henning Kamp, Leslie Kordas, Simon Leinen,
    Philip Yzarn de Louraille, Stephen Mahler, Fletcher Mattox, Ken
    McDonell, Wes Morgan, Phil Moyer, Dan O'Neill, Joe Polcari,
    Phillip Porch, Brad Powell, W.  Purvis, Daniel Ray, Dean Rich,
    Bill Romine, John P. Rouillard, Rich Salz, Christopher Samuel,
    Pete Shipley., David W. Smith, Harlan Stenn, Margarita Suarez,
    John G. Sutton, Tim Tessin, John Wagner, David Wiseman, Irving
    Wolfe, Stephen M.  Youndt

    GeneK and Spaf want to apologize in advance to anyone who sent us
patches, comments or configuration info and whose name doesn't appear
(but should).  Please write to us and so we can correct the situation!



Gene & Gene 
Kim  & Spafford

November 2, 1992
(genek@mentor.cc.purdue.edu)
(spaf@cs.purdue.edu)

