Newsgroups: comp.sources.unix From: spaf@cs.purdue.edu (Gene Spafford) Subject: v27i160: tripwire-1.1 - security integrity monitor, V1.1, Part14/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 160 Archive-Name: tripwire-1.1/part14 #! /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/sigs/snefru/snefruac' <<'END_OF_FILE' X/* 65*/ 0x99efba31L,0x2eab4e1cL,0xfc6ca5e7L,0x0ebe5d4eL,0xa0717d0cL, X/* 70*/ 0xb64f8199L,0x946b31a1L,0x5656cbc6L,0xcffec3efL,0x622766c9L, X/* 75*/ 0xfa211e35L,0x52f98b89L,0x6d01674bL,0x4978a802L,0xf651f701L, X/* 80*/ 0x15b0d43dL,0xd6ff4683L,0x3463855fL,0x672ba29cL,0xbc128312L, X/* 85*/ 0x4626a70dL,0xc8927a5aL,0xb8481cf9L,0x1c962262L,0xa21196baL, X/* 90*/ 0xbaba5ee9L,0x5bb162d0L,0x69943bd1L,0x0c47e35cL,0x8cc9619aL, X/* 95*/ 0xe284d948L,0x271bf264L,0xc27fb398L,0x4bc70897L,0x60cf202cL, X/* 100*/ 0x7f42d6aaL,0xa5a13506L,0x5d3e8860L,0xcea63d3cL,0x63bf0a8fL, X/* 105*/ 0xf02e9efaL,0xb17b0674L,0xb072b1d3L,0x06e5723bL,0x3737e436L, X/* 110*/ 0x24aa49c7L,0x0ded0d18L,0xdb256b14L,0x58b27877L,0xecb49f54L, X/* 115*/ 0x6c40256aL,0x6ea92ffbL,0x3906aa4cL,0xc9866fd5L,0x4549323eL, X/* 120*/ 0xa7b85fabL,0x1918cc27L,0x7308d7b5L,0x1e16c7adL,0x71850b37L, X/* 125*/ 0x3095fd78L,0xa63b70e6L,0xd880e2aeL,0x3e282769L,0xa39ba6bcL, X/* 130*/ 0x98700fa3L,0xf34c53e8L,0x288af426L,0xb99d930fL,0xf5b99df1L, X/* 135*/ 0xe9d0c8cfL,0x5ac8405dL,0x50e7217bL,0x511fbbbeL,0x2ca2e639L, X/* 140*/ 0xc020301bL,0x356dbc00L,0x8e43ddb9L,0x4d327b4aL,0xf20ff3edL, X/* 145*/ 0x1dbb29bdL,0x43d44779L,0xa1b68f70L,0x6114455bL,0xe63d280bL, X/* 150*/ 0x6bf6ff65L,0x10fc39e5L,0x3dae126eL,0xc1d7cf11L,0xcb60b795L, X/* 155*/ 0x1789d5b3L,0x9bca36b7L,0x08306075L,0x84615608L,0x8b3a0186L, X/* 160*/ 0xe88fbecdL,0x7ba47c4dL,0x2de44dacL,0x653fe58dL,0xcca0b968L, X/* 165*/ 0xd7fa0e72L,0x93901780L,0x1f2c26ccL,0xae595b6bL,0xa9ecea9bL, X/* 170*/ 0xe3dbf8c4L,0x319cc130L,0x12981196L,0x01a3a4deL,0x32c454b6L, X/* 175*/ 0x755bd817L,0x3cd871e4L,0xa48bb8daL,0x02fdec09L,0xfd2dc2e2L, X/* 180*/ 0x9e578088L,0x9a9f916dL,0x4065fe6cL,0x1853999eL,0xc7793f23L, X/* 185*/ 0xdc1016bbL,0x969355ffL,0x7ef292f6L,0xcdce4adcL,0x05e24416L, X/* 190*/ 0x85c16c46L,0xd441d37fL,0x57bd6855L,0x8746f54fL,0x9ca773dfL, X/* 195*/ 0x770bae22L,0x54828413L,0xb75e4b19L,0x04c35c03L,0xbf7cca07L, X/* 200*/ 0x2955c4ddL,0x721db041L,0xb2394f33L,0x03f51387L,0x89b73c9fL, X/* 205*/ 0x0b1737f3L,0x07e69024L,0x9231d245L,0x76193861L,0x88159c15L, X/* 210*/ 0xdeb552d9L,0xd9767e40L,0x20c6c0c3L,0x4281977cL,0xf8afe1e0L, X/* 215*/ 0xd32a0751L,0x3fc27432L,0xddf1dcc5L,0x68581f34L,0x3bcd5025L, X/* 220*/ 0x0091b2eeL,0x4aeb6944L,0x1602e743L,0xea09eb58L,0xef0a2a8bL, X/* 225*/ 0x641e03a5L,0xeb50e021L,0x5c8ccef8L,0x802ff0b8L,0xd5e3edfeL, X/* 230*/ 0xc4dd1b49L,0x5334cd2aL,0x13f82d2fL,0x47450c20L,0x55dafbd2L, X/* 235*/ 0xbec0c6f4L,0xb45d7959L,0x3ad36e8cL,0x0aa8ac57L,0x1a3c8d73L, X/* 240*/ 0xe45aafb1L,0x9f664838L,0xc6880053L,0xd0039bbfL,0xee5f19ebL, X/* 245*/ 0xca0041d8L,0xbbea3aafL,0xda628291L,0x9d5c95d4L,0xadd504a6L, X/* 250*/ 0xc39ab482L,0x5e9e14a4L,0x2be065f0L,0x2a13fc3aL,0x9052e8ecL, X/* 255*/ 0xaf6f5afcL X /* End of S Box 14 */ }, X X X { /* Start of S Box 15 */ X X/* 0*/ 0x519aa8b5L,0xbb303da9L,0xe00e2b10L,0xdfa6c1dbL,0x2e6b952eL, X/* 5*/ 0xee10dc23L,0x37936d09L,0x1fc42e92L,0x39b25a9fL,0x13ff89f4L, X/* 10*/ 0xc8f53feaL,0x18500bc7L,0x95a0379dL,0x98f751c2L,0x2289c42fL, X/* 15*/ 0xa21e4098L,0x6f391f41L,0xf27e7e58L,0x0d0df887L,0x4b79d540L, X/* 20*/ 0x8e8409aaL,0x71fe46f8L,0x688a9b29L,0x3f08b548L,0x84abe03aL, X/* 25*/ 0x5e91b6c1L,0xfde4c2aeL,0x251d0e72L,0x92d4fee5L,0xf9371967L, X/* 30*/ 0x9175108fL,0xe6e81835L,0x8c8cb8eeL,0xb55a67b3L,0xcef138ccL, X/* 35*/ 0x8b256268L,0x00d815f5L,0xe8810812L,0x77826189L,0xea73267dL, X/* 40*/ 0x19b90f8dL,0x45c33bb4L,0x82477056L,0xe1770075L,0x09467aa6L, X/* 45*/ 0xa7c6f54aL,0x79768742L,0x61b86bcaL,0xd6644a44L,0xe33f0171L, X/* 50*/ 0xc229fbcdL,0x41b08febL,0xd1903e30L,0x65ec9080L,0x563d6fbdL, X/* 55*/ 0xf56da488L,0xebf64cd8L,0x4934426bL,0x7c8592fcL,0x6aca8cf2L, X/* 60*/ 0x1cea111bL,0x3a57ee7aL,0xace11c0dL,0x9942d85eL,0xc4613407L, X/* 65*/ 0xfa8e643bL,0x327fc701L,0x4ca9be82L,0x3352526dL,0x2c047f63L, X/* 70*/ 0xf3a8f7ddL,0x1a4a98a8L,0x762ed4d1L,0x27c75008L,0xbdf497c0L, X/* 75*/ 0x7a7b84dfL,0x315c28abL,0x801f93e3L,0xf19b0ca1L,0x8f14e46aL, X/* 80*/ 0xe48ba333L,0x9605e625L,0xf03ecb60L,0x60385f2dL,0x902845baL, X/* 85*/ 0x7f96d66fL,0x24bff05cL,0x2820730bL,0x947133cbL,0xd444828aL, X/* 90*/ 0xb343f6f1L,0x0bef4705L,0x8da574f9L,0x01e25d6cL,0x1732793eL, X/* 95*/ 0x4f0f7b27L,0x364b7117L,0xb2d1da77L,0xa6c5f1e9L,0x574ca5b1L, X/* 100*/ 0x386a3076L,0xad6894d6L,0x1156d7faL,0xa48d1d9aL,0x4794c0afL, X/* 105*/ 0x150c0aa0L,0x26d348acL,0x29fdeabeL,0xa5dede53L,0x81671e8eL, X/* 110*/ 0x594ee3bfL,0xa96c56e6L,0x3426a726L,0xc5976579L,0xbc22e5e4L, X/* 115*/ 0xc1006319L,0xdaafdd2aL,0xa1a1aa83L,0x3badd0e7L,0xc3b14981L, X/* 120*/ 0xd770b155L,0xccd7c693L,0x42e944c5L,0x03e0064fL,0xca95b4efL, X/* 125*/ 0x3dee81c3L,0xfbbcd98cL,0x1e07e15bL,0x667ce949L,0xe7d6773fL, X/* 130*/ 0x21b6124bL,0x6b2a6ef7L,0xd3278a9cL,0x9a988304L,0x75d2ae9bL, X/* 135*/ 0xfe49e2ffL,0x9bc24f46L,0x74cc2cf6L,0xa3139f36L,0x6c9ef35aL, X/* 140*/ 0x9fc1dffeL,0x9e5facdcL,0xaadc8bbbL,0x5abdbc5fL,0x44b3b390L, X/* 145*/ 0xf754efa7L,0x5fe3bdb7L,0x4e59c886L,0x06a4c984L,0xa0338878L, X/* 150*/ 0xcd513cd7L,0x63ebd27eL,0x8aba80adL,0x50da144eL,0x5d9f4e97L, X/* 155*/ 0x025b751cL,0x2d580200L,0xb6c05837L,0x580aa15dL,0x54022a6eL, X/* 160*/ 0xb41a5415L,0x4863fab6L,0xb0b79957L,0x46d0d159L,0xdc2b8650L, X/* 165*/ 0x20a7bb0cL,0x4a032974L,0xec8636a2L,0x8548f24cL,0xf6a2bf16L, X/* 170*/ 0x1088f4b0L,0x0c2f3a94L,0x525dc396L,0x14065785L,0x2b4dca52L, X/* 175*/ 0x08aeed39L,0xabedfc99L,0xb1dbcf18L,0x87f85bbcL,0xae3aff61L, X/* 180*/ 0x433ccd70L,0x5b23cc64L,0x7b453213L,0x5355c545L,0x9318ec0aL, X/* 185*/ 0x78692d31L,0x0a21693dL,0xd5666814L,0x05fb59d9L,0xc71985b2L, X/* 190*/ 0x2abb8e0eL,0xcf6e6c91L,0xd9cfe7c6L,0xefe7132cL,0x9711ab28L, X/* 195*/ 0x3ce52732L,0x12d516d2L,0x7209a0d0L,0xd278d306L,0x70fa4b7bL, X/* 200*/ 0x1d407dd3L,0xdb0beba4L,0xbfd97621L,0xa8be21e1L,0x1b6f1b66L, X/* 205*/ 0x30650ddaL,0xba7ddbb9L,0x7df953fbL,0x9d1c3902L,0xedf0e8d5L, X/* 210*/ 0xb8741ae0L,0x0f240565L,0x62cd438bL,0xc616a924L,0xaf7a96a3L, X/* 215*/ 0x35365538L,0xe583af4dL,0x73415eb8L,0x23176a47L,0xfc9ccee8L, X/* 220*/ 0x7efc9de2L,0x695e03cfL,0xf8ce66d4L,0x88b4781dL,0x67dd9c03L, X/* 225*/ 0x3e8f9e73L,0xc0c95c51L,0xbe314d22L,0x55aa0795L,0xcb1bb011L, X/* 230*/ 0xe980fdc8L,0x9c62b7ceL,0xde2d239eL,0x042cadf3L,0xffdf04deL, X/* 235*/ 0x5ce6a60fL,0xd8c831edL,0xb7b5b9ecL,0xb9cbf962L,0xe253b254L, X/* 240*/ 0x0735ba1fL,0x16ac917fL,0xdd607c2bL,0x64a335c4L,0x40159a7cL, X/* 245*/ 0x869222f0L,0x6ef21769L,0x839d20a5L,0xd03b24c9L,0xf412601eL, X/* 250*/ 0x6d72a243L,0x0e018dfdL,0x89f3721aL,0xc94f4134L,0x2f992f20L, X/* 255*/ 0x4d87253cL X /* End of S Box 15 */ } X}; X X/* X * The following routine is a simple error exit routine -- it prints a X * message and aborts X */ Xvoid XErrAbort (s) X char *s; X{ X fprintf (stderr, "%s\n", s); X exit (1); X} X X X/* X * The following routine converts a byte array to an array of word32 X * int. It is primarily intended to eliminate the byte-ordering problem. X * VAXes order the bytes in a character array differently than SUN's do. This X * routine should be portable across different computer architectures. X * However, it is not very efficient. X */ Xvoid XConvertChunkOfBytes (charBuffer, wordBuffer) X /* an input buffer of characters */ X char charBuffer[CHUNK_SIZE*4]; X /* an output buffer of word32's */ X word32 wordBuffer[CHUNK_SIZE]; X{ X int i; X word32 t0, t1, t2, t3; X X for (i = 0; i < CHUNK_SIZE; i++) { X t0 = charBuffer[4*i]; X t1 = charBuffer[4*i + 1]; X t2 = charBuffer[4*i + 2]; X t3 = charBuffer[4*i + 3]; X t0 &= 0xffL; X t1 &= 0xffL; X t2 &= 0xffL; X t3 &= 0xffL; X wordBuffer[i] = (t0 << 24) | (t1 << 16) | (t2 << 8) | t3; X }; X} X X/* X * The following routine trys to read 4*"CHUNK_SIZE" bytes from the input X * file. It will only return a non-full buffer if an EOF is encountered. X * X * It returns the number of bytes actually read. If there are any errors, it X * aborts. If this routine cannot read all the bytes it's supposed to, it X * pads the output array, "buf", with trailing 0 bytes. X */ Xint XReadChunk (buf, fd) X word32 buf[CHUNK_SIZE]; X int fd; X{ X char charBuf[CHUNK_SIZE*4]; X int byteCount; X int i; X X byteCount = read(fd, charBuf, CHUNK_SIZE*4); X if (byteCount < 0) X ErrAbort ("error on read"); X /* Zero out rest of buffer */ X for (i = byteCount; i < CHUNK_SIZE*4; i++) X charBuf[i] = 0; X /* X * The following conversion is required for machines with X * byte-ordering unlike the SUN's (68000's or SPARC) X * ConvertChunkOfBytes (charBuf, buf); X */ X { X unsigned long *plsrc = (unsigned long *) charBuf, X *pldest = (unsigned long *) buf; X X for (i = 0; i < CHUNK_SIZE; i++) { X pldest[i] = *plsrc++; X ntohl(pldest[i]); X } X } X X return (byteCount); X} X X X/* X * HashN is a conceptually simpler and more general version of Hash512. X * It accepts an input of X * INPUT_BLOCK_SIZE 32-bit words and produces an output of X * OUTPUT_BLOCK_SIZE 32-bit words. The INPUT_BLOCK_SIZE must be at X * least two words larger than the output, or a serious degradation X * in security will occur. In addition, the use of outputs less X * than 128 bits will often significantly reduce security. While X * possible, it requires great caution. X */ Xvoid XHashN (output, input) X word32 output[OUTPUT_BLOCK_SIZE]; X word32 input[INPUT_BLOCK_SIZE]; X{ X static int shiftTable[4] = {16, 8, 16, 24}; X /* the array of data being hashed */ X word32 block[INPUT_BLOCK_SIZE]; X word32 SBoxEntry; /* just a temporary */ X int shift; X int i; X int index; X int next, last; X int byteInWord; X X /* initialize the block to be encrypted from the input */ X for (i = 0; i < INPUT_BLOCK_SIZE; i++) X block[i] = input[i]; X X for (index = 0; index < SECURITY_LEVEL; index++) { X for (byteInWord = 0; byteInWord < 4; byteInWord++) { X for (i = 0; i < INPUT_BLOCK_SIZE; i++) { X /* compute i+1 and i-1 mod INPUT_BLOCK_SIZE */ X next = (i + 1) & MASK; X last = (i + MASK) & MASK; X /* Load an entry from the S-box */ X SBoxEntry = standardSBoxes X [2*index + ((i / 2) & 1)] X [block[i] & 0xffL]; X /* X * and XOR that entry with the preceding and X * following words X */ X block[next] ^= SBoxEntry; X block[last] ^= SBoxEntry; X }; X /* X * Rotate right all 32-bit words in the entire block X * at once. X */ X shift = shiftTable[byteInWord]; X for (i = 0; i < INPUT_BLOCK_SIZE; i++) X block[i] = (block[i] >> shift) | X (block[i] << (32 - shift)); X X }; /* end of byteInWord going from 0 to 3 */ X }; /* end of index going from 0 to X * SECURITY_LEVEL-1 */ X X for (i = 0; i < OUTPUT_BLOCK_SIZE; i++) X output[i] = input[i] ^ block[MASK - i]; X} X X X/* X * Hash512 is a more efficient and specialized version of HashN. X * It accepts an input of INPUT_BLOCK_SIZE 32-bit words and X * produces an output of X * OUTPUT_BLOCK_SIZE 32-bit words. The INPUT_BLOCK_SIZE must be at X * least two words larger than the output, or a serious degradation X * in security will occur. In addition, the use of outputs less X * than 128 bits will often significantly reduce security. While X * possible, it requires great caution. X */ Xvoid XHash512 (output, input) X word32 output[OUTPUT_BLOCK_SIZE]; X word32 input[INPUT_BLOCK_SIZE]; X{ X static int shiftTable[4] = {16, 8, 16, 24}; X /* the array of data being hashed */ X word32 block[INPUT_BLOCK_SIZE]; X word32 SBE; /* just a temporary */ X int shift, leftShift; X int i; X int index; X int next, last; X int byteInWord; X word32 *SBox0; X word32 *SBox1; X word32 B00,B01,B02,B03,B04,B05,B06,B07,B08,B09,B10,B11,B12,B13,B14,B15; X X /* initialize the block to be encrypted from the input */ X B00 = input[0]; X B01 = input[1]; X B02 = input[2]; X B03 = input[3]; X B04 = input[4]; X B05 = input[5]; X B06 = input[6]; X B07 = input[7]; X B08 = input[8]; X B09 = input[9]; X B10 = input[10]; X B11 = input[11]; X B12 = input[12]; X B13 = input[13]; X B14 = input[14]; X B15 = input[15]; X X X for (index = 0; index < SECURITY_LEVEL; index++) { X SBox0 = standardSBoxes[2*index+0]; X SBox1 = standardSBoxes[2*index+1]; X for (byteInWord = 0; byteInWord < 4; byteInWord++) { X round(B15,B00,B01,SBox0); X round(B00,B01,B02,SBox0); X round(B01,B02,B03,SBox1); X round(B02,B03,B04,SBox1); X round(B03,B04,B05,SBox0); X round(B04,B05,B06,SBox0); X round(B05,B06,B07,SBox1); X round(B06,B07,B08,SBox1); X round(B07,B08,B09,SBox0); X round(B08,B09,B10,SBox0); X round(B09,B10,B11,SBox1); X round(B10,B11,B12,SBox1); X round(B11,B12,B13,SBox0); X round(B12,B13,B14,SBox0); X round(B13,B14,B15,SBox1); X round(B14,B15,B00,SBox1); X /* X * Rotate right all 32-bit words in the entire block X * at once. X */ X shift = shiftTable[byteInWord]; X leftShift = 32-shift; X rotate(B00); X rotate(B01); X rotate(B02); X rotate(B03); X rotate(B04); X rotate(B05); X rotate(B06); X rotate(B07); X rotate(B08); X rotate(B09); X rotate(B10); X rotate(B11); X rotate(B12); X rotate(B13); X rotate(B14); X rotate(B15); X }; /* end of byteInWord going from 0 to 3 */ X }; /* end of index going from 0 to X * SECURITY_LEVEL-1 */ X output[0] = input[0] ^ B15; X output[1] = input[1] ^ B14; X output[2] = input[2] ^ B13; X output[3] = input[3] ^ B12; X if(OUTPUT_BLOCK_SIZE == 4) return; X output[4] = input[4] ^ B11; X output[5] = input[5] ^ B10; X output[6] = input[6] ^ B09; X output[7] = input[7] ^ B08; X if(OUTPUT_BLOCK_SIZE == 8) return; X X ErrAbort("Bad value for OUTPUT_BLOCK_SIZE"); X} X X/* X * This routine increments a 64-bit counter by the given increment. X */ Xvoid XIncrement64BitCounter (counter, increment) X word32 counter[2]; X long int increment; X{ X word32 maxInt = 0xffffffffL; X X if ( (maxInt-counter[1]) < increment) { X /* Overflow from the lower 32 bits */ X if (counter[0] == maxInt) X ErrAbort("64-bit counter overflowed"); X /* bump the upper 32 bits */ X counter[0]++; X /* and then increment the lower 32 bits */ X /* without ever overflowing! */ X counter[1] = maxInt-counter[1]; X counter[1] = increment - counter[1]; X } X else X /* increment the total number of bits read */ X counter[1] += increment; X} X X X/* X * The main program reads the input, hashes it, and prints the result. X * X * The basic idea is simple. As an example, if H is the hash function that X * produces 128-bit outputs, and if we pick an input string that is 3 X * "chunks" long then we are computing: X * X * output = H( H( H( H( 0 || chunk[0]) || chunk[1]) X * || chunk[2]) || bit-length) X * X * "bit-length" is a "chunk" sized field into which has been put the length of X * the input, in bits, right justified. Note that the size of a "chunk" is X * just the input size minus the output size (typically 48 bytes or 12 X * words). X * X * "0" is a vector of 0 bits of the same size (in bits) as the output of H X * (i.e., typically 128 bits). X * X * "||" is the concatenation operator, and is used to concatenate the output X * field of the preceding computation of H with the next "chunk" of bits from X * the input. X * X * "chunk" is an array which holds the input in words. The final element of the X * array is left justified and zero-filled on the right. X * X */ Xint Xsig_snefru_get(fd_in, ps_signature, siglen) X int fd_in; X char *ps_signature; X int siglen; X{ X int i; X char s[512], sword[512]; X word32 hash[INPUT_BLOCK_SIZE]; X word32 bitCount[2]; /* the 64-bit count of the number of X * bits in the input */ X long int byteCount; /* the count of the number of bytes we just X * read */ X X ps_signature[0] = 0; X /* rewind the file descriptor */ X if (lseek(fd_in, 0, SEEK_SET) < 0) { X perror("sig_snefru_get: lseek()"); X exit(1); X } X X#ifdef MAIN X /* Test for various error conditions and logic problems */ X if (SECURITY_LEVEL*2 > MAX_SBOX_COUNT) X ErrAbort ("Too few S-boxes for specified SECURITY_LEVEL"); X if (OUTPUT_BLOCK_SIZE < 4) X ErrAbort ("OUTPUT_BLOCK_SIZE too small"); X if ((INPUT_BLOCK_SIZE & MASK) != 0) X ErrAbort ("logic error, INPUT_BLOCK_SIZE not a power of 2"); X if ((INPUT_BLOCK_SIZE % 4) != 0) X ErrAbort ("logic error, INPUT_BLOCK_SIZE not a multiple of 4"); X if (OUTPUT_BLOCK_SIZE > INPUT_BLOCK_SIZE - 2) X ErrAbort ("logic error, OUTPUT_BLOCK_SIZE is too big"); X if (CHUNK_SIZE < 2) X ErrAbort ("logic error, CHUNK_SIZE is too small"); X#endif X X /* X * The error condtions have now been checked -- everything should X * work smoothly X */ X bitCount[0] = 0; X bitCount[1] = 0; X for (i = 0; i < INPUT_BLOCK_SIZE; i++) X hash[i] = 0; /* initialize hash */ X /* X * Hash each chunk in the input (either 48 byte chunks or 32 byte X * chunks) -- and keep the result in hash. Note that the first 16 X * (32) bytes of hash holds the output of the previous hash X * computation done during the previous iteration of the loop X */ X do { X /* Get the next chunk */ X byteCount = ReadChunk (&hash[OUTPUT_BLOCK_SIZE], fd_in); X Increment64BitCounter (bitCount, 8*byteCount); X /* hash in the block we just read */ X if (byteCount > 0) X Hash512 (hash, hash); X } while (byteCount > 0); /* end of while */ X X /* X * Put the 64-bit bit-count into the final 64-bits of the block about X * to be hashed X */ X hash[INPUT_BLOCK_SIZE - 2] = bitCount[0]; /* upper 32 bits of X * count */ X hash[INPUT_BLOCK_SIZE - 1] = bitCount[1]; /* lower 32 bits of X * count */ X /* Final hash down. */ X Hash512 (hash, hash); X X /* X * the first OUTPUT_BLOCK_SIZE words of "hash" now hold the hashed X * result, which is printed on standard output X */ X /* X * the first OUTPUT_BLOCK_SIZE words of "hash" now hold the hashed X * result, which is printed on standard output X */ X if (printhex) { X for (i = 0; i < OUTPUT_BLOCK_SIZE; i++) { X sprintf (s, "%08lx", hash[i]); X strcat(ps_signature, s); X } X } X /* base 64 */ X else { X pltob64(hash, ps_signature, OUTPUT_BLOCK_SIZE); X } X /* X for (i = 0; i < OUTPUT_BLOCK_SIZE; i++) X printf (" %08lx", hash[i]); X * Note that if the user wishes to view the output as a sequence X * of bytes, then the byte order is the same as the order X * in which the bytes are printed by "printf" above. The X * first byte (designated byte 0) is the left-most byte X * printed by "printf" above. The last byte (designated X * byte 15) is the right-most byte printed. X * This can also be viewed as: X * X * the first byte is the most significant byte of hash[0], X * the second byte is the second most significant byte of hash[0], X * the third byte is the third most significant byte of hash[0], X * the fourth byte is the least significant byte of hash[0], X * the fifth byte is the most significant byte of hash[1], X * etc. This process continues until the last byte is reached. X * The last byte is the least significant byte of hash[3]. X * X * This is basically "big-endian" or network byte order. X * X * Although the use of the full 128 bits of output is recommended, X * in some applications it will be both useful and safe to use X * a smaller output. From a purely technical point of view, which X * bytes are retained and which are discarded is not an issue X * of any great significance. If there is any issue of standardization X * in the particular application, then the bytes that should be X * retained are the left-most bytes printed out by "printf" above, and X * the bytes that are to be discarded are the right-most bytes X * printed out by "printf" above. That is, the most significant X * (left most, lower numbered) bytes are retained, while the X * least significant (right most, higher numbered) bytes are discarded. X * X * When the output size is other than 128 bits, the above comments X * should be extended in the obvious fashion. X printf ("\n"); X exit (0); X */ X return 0; X} END_OF_FILE if test 19362 -ne `wc -c <'tripwire-1.1/sigs/snefru/snefruac'`; then echo shar: \"'tripwire-1.1/sigs/snefru/snefruac'\" unpacked with wrong size! fi # end of 'tripwire-1.1/sigs/snefru/snefruac' fi if test -f 'tripwire-1.1/src/config.parse.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tripwire-1.1/src/config.parse.c'\" else echo shar: Extracting \"'tripwire-1.1/src/config.parse.c'\" \(14760 characters\) sed "s/^X//" >'tripwire-1.1/src/config.parse.c' <<'END_OF_FILE' X#ifndef lint Xstatic char rcsid[] = "$Id: config.parse.c,v 1.17 1993/12/13 04:02:34 genek Exp $"; X#endif X X/* X * config.parse.c X * X * read in the preen.config file X * X * Gene Kim X * Purdue University X */ X X#include "../include/config.h" X#include X#ifdef STDLIBH X#include X#include X#endif X#include X#include X#include X#ifdef DIRENT X# include X#else X# ifndef XENIX X# include X# else /* XENIX */ X# include X# endif /* XENIX */ X#endif /* DIRENT */ X#if (defined(SYSV) && (SYSV < 3)) X# include X#endif /* SVR2 */ X#include X#ifdef STRINGH X#include X#else X#include X#endif X#include "../include/list.h" X#include "../include/tripwire.h" X X#if defined(SYSV) && (SYSV < 4) X#ifndef HAVE_LSTAT X# define lstat(x,y) stat(x,y) X#endif X#endif /* SYSV */ X X#if !defined(major) X#define major(x) (((unsigned)(x)>>16)&0xffff) X#endif X#if !defined(minor) X#define minor(x) ((x)&0xffff) X#endif X X/* prototypes */ Xchar *mktemp(); Xstatic void configfile_descend(); X X#ifndef L_tmpnam X# define L_tmpnam (unsigned int) MAXPATHLEN X#endif X X/* global */ X/* we keep track of all the entry headers */ Xstatic struct list *prune_list = (struct list *) NULL; X X/* X * configfile_read(struct list **pp_list, struct list **pp_entry_list) X * X * open the configuration file, and pulls out the {file/dir,ignore-flag} X * pairs. X * X * (**pp_list) is pointer the head of the file list, where all the X * files are added to. X */ X Xvoid Xconfigfile_read(pp_list, pp_entry_list) X struct list **pp_list; X struct list **pp_entry_list; X{ X FILE *fpin, *fpout; X char filename[MAXPATHLEN+512]; X char ignorestring[1024]; X char s[MAXPATHLEN+1024]; X char configfile[MAXPATHLEN+512]; X char *tmpfilename; X char number[128]; X int entrynum = 0; X int err; X X /* to make code semi-reentrant */ X list_reset(&prune_list); X X /* don't print banner if we're in print-preprocessor mode */ X if (!printpreprocess && !quietmode) X fputs("### Phase 1: Reading configuration file\n", stderr); X X /* generate temporary file name */ X if ((tmpfilename = (char *) malloc(L_tmpnam)) == NULL) { X perror("configfile_read: malloc()"); X exit(1); X }; X (void) strcpy(tmpfilename, TEMPFILE_TEMPLATE); X X if ((char *) mktemp(tmpfilename) == NULL) { X perror("configfile_read: mktemp()"); X exit(1); X } X X /* generate configuration file name */ X if (specified_configfile == NULL) X sprintf(configfile, "%s/%s", config_path, config_file); X else X (void) strcpy(configfile, specified_configfile); X X /* open the files */ X /* check to see if input is just stdin */ X if (*configfile == '-' && !configfile[1]) { /* configfile == "-" */ X fpin = stdin; X } X /* were we given a specific fd to use? */ X else if (specified_configfd != -1) { X char errstr[1024]; X X /* we already checked to see that it's a valid fd */ X if (!(fpin = fdopen(specified_configfd, "r"))) { X sprintf(errstr, "tripwire: Couldn't open fd! fdopen()"); X perror(errstr); X exit(1); X } X } X /* otherwise, it's just a normal file */ X else if ((fpin = fopen(configfile, "r")) == NULL) { X char errstr[1024]; X sprintf(errstr, "tripwire: Couldn't open config file '%s'", configfile); X perror(errstr); X exit(1); X } X X err = umask(077); /* to protect the tempfile */ X X if ((fpout = fopen(tmpfilename, "w+")) == NULL) { X sprintf(s, "tripwire: Couldn't open config file '%s'", configfile); X perror(s); X exit(1); X } X (void) umask(err); /* return it to its former state */ X X /* The following unlink accomplishes two things: X * 1) if the program terminates, we won't leave a temp X * file sitting around with potentially sensitive names X * in it. X * 2) the file is "hidden" while we run X */ X if (unlink(tmpfilename) < 0) { X perror("configfile_read: unlink()"); X exit(1); X } X free(tmpfilename); X X X /* X * pass 0: preprocess file X * call the yacc hook, located in y.tab.c X */ X X tw_macro_parse(configfile, fpin, fpout, (struct list **) pp_entry_list); X X if (fpin != stdin) X (void) fclose(fpin); X#ifdef FOO X if (fflush(fpout) == EOF) { X char s[256]; X /* X fputs("configfile_read: unknown error on fflush(fpout)\n", stderr); X */ X sprintf(s, "configfile_read: fflush(fpout)"); X perror(s); X exit(1); X } X else X#endif X fflush(fpout); X rewind(fpout); X X fpin = fpout; X X /* do we just print out the file, and then exit? */ X if (printpreprocess) { X int t; X X while ((t = getc(fpin)) != EOF) X putc((char) t, stdout); X exit(0); X } X X /* pass 1: get all of the prune entries '!' */ X while (fgets(s, sizeof(s), fpin) != NULL) { X X int prune_mode; X static int linenumber = 1; X X /* read in database entry */ X if ((err = sscanf(s, "%s %s", filename, ignorestring)) == 1) { X (void) strcpy(ignorestring, defaultignore); X } X else if (err != 2) { X fprintf(stderr, X "configfile_read: parse error in the following line\n"); X fprintf(stderr, "\t>> %s", s); X X exit(1); X } X linenumber++; X X /* check for removeflag (preceding "!" or "=") */ X switch (*filename) { X case '!': X prune_mode = PRUNE_ALL; X (void) strcpy(filename, filename+1); /* adjust name */ X break; X case '=': X prune_mode = PRUNE_ONE; X (void) strcpy(filename, filename+1); /* adjust name */ X break; X default: X continue; /* nothing */ X } X X X /* check for fully qualified pathname X */ X if (*filename != '/') { X fprintf(stderr, X "config: %s is not fully qualified! Skipping...\n" , X filename); X /* XXX -- error handling needed here */ X continue; X } X X /* expand any escaped octal characters in name */ X filename_escape_expand(filename); X X /* add to local prune list */ X list_set(filename, "", 0, &prune_list); X X /* set appropriate prune flag */ X list_setflag(filename, prune_mode, &prune_list); X } X X /* rewind the file for pass 2 */ X rewind(fpin); X X /* pass 2: build file lists */ X X /* it's time for another banner */ X if (!printpreprocess && !quietmode) X fputs("### Phase 2: Generating file list\n", stderr); X X while (fgets(s, sizeof(s), fpin) != NULL) { X int howdeep; X int prunedir = 0; X X /* X * get {filename,ignore} pair: X * if only argument, then apply default ignore-flags X * X * note that {ignore} used in the tripwire.config file is X * different than the one stored in the database file! X * X * humans use the [N|R|L]+/-[pinugsmc3] format. in the database, X * we use the old style where any capitalized letter X * means it's to be ignored. X */ X X /* make sure to remember that the ignorestring could be a comment! */ X if ( ((err = sscanf(s, "%s %s", filename, ignorestring)) == 1) || X (ignorestring[0] == '#')) { X (void) strcpy(ignorestring, defaultignore); X } X else if (err != 2) { X fprintf(stderr, "'%s'\nconfigfile_read: parse error\n", s); X X exit(1); X } X X /* skip all prune entries (we've already taken care of it) */ X if (*filename == '!') X continue; X X /* check for leading '=', prune after one recursion */ X else if (*filename == '=') { X (void) strcpy(filename, filename+1); X prunedir++; X } X X /* check for fully qualified pathname X */ X if (*filename != '/') { X fprintf(stderr, X "config: %s is not fully qualified! Skipping...\n" , X filename); X /* XXX -- error handling needed here */ X continue; X } X X /* X * convert configuration-file style ignore-string to our database X * representation. X */ X ignore_configvec_to_dvec(ignorestring); X X /* add it to the list while it still has escaped characters */ X sprintf(number, "%d %s", entrynum, ignorestring); X list_set(filename, number, 0, pp_entry_list); X /* reverse index (number --> entryname) */ X { X char eindex[50]; X sprintf(eindex, "%d", entrynum); X list_set(eindex, filename, 0, pp_entry_list); X list_setflag(eindex, 1, pp_entry_list); X } X X /* expand any escaped octal characters in name */ X filename_escape_expand(filename); X X /* pass down the priority -- based on how fully-qualified the X * entry was. X */ X howdeep = slash_count(filename); X X /* X * add the entry to list of entry headers (used for incremental X * database updates. X */ X configfile_descend(filename, ignorestring, howdeep, prunedir, X pp_list, entrynum++); X } /* end reading file */ X X /* print out the list, if we're in a debuggin mode */ X if (debuglevel > 10) X list_print(pp_list); X X /* clean up */ X (void) fclose(fpin); X X return; X} X X/* X * configfile_descend(char *filename, char *ignorestring, int howdeep, X * int prunedir, struct list **pp_list, X * int entrynum) X * X * recurses down the specified filename. when it finally hits a real X * file, it is added to the list of files. X * X * if (prunedir) is set, then we quit after one recursion. X * X * this routine also resolves any multiple instances of a file by X * using (howdeep) as a precendence level. X * X * (entrynum) is the unique entry number tag from tw.config. X */ X Xstatic void Xconfigfile_descend (filename, ignorestring, howdeep, X prunedir, pp_list, entrynum) X char *filename; X char *ignorestring; X int howdeep; X int prunedir; X struct list **pp_list; X int entrynum; X{ X struct stat statbuf; X static int countrecurse = 0; /* count how many levels deep we are */ X static int majordev, minordev; X char t[512]; X extern int errno; X X countrecurse++; X XSPDEBUG(10) Xprintf("---> %d: %s\n", countrecurse, filename); X X /* check to see if it's on the prune list */ X if (list_lookup(filename, &prune_list) != NULL) { X X int flag; X X /* return only if it was a '!' directive */ X if ((flag = list_getflag(filename, &prune_list)) == PRUNE_ALL) { X countrecurse--; X return; X } X else if (flag == PRUNE_ONE) X prunedir = 1; X } X X /* get the stat structure of the (real) file */ X if (lstat(filename, &statbuf) < 0) { X char err[MAXPATHLEN+256]; X int real_err = errno; /* in case sprintf clobbers the value */ X X if (debuglevel > 10) { X sprintf(err, "configfile_descend: lstat(%s)", filename); X } else { X sprintf(err, "%s: %s", progname, filename); X } X errno = real_err; X if (!quietmode) X perror(err); X X /* so we just skip it */ X countrecurse--; X return; X } X X /* X * record our {major,minor} device pair if this is our first time X * recursing. then we check if it changes. if it does, we've crossed X * a filesystem, and we prune our tree. X */ X if (countrecurse == 1) { X XSPDEBUG(4) Xprintf("configfile_descend: r=%d: %s\n", countrecurse, filename); X X majordev = major(statbuf.st_dev); X minordev = minor(statbuf.st_dev); X } else { X if (major(statbuf.st_dev) != majordev || X minor(statbuf.st_dev) != minordev) { X XSPDEBUG(4) Xprintf("configfile_descend: pruning '%s' n(%d,%d) != o(%d, %d)\n", filename, X major(statbuf.st_dev), minor(statbuf.st_dev), X majordev, minordev); X X countrecurse--; X return; X /* prune */ X } X } X X /* X * if it is a directory file, then we read in the directory entries X * and then recurse into the directory. X * X * remember, check to see if it's a symbolic link. we never traverse X * them. X */ X if (((statbuf.st_mode & S_IFMT) == S_IFDIR) X X#if !defined(SYSV) || (SYSV > 3) X && !((statbuf.st_mode & S_IFMT) == S_IFLNK)) X#else X ) X#endif X { X DIR *p_dir; X X#ifdef DIRENT X struct dirent *pd; X#else X struct direct *pd; X#endif X X char recursefile[MAXPATHLEN+256]; X X /* handle prunedir flag */ X X /* X * concatenate entry number to the ignore-string X */ X X sprintf(t, "%d %s", entrynum, ignorestring); X X /* X * just nix it from the list? X */ X X /* XXX X if (strcmp(filename, "/tmp") == 0) X ; X if (strcmp(filename, "/tmp") == 0) X list_print(pp_list); X */ X X /* remember, we save filenames with escape sequences in the lists */ X list_set(filename_escape(filename), t, howdeep, pp_list); X (void) list_setflag(filename, FLAG_NOOPEN, pp_list); X X /* if it's a symbolic link, make sure we flag it as such! */ X X#if !defined(SYSV) || (SYSV > 3) X if ((statbuf.st_mode & S_IFMT) == S_IFLNK) { X (void) list_setflag(filename, FLAG_SYMLINK, pp_list); X } X#endif X X if (prunedir) { X countrecurse--; X return; X } X XSPDEBUG(4) Xfprintf(stderr, "configfile_descend: %s: it's a directory!\n", filename); X X if ((p_dir = opendir(filename)) == NULL) { X if (debuglevel > 10) { X perror("configfile_descend: opendir()"); X } else { X char err[MAXPATHLEN+256]; X int real_errno = errno; X X sprintf(err, "%s: %s", progname, filename); X errno = real_errno; X if (!quietmode) X perror(err); X } X countrecurse--; X return; X } X X X/* broken xenix compiler returns "illegal continue" ?!? */ X#ifdef XENIX X#define XCONTINUE goto XENIX_CONT X#else X#define XCONTINUE continue X#endif X X for (pd = readdir(p_dir); pd != NULL; pd = readdir(p_dir)) { X /* we could use strcmp in the following, but this is much faster */ X if (pd->d_name[0] == '.') { X if (pd->d_name[1] == 0) /* must be . */ X XCONTINUE; X else if (pd->d_name[1] == '.') { X if (pd->d_name[2] == 0) /* must be .. */ X XCONTINUE; X } X } X XSPDEBUG(4) Xprintf("--> descend: %s\n", pd->d_name); X X /* build pathname of file */ X /* Assume all filenames ar root anchored. X If so, and filename[1] is null, then filename must be X '/'. Thus we don't need to concatenate a slash X into the recursefile. */ X X if (filename[1] == '\0') { X sprintf(recursefile, "%s%s", filename, pd->d_name); X } else { X sprintf(recursefile, "%s/%s", filename, pd->d_name); X } X X X /* recurse. it'll pop right back if it is just a file */ X configfile_descend(recursefile, ignorestring, howdeep, 0, X pp_list, entrynum); X XXENIX_CONT: ; X X } /* end foreach file */ X X /* cleanup */ X closedir(p_dir); X } /* end if dir */ X else { X X /* X * concatenate entry number to the ignore-string X */ X X sprintf(t, "%d %s", entrynum, ignorestring); X X /* add to list */ X list_set(filename, t, howdeep, pp_list); X X /* X * if it is a special file or device, add it to the list, but X * make sure we don't open it and read from it! X */ X switch (statbuf.st_mode & S_IFMT) { X case S_IFIFO: X case S_IFCHR: X case S_IFBLK: X#if !defined(SYSV) || (SYSV > 3) X case S_IFSOCK: X#endif X (void) list_setflag(filename, FLAG_NOOPEN, pp_list); X break; X#if !defined(SYSV) || (SYSV > 3) X case S_IFLNK: /* if it's a symbolic link, make sure we flag it as such! */ X (void) list_setflag(filename, FLAG_SYMLINK, pp_list); X#endif X break; X default: X break; /* do nothing for regular files */ X } X } /* end else dir */ X X countrecurse--; X return; X} X END_OF_FILE if test 14760 -ne `wc -c <'tripwire-1.1/src/config.parse.c'`; then echo shar: \"'tripwire-1.1/src/config.parse.c'\" unpacked with wrong size! fi # end of 'tripwire-1.1/src/config.parse.c' fi if test -f 'tripwire-1.1/configs/conf-svr4.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tripwire-1.1/configs/conf-svr4.h'\" else echo shar: Extracting \"'tripwire-1.1/configs/conf-svr4.h'\" \(874 characters\) sed "s/^X//" >'tripwire-1.1/configs/conf-svr4.h' <<'END_OF_FILE' X/* $Id: conf-svr4.h,v 1.2 1993/08/19 05:27:07 genek Exp $ */ X X/* X * conf-svr4.h X * X * Tripwire configuration file X * X * Gene Kim X * Purdue University X */ X X/*** X *** Operating System specifics X *** X *** If the answer to a question in the comment is "Yes", then X *** change the corresponding "#undef" to a "#define" X ***/ X X/* X * is your OS a System V derivitive? if so, what version? X * (e.g., define SYSV 4) X */ X X#define SYSV 4 X X/* X * does your system have a like System V? X */ X X#define MALLOCH X X/* X * does your system have a like POSIX says you should? X */ X X#define STDLIBH X X/* X * does your system use readdir(3) that returns (struct dirent *)? X */ X X#define DIRENT X X/* X * is #include ok? (as opposed to ) X */ X X#define STRINGH X X/* X * does your system have gethostname(2) (instead of uname(2))? X */ X X#undef GETHOSTNAME END_OF_FILE if test 874 -ne `wc -c <'tripwire-1.1/configs/conf-svr4.h'`; then echo shar: \"'tripwire-1.1/configs/conf-svr4.h'\" unpacked with wrong size! fi # end of 'tripwire-1.1/configs/conf-svr4.h' fi echo shar: End of archive 14 \(of 25\). cp /dev/null ark14isdone 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