From ea47308a8e56e633928f9d296dd0c6d4960436f8 Mon Sep 17 00:00:00 2001 From: robiscool Date: Tue, 2 Aug 2011 10:59:38 -0700 Subject: Change snort-dev to orion --- config/snort-dev/patches/SnortSam/TODAO.txt | 1 - .../patches/SnortSam/snortsam-2.8.6.1.diff | 3021 -------------------- 2 files changed, 3022 deletions(-) delete mode 100644 config/snort-dev/patches/SnortSam/TODAO.txt delete mode 100644 config/snort-dev/patches/SnortSam/snortsam-2.8.6.1.diff (limited to 'config/snort-dev/patches/SnortSam') diff --git a/config/snort-dev/patches/SnortSam/TODAO.txt b/config/snort-dev/patches/SnortSam/TODAO.txt deleted file mode 100644 index 3abf0303..00000000 --- a/config/snort-dev/patches/SnortSam/TODAO.txt +++ /dev/null @@ -1 +0,0 @@ -Patch current snort 2.9 \ No newline at end of file diff --git a/config/snort-dev/patches/SnortSam/snortsam-2.8.6.1.diff b/config/snort-dev/patches/SnortSam/snortsam-2.8.6.1.diff deleted file mode 100644 index 983165e1..00000000 --- a/config/snort-dev/patches/SnortSam/snortsam-2.8.6.1.diff +++ /dev/null @@ -1,3021 +0,0 @@ -Index: snort-2.8.6.1/src/twofish.c -=================================================================== ---- snort-2.8.6.1/src/twofish.c (Revision 0) -+++ snort-2.8.6.1/src/twofish.c (Revision 3) -@@ -0,0 +1,971 @@ -+/* $Id: twofish.c,v 2.1 2008/12/15 20:36:05 fknobbe Exp $ -+ * -+ * -+ * Copyright (C) 1997-2000 The Cryptix Foundation Limited. -+ * Copyright (C) 2000 Farm9. -+ * Copyright (C) 2001 Frank Knobbe. -+ * All rights reserved. -+ * -+ * For Cryptix code: -+ * Use, modification, copying and distribution of this software is subject -+ * the terms and conditions of the Cryptix General Licence. You should have -+ * received a copy of the Cryptix General Licence along with this library; -+ * if not, you can download a copy from http://www.cryptix.org/ . -+ * -+ * For Farm9: -+ * --- jojo@farm9.com, August 2000, converted from Java to C++, added CBC mode and -+ * ciphertext stealing technique, added AsciiTwofish class for easy encryption -+ * decryption of text strings -+ * -+ * Frank Knobbe : -+ * --- April 2001, converted from C++ to C, prefixed global variables -+ * with TwoFish, substituted some defines, changed functions to make use of -+ * variables supplied in a struct, modified and added routines for modular calls. -+ * Cleaned up the code so that defines are used instead of fixed 16's and 32's. -+ * Created two general purpose crypt routines for one block and multiple block -+ * encryption using Joh's CBC code. -+ * Added crypt routines that use a header (with a magic and data length). -+ * (Basically a major rewrite). -+ * -+ * Note: Routines labeled _TwoFish are private and should not be used -+ * (or with extreme caution). -+ * -+ */ -+ -+#ifndef __TWOFISH_LIBRARY_SOURCE__ -+#define __TWOFISH_LIBRARY_SOURCE__ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef WIN32 -+ -+#ifndef u_long -+typedef unsigned long u_long; -+#endif -+#ifndef u_int32_t -+typedef unsigned long u_int32_t; -+#endif -+#ifndef u_word -+typedef unsigned short u_word; -+#endif -+#ifndef u_int16_t -+typedef unsigned short u_int16_t; -+#endif -+#ifndef u_char -+typedef unsigned char u_char; -+#endif -+#ifndef u_int8_t -+typedef unsigned char u_int8_t; -+#endif -+ -+#endif /* WIN32 */ -+ -+#include "twofish.h" -+ -+ -+bool TwoFish_srand=TRUE; /* if TRUE, first call of TwoFishInit will seed rand(); */ -+ /* of TwoFishInit */ -+ -+/* Fixed 8x8 permutation S-boxes */ -+static const u_int8_t TwoFish_P[2][256] = -+{ -+ { /* p0 */ -+ 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, -+ 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, -+ 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, -+ 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, -+ 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, -+ 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, -+ 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, -+ 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, -+ 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, -+ 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, -+ 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, -+ 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, -+ 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, -+ 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, -+ 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, -+ 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, -+ 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, -+ 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, -+ 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, -+ 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, -+ 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, -+ 0x4A, 0x5E, 0xC1, 0xE0 -+ }, -+ { /* p1 */ -+ 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, -+ 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, -+ 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, -+ 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, -+ 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, -+ 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, -+ 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, -+ 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, -+ 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, -+ 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, -+ 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, -+ 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, -+ 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, -+ 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, -+ 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, -+ 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, -+ 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, -+ 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, -+ 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, -+ 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, -+ 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, -+ 0x55, 0x09, 0xBE, 0x91 -+ } -+}; -+ -+static bool TwoFish_MDSready=FALSE; -+static u_int32_t TwoFish_MDS[4][256]; /* TwoFish_MDS matrix */ -+ -+ -+#define TwoFish_LFSR1(x) (((x)>>1)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/2:0)) -+#define TwoFish_LFSR2(x) (((x)>>2)^(((x)&0x02)?TwoFish_MDS_GF_FDBK/2:0)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/4:0)) -+ -+#define TwoFish_Mx_1(x) ((u_int32_t)(x)) /* force result to dword so << will work */ -+#define TwoFish_Mx_X(x) ((u_int32_t)((x)^TwoFish_LFSR2(x))) /* 5B */ -+#define TwoFish_Mx_Y(x) ((u_int32_t)((x)^TwoFish_LFSR1(x)^TwoFish_LFSR2(x))) /* EF */ -+#define TwoFish_RS_rem(x) { u_int8_t b=(u_int8_t)(x>>24); u_int32_t g2=((b<<1)^((b&0x80)?TwoFish_RS_GF_FDBK:0))&0xFF; u_int32_t g3=((b>>1)&0x7F)^((b&1)?TwoFish_RS_GF_FDBK>>1:0)^g2; x=(x<<8)^(g3<<24)^(g2<<16)^(g3<<8)^b; } -+ -+/*#define TwoFish__b(x,N) (((u_int8_t *)&x)[((N)&3)^TwoFish_ADDR_XOR])*/ /* pick bytes out of a dword */ -+ -+#define TwoFish_b0(x) TwoFish__b(x,0) /* extract LSB of u_int32_t */ -+#define TwoFish_b1(x) TwoFish__b(x,1) -+#define TwoFish_b2(x) TwoFish__b(x,2) -+#define TwoFish_b3(x) TwoFish__b(x,3) /* extract MSB of u_int32_t */ -+ -+u_int8_t TwoFish__b(u_int32_t x,int n) -+{ n&=3; -+ while(n-->0) -+ x>>=8; -+ return (u_int8_t)x; -+} -+ -+ -+/* TwoFish Initialization -+ * -+ * This routine generates a global data structure for use with TwoFish, -+ * initializes important values (such as subkeys, sBoxes), generates subkeys -+ * and precomputes the MDS matrix if not already done. -+ * -+ * Input: User supplied password (will be appended by default password of 'SnortHas2FishEncryptionRoutines!') -+ * -+ * Output: Pointer to TWOFISH structure. This data structure contains key dependent data. -+ * This pointer is used with all other crypt functions. -+ */ -+ -+TWOFISH *TwoFishInit(char *userkey) -+{ TWOFISH *tfdata; -+ int i,x,m; -+ char tkey[TwoFish_KEY_LENGTH+40]; -+ -+ tfdata=malloc(sizeof(TWOFISH)); /* allocate the TwoFish structure */ -+ if(tfdata!=NULL) -+ { if(*userkey) -+ { strncpy(tkey,userkey,TwoFish_KEY_LENGTH); /* use first 32 chars of user supplied password */ -+ tkey[TwoFish_KEY_LENGTH]=0; /* make sure it wasn't more */ -+ } -+ else -+ strcpy(tkey,TwoFish_DEFAULT_PW); /* if no key defined, use default password */ -+ for(i=0,x=0,m=strlen(tkey);ikey[i]=tkey[x++]; /* fill the whole keyspace with repeating key. */ -+ if(x==m) -+ x=0; -+ } -+ -+ if(!TwoFish_MDSready) -+ _TwoFish_PrecomputeMDSmatrix(); /* "Wake Up, Neo" */ -+ _TwoFish_MakeSubKeys(tfdata); /* generate subkeys */ -+ _TwoFish_ResetCBC(tfdata); /* reset the CBC */ -+ tfdata->output=NULL; /* nothing to output yet */ -+ tfdata->dontflush=FALSE; /* reset decrypt skip block flag */ -+ if(TwoFish_srand) -+ { TwoFish_srand=FALSE; -+ srand(time(NULL)); -+ } -+ } -+ return tfdata; /* return the data pointer */ -+} -+ -+ -+void TwoFishDestroy(TWOFISH *tfdata) -+{ if(tfdata!=NULL) -+ free(tfdata); -+} -+ -+ -+/* en/decryption with CBC mode */ -+unsigned long _TwoFish_CryptRawCBC(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata) -+{ unsigned long rl; -+ -+ rl=len; /* remember how much data to crypt. */ -+ while(len>TwoFish_BLOCK_SIZE) /* and now we process block by block. */ -+ { _TwoFish_BlockCrypt(in,out,TwoFish_BLOCK_SIZE,decrypt,tfdata); /* de/encrypt it. */ -+ in+=TwoFish_BLOCK_SIZE; /* adjust pointers. */ -+ out+=TwoFish_BLOCK_SIZE; -+ len-=TwoFish_BLOCK_SIZE; -+ } -+ if(len>0) /* if we have less than a block left... */ -+ _TwoFish_BlockCrypt(in,out,len,decrypt,tfdata); /* ...then we de/encrypt that too. */ -+ if(tfdata->qBlockDefined && !tfdata->dontflush) /* in case len was exactly one block... */ -+ _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); /* ...we need to write the... */ -+ /* ...remaining bytes of the buffer */ -+ return rl; -+} -+ -+/* en/decryption on one block only */ -+unsigned long _TwoFish_CryptRaw16(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata) -+{ /* qBlockPlain already zero'ed through ResetCBC */ -+ memcpy(tfdata->qBlockPlain,in,len); /* toss the data into it. */ -+ _TwoFish_BlockCrypt16(tfdata->qBlockPlain,tfdata->qBlockCrypt,decrypt,tfdata); /* encrypt just that block without CBC. */ -+ memcpy(out,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE); /* and return what we got */ -+ return TwoFish_BLOCK_SIZE; -+} -+ -+/* en/decryption without reset of CBC and output assignment */ -+unsigned long _TwoFish_CryptRaw(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata) -+{ -+ if(in!=NULL && out!=NULL && len>0 && tfdata!=NULL) /* if we have valid data, then... */ -+ { if(len>TwoFish_BLOCK_SIZE) /* ...check if we have more than one block. */ -+ return _TwoFish_CryptRawCBC(in,out,len,decrypt,tfdata); /* if so, use the CBC routines... */ -+ else -+ return _TwoFish_CryptRaw16(in,out,len,decrypt,tfdata); /* ...otherwise just do one block. */ -+ } -+ return 0; -+} -+ -+ -+/* TwoFish Raw Encryption -+ * -+ * Does not use header, but does use CBC (if more than one block has to be encrypted). -+ * -+ * Input: Pointer to the buffer of the plaintext to be encrypted. -+ * Pointer to the buffer receiving the ciphertext. -+ * The length of the plaintext buffer. -+ * The TwoFish structure. -+ * -+ * Output: The amount of bytes encrypted if successful, otherwise 0. -+ */ -+ -+unsigned long TwoFishEncryptRaw(char *in, -+ char *out, -+ unsigned long len, -+ TWOFISH *tfdata) -+{ _TwoFish_ResetCBC(tfdata); /* reset CBC flag. */ -+ tfdata->output=out; /* output straight into output buffer. */ -+ return _TwoFish_CryptRaw(in,out,len,FALSE,tfdata); /* and go for it. */ -+} -+ -+/* TwoFish Raw Decryption -+ * -+ * Does not use header, but does use CBC (if more than one block has to be decrypted). -+ * -+ * Input: Pointer to the buffer of the ciphertext to be decrypted. -+ * Pointer to the buffer receiving the plaintext. -+ * The length of the ciphertext buffer (at least one cipher block). -+ * The TwoFish structure. -+ * -+ * Output: The amount of bytes decrypted if successful, otherwise 0. -+ */ -+ -+unsigned long TwoFishDecryptRaw(char *in, -+ char *out, -+ unsigned long len, -+ TWOFISH *tfdata) -+{ _TwoFish_ResetCBC(tfdata); /* reset CBC flag. */ -+ tfdata->output=out; /* output straight into output buffer. */ -+ return _TwoFish_CryptRaw(in,out,len,TRUE,tfdata); /* and go for it. */ -+} -+ -+/* TwoFish Free -+ * -+ * Free's the allocated buffer. -+ * -+ * Input: Pointer to the TwoFish structure -+ * -+ * Output: (none) -+ */ -+ -+void TwoFishFree(TWOFISH *tfdata) -+{ if(tfdata->output!=NULL) /* if a valid buffer is present... */ -+ { free(tfdata->output); /* ...then we free it for you... */ -+ tfdata->output=NULL; /* ...and mark as such. */ -+ } -+} -+ -+/* TwoFish Set Output -+ * -+ * If you want to allocate the output buffer yourself, -+ * then you can set it with this function. -+ * -+ * Input: Pointer to your output buffer -+ * Pointer to the TwoFish structure -+ * -+ * Output: (none) -+ */ -+ -+void TwoFishSetOutput(char *outp,TWOFISH *tfdata) -+{ tfdata->output=outp; /* (do we really need a function for this?) */ -+} -+ -+/* TwoFish Alloc -+ * -+ * Allocates enough memory for the output buffer that would be required -+ * -+ * Input: Length of the plaintext. -+ * Boolean flag for BinHex Output. -+ * Pointer to the TwoFish structure. -+ * -+ * Output: Returns a pointer to the memory allocated. -+ */ -+ -+void *TwoFishAlloc(unsigned long len,bool binhex,bool decrypt,TWOFISH *tfdata) -+{ -+/* TwoFishFree(tfdata); */ /* (don't for now) discard whatever was allocated earlier. */ -+ if(decrypt) /* if decrypting... */ -+ { if(binhex) /* ...and input is binhex encoded... */ -+ len/=2; /* ...use half as much for output. */ -+ len-=TwoFish_BLOCK_SIZE; /* Also, subtract the size of the header. */ -+ } -+ else -+ { len+=TwoFish_BLOCK_SIZE; /* the size is just increased by the header... */ -+ if(binhex) -+ len*=2; /* ...and doubled if output is to be binhexed. */ -+ } -+ tfdata->output=malloc(len+TwoFish_BLOCK_SIZE);/* grab some memory...plus some extra (it's running over somewhere, crashes without extra padding) */ -+ -+ return tfdata->output; /* ...and return to caller. */ -+} -+ -+/* bin2hex and hex2bin conversion */ -+void _TwoFish_BinHex(u_int8_t *buf,unsigned long len,bool bintohex) -+{ u_int8_t *pi,*po,c; -+ -+ if(bintohex) -+ { for(pi=buf+len-1,po=buf+(2*len)-1;len>0;pi--,po--,len--) /* let's start from the end of the bin block. */ -+ { c=*pi; /* grab value. */ -+ c&=15; /* use lower 4 bits. */ -+ if(c>9) /* convert to ascii. */ -+ c+=('a'-10); -+ else -+ c+='0'; -+ *po--=c; /* set the lower nibble. */ -+ c=*pi; /* grab value again. */ -+ c>>=4; /* right shift 4 bits. */ -+ c&=15; /* make sure we only have 4 bits. */ -+ if(c>9) /* convert to ascii. */ -+ c+=('a'-10); -+ else -+ c+='0'; -+ *po=c; /* set the higher nibble. */ -+ } /* and keep going. */ -+ } -+ else -+ { for(pi=buf,po=buf;len>0;pi++,po++,len-=2) /* let's start from the beginning of the hex block. */ -+ { c=tolower(*pi++)-'0'; /* grab higher nibble. */ -+ if(c>9) /* convert to value. */ -+ c-=('0'-9); -+ *po=c<<4; /* left shit 4 bits. */ -+ c=tolower(*pi)-'0'; /* grab lower nibble. */ -+ if(c>9) /* convert to value. */ -+ c-=('0'-9); -+ *po|=c; /* and add to value. */ -+ } -+ } -+} -+ -+ -+/* TwoFish Encryption -+ * -+ * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, -+ * this routine will alloc the memory. In addition, it will include a small 'header' -+ * containing the magic and some salt. That way the decrypt routine can check if the -+ * packet got decrypted successfully, and return 0 instead of garbage. -+ * -+ * Input: Pointer to the buffer of the plaintext to be encrypted. -+ * Pointer to the pointer to the buffer receiving the ciphertext. -+ * The pointer either points to user allocated output buffer space, or to NULL, in which case -+ * this routine will set the pointer to the buffer allocated through the struct. -+ * The length of the plaintext buffer. -+ * Can be -1 if the input is a null terminated string, in which case we'll count for you. -+ * Boolean flag for BinHex Output (if used, output will be twice as large as input). -+ * Note: BinHex conversion overwrites (converts) input buffer! -+ * The TwoFish structure. -+ * -+ * Output: The amount of bytes encrypted if successful, otherwise 0. -+ */ -+ -+unsigned long TwoFishEncrypt(char *in, -+ char **out, -+ signed long len, -+ bool binhex, -+ TWOFISH *tfdata) -+{ unsigned long ilen,olen; -+ -+ -+ if(len== -1) /* if we got -1 for len, we'll assume IN is a... */ -+ ilen=strlen(in); /* ...\0 terminated string and figure len out ourselves... */ -+ else -+ ilen=len; /* ...otherwise we trust you supply a correct length. */ -+ -+ if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */ -+ { if(*out==NULL) /* if OUT points to a NULL pointer... */ -+ *out=TwoFishAlloc(ilen,binhex,FALSE,tfdata); /* ...we'll (re-)allocate buffer space. */ -+ if(*out!=NULL) -+ { tfdata->output=*out; /* set output buffer. */ -+ tfdata->header.salt=rand()*65536+rand(); /* toss in some salt. */ -+ tfdata->header.length[0]= (u_int8_t)(ilen); -+ tfdata->header.length[1]= (u_int8_t)(ilen>>8); -+ tfdata->header.length[2]= (u_int8_t)(ilen>>16); -+ tfdata->header.length[3]= (u_int8_t)(ilen>>24); -+ memcpy(tfdata->header.magic,TwoFish_MAGIC,TwoFish_MAGIC_LEN); /* set the magic. */ -+ olen=TwoFish_BLOCK_SIZE; /* set output counter. */ -+ _TwoFish_ResetCBC(tfdata); /* reset the CBC flag */ -+ _TwoFish_BlockCrypt((u_int8_t *)&(tfdata->header),*out,olen,FALSE,tfdata); /* encrypt first block (without flush on 16 byte boundary). */ -+ olen+=_TwoFish_CryptRawCBC(in,*out+TwoFish_BLOCK_SIZE,ilen,FALSE,tfdata); /* and encrypt the rest (we do not reset the CBC flag). */ -+ if(binhex) /* if binhex... */ -+ { _TwoFish_BinHex(*out,olen,TRUE); /* ...convert output to binhex... */ -+ olen*=2; /* ...and size twice as large. */ -+ } -+ tfdata->output=*out; -+ return olen; -+ } -+ } -+ return 0; -+} -+ -+/* TwoFish Decryption -+ * -+ * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, -+ * this routine will alloc the memory. In addition, it will check the small 'header' -+ * containing the magic. If magic does not match we return 0. Otherwise we return the -+ * amount of bytes decrypted (should be the same as the length in the header). -+ * -+ * Input: Pointer to the buffer of the ciphertext to be decrypted. -+ * Pointer to the pointer to the buffer receiving the plaintext. -+ * The pointer either points to user allocated output buffer space, or to NULL, in which case -+ * this routine will set the pointer to the buffer allocated through the struct. -+ * The length of the ciphertext buffer. -+ * Can be -1 if the input is a null terminated binhex string, in which case we'll count for you. -+ * Boolean flag for BinHex Input (if used, plaintext will be half as large as input). -+ * Note: BinHex conversion overwrites (converts) input buffer! -+ * The TwoFish structure. -+ * -+ * Output: The amount of bytes decrypted if successful, otherwise 0. -+ */ -+ -+unsigned long TwoFishDecrypt(char *in, -+ char **out, -+ signed long len, -+ bool binhex, -+ TWOFISH *tfdata) -+{ unsigned long ilen,elen,olen; -+ const u_int8_t cmagic[TwoFish_MAGIC_LEN]=TwoFish_MAGIC; -+ u_int8_t *tbuf; -+ -+ -+ -+ if(len== -1) /* if we got -1 for len, we'll assume IN is... */ -+ ilen=strlen(in); /* ...\0 terminated binhex and figure len out ourselves... */ -+ else -+ ilen=len; /* ...otherwise we trust you supply a correct length. */ -+ -+ if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */ -+ { if(*out==NULL) /* if OUT points to a NULL pointer... */ -+ *out=TwoFishAlloc(ilen,binhex,TRUE,tfdata); /* ...we'll (re-)allocate buffer space. */ -+ if(*out!=NULL) -+ { if(binhex) /* if binhex... */ -+ { _TwoFish_BinHex(in,ilen,FALSE); /* ...convert input to values... */ -+ ilen/=2; /* ...and size half as much. */ -+ } -+ _TwoFish_ResetCBC(tfdata); /* reset the CBC flag. */ -+ -+ tbuf=(u_int8_t *)malloc(ilen+TwoFish_BLOCK_SIZE); /* get memory for data and header. */ -+ if(tbuf==NULL) -+ return 0; -+ tfdata->output=tbuf; /* set output to temp buffer. */ -+ -+ olen=_TwoFish_CryptRawCBC(in,tbuf,ilen,TRUE,tfdata)-TwoFish_BLOCK_SIZE; /* decrypt the whole thing. */ -+ memcpy(&(tfdata->header),tbuf,TwoFish_BLOCK_SIZE); /* copy first block into header. */ -+ tfdata->output=*out; -+ for(elen=0;elenheader.magic[elen]!=cmagic[elen]) -+ break; -+ if(elen==TwoFish_MAGIC_LEN) /* if magic matches then... */ -+ { elen=(tfdata->header.length[0]) | -+ (tfdata->header.length[1])<<8 | -+ (tfdata->header.length[2])<<16 | -+ (tfdata->header.length[3])<<24; /* .. we know how much to expect. */ -+ if(elen>olen) /* adjust if necessary. */ -+ elen=olen; -+ memcpy(*out,tbuf+TwoFish_BLOCK_SIZE,elen); /* copy data into intended output. */ -+ free(tbuf); -+ return elen; -+ } -+ free(tbuf); -+ } -+ } -+ return 0; -+} -+ -+void _TwoFish_PrecomputeMDSmatrix(void) /* precompute the TwoFish_MDS matrix */ -+{ u_int32_t m1[2]; -+ u_int32_t mX[2]; -+ u_int32_t mY[2]; -+ u_int32_t i, j; -+ -+ for (i = 0; i < 256; i++) -+ { j = TwoFish_P[0][i] & 0xFF; /* compute all the matrix elements */ -+ m1[0] = j; -+ mX[0] = TwoFish_Mx_X( j ) & 0xFF; -+ mY[0] = TwoFish_Mx_Y( j ) & 0xFF; -+ -+ j = TwoFish_P[1][i] & 0xFF; -+ m1[1] = j; -+ mX[1] = TwoFish_Mx_X( j ) & 0xFF; -+ mY[1] = TwoFish_Mx_Y( j ) & 0xFF; -+ -+ TwoFish_MDS[0][i] = m1[TwoFish_P_00] | /* fill matrix w/ above elements */ -+ mX[TwoFish_P_00] << 8 | -+ mY[TwoFish_P_00] << 16 | -+ mY[TwoFish_P_00] << 24; -+ TwoFish_MDS[1][i] = mY[TwoFish_P_10] | -+ mY[TwoFish_P_10] << 8 | -+ mX[TwoFish_P_10] << 16 | -+ m1[TwoFish_P_10] << 24; -+ TwoFish_MDS[2][i] = mX[TwoFish_P_20] | -+ mY[TwoFish_P_20] << 8 | -+ m1[TwoFish_P_20] << 16 | -+ mY[TwoFish_P_20] << 24; -+ TwoFish_MDS[3][i] = mX[TwoFish_P_30] | -+ m1[TwoFish_P_30] << 8 | -+ mY[TwoFish_P_30] << 16 | -+ mX[TwoFish_P_30] << 24; -+ } -+ TwoFish_MDSready=TRUE; -+} -+ -+ -+void _TwoFish_MakeSubKeys(TWOFISH *tfdata) /* Expand a user-supplied key material into a session key. */ -+{ u_int32_t k64Cnt = TwoFish_KEY_LENGTH / 8; -+ u_int32_t k32e[4]; /* even 32-bit entities */ -+ u_int32_t k32o[4]; /* odd 32-bit entities */ -+ u_int32_t sBoxKey[4]; -+ u_int32_t offset,i,j; -+ u_int32_t A, B, q=0; -+ u_int32_t k0,k1,k2,k3; -+ u_int32_t b0,b1,b2,b3; -+ -+ /* split user key material into even and odd 32-bit entities and */ -+ /* compute S-box keys using (12, 8) Reed-Solomon code over GF(256) */ -+ -+ -+ for (offset=0,i=0,j=k64Cnt-1;i<4 && offsetkey[offset++]; -+ k32e[i]|= tfdata->key[offset++]<<8; -+ k32e[i]|= tfdata->key[offset++]<<16; -+ k32e[i]|= tfdata->key[offset++]<<24; -+ k32o[i] = tfdata->key[offset++]; -+ k32o[i]|= tfdata->key[offset++]<<8; -+ k32o[i]|= tfdata->key[offset++]<<16; -+ k32o[i]|= tfdata->key[offset++]<<24; -+ sBoxKey[j] = _TwoFish_RS_MDS_Encode( k32e[i], k32o[i] ); /* reverse order */ -+ } -+ -+ /* compute the round decryption subkeys for PHT. these same subkeys */ -+ /* will be used in encryption but will be applied in reverse order. */ -+ i=0; -+ while(i < TwoFish_TOTAL_SUBKEYS) -+ { A = _TwoFish_F32( k64Cnt, q, k32e ); /* A uses even key entities */ -+ q += TwoFish_SK_BUMP; -+ -+ B = _TwoFish_F32( k64Cnt, q, k32o ); /* B uses odd key entities */ -+ q += TwoFish_SK_BUMP; -+ -+ B = B << 8 | B >> 24; -+ -+ A += B; -+ tfdata->subKeys[i++] = A; /* combine with a PHT */ -+ -+ A += B; -+ tfdata->subKeys[i++] = A << TwoFish_SK_ROTL | A >> (32-TwoFish_SK_ROTL); -+ } -+ -+ /* fully expand the table for speed */ -+ k0 = sBoxKey[0]; -+ k1 = sBoxKey[1]; -+ k2 = sBoxKey[2]; -+ k3 = sBoxKey[3]; -+ -+ for (i = 0; i < 256; i++) -+ { b0 = b1 = b2 = b3 = i; -+ switch (k64Cnt & 3) -+ { case 1: /* 64-bit keys */ -+ tfdata->sBox[ 2*i ] = TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0]) ^ TwoFish_b0(k0)]; -+ tfdata->sBox[ 2*i+1] = TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1]) ^ TwoFish_b1(k0)]; -+ tfdata->sBox[0x200+2*i ] = TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2]) ^ TwoFish_b2(k0)]; -+ tfdata->sBox[0x200+2*i+1] = TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3]) ^ TwoFish_b3(k0)]; -+ break; -+ case 0: /* 256-bit keys (same as 4) */ -+ b0 = (TwoFish_P[TwoFish_P_04][b0]) ^ TwoFish_b0(k3); -+ b1 = (TwoFish_P[TwoFish_P_14][b1]) ^ TwoFish_b1(k3); -+ b2 = (TwoFish_P[TwoFish_P_24][b2]) ^ TwoFish_b2(k3); -+ b3 = (TwoFish_P[TwoFish_P_34][b3]) ^ TwoFish_b3(k3); -+ case 3: /* 192-bit keys */ -+ b0 = (TwoFish_P[TwoFish_P_03][b0]) ^ TwoFish_b0(k2); -+ b1 = (TwoFish_P[TwoFish_P_13][b1]) ^ TwoFish_b1(k2); -+ b2 = (TwoFish_P[TwoFish_P_23][b2]) ^ TwoFish_b2(k2); -+ b3 = (TwoFish_P[TwoFish_P_33][b3]) ^ TwoFish_b3(k2); -+ case 2: /* 128-bit keys */ -+ tfdata->sBox[ 2*i ]= -+ TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0]) ^ -+ TwoFish_b0(k1)]) ^ TwoFish_b0(k0)]; -+ -+ tfdata->sBox[ 2*i+1]= -+ TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1]) ^ -+ TwoFish_b1(k1)]) ^ TwoFish_b1(k0)]; -+ -+ tfdata->sBox[0x200+2*i ]= -+ TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2]) ^ -+ TwoFish_b2(k1)]) ^ TwoFish_b2(k0)]; -+ -+ tfdata->sBox[0x200+2*i+1]= -+ TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3]) ^ -+ TwoFish_b3(k1)]) ^ TwoFish_b3(k0)]; -+ } -+ } -+} -+ -+ -+/** -+ * Encrypt or decrypt exactly one block of plaintext in CBC mode. -+ * Use "ciphertext stealing" technique described on pg. 196 -+ * of "Applied Cryptography" to encrypt the final partial -+ * (i.e. <16 byte) block if necessary. -+ * -+ * jojo: the "ciphertext stealing" requires we read ahead and have -+ * special handling for the last two blocks. Because of this, the -+ * output from the TwoFish algorithm is handled internally here. -+ * It would be better to have a higher level handle this as well as -+ * CBC mode. Unfortunately, I've mixed the two together, which is -+ * pretty crappy... The Java version separates these out correctly. -+ * -+ * fknobbe: I have reduced the CBC mode to work on memory buffer only. -+ * Higher routines should use an intermediate buffer and handle -+ * their output seperately (mainly so the data can be flushed -+ * in one chunk, not seperate 16 byte blocks...) -+ * -+ * @param in The plaintext. -+ * @param out The ciphertext -+ * @param size how much to encrypt -+ * @param tfdata: Pointer to the global data structure containing session keys. -+ * @return none -+ */ -+void _TwoFish_BlockCrypt(u_int8_t *in,u_int8_t *out,unsigned long size,int decrypt,TWOFISH *tfdata) -+{ u_int8_t PnMinusOne[TwoFish_BLOCK_SIZE]; -+ u_int8_t CnMinusOne[TwoFish_BLOCK_SIZE]; -+ u_int8_t CBCplusCprime[TwoFish_BLOCK_SIZE]; -+ u_int8_t Pn[TwoFish_BLOCK_SIZE]; -+ u_int8_t *p,*pout; -+ unsigned long i; -+ -+ /* here is where we implement CBC mode and cipher block stealing */ -+ if(size==TwoFish_BLOCK_SIZE) -+ { /* if we are encrypting, CBC means we XOR the plain text block with the */ -+ /* previous cipher text block before encrypting */ -+ if(!decrypt && tfdata->qBlockDefined) -+ { for(p=in,i=0;iqBlockCrypt[i]; /* FK: I'm copying the xor'ed input into Pn... */ -+ } -+ else -+ memcpy(Pn,in,TwoFish_BLOCK_SIZE); /* FK: same here. we work of Pn all the time. */ -+ -+ /* TwoFish block level encryption or decryption */ -+ _TwoFish_BlockCrypt16(Pn,out,decrypt,tfdata); -+ -+ /* if we are decrypting, CBC means we XOR the result of the decryption */ -+ /* with the previous cipher text block to get the resulting plain text */ -+ if(decrypt && tfdata->qBlockDefined) -+ { for (p=out,i=0;iqBlockPlain[i]; -+ } -+ -+ /* save the input and output blocks, since CBC needs these for XOR */ -+ /* operations */ -+ _TwoFish_qBlockPush(Pn,out,tfdata); -+ } -+ else -+ { /* cipher block stealing, we are at Pn, */ -+ /* but since Cn-1 must now be replaced with CnC' */ -+ /* we pop it off, and recalculate Cn-1 */ -+ -+ if(decrypt) -+ { /* We are on an odd block, and had to do cipher block stealing, */ -+ /* so the PnMinusOne has to be derived differently. */ -+ -+ /* First we decrypt it into CBC and C' */ -+ _TwoFish_qBlockPop(CnMinusOne,PnMinusOne,tfdata); -+ _TwoFish_BlockCrypt16(CnMinusOne,CBCplusCprime,decrypt,tfdata); -+ -+ /* we then xor the first few bytes with the "in" bytes (Cn) */ -+ /* to recover Pn, which we put in out */ -+ for(p=in,pout=out,i=0;iprevCipher[i]; -+ -+ /* So at this point, out has PnMinusOne */ -+ _TwoFish_qBlockPush(CnMinusOne,PnMinusOne,tfdata); -+ _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); -+ _TwoFish_FlushOutput(out,size,tfdata); -+ } -+ else -+ { _TwoFish_qBlockPop(PnMinusOne,CnMinusOne,tfdata); -+ memset(Pn,0,TwoFish_BLOCK_SIZE); -+ memcpy(Pn,in,size); -+ for(i=0;iqBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); -+ _TwoFish_FlushOutput(CnMinusOne,size,tfdata); /* old Cn-1 becomes new partial Cn */ -+ } -+ tfdata->qBlockDefined=FALSE; -+ } -+} -+ -+void _TwoFish_qBlockPush(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata) -+{ if(tfdata->qBlockDefined) -+ _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); -+ memcpy(tfdata->prevCipher,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE); -+ memcpy(tfdata->qBlockPlain,p,TwoFish_BLOCK_SIZE); -+ memcpy(tfdata->qBlockCrypt,c,TwoFish_BLOCK_SIZE); -+ tfdata->qBlockDefined=TRUE; -+} -+ -+void _TwoFish_qBlockPop(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata) -+{ memcpy(p,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE ); -+ memcpy(c,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE ); -+ tfdata->qBlockDefined=FALSE; -+} -+ -+/* Reset's the CBC flag and zero's PrevCipher (through qBlockPlain) (important) */ -+void _TwoFish_ResetCBC(TWOFISH *tfdata) -+{ tfdata->qBlockDefined=FALSE; -+ memset(tfdata->qBlockPlain,0,TwoFish_BLOCK_SIZE); -+} -+ -+void _TwoFish_FlushOutput(u_int8_t *b,unsigned long len,TWOFISH *tfdata) -+{ unsigned long i; -+ -+ for(i=0;idontflush;i++) -+ *tfdata->output++ = *b++; -+ tfdata->dontflush=FALSE; -+} -+ -+void _TwoFish_BlockCrypt16(u_int8_t *in,u_int8_t *out,bool decrypt,TWOFISH *tfdata) -+{ u_int32_t x0,x1,x2,x3; -+ u_int32_t k,t0,t1,R; -+ -+ -+ x0=*in++; -+ x0|=(*in++ << 8 ); -+ x0|=(*in++ << 16); -+ x0|=(*in++ << 24); -+ x1=*in++; -+ x1|=(*in++ << 8 ); -+ x1|=(*in++ << 16); -+ x1|=(*in++ << 24); -+ x2=*in++; -+ x2|=(*in++ << 8 ); -+ x2|=(*in++ << 16); -+ x2|=(*in++ << 24); -+ x3=*in++; -+ x3|=(*in++ << 8 ); -+ x3|=(*in++ << 16); -+ x3|=(*in++ << 24); -+ -+ if(decrypt) -+ { x0 ^= tfdata->subKeys[4]; /* swap input and output whitening keys when decrypting */ -+ x1 ^= tfdata->subKeys[5]; -+ x2 ^= tfdata->subKeys[6]; -+ x3 ^= tfdata->subKeys[7]; -+ -+ k = 7+(TwoFish_ROUNDS*2); -+ for (R = 0; R < TwoFish_ROUNDS; R += 2) -+ { t0 = _TwoFish_Fe320( tfdata->sBox, x0); -+ t1 = _TwoFish_Fe323( tfdata->sBox, x1); -+ x3 ^= t0 + (t1<<1) + tfdata->subKeys[k--]; -+ x3 = x3 >> 1 | x3 << 31; -+ x2 = x2 << 1 | x2 >> 31; -+ x2 ^= t0 + t1 + tfdata->subKeys[k--]; -+ -+ t0 = _TwoFish_Fe320( tfdata->sBox, x2); -+ t1 = _TwoFish_Fe323( tfdata->sBox, x3); -+ x1 ^= t0 + (t1<<1) + tfdata->subKeys[k--]; -+ x1 = x1 >> 1 | x1 << 31; -+ x0 = x0 << 1 | x0 >> 31; -+ x0 ^= t0 + t1 + tfdata->subKeys[k--]; -+ } -+ -+ x2 ^= tfdata->subKeys[0]; -+ x3 ^= tfdata->subKeys[1]; -+ x0 ^= tfdata->subKeys[2]; -+ x1 ^= tfdata->subKeys[3]; -+ } -+ else -+ { x0 ^= tfdata->subKeys[0]; -+ x1 ^= tfdata->subKeys[1]; -+ x2 ^= tfdata->subKeys[2]; -+ x3 ^= tfdata->subKeys[3]; -+ -+ k = 8; -+ for (R = 0; R < TwoFish_ROUNDS; R += 2) -+ { t0 = _TwoFish_Fe320( tfdata->sBox, x0); -+ t1 = _TwoFish_Fe323( tfdata->sBox, x1); -+ x2 ^= t0 + t1 + tfdata->subKeys[k++]; -+ x2 = x2 >> 1 | x2 << 31; -+ x3 = x3 << 1 | x3 >> 31; -+ x3 ^= t0 + (t1<<1) + tfdata->subKeys[k++]; -+ -+ t0 = _TwoFish_Fe320( tfdata->sBox, x2); -+ t1 = _TwoFish_Fe323( tfdata->sBox, x3); -+ x0 ^= t0 + t1 + tfdata->subKeys[k++]; -+ x0 = x0 >> 1 | x0 << 31; -+ x1 = x1 << 1 | x1 >> 31; -+ x1 ^= t0 + (t1<<1) + tfdata->subKeys[k++]; -+ } -+ -+ x2 ^= tfdata->subKeys[4]; -+ x3 ^= tfdata->subKeys[5]; -+ x0 ^= tfdata->subKeys[6]; -+ x1 ^= tfdata->subKeys[7]; -+ } -+ -+ *out++ = (u_int8_t)(x2 ); -+ *out++ = (u_int8_t)(x2 >> 8); -+ *out++ = (u_int8_t)(x2 >> 16); -+ *out++ = (u_int8_t)(x2 >> 24); -+ -+ *out++ = (u_int8_t)(x3 ); -+ *out++ = (u_int8_t)(x3 >> 8); -+ *out++ = (u_int8_t)(x3 >> 16); -+ *out++ = (u_int8_t)(x3 >> 24); -+ -+ *out++ = (u_int8_t)(x0 ); -+ *out++ = (u_int8_t)(x0 >> 8); -+ *out++ = (u_int8_t)(x0 >> 16); -+ *out++ = (u_int8_t)(x0 >> 24); -+ -+ *out++ = (u_int8_t)(x1 ); -+ *out++ = (u_int8_t)(x1 >> 8); -+ *out++ = (u_int8_t)(x1 >> 16); -+ *out++ = (u_int8_t)(x1 >> 24); -+} -+ -+/** -+ * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box -+ * 32-bit entity from two key material 32-bit entities. -+ * -+ * @param k0 1st 32-bit entity. -+ * @param k1 2nd 32-bit entity. -+ * @return Remainder polynomial generated using RS code -+ */ -+u_int32_t _TwoFish_RS_MDS_Encode(u_int32_t k0,u_int32_t k1) -+{ u_int32_t i,r; -+ -+ for(r=k1,i=0;i<4;i++) /* shift 1 byte at a time */ -+ TwoFish_RS_rem(r); -+ r ^= k0; -+ for(i=0;i<4;i++) -+ TwoFish_RS_rem(r); -+ -+ return r; -+} -+ -+u_int32_t _TwoFish_F32(u_int32_t k64Cnt,u_int32_t x,u_int32_t *k32) -+{ u_int8_t b0,b1,b2,b3; -+ u_int32_t k0,k1,k2,k3,result = 0; -+ -+ b0=TwoFish_b0(x); -+ b1=TwoFish_b1(x); -+ b2=TwoFish_b2(x); -+ b3=TwoFish_b3(x); -+ k0=k32[0]; -+ k1=k32[1]; -+ k2=k32[2]; -+ k3=k32[3]; -+ -+ switch (k64Cnt & 3) -+ { case 1: /* 64-bit keys */ -+ result = -+ TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0] & 0xFF) ^ TwoFish_b0(k0)] ^ -+ TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1] & 0xFF) ^ TwoFish_b1(k0)] ^ -+ TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2] & 0xFF) ^ TwoFish_b2(k0)] ^ -+ TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3] & 0xFF) ^ TwoFish_b3(k0)]; -+ break; -+ case 0: /* 256-bit keys (same as 4) */ -+ b0 = (TwoFish_P[TwoFish_P_04][b0] & 0xFF) ^ TwoFish_b0(k3); -+ b1 = (TwoFish_P[TwoFish_P_14][b1] & 0xFF) ^ TwoFish_b1(k3); -+ b2 = (TwoFish_P[TwoFish_P_24][b2] & 0xFF) ^ TwoFish_b2(k3); -+ b3 = (TwoFish_P[TwoFish_P_34][b3] & 0xFF) ^ TwoFish_b3(k3); -+ -+ case 3: /* 192-bit keys */ -+ b0 = (TwoFish_P[TwoFish_P_03][b0] & 0xFF) ^ TwoFish_b0(k2); -+ b1 = (TwoFish_P[TwoFish_P_13][b1] & 0xFF) ^ TwoFish_b1(k2); -+ b2 = (TwoFish_P[TwoFish_P_23][b2] & 0xFF) ^ TwoFish_b2(k2); -+ b3 = (TwoFish_P[TwoFish_P_33][b3] & 0xFF) ^ TwoFish_b3(k2); -+ case 2: /* 128-bit keys (optimize for this case) */ -+ result = -+ TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0] & 0xFF) ^ TwoFish_b0(k1)] & 0xFF) ^ TwoFish_b0(k0)] ^ -+ TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1] & 0xFF) ^ TwoFish_b1(k1)] & 0xFF) ^ TwoFish_b1(k0)] ^ -+ TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2] & 0xFF) ^ TwoFish_b2(k1)] & 0xFF) ^ TwoFish_b2(k0)] ^ -+ TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3] & 0xFF) ^ TwoFish_b3(k1)] & 0xFF) ^ TwoFish_b3(k0)]; -+ break; -+ } -+ return result; -+} -+ -+u_int32_t _TwoFish_Fe320(u_int32_t *lsBox,u_int32_t x) -+{ return lsBox[ TwoFish_b0(x)<<1 ]^ -+ lsBox[ ((TwoFish_b1(x)<<1)|1)]^ -+ lsBox[0x200+ (TwoFish_b2(x)<<1) ]^ -+ lsBox[0x200+((TwoFish_b3(x)<<1)|1)]; -+} -+ -+u_int32_t _TwoFish_Fe323(u_int32_t *lsBox,u_int32_t x) -+{ return lsBox[ (TwoFish_b3(x)<<1) ]^ -+ lsBox[ ((TwoFish_b0(x)<<1)|1)]^ -+ lsBox[0x200+ (TwoFish_b1(x)<<1) ]^ -+ lsBox[0x200+((TwoFish_b2(x)<<1)|1)]; -+} -+ -+u_int32_t _TwoFish_Fe32(u_int32_t *lsBox,u_int32_t x,u_int32_t R) -+{ return lsBox[ 2*TwoFish__b(x,R ) ]^ -+ lsBox[ 2*TwoFish__b(x,R+1)+1]^ -+ lsBox[0x200+2*TwoFish__b(x,R+2) ]^ -+ lsBox[0x200+2*TwoFish__b(x,R+3)+1]; -+} -+ -+ -+#endif - -Index: snort-2.8.6.1/src/twofish.h -=================================================================== ---- snort-2.8.6.1/src/twofish.h (Revision 0) -+++ snort-2.8.6.1/src/twofish.h (Revision 3) -@@ -0,0 +1,276 @@ -+/* $Id: twofish.h,v 2.1 2008/12/15 20:36:05 fknobbe Exp $ -+ * -+ * -+ * Copyright (C) 1997-2000 The Cryptix Foundation Limited. -+ * Copyright (C) 2000 Farm9. -+ * Copyright (C) 2001 Frank Knobbe. -+ * All rights reserved. -+ * -+ * For Cryptix code: -+ * Use, modification, copying and distribution of this software is subject -+ * the terms and conditions of the Cryptix General Licence. You should have -+ * received a copy of the Cryptix General Licence along with this library; -+ * if not, you can download a copy from http://www.cryptix.org/ . -+ * -+ * For Farm9: -+ * --- jojo@farm9.com, August 2000, converted from Java to C++, added CBC mode and -+ * ciphertext stealing technique, added AsciiTwofish class for easy encryption -+ * decryption of text strings -+ * -+ * Frank Knobbe : -+ * --- April 2001, converted from C++ to C, prefixed global variables -+ * with TwoFish, substituted some defines, changed functions to make use of -+ * variables supplied in a struct, modified and added routines for modular calls. -+ * Cleaned up the code so that defines are used instead of fixed 16's and 32's. -+ * Created two general purpose crypt routines for one block and multiple block -+ * encryption using Joh's CBC code. -+ * Added crypt routines that use a header (with a magic and data length). -+ * (Basically a major rewrite). -+ * -+ * Note: Routines labeled _TwoFish are private and should not be used -+ * (or with extreme caution). -+ * -+ */ -+ -+#ifndef __TWOFISH_LIBRARY_HEADER__ -+#define __TWOFISH_LIBRARY_HEADER__ -+ -+#ifndef FALSE -+#define FALSE 0 -+#endif -+#ifndef TRUE -+#define TRUE !FALSE -+#endif -+#ifndef bool -+#define bool int -+#endif -+ -+ -+/* Constants */ -+ -+#define TwoFish_DEFAULT_PW "SnortHas2FishEncryptionRoutines!" /* default password (not more than 32 chars) */ -+#define TwoFish_MAGIC "TwoFish" /* to indentify a successful decryption */ -+ -+enum -+{ TwoFish_KEY_SIZE = 256, /* Valid values: 64, 128, 192, 256 */ -+ /* User 256, other key sizes have not been tested. */ -+ /* (But should work. I substituted as much as */ -+ /* I could with this define.) */ -+ TwoFish_ROUNDS = 16, -+ TwoFish_BLOCK_SIZE = 16, /* bytes in a data-block */ -+ TwoFish_KEY_LENGTH = TwoFish_KEY_SIZE/8, /* 32= 256-bit key */ -+ TwoFish_TOTAL_SUBKEYS = 4+4+2*TwoFish_ROUNDS, -+ TwoFish_MAGIC_LEN = TwoFish_BLOCK_SIZE-8, -+ TwoFish_SK_BUMP = 0x01010101, -+ TwoFish_SK_ROTL = 9, -+ TwoFish_P_00 = 1, -+ TwoFish_P_01 = 0, -+ TwoFish_P_02 = 0, -+ TwoFish_P_03 = TwoFish_P_01 ^ 1, -+ TwoFish_P_04 = 1, -+ TwoFish_P_10 = 0, -+ TwoFish_P_11 = 0, -+ TwoFish_P_12 = 1, -+ TwoFish_P_13 = TwoFish_P_11 ^ 1, -+ TwoFish_P_14 = 0, -+ TwoFish_P_20 = 1, -+ TwoFish_P_21 = 1, -+ TwoFish_P_22 = 0, -+ TwoFish_P_23 = TwoFish_P_21 ^ 1, -+ TwoFish_P_24 = 0, -+ TwoFish_P_30 = 0, -+ TwoFish_P_31 = 1, -+ TwoFish_P_32 = 1, -+ TwoFish_P_33 = TwoFish_P_31 ^ 1, -+ TwoFish_P_34 = 1, -+ TwoFish_GF256_FDBK = 0x169, -+ TwoFish_GF256_FDBK_2 = 0x169 / 2, -+ TwoFish_GF256_FDBK_4 = 0x169 / 4, -+ TwoFish_RS_GF_FDBK = 0x14D, /* field generator */ -+ TwoFish_MDS_GF_FDBK = 0x169 /* primitive polynomial for GF(256) */ -+}; -+ -+ -+/* Global data structure for callers */ -+ -+typedef struct -+{ u_int32_t sBox[4 * 256]; /* Key dependent S-box */ -+ u_int32_t subKeys[TwoFish_TOTAL_SUBKEYS]; /* Subkeys */ -+ u_int8_t key[TwoFish_KEY_LENGTH]; /* Encryption Key */ -+ u_int8_t *output; /* Pointer to output buffer */ -+ u_int8_t qBlockPlain[TwoFish_BLOCK_SIZE]; /* Used by CBC */ -+ u_int8_t qBlockCrypt[TwoFish_BLOCK_SIZE]; -+ u_int8_t prevCipher[TwoFish_BLOCK_SIZE]; -+ struct /* Header for crypt functions. Has to be at least one block long. */ -+ { u_int32_t salt; /* Random salt in first block (will salt the rest through CBC) */ -+ u_int8_t length[4]; /* The amount of data following the header */ -+ u_int8_t magic[TwoFish_MAGIC_LEN]; /* Magic to identify successful decryption */ -+ } header; -+ bool qBlockDefined; -+ bool dontflush; -+} TWOFISH; -+ -+#ifndef __TWOFISH_LIBRARY_SOURCE__ -+ -+extern bool TwoFish_srand; /* if set to TRUE (default), first call of TwoFishInit will seed rand(); */ -+ /* call of TwoFishInit */ -+#endif -+ -+ -+/**** Public Functions ****/ -+ -+/* TwoFish Initialization -+ * -+ * This routine generates a global data structure for use with TwoFish, -+ * initializes important values (such as subkeys, sBoxes), generates subkeys -+ * and precomputes the MDS matrix if not already done. -+ * -+ * Input: User supplied password (will be appended by default password of 'SnortHas2FishEncryptionRoutines!') -+ * -+ * Output: Pointer to TWOFISH structure. This data structure contains key dependent data. -+ * This pointer is used with all other crypt functions. -+ */ -+TWOFISH *TwoFishInit(char *userkey); -+ -+ -+/* TwoFish Destroy -+ * -+ * Nothing else but a free... -+ * -+ * Input: Pointer to the TwoFish structure. -+ * -+ */ -+void TwoFishDestroy(TWOFISH *tfdata); -+ -+ -+/* TwoFish Alloc -+ * -+ * Allocates enough memory for the output buffer as required. -+ * -+ * Input: Length of the plaintext. -+ * Boolean flag for BinHex Output. -+ * Pointer to the TwoFish structure. -+ * -+ * Output: Returns a pointer to the memory allocated. -+ */ -+void *TwoFishAlloc(unsigned long len,bool binhex,bool decrypt,TWOFISH *tfdata); -+ -+ -+/* TwoFish Free -+ * -+ * Free's the allocated buffer. -+ * -+ * Input: Pointer to the TwoFish structure -+ * -+ * Output: (none) -+ */ -+void TwoFishFree(TWOFISH *tfdata); -+ -+ -+/* TwoFish Set Output -+ * -+ * If you want to allocate the output buffer yourself, -+ * then you can set it with this function. -+ * -+ * Input: Pointer to your output buffer -+ * Pointer to the TwoFish structure -+ * -+ * Output: (none) -+ */ -+void TwoFishSetOutput(char *outp,TWOFISH *tfdata); -+ -+ -+/* TwoFish Raw Encryption -+ * -+ * Does not use header, but does use CBC (if more than one block has to be encrypted). -+ * -+ * Input: Pointer to the buffer of the plaintext to be encrypted. -+ * Pointer to the buffer receiving the ciphertext. -+ * The length of the plaintext buffer. -+ * The TwoFish structure. -+ * -+ * Output: The amount of bytes encrypted if successful, otherwise 0. -+ */ -+unsigned long TwoFishEncryptRaw(char *in,char *out,unsigned long len,TWOFISH *tfdata); -+ -+/* TwoFish Raw Decryption -+ * -+ * Does not use header, but does use CBC (if more than one block has to be decrypted). -+ * -+ * Input: Pointer to the buffer of the ciphertext to be decrypted. -+ * Pointer to the buffer receiving the plaintext. -+ * The length of the ciphertext buffer (at least one cipher block). -+ * The TwoFish structure. -+ * -+ * Output: The amount of bytes decrypted if successful, otherwise 0. -+ */ -+unsigned long TwoFishDecryptRaw(char *in,char *out,unsigned long len,TWOFISH *tfdata); -+ -+ -+/* TwoFish Encryption -+ * -+ * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, -+ * this routine will alloc the memory. In addition, it will include a small 'header' -+ * containing the magic and some salt. That way the decrypt routine can check if the -+ * packet got decrypted successfully, and return 0 instead of garbage. -+ * -+ * Input: Pointer to the buffer of the plaintext to be encrypted. -+ * Pointer to the pointer to the buffer receiving the ciphertext. -+ * The pointer either points to user allocated output buffer space, or to NULL, in which case -+ * this routine will set the pointer to the buffer allocated through the struct. -+ * The length of the plaintext buffer. -+ * Can be -1 if the input is a null terminated string, in which case we'll count for you. -+ * Boolean flag for BinHex Output (if used, output will be twice as large as input). -+ * Note: BinHex conversion overwrites (converts) input buffer! -+ * The TwoFish structure. -+ * -+ * Output: The amount of bytes encrypted if successful, otherwise 0. -+ */ -+unsigned long TwoFishEncrypt(char *in,char **out,signed long len,bool binhex,TWOFISH *tfdata); -+ -+ -+/* TwoFish Decryption -+ * -+ * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc, -+ * this routine will alloc the memory. In addition, it will check the small 'header' -+ * containing the magic. If magic does not match we return 0. Otherwise we return the -+ * amount of bytes decrypted (should be the same as the length in the header). -+ * -+ * Input: Pointer to the buffer of the ciphertext to be decrypted. -+ * Pointer to the pointer to the buffer receiving the plaintext. -+ * The pointer either points to user allocated output buffer space, or to NULL, in which case -+ * this routine will set the pointer to the buffer allocated through the struct. -+ * The length of the ciphertext buffer. -+ * Can be -1 if the input is a null terminated binhex string, in which case we'll count for you. -+ * Boolean flag for BinHex Input (if used, plaintext will be half as large as input). -+ * Note: BinHex conversion overwrites (converts) input buffer! -+ * The TwoFish structure. -+ * -+ * Output: The amount of bytes decrypted if successful, otherwise 0. -+ */ -+unsigned long TwoFishDecrypt(char *in,char **out,signed long len,bool binhex,TWOFISH *tfdata); -+ -+ -+/**** Private Functions ****/ -+ -+u_int8_t TwoFish__b(u_int32_t x,int n); -+void _TwoFish_BinHex(u_int8_t *buf,unsigned long len,bool bintohex); -+unsigned long _TwoFish_CryptRawCBC(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata); -+unsigned long _TwoFish_CryptRaw16(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata); -+unsigned long _TwoFish_CryptRaw(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata); -+void _TwoFish_PrecomputeMDSmatrix(void); -+void _TwoFish_MakeSubKeys(TWOFISH *tfdata); -+void _TwoFish_qBlockPush(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata); -+void _TwoFish_qBlockPop(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata); -+void _TwoFish_ResetCBC(TWOFISH *tfdata); -+void _TwoFish_FlushOutput(u_int8_t *b,unsigned long len,TWOFISH *tfdata); -+void _TwoFish_BlockCrypt(u_int8_t *in,u_int8_t *out,unsigned long size,int decrypt,TWOFISH *tfdata); -+void _TwoFish_BlockCrypt16(u_int8_t *in,u_int8_t *out,bool decrypt,TWOFISH *tfdata); -+u_int32_t _TwoFish_RS_MDS_Encode(u_int32_t k0,u_int32_t k1); -+u_int32_t _TwoFish_F32(u_int32_t k64Cnt,u_int32_t x,u_int32_t *k32); -+u_int32_t _TwoFish_Fe320(u_int32_t *lsBox,u_int32_t x); -+u_int32_t _TwoFish_Fe323(u_int32_t *lsBox,u_int32_t x); -+u_int32_t _TwoFish_Fe32(u_int32_t *lsBox,u_int32_t x,u_int32_t R); -+ -+ -+#endif - -Index: snort-2.8.6.1/src/plugin_enum.h -=================================================================== ---- snort-2.8.6.1/src/plugin_enum.h (Revision 1) -+++ snort-2.8.6.1/src/plugin_enum.h (Revision 3) -@@ -60,6 +60,7 @@ - PLUGIN_URILEN_CHECK, - PLUGIN_DYNAMIC, - PLUGIN_FLOWBIT, -+ PLUGIN_FWSAM, - PLUGIN_MAX /* sentinel value */ - }; - -Index: snort-2.8.6.1/src/fatal.h -=================================================================== ---- snort-2.8.6.1/src/fatal.h (Revision 0) -+++ snort-2.8.6.1/src/fatal.h (Revision 3) -@@ -0,0 +1,40 @@ -+/* $Id$ */ -+/* -+** Copyright (C) 2002-2008 Sourcefire, Inc. -+** Copyright (C) 1998-2002 Martin Roesch -+** -+** This program is free software; you can redistribute it and/or modify -+** it under the terms of the GNU General Public License Version 2 as -+** published by the Free Software Foundation. You may not use, modify or -+** distribute this program under any other version of the GNU General -+** Public License. -+** -+** This program is distributed in the hope that it will be useful, -+** but WITHOUT ANY WARRANTY; without even the implied warranty of -+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+** GNU General Public License for more details. -+** -+** You should have received a copy of the GNU General Public License -+** along with this program; if not, write to the Free Software -+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+*/ -+ -+#ifndef __FATAL_H__ -+#define __FATAL_H__ -+ -+ -+/* -+ * in debugging mode print out the filename and the line number where the -+ * failure have occured -+ */ -+ -+ -+#ifdef DEBUG -+ #define FATAL(msg) { printf("%s:%d: ", __FILE__, __LINE__); FatalError( (char *) msg); } -+#else -+ #define FATAL(msg) FatalError( (char *) msg) -+#endif -+ -+ -+ -+#endif /* __FATAL_H__ */ - -Index: snort-2.8.6.1/src/output-plugins/spo_alert_fwsam.c -=================================================================== ---- snort-2.8.6.1/src/output-plugins/spo_alert_fwsam.c (Revision 0) -+++ snort-2.8.6.1/src/output-plugins/spo_alert_fwsam.c (Revision 3) -@@ -0,0 +1,1380 @@ -+/* $id: snortpatchb,v 1.2 2002/10/26 03:32:35 fknobbe Exp $ -+** -+** spo_alert_fwsam.c -+** -+** Copyright (c) 2001-2004 Frank Knobbe -+** -+** This program is free software; you can redistribute it and/or modify -+** it under the terms of the GNU General Public License as published by -+** the Free Software Foundation; either version 2 of the License, or -+** (at your option) any later version. -+** -+** This program is distributed in the hope that it will be useful, -+** but WITHOUT ANY WARRANTY; without even the implied warranty of -+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+** GNU General Public License for more details. -+** -+** You should have received a copy of the GNU General Public License -+** along with this program; if not, write to the Free Software -+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+*/ -+ -+/* -+ * Purpose: -+ * -+ * This module sends alerts to a remote service on a host running SnortSam -+ * (the agent) which will block the intruding IP address on a variety of -+ * host and network firewalls. -+ * -+ * SnortSam also performs checks against a white-list of never-to-be-blocked IP addresses, -+ * can override block durations (for example for known proxies), and can detect attack conditions -+ * where too many blocks are received within a defined interval. If an attack is detected -+ * it will unblock the last x blocks and wait for the attack to end. -+ * -+ * See the SnortSam documentation for more information. -+ * -+ * -+ * Output Plugin Parameters: -+ *************************** -+ * -+ * output alert_fwsam: :/ -+ * -+ * : The IP address or host name of the host running SnortSam. -+ * : The port the remote SnortSam service listens on (default 898). -+ * : The key used for authentication (encryption really) -+ * of the communication to the remote service. -+ * -+ * Examples: -+ * -+ * output alert_fwsam: snortsambox/idspassword -+ * output alert_fwsam: fw1.domain.tld:898/mykey -+ * output alert_fwsam: 192.168.0.1/borderfw 192.168.1.254/wanfw -+ * -+ * -+ * Rule Options: -+ *************** -+ * -+ * fwsam: who[how],time; -+ * -+ * who: src, source, dst, dest, destination -+ * IP address to be blocked according to snort rule (some rules -+ * are reversed, i.e. homenet -> any [and you want to block any]). -+ * src denotes IP to the left of -> and dst denotes IP to the right -+ * -+ * how: Optional. In, out, src, dest, either, both, this, conn, connection -+ * Tells FW-1 to block packets INcoming from host, OUTgoing to host, -+ * EITHERway, or only THIS connection (IP/Service pair). -+ * See 'fw sam' for more information. May be ignored by other plugins. -+ * -+ * time: Duration of block in seconds. (Accepts 'days', 'months', 'weeks', -+ * 'years', 'minutes', 'seconds', 'hours'. Alternatively, a value of -+ * 0, or the keyword PERManent, INFinite, or ALWAYS, will block the -+ * host permanently. Be careful with this! -+ * Tells FW-1 (and others) how long to inhibit packets from the host. -+ * -+ * Examples: -+ * -+ * fwsam: src[either],15min; -+ * or dst[in], 2 days 4 hours -+ * or src, 1 hour -+ * -+ * (default: src[either],5min) -+ * -+ * -+ * Effect: -+ * -+ * Alerts are sent to the remote SnortSam services on Firewall-1 Management Stations -+ * or other hosts running SnortSam (as required for Cisco Routers and PIX). -+ * The remote services will invoke the SAM configuration via the fw sam -+ * command line, or by sending a packet to the SAM port 18183, or by using the official -+ * OPSEC API calls, or by telnetting into Cisco routers or PIX firewalls. -+ * The communication over the network is encrypted using two-fish. -+ * (Implementation ripped from CryptCat by Farm9 with permission.) -+ * -+ * Future Plans: -+ * -+ * - Custom alert trigger per rule (x alerts in y secs) --> Seems to exist in Snort 1.9 now. -+ * - Enable/Allow tagged fwsam: arguments to provide different values to -+ * different stations. --> Seems to be accomplished with custom rule-types -+ * -+ * -+ * Comments: -+ * -+ * It seem that above wishes can be implemented with todays setup. Feedback concerning -+ * these is greatly appreciated. -+ * -+*/ -+ -+ -+#include "spo_alert_fwsam.h" -+#include "twofish.h" -+/* external globals from rules.c */ -+extern char *file_name; -+extern int file_line; -+extern OptTreeNode *otn_tmp; -+extern char *snort_conf_dir; /* extern PV pv; */ -+ -+ -+/* my globals */ -+ -+FWsamList *FWsamStationList=NULL; /* Global (for all alert-types) list of snortsam stations */ -+FWsamOptions *FWsamOptionField=NULL; -+unsigned long FWsamMaxOptions=0; -+ -+ -+/* -+ * Function: AlertFWsamSetup() -+ * -+ * Purpose: Registers the output plugin keyword and initialization -+ * function into the output plugin list. This is the function that -+ * gets called from InitOutputPlugins() in plugbase.c. -+ * It also registers itself as a plugin in order to parse every rule -+ * and to set the appropiate flags from fwsam: option. -+ * -+ * Arguments: None. -+ * -+ * Returns: void function -+ * -+*/ -+void AlertFWsamSetup(void) -+{ -+ /* link the preprocessor keyword to the init function in -+ the preproc list */ -+ RegisterOutputPlugin("alert_fwsam", OUTPUT_TYPE_FLAG__ALERT, AlertFWsamInit); -+ RegisterRuleOption("fwsam", AlertFWsamOptionInit, NULL, OPT_TYPE_ACTION, NULL); -+ -+#ifdef FWSAMDEBUG /* This allows debugging of fwsam only */ -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWsamSetup) Output plugin is plugged in...\n"); -+#endif -+} -+ -+ -+/* This function checks if a given snortsam station is already in -+ * a given list. -+*/ -+int FWsamStationExists(FWsamStation *who,FWsamList *list) -+{ -+ while(list) -+ { -+ if(list->station) { -+// if( who->stationip.s_addr==list->station->stationip.s_addr && -+ if(IP_EQUALITY(&who->stationip, &list->station->stationip) && -+ who->stationport==list->station->stationport) -+ return TRUE; -+ } -+ list=list->next; -+ } -+ return FALSE; -+} -+ -+/* -+ * Function: AlertFWsamInit(char *args) -+ * -+ * Purpose: Calls the argument parsing function, performs final setup on data -+ * structs, links the preproc function into the function list. -+ * -+ * Arguments: args => ptr to argument string -+ * -+ * Returns: void function -+ * -+*/ -+void AlertFWsamInit(char *args) -+{ char *ap; -+ unsigned long statip,cnt,again,i; -+ char *stathost,*statport,*statpass; -+ FWsamStation *station; -+ FWsamList *fwsamlist=NULL; /* alert-type dependent list of snortsam stations */ -+ FWsamList *listp,*newlistp; -+ struct hostent *hoste; -+ char buf[1024]=""; -+ FILE *fp; -+ FWsamOptions tempopt; -+ -+#ifdef FWSAMDEBUG -+ unsigned long hostcnt=0; -+ -+ -+ -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Output plugin initializing...\n"); -+#endif -+ -+ /* pv.alert_plugin_active = 1; */ -+ -+ /* parse the argument list from the rules file */ -+ -+ if(args == NULL) -+ FatalError("ERROR %s (%d) => [Alert_FWsam](AlertFWsamInit) No arguments to alert_fwsam preprocessor!\n", file_name, file_line); -+ -+ if(!FWsamOptionField && !FWsamMaxOptions) -+ { strncpy(buf,snort_conf_dir,sizeof(buf)-1); -+ strncpy(buf+strlen(buf),SID_MAPFILE,sizeof(buf)-strlen(buf)-1); -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWsamSetup) Using file: %s\n",buf); -+#endif -+ fp=fopen(buf,"rt"); -+ if(!fp) -+ { strncpy(buf,snort_conf_dir,sizeof(buf)-1); -+ strncpy(buf+strlen(buf),SID_ALT_MAPFILE,sizeof(buf)-strlen(buf)-1); -+ fp=fopen(buf,"rt"); -+ } -+ if(fp) /* Check for presence of map file and read those in, sorted. */ -+ { LogMessage("INFO => [Alert_FWsam](AlertFWsamSetup) Using sid-map file: %s\n",buf); -+ -+ while(FWsamReadLine(buf,sizeof(buf),fp)) -+ if(*buf) -+ FWsamMaxOptions++; -+ if(FWsamMaxOptions) -+ { if((FWsamOptionField=(FWsamOptions *)malloc(sizeof(FWsamOptions)*FWsamMaxOptions))==NULL) -+ FatalError("ERROR => [Alert_FWsam](AlertFWsamSetup) malloc failed for OptionField!\n"); -+ fseek(fp,0,SEEK_SET); -+ for(cnt=0;cnt1) -+ { for(again=TRUE,cnt=FWsamMaxOptions-1;cnt>=1 && again;cnt--) -+ { for(again=FALSE,i=0;iFWsamOptionField[i+1].sid) -+ { memcpy(&tempopt,&(FWsamOptionField[i]),sizeof(FWsamOptions)); -+ memcpy(&(FWsamOptionField[i]),&(FWsamOptionField[i+1]),sizeof(FWsamOptions)); -+ memcpy(&(FWsamOptionField[i+1]),&tempopt,sizeof(FWsamOptions)); -+ again=TRUE; -+ } -+ } -+ } -+ } -+ } -+ else -+ FWsamMaxOptions=1; -+ fclose(fp); -+ } -+ else -+ FWsamMaxOptions=1; -+ } -+ -+ -+ ap=args; /* start at the beginning of the argument */ -+ while(*ap && isspace(*ap)) ap++; -+ while(*ap) -+ { stathost=ap; /* first argument should be host */ -+ statport=NULL; -+ statpass=NULL; -+ while(*ap && *ap!=':' && *ap!='/' && !isspace(*ap)) ap++; /* find token */ -+ switch(*ap) -+ { case ':': *ap++=0; /* grab the port */ -+ statport=ap; -+ while(*ap && *ap!='/' && !isspace(*ap)) ap++; -+ if(*ap!='/') -+ break; -+ case '/': *ap++=0; /* grab the key */ -+ statpass=ap; -+ while(*ap && !isspace(*ap)) ap++; -+ default: break; -+ } -+ if(*ap) -+ { *ap++=0; -+ while(isspace(*ap)) ap++; -+ } -+ /* now we have the first host with port and password (key) */ -+ /* next we check for valid/blank password/port */ -+ if(statpass!=NULL) -+ if(!*statpass) -+ statpass=NULL; -+ if(statport!=NULL) -+ if(!*statport) -+ statport=NULL; -+ statip=0; -+ /* now we check if a valid host was specified */ -+ if(inet_addr(stathost)==INADDR_NONE) -+ { hoste=gethostbyname(stathost); -+ if (!hoste) -+ LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWsamInit) Unable to resolve host '%s'!\n",file_name,file_line,stathost); -+ else -+ statip=*(unsigned long *)hoste->h_addr; -+ } -+ else -+ { statip=inet_addr(stathost); -+ if(!statip) -+ LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWsamInit) Invalid host address '%s'!\n",file_name,file_line,stathost); -+ } -+ if(statip) -+ { /* groovie, a valid host. Let's alloc and assemble the structure for it. */ -+ if((station=(FWsamStation *)malloc(sizeof(FWsamStation)))==NULL) -+ FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for station!\n"); -+ -+// station->stationip.s_addr=statip; /* the IP address */ -+ station->stationip.ip32[0] = statip; /* the IP address */ -+ if(statport!=NULL && atoi(statport)>0) /* if the user specified one */ -+ station->stationport=atoi(statport); /* use users setting */ -+ else -+ station->stationport=FWSAM_DEFAULTPORT; /* set the default port */ -+ -+ if(statpass!=NULL) /* if specified by user */ -+ strncpy(station->stationkey,statpass,TwoFish_KEY_LENGTH); /* use defined key */ -+ else -+ station->stationkey[0]=0; -+ station->stationkey[TwoFish_KEY_LENGTH]=0; /* make sure it's terminated. (damn strncpy...) */ -+ -+ strcpy(station->initialkey,station->stationkey); -+ station->stationfish=TwoFishInit(station->stationkey); -+ -+ station->localsocketaddr.sin_port=htons(0); /* let's use dynamic ports for now */ -+ station->localsocketaddr.sin_addr.s_addr=0; -+ station->localsocketaddr.sin_family=AF_INET; -+ station->stationsocketaddr.sin_port=htons(station->stationport); -+ //station->stationsocketaddr.sin_addr=station->stationip; -+ station->stationsocketaddr.sin_addr.s_addr=station->stationip.ip32[0]; -+ station->stationsocketaddr.sin_family=AF_INET; /* load all socket crap and keep for later */ -+ -+ do -+ station->myseqno=rand(); /* the seqno this host will use */ -+ while(station->myseqno<20 || station->myseqno>65500); -+ station->mykeymod[0]=rand(); -+ station->mykeymod[1]=rand(); -+ station->mykeymod[2]=rand(); -+ station->mykeymod[3]=rand(); -+ station->stationseqno=0; /* peer hasn't answered yet. */ -+ -+ -+ if(!FWsamStationExists(station,FWsamStationList)) /* If we don't have the station already in global list....*/ -+ { if(FWsamCheckIn(station)) /* ...and we can talk to the agent... */ -+ { if((newlistp=(FWsamList *)malloc(sizeof(FWsamList)))==NULL) -+ FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for global newlistp!\n"); -+ newlistp->station=station; -+ newlistp->next=NULL; -+ -+ if(!FWsamStationList) /* ... add it to the global list/ */ -+ FWsamStationList=newlistp; -+ else -+ { listp=FWsamStationList; -+ while(listp->next) -+ listp=listp->next; -+ listp->next=newlistp; -+ } -+ } -+ else -+ { TwoFishDestroy(station->stationfish); /* if not, we trash it. */ -+ free(station); -+ station=NULL; -+ } -+ } -+#ifdef FWSAMDEBUG -+ else -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Host %s:%i already in global list, skipping CheckIn.\n", sfip_ntoa(&station->stationip),station->stationport); -+#endif -+ -+ if(station) -+ { if(!FWsamStationExists(station,fwsamlist)) /* If we don't have the station already in local list....*/ -+ { if((newlistp=(FWsamList *)malloc(sizeof(FWsamList)))==NULL) -+ FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for local newlistp!\n"); -+ newlistp->station=station; -+ newlistp->next=NULL; -+ -+ if(!fwsamlist) /* ... add it to the local list/ */ -+ fwsamlist=newlistp; -+ else -+ { listp=fwsamlist; -+ while(listp->next) -+ listp=listp->next; -+ listp->next=newlistp; -+ } -+ } -+ -+#ifdef FWSAMDEBUG -+ else -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Host %s:%i already in local list, skipping.\n",sfip_ntoa(&station->stationip),station->stationport); -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) #%i: Host %s [%s] port %i password %s\n",++hostcnt,stathost,sfip_ntoa(&station->stationip),station->stationport,station->stationkey); -+#endif -+ } -+ -+ } -+ } /* next one */ -+ -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Linking fwsam alert function to call list...\n"); -+#endif -+ -+ /* Set the preprocessor function into the function list */ -+ AddFuncToOutputList(AlertFWsam, OUTPUT_TYPE_FLAG__ALERT, fwsamlist); -+ AddFuncToCleanExitList(AlertFWsamCleanExitFunc, fwsamlist); -+ AddFuncToRestartList(AlertFWsamRestartFunc, fwsamlist); -+} -+ -+ -+/* This routine reads in a str from a file, snips white-spaces -+ * off the front and back, removes comments, and pretties the -+ * string. Returns true or false if a line was read or not. -+*/ -+int FWsamReadLine(char *buf,unsigned long bufsize,FILE *fp) -+{ char *p; -+ -+ if(fgets(buf,bufsize-1,fp)) -+ { buf[bufsize-1]=0; -+ -+#ifdef FWSAMDEBUG_off -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWsamReadLine) Line: %s\n",buf); -+#endif -+ -+ p=buf; -+ while(isspace(*p)) -+ p++; -+ if(p>buf); -+ strcpy(buf,p); -+ if(*buf) -+ { p=buf+strlen(buf)-1; /* remove leading and trailing spaces */ -+ while(isspace(*p)) -+ *p-- =0; -+ } -+ p=buf; -+ if(*p=='#' || *p==';') -+ *p=0; -+ else -+ p++; -+ while(*p) /* remove inline comments (except escaped #'s and ;'s) */ -+ { if(*p=='#' || *p==';') -+ { if(*(p-1)=='\\') -+ strcpy(p-1,p); -+ else -+ *p=0; -+ } -+ else -+ p++; -+ } -+ return TRUE; -+ } -+ return FALSE; -+} -+ -+ -+/* Parses the duration of the argument, recognizing minutes, hours, etc.. -+*/ -+unsigned long FWsamParseDuration(char *p) -+{ unsigned long dur=0,tdu; -+ char *tok,c1,c2; -+ -+ while(*p) -+ { tok=p; -+ while(*p && isdigit(*p)) -+ p++; -+ if(*p) -+ { c1=tolower(*p); -+ *p=0; -+ p++; -+ if(*p && !isdigit(*p)) -+ { c2=tolower(*p++); -+ while(*p && !isdigit(*p)) -+ p++; -+ } -+ else -+ c2=0; -+ tdu=atol(tok); -+ switch(c1) -+ { case 'm': if(c2=='o') /* month */ -+ tdu*=(60*60*24*30); /* use 30 days */ -+ else -+ tdu*=60; /* minutes */ -+ case 's': break; /* seconds */ -+ case 'h': tdu*=(60*60); /* hours */ -+ break; -+ case 'd': tdu*=(60*60*24); /* days */ -+ break; -+ case 'w': tdu*=(60*60*24*7); /* week */ -+ break; -+ case 'y': tdu*=(60*60*24*365); /* year */ -+ break; -+ } -+ dur+=tdu; -+ } -+ else -+ dur+=atol(tok); -+ } -+ -+ return dur; -+} -+ -+ -+/* This routine parses an option line. It is called by FWsamParseLine, -+ * which parses the sid-block.map file, and also by AlertFWsamOptionInit, -+ * which is called by Snort when processing fwsam: options in rules. -+ * It returns TRUE it there is a possible option problem, otherwise FALSE. -+*/ -+int FWsamParseOption(FWsamOptions *optp,char *ap) -+{ int possprob=FALSE; -+ -+ /* set defaults */ -+ -+ optp->duration=300; /* default of 5 minute block */ -+ optp->how=FWSAM_HOW_INOUT; /* inbound and outbound block */ -+ optp->who=FWSAM_WHO_SRC; /* the source */ -+ optp->loglevel=FWSAM_LOG_LONGALERT; /* the log level default */ -+ /* parse the fwsam keywords */ -+ -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWamOptionInit) Parse Options Args: %s\n",ap); -+#endif -+ -+ if(*ap) /* should be dst/src (the WHO) or duration */ -+ { if(isdigit(*ap)) -+ optp->duration=FWsamParseDuration(ap); -+ else -+ { switch(*ap) /* yeah, we're lazy and check only the first character */ -+ { case 'p': ; /* permanent, perm */ -+ case 'f': ; /* forever */ -+ case 'i': optp->duration=0; /* infinite, inf */ -+ break; -+ case 'd': optp->who=FWSAM_WHO_DST; /* destination, dest, dst */ -+ break; -+ case 's': optp->who=FWSAM_WHO_SRC; /* source, src */ -+ break; -+ default: possprob=TRUE; -+ } -+ while(*ap && *ap!=',' && *ap!='[') -+ ap++; -+ if(*ap=='[') -+ { ap++; /* now we have the HOW */ -+ switch(*ap) -+ { case 'i': ; /* in */ -+ case 's': optp->how=FWSAM_HOW_IN; /* source, src */ -+ break; -+ case 'o': ; /* out */ -+ case 'd': optp->how=FWSAM_HOW_OUT; /* destination, dest, dst */ -+ break; -+ case 'b': ; /* both */ -+ case 'e': optp->how=FWSAM_HOW_INOUT; /* either */ -+ break; -+ case 't': ; /* this */ -+ case 'c': optp->how=FWSAM_HOW_THIS; /* connection, conn */ -+ break; -+ default: possprob=TRUE; -+ } -+ while(*ap && *ap!=',') -+ ap++; -+ } -+ if(*ap==',') -+ { ap++; -+ if(isdigit(*ap)) /* and figure out how long to block */ -+ optp->duration=FWsamParseDuration(ap); -+ else if(*ap=='p' || *ap=='f' || *ap=='i') -+ optp->duration=0; -+ else -+ possprob=TRUE; -+ } -+ else if(!*ap) -+ possprob=TRUE; -+ } -+ } -+ else -+ possprob=TRUE; -+ -+ return possprob; -+} -+ -+ -+/* This goes through the lines of sid-block.map and sets the -+ * options for fwsam if the file is being used. -+*/ -+void FWsamParseLine(FWsamOptions *optp,char *buf) -+{ char *ap; -+ -+ ap=buf; /* start at the beginning of the argument */ -+ -+ while(*ap) -+ { if(isspace(*ap)) /* normalize spaces (tabs into space, etc) */ -+ *ap=' '; -+ if(isupper(*ap)) /* and set to lower case */ -+ *ap=tolower(*ap); -+ ap++; -+ } -+ while((ap=strrchr(buf,' '))!=NULL) /* remove spaces */ -+ strcpy(ap,ap+1); -+ -+ ap=buf; -+ if(*ap) -+ { while(*ap && *ap!=':' && *ap!='|') -+ ap++; -+ *ap++ =0; -+ while(*ap && (*ap==':' || *ap=='|')) -+ ap++; -+ -+ optp->sid=(unsigned long)atol(buf); -+ -+ if(FWsamParseOption(optp,ap)) -+ LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWamOptionInit) Possible option problem. Using %s[%s],%lu.\n",file_name,file_line,(optp->who==FWSAM_WHO_SRC)?"src":"dst",(optp->how==FWSAM_HOW_IN)?"in":((optp->how==FWSAM_HOW_OUT)?"out":"either"),optp->duration); -+ } -+ else -+ optp->sid=0; -+} -+ -+ -+ -+/* -+ * Function: AlertFWsamOptionInit(char *data, OptTreeNode *otn, int protocol) -+ * -+ * Purpose: Parses each rule and sets the option flags in the tree. -+ * -+ * Arguments: args => ptr to argument string -+ * -+ * Returns: void function -+ * -+*/ -+void AlertFWsamOptionInit(char *args,OptTreeNode *otn,int protocol) -+{ -+ FWsamOptions *optp; -+ char *ap; -+ -+ -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWamOptionInit) FWsamOptionInit is parsing...\n"); -+#endif -+ -+ if((optp=(FWsamOptions *)malloc(sizeof(FWsamOptions)))==NULL) -+ FatalError("ERROR => [Alert_FWsam](AlertFWamOptionInit) malloc failed for opt!\n"); -+ -+ -+ ap=args; /* start at the beginning of the argument */ -+ -+ while(*ap) -+ { if(isspace(*ap)) /* normalize spaces (tabs into space, etc) */ -+ *ap=' '; -+ if(isupper(*ap)) /* and set to lower case */ -+ *ap=tolower(*ap); -+ ap++; -+ } -+ while((ap=strrchr(args,' '))!=NULL) /* remove spaces */ -+ strcpy(ap,ap+1); -+ -+ -+ if(FWsamParseOption(optp,args)) -+ LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWamOptionInit) Possible option problem. Using %s[%s],%lu.\n",file_name,file_line,(optp->who==FWSAM_WHO_SRC)?"src":"dst",(optp->how==FWSAM_HOW_IN)?"in":((optp->how==FWSAM_HOW_OUT)?"out":"either"),optp->duration); -+ -+ otn->ds_list[PLUGIN_FWSAM]=(FWsamOptions *)optp; -+} -+ -+ -+/* Generates a new encryption key for TwoFish based on seq numbers and a random that -+ * the SnortSam agents send on checkin (in protocol) -+*/ -+void FWsamNewStationKey(FWsamStation *station,FWsamPacket *packet) -+{ -+ //unsigned char newkey[TwoFish_KEY_LENGTH+2]; -+ char newkey[TwoFish_KEY_LENGTH+2]; -+ int i; -+ -+ newkey[0]=packet->snortseqno[0]; /* current snort seq # (which both know) */ -+ newkey[1]=packet->snortseqno[1]; -+ newkey[2]=packet->fwseqno[0]; /* current SnortSam seq # (which both know) */ -+ newkey[3]=packet->fwseqno[1]; -+ newkey[4]=packet->protocol[0]; /* the random SnortSam chose */ -+ newkey[5]=packet->protocol[1]; -+ -+ strncpy(newkey+6,station->stationkey,TwoFish_KEY_LENGTH-6); /* append old key */ -+ newkey[TwoFish_KEY_LENGTH]=0; -+ -+ newkey[0]^=station->mykeymod[0]; /* modify key with key modifiers which were */ -+ newkey[1]^=station->mykeymod[1]; /* exchanged during the check-in handshake. */ -+ newkey[2]^=station->mykeymod[2]; -+ newkey[3]^=station->mykeymod[3]; -+ newkey[4]^=station->fwkeymod[0]; -+ newkey[5]^=station->fwkeymod[1]; -+ newkey[6]^=station->fwkeymod[2]; -+ newkey[7]^=station->fwkeymod[3]; -+ -+ for(i=0;i<=7;i++) -+ if(newkey[i]==0) -+ newkey[i]++; -+ -+ strcpy(station->stationkey,newkey); -+ TwoFishDestroy(station->stationfish); -+ station->stationfish=TwoFishInit(newkey); -+} -+ -+ -+/* This routine will search the option list as defined -+ * by the sid-block.map file and return a pointer -+ * to the matching record. -+*/ -+FWsamOptions *FWsamGetOption(unsigned long sid) -+{ signed long i,step,diff,o,o2; -+ -+#ifdef FWSAM_FANCYFETCH /* Fancy-fetch jumps in decreasing n/2 steps and takes much less lookups */ -+ o=o2= -1; -+ i=step=FWsamMaxOptions>>1; -+ while(i>=0 && i1) -+ step=step>>1; -+ o2=o; -+ o=i; -+ if(diff>0) -+ i+=step; -+ else -+ i-=step; -+ } -+#else /* This is just a sequential list lookup */ -+ for(i=0;i pointer to the packet data struct -+ * msg => the message to print in the alert -+ * -+ * Returns: void function -+ * -+ ***************************************************************************/ -+void AlertFWsam(Packet *p, char *msg, void *arg, Event *event) -+{ FWsamOptions *optp; -+ FWsamPacket sampacket; -+ FWsamStation *station=NULL; -+ FWsamList *fwsamlist; -+ SOCKET stationsocket; -+ int i,len,deletestation,stationtry=0; -+ //unsigned char *encbuf,*decbuf; -+ char *encbuf,*decbuf; -+ static unsigned long lastbsip[FWSAM_REPET_BLOCKS],lastbdip[FWSAM_REPET_BLOCKS], -+ lastbduration[FWSAM_REPET_BLOCKS],lastbtime[FWSAM_REPET_BLOCKS]; -+ static unsigned short lastbsp[FWSAM_REPET_BLOCKS],lastbdp[FWSAM_REPET_BLOCKS], -+ lastbproto[FWSAM_REPET_BLOCKS],lastbpointer; -+ static unsigned char lastbmode[FWSAM_REPET_BLOCKS]; -+ static unsigned long btime=0; -+ -+ -+ if(otn_tmp==NULL) -+ { -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam] NULL otn_tmp!\n"); -+#endif -+ return; -+ } -+ if(p == NULL) -+ { -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam] NULL packet!\n"); -+#endif -+ return; -+ } -+ if(arg == NULL) -+ { -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam] NULL arg!\n"); -+#endif -+ return; -+ } -+ -+ /* SnortSam does no IPv6 */ -+ if (!IS_IP4(p)) { -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam] not acting on non-IP4 packet!\n"); -+#endif -+ return; -+ } -+ -+ optp=NULL; -+ -+ if(FWsamOptionField) /* If using the file (field present), let's use that */ -+ optp=FWsamGetOption(event->sig_id); -+ -+ if(!optp) /* If file not present, check if an fwsam option was defined on the triggering rule */ -+ optp=otn_tmp->ds_list[PLUGIN_FWSAM]; -+ -+ if(optp) /* if options specified for this rule */ -+ { if(!btime) /* if this is the first time this function is */ -+ { for(i=0;i [Alert_FWsam] Alert -> Msg=\"%s\"\n",msg); -+ -+ LogMessage("DEBUG => [Alert_FWsam] Alert -> Option: %s[%s],%lu.\n",(optp->who==FWSAM_WHO_SRC)?"src":"dst",(optp->how==FWSAM_HOW_IN)?"in":((optp->how==FWSAM_HOW_OUT)?"out":"either"),optp->duration); -+#endif -+ -+ len=TRUE; -+ btime=(unsigned long)time(NULL); /* get current time */ -+ /* This is a cheap check to see if the blocking request matches any of the previous requests. */ -+ for(i=0;ihow==FWSAM_HOW_THIS)? /* if blocking mode SERVICE, check for src and dst */ -+ ( lastbsip[i]==p->iph->ip_src.s_addr && lastbdip[i]==p->iph->ip_dst.s_addr &&lastbproto[i]==p->iph->ip_proto && -+ ((p->iph->ip_proto==IPPROTO_TCP || p->iph->ip_proto==IPPROTO_UDP)? /* check port only of TCP or UDP */ -+/* ((optp->who==FWSAM_WHO_SRC)?(lastbsp[i]==p->sp):(lastbdp[i]==p->dp)):TRUE) ): */ -+ lastbdp[i]==p->dp:TRUE) ): -+ ((optp->who==FWSAM_WHO_SRC)?(lastbsip[i]==p->iph->ip_src.s_addr):(lastbdip[i]==p->iph->ip_dst.s_addr))) && /* otherwise if we block source, only compare source. Same for dest. */ -+ lastbduration[i]==optp->duration && -+ (lastbmode[i]&(FWSAM_HOW|FWSAM_WHO))==(optp->how|optp->who) && -+ (btime-lastbtime[i]<((optp->duration>FWSAM_REPET_TIME)?FWSAM_REPET_TIME:optp->duration))) -+ { len=FALSE; /* If so, we don't need to block again. */ -+ } -+ } -+ if(len) -+ { if(++lastbpointer>=FWSAM_REPET_BLOCKS) /* increase repetitive check pointer */ -+ lastbpointer=0; -+ lastbsip[lastbpointer]=p->iph->ip_src.s_addr; /* and note packet details */ -+ lastbdip[lastbpointer]=p->iph->ip_dst.s_addr; -+ lastbduration[lastbpointer]=optp->duration; -+ lastbmode[lastbpointer]=optp->how|optp->who|optp->loglevel; -+ lastbproto[lastbpointer]=p->iph->ip_proto; -+ if(p->iph->ip_proto==IPPROTO_TCP || p->iph->ip_proto==IPPROTO_UDP) -+ { lastbsp[lastbpointer]=p->sp; /* set ports if TCP or UDP */ -+ lastbdp[lastbpointer]=p->dp; -+ } -+ lastbtime[lastbpointer]=btime; -+ -+ -+ while(fwsamlist!=NULL) -+ { station=fwsamlist->station; -+ //if(station->stationip.s_addr) -+ if(station->stationip.ip32[0]) -+ { deletestation=FALSE; -+ stationtry++; /* first try */ -+ /* create a socket for the station */ -+ stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); -+ if(stationsocket==INVALID_SOCKET) -+ FatalError("ERROR => [Alert_FWsam] Funky socket error (socket)!\n"); -+ if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr))) -+ FatalError("ERROR => [Alert_FWsam] Could not bind socket!\n"); -+ -+ /* let's connect to the agent */ -+ if(connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr))) -+ { -+ LogMessage("WARNING => [Alert_FWsam] Could not send block to host %s. Will try later.\n",sfip_ntoa(&station->stationip)); -+#ifdef WIN32 -+ closesocket(stationsocket); -+#else -+ close(stationsocket); -+#endif -+ stationtry=0; -+ } -+ else -+ { -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam] Connected to host %s.\n",sfip_ntoa(&station->stationip)); -+#endif -+ /* now build the packet */ -+ station->myseqno+=station->stationseqno; /* increase my seqno by adding agent seq no */ -+ sampacket.endiancheck=1; /* This is an endian indicator for Snortsam */ -+ sampacket.snortseqno[0]=(char)station->myseqno; -+ sampacket.snortseqno[1]=(char)(station->myseqno>>8); -+ sampacket.fwseqno[0]=(char)station->stationseqno;/* fill station seqno */ -+ sampacket.fwseqno[1]=(char)(station->stationseqno>>8); -+ sampacket.status=FWSAM_STATUS_BLOCK; /* set block mode */ -+ sampacket.version=FWSAM_PACKETVERSION; /* set packet version */ -+ sampacket.duration[0]=(char)optp->duration; /* set duration */ -+ sampacket.duration[1]=(char)(optp->duration>>8); -+ sampacket.duration[2]=(char)(optp->duration>>16); -+ sampacket.duration[3]=(char)(optp->duration>>24); -+ sampacket.fwmode=optp->how|optp->who|optp->loglevel; /* set the mode */ -+ sampacket.dstip[0]=(char)p->iph->ip_dst.s_addr; /* destination IP */ -+ sampacket.dstip[1]=(char)(p->iph->ip_dst.s_addr>>8); -+ sampacket.dstip[2]=(char)(p->iph->ip_dst.s_addr>>16); -+ sampacket.dstip[3]=(char)(p->iph->ip_dst.s_addr>>24); -+ sampacket.srcip[0]=(char)p->iph->ip_src.s_addr; /* source IP */ -+ sampacket.srcip[1]=(char)(p->iph->ip_src.s_addr>>8); -+ sampacket.srcip[2]=(char)(p->iph->ip_src.s_addr>>16); -+ sampacket.srcip[3]=(char)(p->iph->ip_src.s_addr>>24); -+ sampacket.protocol[0]=(char)p->iph->ip_proto; /* protocol */ -+ sampacket.protocol[1]=(char)(p->iph->ip_proto>>8);/* protocol */ -+ -+ if(p->iph->ip_proto==IPPROTO_TCP || p->iph->ip_proto==IPPROTO_UDP) -+ { sampacket.srcport[0]=(char)p->sp; /* set ports */ -+ sampacket.srcport[1]=(char)(p->sp>>8); -+ sampacket.dstport[0]=(char)p->dp; -+ sampacket.dstport[1]=(char)(p->dp>>8); -+ } -+ else -+ sampacket.srcport[0]=sampacket.srcport[1]=sampacket.dstport[0]=sampacket.dstport[1]=0; -+ -+ sampacket.sig_id[0]=(char)event->sig_id; /* set signature ID */ -+ sampacket.sig_id[1]=(char)(event->sig_id>>8); -+ sampacket.sig_id[2]=(char)(event->sig_id>>16); -+ sampacket.sig_id[3]=(char)(event->sig_id>>24); -+ -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam] Sending BLOCK\n"); -+ LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo: %x\n",station->myseqno); -+ LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo : %x\n",station->stationseqno); -+ LogMessage("DEBUG => [Alert_FWsam] Status : %i\n",FWSAM_STATUS_BLOCK); -+ LogMessage("DEBUG => [Alert_FWsam] Mode : %i\n",optp->how|optp->who|optp->loglevel); -+ LogMessage("DEBUG => [Alert_FWsam] Duration : %li\n",optp->duration); -+ LogMessage("DEBUG => [Alert_FWsam] Protocol : %i\n",GET_IPH_PROTO(p)); -+#ifdef SUP_IP6 -+ LogMessage("DEBUG => [Alert_FWsam] Src IP : %s\n",sfip_ntoa(GET_SRC_IP(p))); -+ LogMessage("DEBUG => [Alert_FWsam] Dest IP : %s\n",sfip_ntoa(GET_DST_IP(p))); -+#else -+ LogMessage("DEBUG => [Alert_FWsam] Src IP : %s\n",inet_ntoa(p->iph->ip_src)); -+ LogMessage("DEBUG => [Alert_FWsam] Dest IP : %s\n",inet_ntoa(p->iph->ip_dst)); -+#endif -+ LogMessage("DEBUG => [Alert_FWsam] Src Port : %i\n",p->sp); -+ LogMessage("DEBUG => [Alert_FWsam] Dest Port : %i\n",p->dp); -+ LogMessage("DEBUG => [Alert_FWsam] Sig_ID : %lu\n",event->sig_id); -+ -+#endif -+ -+ encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get the encryption buffer */ -+ len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt the packet with current key */ -+ -+ if(send(stationsocket,encbuf,len,0)!=len) /* weird...could not send */ -+ { LogMessage("WARNING => [Alert_FWsam] Could not send to host %s. Will try again later.\n",sfip_ntoa(&station->stationip)); -+#ifdef WIN32 -+ closesocket(stationsocket); -+#else -+ close(stationsocket); -+#endif -+ stationtry=0; -+ } -+ else -+ { i=FWSAM_NETWAIT; -+#ifdef WIN32 -+ ioctlsocket(stationsocket,FIONBIO,&i); /* set non blocking and wait for */ -+#else -+ ioctl(stationsocket,FIONBIO,&i); /* set non blocking and wait for */ -+#endif -+ while(i-- >1) /* the response packet */ -+ { waitms(10); /* wait for response (default maximum 3 secs */ -+ if(recv(stationsocket,encbuf,len,0)==len) -+ i=0; /* if we received packet we set the counter to 0. */ -+ /* by the time we check with if, it's already dec'ed to -1 */ -+ } -+ if(!i) /* id we timed out (i was one, then dec'ed)... */ -+ { LogMessage("WARNING => [Alert_FWsam] Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip)); -+#ifdef WIN32 -+ closesocket(stationsocket); -+#else -+ close(stationsocket); -+#endif -+ stationtry=0; -+ } -+ else /* got a packet */ -+ { decbuf=(char *)&sampacket; /* get the pointer to the packet struct */ -+ len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt the packet with current key */ -+ -+ if(len!=sizeof(FWsamPacket)) /* invalid decryption */ -+ { strcpy(station->stationkey,station->initialkey); /* try the intial key */ -+ TwoFishDestroy(station->stationfish); -+ station->stationfish=TwoFishInit(station->stationkey); /* re-initialize the TwoFish with the intial key */ -+ len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try again to decrypt */ -+ LogMessage("INFO => [Alert_FWsam] Had to use initial key!\n"); -+ } -+ if(len==sizeof(FWsamPacket)) /* valid decryption */ -+ { if(sampacket.version==FWSAM_PACKETVERSION)/* master speaks my language */ -+ { if(sampacket.status==FWSAM_STATUS_OK || sampacket.status==FWSAM_STATUS_NEWKEY -+ || sampacket.status==FWSAM_STATUS_RESYNC || sampacket.status==FWSAM_STATUS_HOLD) -+ { station->stationseqno=sampacket.fwseqno[0] | (sampacket.fwseqno[1]<<8); /* get stations seqno */ -+ station->lastcontact=(unsigned long)time(NULL); /* set the last contact time (not used yet) */ -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam] Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK": -+ sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY": -+ sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC": -+ sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR"); -+ LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo: %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8)); -+ LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo : %x\n",station->stationseqno); -+ LogMessage("DEBUG => [Alert_FWsam] Status : %i\n",sampacket.status); -+ LogMessage("DEBUG => [Alert_FWsam] Version : %i\n",sampacket.version); -+#endif -+ if(sampacket.status==FWSAM_STATUS_HOLD) -+ { i=FWSAM_NETHOLD; /* Stay on hold for a maximum of 60 secs (default) */ -+ while(i-- >1) /* the response packet */ -+ { waitms(10); /* wait for response */ -+ if(recv(stationsocket,encbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,0)==sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE) -+ i=0; /* if we received packet we set the counter to 0. */ -+ } -+ if(!i) /* id we timed out (i was one, then dec'ed)... */ -+ { LogMessage("WARNING => [Alert_FWsam] Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip)); -+ stationtry=0; -+ sampacket.status=FWSAM_STATUS_ERROR; -+ } -+ else /* got a packet */ -+ { decbuf=(char *)&sampacket; /* get the pointer to the packet struct */ -+ len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt the packet with current key */ -+ -+ if(len!=sizeof(FWsamPacket)) /* invalid decryption */ -+ { strcpy(station->stationkey,station->initialkey); /* try the intial key */ -+ TwoFishDestroy(station->stationfish); -+ station->stationfish=TwoFishInit(station->stationkey); /* re-initialize the TwoFish with the intial key */ -+ len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try again to decrypt */ -+ LogMessage("INFO => [Alert_FWsam] Had to use initial key again!\n"); -+ } -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam] Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK": -+ sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY": -+ sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC": -+ sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR"); -+ LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo: %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8)); -+ LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo : %x\n",station->stationseqno); -+ LogMessage("DEBUG => [Alert_FWsam] Status : %i\n",sampacket.status); -+ LogMessage("DEBUG => [Alert_FWsam] Version : %i\n",sampacket.version); -+#endif -+ if(len!=sizeof(FWsamPacket)) /* invalid decryption */ -+ { ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip)); -+ deletestation=TRUE; -+ sampacket.status=FWSAM_STATUS_ERROR; -+ } -+ else if(sampacket.version!=FWSAM_PACKETVERSION) /* invalid protocol version */ -+ { ErrorMessage("ERROR => [Alert_FWsam] Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip)); -+ deletestation=TRUE; -+ sampacket.status=FWSAM_STATUS_ERROR; -+ } -+ else if(sampacket.status!=FWSAM_STATUS_OK && sampacket.status!=FWSAM_STATUS_NEWKEY && sampacket.status!=FWSAM_STATUS_RESYNC) -+ { ErrorMessage("ERROR => [Alert_FWsam] Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip)); -+ deletestation=TRUE; -+ sampacket.status=FWSAM_STATUS_ERROR; -+ } -+ } -+ } -+ if(sampacket.status==FWSAM_STATUS_RESYNC) /* if station want's to resync... */ -+ { strcpy(station->stationkey,station->initialkey); /* ...we use the intial key... */ -+ memcpy(station->fwkeymod,sampacket.duration,4); /* and note the random key modifier */ -+ } -+ if(sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC) -+ { -+ FWsamNewStationKey(station,&sampacket); /* generate new TwoFish keys */ -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam] Generated new encryption key...\n"); -+#endif -+ } -+#ifdef WIN32 -+ closesocket(stationsocket); -+#else -+ close(stationsocket); -+#endif -+ stationtry=0; -+ } -+ else if(sampacket.status==FWSAM_STATUS_ERROR) /* if SnortSam reports an error on second try, */ -+ { -+#ifdef WIN32 -+ closesocket(stationsocket); /* something is messed up and ... */ -+#else -+ close(stationsocket); -+#endif -+ if(stationtry>1) /* we ignore that station. */ -+ { deletestation=TRUE; /* flag for deletion */ -+ ErrorMessage("ERROR => [Alert_FWsam] Could not renegotiate key! Ignoring host %s.\n",sfip_ntoa(&station->stationip)); -+ } -+ else /* if we get an error on the first try, */ -+ { if(!FWsamCheckIn(station)) /* we first try to check in again. */ -+ { deletestation=TRUE; -+ ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip)); -+ } -+ } -+ } -+ else /* an unknown status means trouble... */ -+ { ErrorMessage("ERROR => [Alert_FWsam] Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip)); -+#ifdef WIN32 -+ closesocket(stationsocket); -+#else -+ close(stationsocket); -+#endif -+ deletestation=TRUE; -+ } -+ } -+ else /* if the SnortSam agent uses a different packet version, we have no choice but to ignore it. */ -+ { ErrorMessage("ERROR => [Alert_FWsam] Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip)); -+#ifdef WIN32 -+ closesocket(stationsocket); -+#else -+ close(stationsocket); -+#endif -+ deletestation=TRUE; -+ } -+ } -+ else /* if the intial key failed to decrypt as well, the keys are not configured the same, and we ignore that SnortSam station. */ -+ { ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip)); -+#ifdef WIN32 -+ closesocket(stationsocket); -+#else -+ close(stationsocket); -+#endif -+ deletestation=TRUE; -+ } -+ } -+ } -+ free(encbuf); /* release of the TwoFishAlloc'ed encryption buffer */ -+ } -+ if(stationtry==0 || deletestation) /* if everything went real well, or real bad... */ -+ { if(deletestation){ /* If it went bad, we remove the station from the list by marking the IP */ -+// station->stationip.s_addr=0; -+ station->stationip.ip32[0]=0; -+ } -+ fwsamlist=fwsamlist->next; -+ } -+ } -+ else -+ fwsamlist=fwsamlist->next; -+ } -+ } -+ else -+ { -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam] Skipping repetitive block.\n"); -+#endif -+ } -+ } -+} -+ -+/* FWsamCheckOut will be called when Snort exists. It de-registeres this snort sensor -+ * from the list of sensor that the SnortSam agent keeps. -+ */ -+void FWsamCheckOut(FWsamStation *station) -+{ FWsamPacket sampacket; -+ SOCKET stationsocket; -+ int i,len; -+ char *encbuf,*decbuf; -+ //unsigned char *encbuf,*decbuf; -+ -+ -+ stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); -+ if(stationsocket==INVALID_SOCKET) -+ FatalError("ERROR => [Alert_FWsam](FWsamCheckOut) Funky socket error (socket)!\n"); -+ if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr))) -+ FatalError("ERROR => [Alert_FWsam](FWsamCheckOut) Could not bind socket!\n"); -+ -+ /* let's connect to the agent */ -+ if(!connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr))) -+ { LogMessage("INFO => [Alert_FWsam](FWsamCheckOut) Disconnecting from host %s.\n",sfip_ntoa(&station->stationip)); -+ /* now build the packet */ -+ station->myseqno+=station->stationseqno; /* increase my seqno */ -+ sampacket.endiancheck=1; -+ sampacket.snortseqno[0]=(char)station->myseqno; -+ sampacket.snortseqno[1]=(char)(station->myseqno>>8); -+ sampacket.fwseqno[0]=(char)station->stationseqno; /* fill station seqno */ -+ sampacket.fwseqno[1]=(char)(station->stationseqno>>8); -+ sampacket.status=FWSAM_STATUS_CHECKOUT; /* checking out... */ -+ sampacket.version=FWSAM_PACKETVERSION; -+ -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Sending CHECKOUT\n"); -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Snort SeqNo: %x\n",station->myseqno); -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Mgmt SeqNo : %x\n",station->stationseqno); -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Status : %i\n",sampacket.status); -+ -+#endif -+ -+ encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get encryption buffer */ -+ len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt packet with current key */ -+ -+ if(send(stationsocket,encbuf,len,0)==len) -+ { i=FWSAM_NETWAIT; -+#ifdef WIN32 -+ ioctlsocket(stationsocket,FIONBIO,&i); /* set non blocking and wait for */ -+#else -+ ioctl(stationsocket,FIONBIO,&i); /* set non blocking and wait for */ -+#endif -+ while(i-- >1) -+ { waitms(10); /* ...wait a maximum of 3 secs for response... */ -+ if(recv(stationsocket,encbuf,len,0)==len) /* ... for the status packet */ -+ i=0; -+ } -+ if(i) /* if we got the packet */ -+ { decbuf=(char *)&sampacket; -+ len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); -+ -+ if(len!=sizeof(FWsamPacket)) /* invalid decryption */ -+ { strcpy(station->stationkey,station->initialkey); /* try initial key */ -+ TwoFishDestroy(station->stationfish); /* toss this fish */ -+ station->stationfish=TwoFishInit(station->stationkey); /* re-initialze TwoFish with initial key */ -+ len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* and try to decrypt again */ -+ LogMessage("INFO => [Alert_FWsam](FWsamCheckOut) Had to use initial key!\n"); -+ } -+ if(len==sizeof(FWsamPacket)) /* valid decryption */ -+ { if(sampacket.version!=FWSAM_PACKETVERSION) /* but don't really care since we are on the way out */ -+ ErrorMessage("WARNING => [Alert_FWsam](FWsamCheckOut) Protocol version error! What the hell, we're quitting anyway! :)\n"); -+ } -+ else -+ ErrorMessage("WARNING => [Alert_FWsam](FWsamCheckOut) Password mismatch! What the hell, we're quitting anyway! :)\n"); -+ } -+ } -+ free(encbuf); /* release TwoFishAlloc'ed buffer */ -+ } -+ else -+ LogMessage("WARNING => [Alert_FWsam] Could not connect to host %s for CheckOut. What the hell, we're quitting anyway! :)\n",sfip_ntoa(&station->stationip)); -+#ifdef WIN32 -+ closesocket(stationsocket); -+#else -+ close(stationsocket); -+#endif -+} -+ -+ -+/* FWSamFree: Disconnects all FW-1 management stations, -+ * closes sockets, and frees the structures. -+ */ -+void FWsamFree(FWsamList *list) -+{ -+ FWsamList *next; -+ -+ while(list) /* Free pointer list for rule type */ -+ { -+ next=list->next; -+ free(list); -+ list=next; -+ } -+ list=FWsamStationList; -+ -+ while(list) /* Free global pointer list and stations */ -+ { -+ next=list->next; -+ if (list->station) -+ { -+ if(list->station->stationip.ip32[0]) -+ //if(list->station->stationip.s_addr) -+ FWsamCheckOut(list->station); /* Send a Check-Out to SnortSam, */ -+ -+ TwoFishDestroy(list->station->stationfish); /* toss the fish, */ -+ free(list->station); /* free station, */ -+ } -+ free(list); /* free pointer, */ -+ list=next; /* and move to next. */ -+ } -+ FWsamStationList=NULL; -+ if(FWsamOptionField) -+ free(FWsamOptionField); -+} -+ -+void AlertFWsamCleanExitFunc(int signal, void *arg) -+{ FWsamList *fwsamlist; -+ -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWsamCleanExitFunc) Exiting...\n"); -+#endif -+ -+ fwsamlist=(FWsamList *)arg; -+ FWsamFree(fwsamlist); /* Free all elements */ -+} -+ -+void AlertFWsamRestartFunc(int signal, void *arg) -+{ FWsamList *fwsamlist; -+ -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam](AlertFWsamRestartFunc) Restarting...\n"); -+#endif -+ -+ fwsamlist=(FWsamList *)arg; -+ FWsamFree(fwsamlist); /* Free all elements */ -+} -+ -+/* This routine registers this Snort sensor with SnortSam. -+ * It will also change the encryption key based on some variables. -+ */ -+int FWsamCheckIn(FWsamStation *station) -+{ int i,len,stationok=TRUE; -+ FWsamPacket sampacket; -+ char *encbuf,*decbuf; -+ //unsigned char *encbuf,*decbuf; -+ SOCKET stationsocket; -+ -+ -+ /* create a socket for the station */ -+ stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); -+ if(stationsocket==INVALID_SOCKET) -+ FatalError("ERROR => [Alert_FWsam](FWsamCheckIn) Funky socket error (socket)!\n"); -+ if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr))) -+ FatalError("ERROR => [Alert_FWsam](FWsamCheckIn) Could not bind socket!\n"); -+ -+ i=TRUE; -+ /* let's connect to the agent */ -+ if(connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr))) -+ LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Could not connect to host %s. Will try later.\n",sfip_ntoa(&station->stationip)); -+ else -+ { LogMessage("INFO => [Alert_FWsam](FWsamCheckIn) Connected to host %s.\n",sfip_ntoa(&station->stationip)); -+ /* now build the packet */ -+ sampacket.endiancheck=1; -+ sampacket.snortseqno[0]=(char)station->myseqno; /* fill my sequence number number */ -+ sampacket.snortseqno[1]=(char)(station->myseqno>>8); /* fill my sequence number number */ -+ sampacket.status=FWSAM_STATUS_CHECKIN; /* let's check in */ -+ sampacket.version=FWSAM_PACKETVERSION; /* set the packet version */ -+ memcpy(sampacket.duration,station->mykeymod,4); /* we'll send SnortSam our key modifier in the duration slot */ -+ /* (the checkin packet is just the plain initial key) */ -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Sending CheckIn\n"); -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Snort SeqNo: %x\n",station->myseqno); -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Mode : %i\n",sampacket.status); -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Version : %i\n",sampacket.version); -+#endif -+ encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get buffer for encryption */ -+ len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt with initial key */ -+ if(send(stationsocket,encbuf,len,0)!=len) /* weird...could not send */ -+ LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Could not send to host %s. Will try again later.\n",sfip_ntoa(&station->stationip)); -+ else -+ { i=FWSAM_NETWAIT; -+#ifdef WIN32 -+ ioctlsocket(stationsocket,FIONBIO,&i); /* set non blocking and wait for */ -+#else -+ ioctl(stationsocket,FIONBIO,&i); /* set non blocking and wait for */ -+#endif -+ while(i-- >1) -+ { waitms(10); /* wait a maximum of 3 secs for response */ -+ if(recv(stationsocket,encbuf,len,0)==len) -+ i=0; -+ } -+ if(!i) /* time up? */ -+ LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip)); -+ else -+ { decbuf=(char *)&sampacket; /* got status packet */ -+ len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt with initial key */ -+ if(len==sizeof(FWsamPacket)) /* valid decryption */ -+ { -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK": -+ sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY": -+ sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC": -+ sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR"); -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Snort SeqNo: %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8)); -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Mgmt SeqNo : %x\n",sampacket.fwseqno[0]|(sampacket.fwseqno[1]<<8)); -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Status : %i\n",sampacket.status); -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Version : %i\n",sampacket.version); -+#endif -+ if(sampacket.version==FWSAM_PACKETVERSION) /* master speaks my language */ -+ { if(sampacket.status==FWSAM_STATUS_OK || sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC) -+ { station->stationseqno=sampacket.fwseqno[0]|(sampacket.fwseqno[1]<<8); /* get stations seqno */ -+ station->lastcontact=(unsigned long)time(NULL); -+ -+ if(sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC) /* generate new keys */ -+ { memcpy(station->fwkeymod,sampacket.duration,4); /* note the key modifier */ -+ FWsamNewStationKey(station,&sampacket); /* and generate new TwoFish keys (with key modifiers) */ -+#ifdef FWSAMDEBUG -+ LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Generated new encryption key...\n"); -+#endif -+ } -+ } -+ else /* weird, got a strange status back */ -+ { ErrorMessage("ERROR => [Alert_FWsam](FWsamCheckIn) Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip)); -+ stationok=FALSE; -+ } -+ } -+ else /* packet version does not match */ -+ { ErrorMessage("ERROR =>[Alert_FWsam](FWsamCheckIn) Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip)); -+ stationok=FALSE; -+ } -+ } -+ else /* key does not match */ -+ { ErrorMessage("ERROR => [Alert_FWsam](FWsamCheckIn) Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip)); -+ stationok=FALSE; -+ } -+ } -+ } -+ free(encbuf); /* release TwoFishAlloc'ed buffer */ -+ } -+#ifdef WIN32 -+ closesocket(stationsocket); -+#else -+ close(stationsocket); -+#endif -+ return stationok; -+} -+#undef FWSAMDEBUG -+ - -Index: snort-2.8.6.1/src/output-plugins/spo_alert_fwsam.h -=================================================================== ---- snort-2.8.6.1/src/output-plugins/spo_alert_fwsam.h (Revision 0) -+++ snort-2.8.6.1/src/output-plugins/spo_alert_fwsam.h (Revision 3) -@@ -0,0 +1,216 @@ -+/* $Id: snortpatchb,v 1.5 2005/10/06 08:50:39 fknobbe Exp $ -+** -+** spo_alert_fwsam.h -+** -+** Copyright (c) 2001-2004 Frank Knobbe -+** -+** This program is free software; you can redistribute it and/or modify -+** it under the terms of the GNU General Public License as published by -+** the Free Software Foundation; either version 2 of the License, or -+** (at your option) any later version. -+** -+** This program is distributed in the hope that it will be useful, -+** but WITHOUT ANY WARRANTY; without even the implied warranty of -+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+** GNU General Public License for more details. -+** -+** You should have received a copy of the GNU General Public License -+** along with this program; if not, write to the Free Software -+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+*/ -+ -+/* This file gets included in plugbase.c when it is integrated into the rest -+ * of the program. -+ * -+ * For more info, see the beginning of spo_alert_fwsam.c -+ * -+ */ -+ -+#ifndef __SPO_FWSAM_H__ -+#define __SPO_FWSAM_H__ -+ -+#include "snort.h" -+#include "rules.h" -+#include "plugbase.h" -+#include "plugin_enum.h" -+#include "fatal.h" -+#include "util.h" -+#include "twofish.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+/* just some compatibility stuff */ -+#ifdef WIN32 -+#if !defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) -+#include -+#endif -+#define waitms(x) Sleep(x) -+ -+#else -+ -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef SOLARIS -+#include -+#endif -+ -+typedef int SOCKET; -+ -+#ifndef INVALID_SOCKET -+#define INVALID_SOCKET -1 -+#endif -+ -+#define waitms(x) usleep((x)*1000) -+ -+#endif -+ -+#ifndef FALSE -+#define FALSE 0 -+#endif -+#ifndef TRUE -+#define TRUE !FALSE -+#endif -+#ifndef bool -+#define bool int -+#endif -+ -+ -+#if defined(_DEBUG) || defined(DEBUG) -+#ifndef FWSAMDEBUG -+#define FWSAMDEBUG -+#endif -+#else -+#endif -+ -+ -+/* Official Snort PlugIn Number has been moved into plugin_enum.h */ -+ -+ -+/* fixed defines */ -+ -+#define FWSAM_DEFAULTPORT 898 /* Default port if user does not specify one in snort.conf */ -+ /* (Was unused last time I checked...) */ -+#define FWSAM_PACKETVERSION 14 /* version of the packet. Will increase with enhancements. */ -+ -+#define FWSAM_STATUS_CHECKIN 1 /* snort to fw */ -+#define FWSAM_STATUS_CHECKOUT 2 -+#define FWSAM_STATUS_BLOCK 3 -+#define FWSAM_STATUS_UNBLOCK 9 -+ -+#define FWSAM_STATUS_OK 4 /* fw to snort */ -+#define FWSAM_STATUS_ERROR 5 -+#define FWSAM_STATUS_NEWKEY 6 -+#define FWSAM_STATUS_RESYNC 7 -+#define FWSAM_STATUS_HOLD 8 -+ -+#define FWSAM_LOG_NONE 0 -+#define FWSAM_LOG_SHORTLOG 1 -+#define FWSAM_LOG_SHORTALERT 2 -+#define FWSAM_LOG_LONGLOG 3 -+#define FWSAM_LOG_LONGALERT 4 -+#define FWSAM_LOG (FWSAM_LOG_SHORTLOG|FWSAM_LOG_SHORTALERT|FWSAM_LOG_LONGLOG|FWSAM_LOG_LONGALERT) -+#define FWSAM_WHO_DST 8 -+#define FWSAM_WHO_SRC 16 -+#define FWSAM_WHO (FWSAM_WHO_DST|FWSAM_WHO_SRC) -+#define FWSAM_HOW_IN 32 -+#define FWSAM_HOW_OUT 64 -+#define FWSAM_HOW_INOUT (FWSAM_HOW_IN|FWSAM_HOW_OUT) -+#define FWSAM_HOW_THIS 128 -+#define FWSAM_HOW (FWSAM_HOW_IN|FWSAM_HOW_OUT|FWSAM_HOW_THIS) -+ -+ -+/* user adjustable defines */ -+ -+#define FWSAM_REPET_BLOCKS 10 /* Snort remembers this amount of last blocks and... */ -+#define FWSAM_REPET_TIME 20 /* ...checks if they fall within this time. If so,... */ -+ /* ...the blocking request is not send. */ -+ -+#define FWSAM_NETWAIT 300 /* 100th of a second. 3 sec timeout for network connections */ -+#define FWSAM_NETHOLD 6000 /* 100th of a second. 60 sec timeout for holding */ -+ -+#define SID_MAPFILE "sid-block.map" -+#define SID_ALT_MAPFILE "sid-fwsam.map" -+ -+#define FWSAM_FANCYFETCH /* This will invoke a fast sid lookup routine */ -+ -+ -+/* vars */ -+ -+typedef struct _FWsamstation /* structure of a mgmt station */ -+{ unsigned short myseqno; -+ unsigned short stationseqno; -+ unsigned char mykeymod[4]; -+ unsigned char fwkeymod[4]; -+ unsigned short stationport; -+ //struct in_addr stationip; -+ sfip_t stationip; -+ struct sockaddr_in localsocketaddr; -+ struct sockaddr_in stationsocketaddr; -+ TWOFISH *stationfish; -+ char initialkey[TwoFish_KEY_LENGTH+2]; -+ char stationkey[TwoFish_KEY_LENGTH+2]; -+ time_t lastcontact; -+/* time_t sleepstart; */ -+} FWsamStation; -+ -+typedef struct _FWsampacket /* 2 blocks (3rd block is header from TwoFish) */ -+{ unsigned short endiancheck; /* 0 */ -+ unsigned char srcip[4]; /* 2 */ -+ unsigned char dstip[4]; /* 6 */ -+ unsigned char duration[4]; /* 10 */ -+ unsigned char snortseqno[2]; /* 14 */ -+ unsigned char fwseqno[2]; /* 16 */ -+ unsigned char srcport[2]; /* 18 */ -+ unsigned char dstport[2]; /* 20 */ -+ unsigned char protocol[2]; /* 22 */ -+ unsigned char fwmode; /* 24 */ -+ unsigned char version; /* 25 */ -+ unsigned char status; /* 26 */ -+ unsigned char sig_id[4]; /* 27 */ -+ unsigned char fluff; /* 31 */ -+} FWsamPacket; /* 32 bytes in size */ -+ -+typedef struct _FWsamoptions /* snort rule options */ -+{ unsigned long sid; -+ unsigned long duration; -+ unsigned char who; -+ unsigned char how; -+ unsigned char loglevel; -+} FWsamOptions; -+ -+typedef struct _FWsamlistpointer -+{ FWsamStation *station; -+ struct _FWsamlistpointer *next; -+} FWsamList; -+ -+ -+/* functions */ -+void AlertFWsamSetup(void); -+void AlertFWsamInit(char *args); -+void AlertFWsamOptionInit(char *args,OptTreeNode *otn,int protocol); -+void AlertFWsamCleanExitFunc(int signal, void *arg); -+void AlertFWsamRestartFunc(int signal, void *arg); -+void AlertFWsam(Packet *p, char *msg, void *arg, Event *event); -+int FWsamCheckIn(FWsamStation *station); -+void FWsamCheckOut(FWsamStation *station); -+void FWsamNewStationKey(FWsamStation *station,FWsamPacket *packet); -+void FWsamFixPacketEndian(FWsamPacket *p); -+unsigned long FWsamParseDuration(char *p); -+void FWsamFree(FWsamList *fwsamlist); -+int FWsamStationExists(FWsamStation *who,FWsamList *list); -+int FWsamReadLine(char *,unsigned long,FILE *); -+void FWsamParseLine(FWsamOptions *,char *); -+FWsamOptions *FWsamGetOption(unsigned long); -+int FWsamParseOption(FWsamOptions *,char *); -+ -+#endif /* __SPO_FWSAM_H__ */ - -Index: snort-2.8.6.1/src/output-plugins/Makefile.am -=================================================================== ---- snort-2.8.6.1/src/output-plugins/Makefile.am (Revision 1) -+++ snort-2.8.6.1/src/output-plugins/Makefile.am (Revision 3) -@@ -11,6 +11,7 @@ - spo_log_tcpdump.h spo_unified.c spo_unified2.c spo_unified.h spo_unified2.h \ - spo_log_ascii.c spo_log_ascii.h spo_alert_sf_socket.h spo_alert_sf_socket.c \ - spo_alert_prelude.c spo_alert_prelude.h spo_alert_arubaaction.c spo_alert_arubaaction.h \ -+spo_alert_fwsam.c spo_alert_fwsam.h \ - spo_alert_test.c spo_alert_test.h - - INCLUDES = @INCLUDES@ -Index: snort-2.8.6.1/src/plugbase.c -=================================================================== ---- snort-2.8.6.1/src/plugbase.c (Revision 1) -+++ snort-2.8.6.1/src/plugbase.c (Revision 3) -@@ -125,6 +125,7 @@ - #endif - - #include "output-plugins/spo_alert_test.h" -+#include "output-plugins/spo_alert_fwsam.h" - - extern ListHead *head_tmp; - extern PreprocConfigFuncNode *preproc_config_funcs; -@@ -1240,6 +1241,7 @@ - #endif - - AlertTestSetup(); -+ AlertFWsamSetup(); - } - - /**************************************************************************** -Index: snort-2.8.6.1/src/Makefile.am -=================================================================== ---- snort-2.8.6.1/src/Makefile.am (Revision 1) -+++ snort-2.8.6.1/src/Makefile.am (Revision 3) -@@ -52,7 +52,8 @@ - detection_filter.c detection_filter.h \ - rate_filter.c rate_filter.h \ - obfuscation.c obfuscation.h \ --rule_option_types.h -+rule_option_types.h \ -+twofish.c twofish.h - - snort_LDADD = output-plugins/libspo.a \ - detection-plugins/libspd.a \ -Index: snort-2.8.6.1/autojunk.sh -=================================================================== ---- snort-2.8.6.1/autojunk.sh (Revision 0) -+++ snort-2.8.6.1/autojunk.sh (Revision 3) -@@ -0,0 +1,7 @@ -+#!/bin/sh -+# the list of commands that need to run before we do a compile -+libtoolize --automake --copy -+aclocal -I m4 -+autoheader -+automake --add-missing --copy -+autoconf - -Index: snort-2.8.6.1/etc/snort.conf -=================================================================== ---- snort-2.8.6.1/etc/snort.conf (Revision 1) -+++ snort-2.8.6.1/etc/snort.conf (Revision 3) -@@ -277,6 +277,32 @@ - # prelude - # output alert_prelude - -+# snortsam -+# In order to cause Snort to send a blocking request to the SnortSam agent, -+# that agent has to be listed, including the port it listens on, -+# and the encryption key it is using. The statement for that is: -+# -+# output alert_fwsam: {SnortSam Station}:{port}/{password} -+# -+# {SnortSam Station}: IP address or host name of the host where SnortSam is running. -+# {port}: The port the remote SnortSam agent listens on. -+# {password}: The password, or key, used for encryption of the -+# communication to the remote agent. -+# -+# At the very least, the IP address or host name of the host running SnortSam -+# needs to be specified. If the port is omitted, it defaults to TCP port 898. -+# If the password is omitted, it defaults to a preset password. -+# (In which case it needs to be omitted on the SnortSam agent as well) -+# -+# More than one host can be specified, but has to be done on the same line. -+# Just separate them with one or more spaces. -+# -+# Examples: -+# -+# output alert_fwsam: firewall/idspassword -+# output alert_fwsam: fw1.domain.tld:898/mykey -+# output alert_fwsam: 192.168.0.1/borderfw 192.168.1.254/wanfw -+ - # metadata reference data. do not modify these lines - include classification.config - include reference.config -- cgit v1.2.3