Newsgroups: comp.sources.unix From: spaf@cs.purdue.edu (Gene Spafford) Subject: v27i163: tripwire-1.1 - security integrity monitor, V1.1, Part17/26 References: <1.756157401.21864@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: spaf@cs.purdue.edu (Gene Spafford) Posting-Number: Volume 27, Issue 163 Archive-Name: tripwire-1.1/part17 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'tripwire-1.1/src/list.c' <<'END_OF_FILE' X#ifndef lint Xstatic char rcsid[] = "$Id: list.c,v 1.8 1993/12/02 18:03:22 genek Exp $"; X#endif X X/* X * list.c X * X * generic linked list routines. X * X * These routines generally use a (struct list **) as an argument X * (ie: a pointer to a pointer to the head of the list). This way, X * a NULL list pointer will automatically be malloc()'d into existence. X * X * These routines started as extremely simple routines. Unfortunately, the X * O(n) search times made Tripwire extremely slow. So, v3.1 of X * the linked list routines incorporate a hash table into each of X * the list structures. *whew* It's faster, but it's not simple X * anymore. (The addition of back pointers didn't help either...) X * X * Why? Well, we need to preserve order for the list of generated files. X * So, a hash table won't do, and a simple linked list is too slow. X * X * However, the neat thing is that the object-oriented nature of X * the list routines is preserved. X * X * Gene Kim X * Purdue University X */ X X#include "../include/config.h" X#include X#ifdef STDLIBH X#include X#endif X#include X#ifdef MALLOCH X# include X#endif X#ifdef STRINGH X#include X#else X#include X#endif X#include "../include/list.h" X X/* prototypes */ Xstatic unsigned int string_hash (); X Xstatic int listdebug = 0; X X#define LISTDEBUG(x) if (listdebug >= (x)) X X/* X * list_set(pc_name, pc_value, prioirty, pp_list) X * X * insert structure with (name=pc_name) and (value=pc_value) X * into the specified list X */ X Xvoid Xlist_set(pc_name, pc_value, priority, pp_list) X int priority; X char *pc_name, *pc_value; X struct list **pp_list; X{ X struct list_elem *p; X struct list_hash *phash, *qhash = NULL; X int clobber = 0; X struct list_elem *head; X unsigned int hindex; /* hash index */ X struct list_hash *hentry; X X /* get the hash value */ X hindex = string_hash(pc_name); X X /* were we handed a NULL list pointer? */ X if (*pp_list == NULL) X goto INSERT; X else X head = (*pp_list)->p_head; X X hentry = &( ((*pp_list)->hashtable)[hindex]); X X /* X * 1) if pc_name is already in the list, then we compare priority X * levels. replace only if new priority is higher than X * existing priority. X * X * 2) if pc_name is not on the list, then we just add it to the X * end of the list X */ X X /* walk through hash chain */ X for (phash = hentry; phash && phash->used; qhash = phash, X phash = phash->next) { X if (strcmp(phash->key, pc_name) == 0) { X /* X * if existing priority is equal or less than this one, X * then go ahead and clobber it. X */ X p = phash->lptr; X if (p->priority <= priority) { X XLISTDEBUG(10) Xfprintf(stderr, "list_set(): '%s' variable already found. Clobbering...\n", X pc_name); X X clobber++; X goto INSERT; X } /* end if clobber */ X else { X XLISTDEBUG(10) Xfprintf(stderr, "list_set(): variable already found, but not clobbering...\n"); X X return; X } /* end if not clobber */ X } X } X /* back up one if we're not at head of chain */ X if (phash == (struct list_hash *) NULL) X phash = qhash; X XINSERT: X /* insert the element into the list */ X X /* do we first need to create the list object? */ X if (*pp_list == NULL) { X X int i; X struct list *pl; X X /* create the list structure pointer */ X if ((pl = *pp_list = (struct list *) malloc(sizeof(struct list))) X == NULL) { X fprintf(stderr, "list_insert(): malloc() failed!\n"); X exit(1); X } X X /* create the pointers inside the structure */ X if ((p = (struct list_elem *) malloc(sizeof(struct list_elem))) X == NULL) { X fprintf(stderr, "list_insert(): malloc() failed!\n"); X exit(1); X } X /* cauterize the prev pointer */ X p->prev = NULL; X p->varname = NULL; X X /* attach to list structure */ X pl->p_head = head = pl->p_tail = p; X head->next = NULL; X X /* initialize the hash table */ X for (i = 0; i < LIST_HASHSZ; i++) { X hentry = &( ((*pp_list)->hashtable)[i]); X hentry->key = (char *) NULL; X hentry->used = 0; X hentry->lptr = (struct list_elem *) NULL; X hentry->next = (struct list_hash *) NULL; X } X X /* get correct hash bucket */ X hentry = &( ((*pp_list)->hashtable)[hindex]); X } X else if (clobber) { X free(p->varvalue); X } X else X { X /* add a list entry at tail of list */ X p = (*pp_list)->p_tail; X X if ((p->next = (struct list_elem *) X malloc(sizeof(struct list_elem))) == NULL) { X X fprintf(stderr, "list_insert(): malloc() failed!\n"); X exit(1); X } X X /* attach the prev pointer */ X p->next->prev = p; X X /* now the rest */ X p = p->next; X p->next = NULL; X X /* bind to tail */ X (*pp_list)->p_tail = p; X X if (phash->used) { X /* now create the hash chain entry */ X /* do we need a new structure to chain on? */ X if ((qhash = (struct list_hash *) malloc(sizeof(struct list_hash))) X == NULL) { X fprintf(stderr, "list_insert(): malloc() failed!\n"); X exit(1); X } X qhash->used = 0; X qhash->next = NULL; X X phash->next = qhash; X hentry = phash = qhash; X } X } X X /* start filling in fields */ X if (!clobber) { X if ((p->varname = (char *) malloc((unsigned) (strlen(pc_name) + 1))) X == NULL) { X fprintf(stderr, "list_insert(): malloc() failed!\n"); X exit(1); X } X (void) strcpy(p->varname, pc_name); X p->flag = 0; X p->priority = 0; X } X X if ((p->varvalue = (char *) malloc((unsigned) (strlen(pc_value) + 1))) X == NULL) { X fprintf(stderr, "list_insert(): malloc() failed!\n"); X exit(1); X } X (void) strcpy(p->varvalue, pc_value); X X /* fill in hash chain structure */ X if (!qhash || !clobber) { X hentry->key = p->varname; X if (hentry->used == 0) X hentry->used++; X hentry->lptr = p; X hentry->next = NULL; X } else { X qhash->next->key = p->varname; X } X assert(hentry->used == 1); X X return; X X} X X/* X * char * X * list_lookup(pc_name, pp_list) X * X * return the string value assigned to the environment value named X * pc_name in the specified list. X * X * you must copy the contents of the (char *). X */ X Xchar * Xlist_lookup(pc_name, pp_list) X char *pc_name; X struct list **pp_list; X{ X struct list_elem *p; X struct list_hash *phash; X char *s; X unsigned int hindex; X struct list_hash *hentry; X X /* X * 1) if *pp_list is NULL, then we know it's emtpy X * 2) if it's not in the hash table, then return NULL X * 3) search hash table chain X */ X X /* check for empty list */ X if (*pp_list == NULL) { X return NULL; X } X X /* look in hash table */ X hindex = string_hash(pc_name); X hentry = &(((*pp_list)->hashtable)[hindex]); X X if (hentry->used == 0) { X return NULL; X } X X /* now search through hash chain */ X for (phash = hentry; phash; phash = phash->next) { X if (strcmp(phash->key, pc_name) == 0) { X p = phash->lptr; X /* X s = (char *) malloc((unsigned) (strlen(p->varvalue) + 1)); X (void) strcpy(s, p->varvalue); X */ X s = p->varvalue; X return s; X } X } X return NULL; X} X X/* X * int X * list_isthere(pc_name, pp_list) X * X * returns (1) if pc_name is in the specified list. X * else returns (0). X */ X Xint Xlist_isthere(pc_name, pp_list) X char *pc_name; X struct list **pp_list; X{ X struct list_hash *phash; X unsigned int hindex; X struct list_hash *hentry; X X /* X * 1) if *pp_list is NULL, then we know it's emtpy X * 2) if it's not in the hash table, then return NULL X * 3) search hash table chain X */ X X /* check for empty list */ X if (*pp_list == NULL) { X return 0; X } X X /* look in hash table */ X hindex = string_hash(pc_name); X hentry = &(((*pp_list)->hashtable)[hindex]); X X if (hentry->used == 0) { X return 0; X } X X /* now search through hash chain */ X for (phash = hentry; phash; phash = phash->next) { X if (strcmp(phash->key, pc_name) == 0) { X return 1; X } X } X return 0; X} X X/* X * list_unset(pc_name, pp_list) X * remove the list entry with (varname == pcname) from the X * environment X */ X Xvoid Xlist_unset(pc_name, pp_list) X char *pc_name; X struct list **pp_list; X{ X struct list_hash *phash, *qhash = (struct list_hash *) NULL; X struct list_elem *plist; X unsigned int hindex; X struct list_hash *hentry; X X if (*pp_list == NULL) X return; X X /* X * 1) if pc_name isn't found in the hash chain, return X * 2) if found, remove the element from the list, and then remove X * from hash chain. X * check to see if we're the only element on the hash chain, X * too. X */ X X /* look in hash table */ X hindex = string_hash(pc_name); X hentry = &(((*pp_list)->hashtable)[hindex]); X X /* if not in hash table, return */ X if (hentry->used == 0) { X XLISTDEBUG(0) Xfprintf(stderr, "list_unset(): couldn't find '%s' in environment\n", pc_name); X X return; X } X X /* find the element, but playing pointer tag w/two pointers */ X for (phash = hentry; phash; qhash = phash, phash = phash->next) { X assert(qhash == NULL || qhash->next == phash); X if (strcmp(phash->key, pc_name) == 0) { X /* remove the element from the list */ X plist = phash->lptr; X X /* prev->next = this->next X * next->prev = this->prev X */ X X /* are we at the head of the list? */ X if (plist->prev) X plist->prev->next = plist->next; X /* are we at the end of the list? */ X if (plist->next) X plist->next->prev = plist->prev; X X /* adjust list head and tail pointers */ X if (((*pp_list)->p_head) == plist) X (*pp_list)->p_head = plist->next; X if (((*pp_list)->p_tail) == plist) X (*pp_list)->p_tail = plist->prev; X X free((char *) plist); X X /* now remove from hash chain */ X /* if it was at top of list */ X if (qhash == NULL) { X hentry->used = 0; X hentry->next = (struct list_hash *) NULL; X } else { X qhash->next = phash->next; X free((char *) phash); X } X return; X } X } X X X return; X} X X/* X * list_setflag(pc_name, flag, pp_list) X * X * OR the the specified flag to the existing flag value. X */ X Xint Xlist_setflag(pc_name, flag, pp_list) X char *pc_name; X int flag; X struct list **pp_list; X{ X struct list_elem *plist; X struct list_hash *phash, *hentry; X unsigned int hindex; X X if (*pp_list == NULL) X return -1; X X /* X * 1) look in hash table for entry. if not found, return with error. X * 2) walk down hash chain until entry is found, then modify the X * list entry X */ X X /* look in hash table */ X hindex = string_hash(pc_name); X hentry = &(((*pp_list)->hashtable)[hindex]); X X /* walk down chain */ X for (phash = hentry; phash && phash->used; phash = phash->next) { X if (strcmp(phash->key, pc_name) == 0) { X plist = phash->lptr; X plist->flag |= flag; X return 0; X } X } X X return 0; X} X X/* X * list_getflag(pc_name, pp_list) X * return the flag value embedded in structure. X */ X Xint Xlist_getflag(pc_name, pp_list) X char *pc_name; X struct list **pp_list; X{ X X struct list_elem *plist; X struct list_hash *phash, *hentry; X unsigned int hindex; X X if (*pp_list == NULL) X return -1; X X /* X * 1) look in hash table for entry. if not found, return with error. X * 2) walk down hash chain until entry is found, then modify the X * list entry X */ X X /* look in hash table */ X hindex = string_hash(pc_name); X hentry = &(((*pp_list)->hashtable)[hindex]); X X /* walk down chain */ X for (phash = hentry; phash && phash->used; phash = phash->next) { X if (strcmp(phash->key, pc_name) == 0) { X plist = phash->lptr; X return plist->flag; X } X } X X return -1; X} X X/* X * list_print() X * print out the entire contents of the linked list X */ X Xvoid Xlist_print(pp_list) X struct list **pp_list; X{ X struct list_elem *p; X struct list_elem *head; X X /* check to see if list is empty */ X if (*pp_list == NULL) X return; X X head = (*pp_list)->p_head; X X /* walk down entire list */ X for (p = head; p; p = p->next) { X /* X printf("%-40s\t%20s %d\n", p->varname, p->varvalue, p->flag); X */ X printf("(%s) %20s %d\n", p->varname, p->varvalue, p->flag); X } X return; X} X X/* X * list_reset() X * X * given a pointer to a list, delete the entire list, and set the X * pointer to NULL; X */ X Xvoid Xlist_reset (pp_list) X struct list **pp_list; X{ X struct list_elem *p, *q; X struct list_hash *phash, *qhash; X int i; X X if (*pp_list == NULL) X return; X X /* walk down the list, deleting the element that we just came from */ X for (p = (*pp_list)->p_head; p; q = p, p = p->next, free((char *) q)) ; X X /* walk down the hash table, and remove its hash chain */ X for (i = 0; i < LIST_HASHSZ; i++) { X phash = &(((*pp_list)->hashtable)[i]); X if (phash->used) { X /* don't delete the first entry! it's static! */ X for (phash = phash->next; phash; qhash = phash, X phash = qhash->next, free((char *) qhash)) ; X } X } X X /* now free up the list structure */ X free((char *) *pp_list); X X /* now invalidate the list structure pointer */ X *pp_list = NULL; X X return; X} X X X/* X * list_init () X * list_open (struct list **pp_list) X * list_get (struct list **pp_list) X * list_close(struct list **pp_list) X * X * this allows the retrieval of individual list elements through X * successive calls to list_get(). X * X * 0) list_init() initializes the tables. X * 1) list_open() creates a table entry with *pp_head as the key X * 2) any calls to list_get() will get the next element. the X * index is stored in the table, with *pp_head as the X * key. X * 3) list_close() removes the table entry, with *pp_head as the X * key. X */ X X#define LIST_TABLE_SZ 16 Xstruct list_table_entry { X struct list *p_key; /* pointer to head is used as key */ X struct list_elem *p_pindex; /* pointer to current element */ X}; X Xstatic struct list_table_entry list_table[LIST_TABLE_SZ]; X Xint Xlist_init() X{ X int i; X struct list_table_entry *p; X X /* clear all keys and indexes */ X for (i = 0; i < LIST_TABLE_SZ; i++) { X p = &list_table[i]; X p->p_key = NULL; X p->p_pindex = NULL; X } X return 0; X} X X/* X * list_open(struct list **pp_list) X * X * create a table entry with *pp_head as a key. X * returns (-1) if an entry with the specified key was already X * in the table, else (0). X */ X Xint Xlist_open (pp_list) X struct list **pp_list; X{ X int i; X struct list_table_entry *p; X X /* is the list NULL? */ X if (*pp_list == NULL) { X return 0; /* we'll fake it later on */ X } X X /* is there already an entry with a matching key? is there any X * an empty table entry for us? X */ X for (i = 0; i < LIST_TABLE_SZ; i++) { X p = &list_table[i]; X if (p->p_key == NULL) X break; X if (p->p_key == *pp_list) X break; X } /* end for loop */ X X /* X * return with error if there was a collision. (if the index rolled X * all the way to the top, and its index value was non-null, then X * we overflowed the table.) X */ X if (i == LIST_TABLE_SZ && p->p_key != NULL) X return -1; X X /* X * create the table entry. assertion: p already points to an empty X * table entry. Have index point to the head. X */ X p->p_key = *pp_list; X p->p_pindex = (*pp_list)->p_head; X X return 0; X} X X/* X * struct list_elem * X * list_get(struct list **pp_list) X * X * get the next entry in the specified list (using *pp_list as the key), X * and bump the internal pointer to the next element, ready X * for the next call to list_get(). X * we return NULL if we're sitting on the tail end of the list. X */ X Xstruct list_elem * Xlist_get (pp_list) X struct list **pp_list; X{ X int i; X struct list_table_entry *p, *q; X struct list_elem *p_elem; X X /* fake it if you pass it a NULL */ X if (*pp_list == NULL) { X return NULL; X } X X /* find entry with matching key */ X for (i = 0; i < LIST_TABLE_SZ; i++) { X p = &list_table[i]; X if (p->p_key == *pp_list) X break; X } /* end for loop */ X X /* bounds checking. if we rolled through the entire array, then X * we never found the key! X */ X X if (i == LIST_TABLE_SZ) X return NULL; X X /* are we already at the end of the list? */ X X if (p->p_pindex == NULL) X return NULL; X X /* if not, return a pointer to the current list element, and increment X * the table pointer. X */ X X p_elem = p->p_pindex; X q = p; X q->p_pindex = q->p_pindex->next; /* walk through pointer */ X X return p_elem; X} X X/* X * list_close(struct list **pp_list) X * X * remove the table entry with (*pp_list) as the key. X * return -1 if entry not found. else 0. X */ X Xint Xlist_close (pp_list) X struct list **pp_list; X{ X int i; X struct list_table_entry *p; X X /* fake it if you pass it a NULL */ X if (*pp_list == NULL) { X return 0; X } X X /* find entry with matching key */ X for (i = 0; i < LIST_TABLE_SZ; i++) { X p = &list_table[i]; X if (p->p_key == *pp_list) X break; X } /* end for loop */ X X /* bounds checking. if we rolled through the entire array, then X * we never found the key! X */ X X if (i == LIST_TABLE_SZ) X return -1; X X /* remove the entry. assertion: p is pointing to our entry */ X p->p_key = NULL; X p->p_pindex = NULL; X X return 0; X} X Xstatic unsigned int Xstring_hash (string) X char *string; X{ X unsigned int hindex; X char *pc = string; X X hindex = *pc; X while (*pc) { X hindex = ((hindex << 9) ^ *pc++) % LIST_HASHSZ; X /* X hindex = ((hindex << 7) | (string[i] + len)) % LIST_HASHSZ; X */ X } X return hindex; X} X X#ifdef TEST Xmain() X{ X char s[1024]; X struct list *list = (struct list *) NULL; X FILE *fpin; X X#define X2 X#ifdef X1 X if (!(fpin = fopen("/tmp/x", "r"))) { X perror("fopen()"); X exit(1); X } X X while (fgets(s, 1024, fpin) != 0) { X s[strlen(s)-1] = 0; X list_set(s, "", 0, &list); X if (!list_lookup("/scr/genek/mush/expr.c", &list)) { X printf("Yikes! (%s)\n", s); X } X } X X fseek(fpin, 0, 0); X while (fgets(s, 1024, fpin) != 0) { X s[strlen(s)-1] = 0; X list_set(s, "", 0, &list); X if (!list_lookup("/scr/genek/mush/expr.c", &list)) { X printf("Yikes! (%s)\n", s); X } X } X fseek(fpin, 0, 0); X X while (fgets(s, 1024, fpin) != 0) { X s[strlen(s)-1] = 0; X if (!list_lookup(s, &list)) { X printf("Yikes! (%s)\n", s); X } X } X#endif X} X#endif X X#ifdef TEST2 Xmain() X{ X struct list *l = NULL; X X list_set("a", "", 0, &l); X list_set("b", "", 0, &l); X list_set("c", "", 0, &l); X list_set("d", "", 0, &l); X list_set("e", "", 0, &l); X list_print(&l); X list_unset("a", &l); X list_print(&l); X list_unset("b", &l); X list_print(&l); X list_unset("d", &l); X list_print(&l); X} X#endif /* TEST2 */ END_OF_FILE if test 18568 -ne `wc -c <'tripwire-1.1/src/list.c'`; then echo shar: \"'tripwire-1.1/src/list.c'\" unpacked with wrong size! fi # end of 'tripwire-1.1/src/list.c' fi if test -f 'tripwire-1.1/Changelog' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tripwire-1.1/Changelog'\" else echo shar: Extracting \"'tripwire-1.1/Changelog'\" \(15952 characters\) sed "s/^X//" >'tripwire-1.1/Changelog' <<'END_OF_FILE' X# $Id: Changelog,v 1.33 1993/12/15 17:36:25 genek Exp $ X XThe following is the official list of changes between revisions: X X1.1.beta5 Wed Dec 15 01:06:07 EST 1993 X changed b64 representation yet again. (thanks Spaf) X changed dbaseversion number up to 3. (thanks Spaf) X reading in old database sooner for more timely error messages. X fixed missing L_tmpnam. X updated manual pages. X fixed siggen to better handle stdin. X X1.1.beta5 Sun Dec 12 22:32:38 EST 1993 X converging on Tripwire v1.1 release. (thanks Spaf) X X1.1.beta4 Fri Dec 10 16:55:00 EST 1993 X changed DB_VERSION_NUM to 2. X added program twconvert to help convert to Tripwire format. X added better handling for old dbase formats. X removed opportunity for temporary database file spoofing. (thanks X Matt Bishop) X fixed inconsistent storage of dbase table of contents when X updating the database. (thanks Eric Berggren) X added better fatal error messages. X fixed documentation and manual pages. (thanks Spaf) X added -dfd option to specify open file descriptor for database files. X (thanks Spaf) X X1.1.beta3 Thu Dec 2 11:58:13 EST 1993 X fixed interactive update oddities. (thanks Sam Gassel) X fixed database not found error. (thanks Sam Gassel) X added interactive test suite. X added @@include to preprocessor test suite. X made interactive update messages more human readable. X X1.1.beta2 Fri Nov 26 06:16:52 EST 1993 X fixed usage message. (thanks Drew Gonczi) X fixed @@ifhost warning messages. (thanks Chris Kern, Jason Downs) X fixed non-inheritance of new tw.config ignore-masks when doing X updates. (thanks Berggren) X fixed notice of SHA code optimization in WHATSNEW. (thanks Rik Farrow) X added more thorough SunOS tw.conf.sun file. (thanks Rik Farrow) X (old file moved to tw.conf.sun.old) X fixed output of @@contents. X allows @@{varname} expressions in parser. (thanks Spaf and Jim Napier) X added reporting of symbolic link file types in integrity check report. X "-rwxrwxrwx" now is correctly shown as "lrwxrwxrwx" (thanks Jim Napier) X expanded preprocessor test suite. X expanded update test suite. X fixed "-d -" error case. (thanks Bruce Jolliffe and Drew Gonczi) X got the Encore Multimax users running at last. (thanks Georges Tomazi) X corrected preprocessor filename tracking, and error/warning messages. X (thanks Eric Berggren) X X1.1beta Sun Nov 14 00:32:17 EST 1993 X made quietmode (-q) really quiet. (thanks Spaf) X added exit status to indicate filesystem changes (see manual page). X added support for ">" template for growing files. (thanks John Rouillard) X fixed -update to add files in a more intelligent manner. X fixed problem of `Hint: can't find database...' error message. X changed "-update" logic. is now correct. X all entries are now added if not in configuration file. X all entries now are added with reasonable ignore mask. X moved macro expansion into lexer. now, it really works. (thanks Spaf) X this works too: @@foo/@@dir @@ignore X added warning to catch partially-qualified @@ifhost directives. X (thanks Baron Fujimoto) X fixed root-anchoring problem that caused files to be scanned twice. X (thanks John Rouillard) X fixed handling of files with embedded spaces. (thanks Alain Brossard) X added warning about possible overflows when building byteorder.h. X (thanks Alain Brossard) X fixed typo in tw.config(5) manual page. (thanks Eric Bergren) X fixed handling of undefined macros. (thanks Patrick Sullivan) X fixed misreporting of unchanged entries. X fixed ./man install rule. (thanks Nora Hermida) X changed the way filename are stored in lists to handle special X characters in databases. X got rid of misleading variable and function names in source. X fixed boundary condition in list.c (removing head or tail of the X list wasn't reflected in the hash table structure.) X fixed Makefile dependencies for siggen. X fixed entry number problem X chaged order of file operations to allow -E to run w/o dbasefile. X X1.0.5 Thu Sep 30 05:08:33 EDT 1993 X fixed crc32 -- it didn't rewind the file descriptor. (thanks Eugene X Zaustinsky) X changed base64 alphabet. (thanks Eugene Zaustinsky) X fixed filename escaping bug. X fixed routines in list library that improperly handled case where X items are clobbered. this caused files to appear on both the X added and deleted lists in Tripwire. X backed out '/dir/dir/@@variable' change. it breaks 'file @@ignore'! X (thanks Bert Lindgren) X updated README. X X1.0.4 Wed Aug 18 23:02:14 EDT 1993 X added support for '-cfd fd' option to allow open file descriptor X to be specified for configuration file. (thanks Spaf) X added SHS/SHA Secure Hash Algorithm to Tripwire distribution. X changed CRC32 code to POSIX 1003.2 compliant signature (thanks Dan X Bernstein) X updated FAQ. (thanks Pat Macdonald, Eric Demerling). X changed log-file template to ignore changes in inode ctime. X (thanks John Rouillard) X added support for Solaris 2.2/SunOS 5.2. (thanks Bob Cunningham) X fixed another POSIX realloc() misuse, this time in -interactive code. X (thanks E. Clinton Arbaugh) X fixed lexical analyzer to allow '/dir/dir/@@variable' to expand X correctly. (thanks Neil Todd) X fixed grammar to make sure you can have @@variables in the middle X of strings. (thanks John Rouillard) X fixed MD4, MD5, MD2 code. finally got it right with a lot of cajoling X and hand-holding. (thanks Eugene Zaustinsky) X fixed Snefru code, backing out speedups to match Ralph Merkle's code X more closely. X added a rigorous signature test suite that is run before checking X test database. X changed name of sigfetch to siggen. added corresponding manual page X and defunctified sigfetch manual page. (thanks Spaf) X fixed siggen to use SIGNAME constants in config.h. X siggen now gives a list of signature number to signature name mappings X in usage message. X changed ./src/Makefile CFLAGS option (thanks Spaf) X changed test suite so it won't run from bottom-level makefile. X changed test to ascertain whether '-cfd fd' was given a legit fd. X changed test tw.config file to cover new files and uncover the X files that we know will change (config.h, et al) X X(limited release for testing purposes) X1.0.3: Tue Apr 27 18:40:54 EST 1993 X added 'tripwire -interactive' to allow users to be asked whether each X added, deleted, or changed file should be updated. X added help function in '-interactive' mode and '-help' that describes X each inode field. (thanks John Rouillard) X implemented a more consistent 'tripwire -update' routine that takes X care of added, deleted, and updated entries. X fixed incorrect 'tripwire -update' when used with symbolic links. X (thanks E. Clinton Arbaugh) X implemented printhex functionality in all signature routines. X updated README and manual pages to refelct new modes. X fixed MIPS/RISC-OS settings in Makefile. (thanks John Rouillard) X fixed aux/Makefile clean and top-level Makefile. (thanks John Rouillard) X fixed MD4 code -- I was thoroughly confused by the odd conventions used X in this routine. (thanks Eugene Zaustinsky) X chose more opportune time to print backup warning banner in '-update' X mode. X added AT&T 3B2 family of machines to ./configs directory and generalized X routines for machines that don't have gettimeofday(). (thanks Joe X Sirrianni) X increased size of too-small char array in preen.c. (thanks Bob Hutchinson) X changed filelist variable names to much more descriptive names. X added machine-generated banner to ./aux/byteorder.c. X fixed description of database file in ./includes/config.h. X fixed 'sigfetch' utility to return correct error codes. X added RCS tags to some straggler files. X X1.0.2: Thu Dec 10 05:45:48 EST 1992 X fixed @@ifhost xxx problem which dumped core. (thanks Rich Asmuth) X fixed realloc() problem. (thanks Beth Elias and Joe Ramus) X fixed -update problem which caused Tripwire to forget all about X special files. (thanks Joe Ramus) X fixed Changelog. I forgot about the Makefile fix. (thanks Tom Orban) X more useful error message when Tripwire can't find configuration file. X fixed 'tripwire -update' so it adds files explicitly specified on X command line, but not in database. (thanks Drew Gonczi) X Note that this needs some work -- we'll need to have an -add X and -delete option to make this functionally clean and preserve X database/tw.config semantics. X Xfirst official patch :-) X1.0.1: Mon Nov 23 15:58:50 EST 1992 X fixed placement of backup database file in database update mode. X fixed install target in ./src and ./man Makefiles. (thanks Hugo Cartaxeiro) X changed Ported entries for Pyramids. (thanks Peter Riili) X fixed Acknowledgements section in README. (thanks Michael Barnett) X fixed temporary filename generation problem. (thanks Gene Spafford) X fixed DIST variable in ./tests Makefile. X fixed typo in config.pre.y that prevented compilation with bison. X Xfirst official release X1.0: Tue Nov 3 02:35:17 EST 1992 X reorganized distribution into heirarchy. X changed pathnames (./Tests -> ./tests, ./Databases -> ./databases). X tripwire now creates ./databases directory if it doesn't already exist X when -initialize. X finished TODO list. X Xended beta testing period X0.92 beta 6: Tue Oct 20 14:55:03 EST 1992 X attempting to fix macro recursion problem. (thanks Shabbir Safdar) X fixed 'make test' variable assignment problem. (thanks Tom Gutnick) X fixed lstat()/SVR3 problem. (thanks Simon Leinen) X X0.92 beta 5: Sun Oct 18 19:33:19 EST 1992 X integrated substantial source code cleanup patch. X (thanks Ken McDonell) X added types.c to glean struct stat info. X added -i #|all flags, to specify which signatures to skip. X this feature was added to make running Tripwire on an hourly X basis reasonable. i.e., on hourly runs, check only CRC's. X On daily runs, check md5. On weekly runs, check all signatures. X (thanks John Rouillard) X fixed usage message, and -D and -U error handling. X added "-initialise" for people who don't speak American. :-) X (thanks Michael Barnett) X got signature object file dependencies right, finally. X X0.92 beta 4: Fri Oct 16 18:32:36 EST 1992 X the day of patch-infamy. X a one-line fix to stop tripwire from saying all filenames are X not absolutely qualified. *sigh* X X0.92 beta 3: Fri Oct 16 18:02:59 EST 1992 X fixed Makefile rule. (thanks Rich Salz) X fixed duplicate yacc token. (thanks Rich Salz) X fixed qualified filename bug. (thanks Ken McDonnel) X removed htonl(), ntohl() routines in utils.c. X added -D, -U flags to do command-line defines and undefines. X (thanks John Rouillard) X added more checks for null lists in list.c. X @@ifdef and @@ifhost support logical expressions: X @@ifdef (x || y && (z1 && (z2))) is now legal in tw.config grammar. X @@ifhost (x || y && (z1 && (z2))) is now legal in tw.config grammar. X added line continuation with '\' in tw.config grammar. X added @@echo for testing. maybe we'll keep it? X default ignore flags and templates now ignore signatures 3-9. X added [()|&] as characters that need to be escaped in database. X fixed filename_escape_expand(). X X0.92 beta 2: Fri Oct 16 12:18:28 EST 1992 X finally fixed up '=' pruning. (thanks David Wiseman) X added Porting database. X added transient file handling in config.parse.c. X fixed comment handling in config.parse.c. X merged gazillions of platform dependencies. let's hope everything X still works. X reorganized Makefile so it's easier to spot your own platform, I hope. X make Tripwire compiles bearable for systems w/o BSD filesystems. X various semantic and lint cleanups. X reorganized phase 3 presenation. more verbose, hopefully clearer. X (thanks Christopher Samuel) X added user-contributed tripwire.config files. X purged >14 character filenames: X database.build.c -> dbase.build.c X tripwire.config -> tw.config X tripwire.database_@ -> tw.db_@ X ^^-- room for 9-character hostname X added COPS interface in ./contrib. (thanks Shabbir Safdar) X added "-f dbasefile" option to specify alternate dbase file. X (allows "-f -" to read from stdin.) X added "-c configfile" option to specify alternate config file X (allows "-c -" to read from stdin.) X added code to escape filenames starting with '#'. X added tw.config preprocessor directives: X @@ifhost X @@define x VAR X @@undef x X @@ifdef x X @@endif X @@include X ...and X variable substition (@@x --(turns into)--> VAR) X added "-E" or "-preprocess" to print out processed tw.config X file. (ala "cc -E" or "cpp".) X added incremental database. (-update entry) X md5 fix for Cray. (thanks John Cristy) X AIX fix for stat structure. (thanks Shabbir Safdar) X config_interpolate() now caches vectors, instead recomputing every X time. X tripwire now makes backup of files when doing "-update". X played with profiler. halved the number of calls strlen(). X (I wonder if we can do the same with strcpy().) X made backup file 14-character length friendly for SVR3 people. X so, now tripwire is completely 14-character filename friendly, right? X implemented tw.config parsing routines in lex and yacc X added @@dbaseversion directive to specify what format the tw_db files X use. this is to prevent reading in unknown database files. X completed filename_escape_expand() to handle all sorts of escape X sequences (escaped octals, cooked-style escaped characters, X and all of tripwire's special characters [e.g., '\@']). X added warning of null characters in filename. X created consistent escaping and de-escaping of characters to and X from database. X sped up character escaping routines by using all table-lookups. X moved database format strings into the header file. X list generation sped up (1500 files in 20 seconds on Sequent). X added tw.config.5 manual page, which describes the tw.config X syntax and preprocessor directives. X added @@else directive to tw.config parser. X changed signature routines to return number in base-64. X this has the unfortunate effect of making all the signatures look X like pathnames, but it does make signature storage 6 bytes instead X of 8 bytes. X added support for 10 signatures. X fixed tripwire -update. now skips directory entries when regenerating X database. X added CRC16 and CRC32 to signature routine repository. X added "sigs.h" to make signature routines more general. X added MD2 and MD4. X changed 'make test' so no files are clobbered. X fixed '-d dbasefile' bug. X X X X0.9beta8: Thu Sep 17 19:06:18 EST 1992 X eliminated use of 'sort' and 'diff', using list routines instead X (fixed tripwire confusion in parsing '=' additions from diff X which generated zillions of bogus changed file entries.) X this speeds up Phase 3 considerably, since we don't sort! X sped up linked-list/hash routines (HASHSZ increased by 100x) X removed diff.sorted.c X (thanks to the five people who tested this: David Wiseman, John X Sutton, Lance Bailey, John Rouillard, David Smith). X X0.9beta7: Thu Sep 10 20:45:02 EST 1992 X fixed list initialization routine. X fixed Makefile, README, manual page. X fixed memory leak problems (spotted by Purify). X fixed default ignore-masking handling bug. X (didn't convert to internal form first) X fixed ignore-mask parsing. (David Smith) X added banner to Tripwire databases on creation. X taught tripwire to say what version it is. X sped up most commonly called routines (config_interpolate() and X slash_count()). Thanks Rich Salz! X X0.9beta6: Wed Sep 09 21:04:35 EST 1992 X First version of Tripwire to see the light of day. X END_OF_FILE if test 15952 -ne `wc -c <'tripwire-1.1/Changelog'`; then echo shar: \"'tripwire-1.1/Changelog'\" unpacked with wrong size! fi # end of 'tripwire-1.1/Changelog' fi if test -f 'tripwire-1.1/README.kits' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tripwire-1.1/README.kits'\" else echo shar: Extracting \"'tripwire-1.1/README.kits'\" \(479 characters\) sed "s/^X//" >'tripwire-1.1/README.kits' <<'END_OF_FILE' XNow that you have unpacked all of the Tripwire distribution kits, Xcd into the tripwire-1.1 directory and use the Bourne shell to Xexecute the "reform" shell script. This will rebuild some files Xthat needed to be split into pieces to fit into shar kits. X XNext, read the README file. It will tell you what you need to Xedit and change to build Tripwire. Be sure to read section 0.0 Xabout "twconvert" if you have already been running a version of XTripwire prior to version 1.1 !! END_OF_FILE if test 479 -ne `wc -c <'tripwire-1.1/README.kits'`; then echo shar: \"'tripwire-1.1/README.kits'\" unpacked with wrong size! fi # end of 'tripwire-1.1/README.kits' fi echo shar: End of archive 17 \(of 25\). cp /dev/null ark17isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 25 archives. echo "Now read tripwire-1.1/README.kits" rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0