/[packages]/cauldron/snort/current/SOURCES/snortsam-2.9.0-dlucio.diff
ViewVC logotype

Contents of /cauldron/snort/current/SOURCES/snortsam-2.9.0-dlucio.diff

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30270 - (show annotations) (download)
Fri Jan 21 20:13:20 2011 UTC (13 years, 3 months ago) by dlucio
File size: 114296 byte(s)
imported package snort
1 --- snort-2.9.0/src/twofish.c 1970-01-01 01:00:00.000000000 +0100
2 +++ snort-2.9.0.dlucio/src/twofish.c 2010-10-08 18:05:37.000000000 +0200
3 @@ -0,0 +1,971 @@
4 +/* $Id: twofish.c,v 2.1 2008/12/15 20:36:05 fknobbe Exp $
5 + *
6 + *
7 + * Copyright (C) 1997-2000 The Cryptix Foundation Limited.
8 + * Copyright (C) 2000 Farm9.
9 + * Copyright (C) 2001 Frank Knobbe.
10 + * All rights reserved.
11 + *
12 + * For Cryptix code:
13 + * Use, modification, copying and distribution of this software is subject
14 + * the terms and conditions of the Cryptix General Licence. You should have
15 + * received a copy of the Cryptix General Licence along with this library;
16 + * if not, you can download a copy from http://www.cryptix.org/ .
17 + *
18 + * For Farm9:
19 + * --- jojo@farm9.com, August 2000, converted from Java to C++, added CBC mode and
20 + * ciphertext stealing technique, added AsciiTwofish class for easy encryption
21 + * decryption of text strings
22 + *
23 + * Frank Knobbe <frank@knobbe.us>:
24 + * --- April 2001, converted from C++ to C, prefixed global variables
25 + * with TwoFish, substituted some defines, changed functions to make use of
26 + * variables supplied in a struct, modified and added routines for modular calls.
27 + * Cleaned up the code so that defines are used instead of fixed 16's and 32's.
28 + * Created two general purpose crypt routines for one block and multiple block
29 + * encryption using Joh's CBC code.
30 + * Added crypt routines that use a header (with a magic and data length).
31 + * (Basically a major rewrite).
32 + *
33 + * Note: Routines labeled _TwoFish are private and should not be used
34 + * (or with extreme caution).
35 + *
36 + */
37 +
38 +#ifndef __TWOFISH_LIBRARY_SOURCE__
39 +#define __TWOFISH_LIBRARY_SOURCE__
40 +
41 +#include <string.h>
42 +#include <stdlib.h>
43 +#include <time.h>
44 +#include <ctype.h>
45 +#include <sys/types.h>
46 +
47 +#ifdef WIN32
48 +
49 +#ifndef u_long
50 +typedef unsigned long u_long;
51 +#endif
52 +#ifndef u_int32_t
53 +typedef unsigned long u_int32_t;
54 +#endif
55 +#ifndef u_word
56 +typedef unsigned short u_word;
57 +#endif
58 +#ifndef u_int16_t
59 +typedef unsigned short u_int16_t;
60 +#endif
61 +#ifndef u_char
62 +typedef unsigned char u_char;
63 +#endif
64 +#ifndef u_int8_t
65 +typedef unsigned char u_int8_t;
66 +#endif
67 +
68 +#endif /* WIN32 */
69 +
70 +#include "twofish.h"
71 +
72 +
73 +bool TwoFish_srand=TRUE; /* if TRUE, first call of TwoFishInit will seed rand(); */
74 + /* of TwoFishInit */
75 +
76 +/* Fixed 8x8 permutation S-boxes */
77 +static const u_int8_t TwoFish_P[2][256] =
78 +{
79 + { /* p0 */
80 + 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78,
81 + 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
82 + 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30,
83 + 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
84 + 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE,
85 + 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
86 + 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45,
87 + 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
88 + 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF,
89 + 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
90 + 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED,
91 + 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
92 + 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B,
93 + 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
94 + 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F,
95 + 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
96 + 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17,
97 + 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
98 + 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68,
99 + 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
100 + 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42,
101 + 0x4A, 0x5E, 0xC1, 0xE0
102 + },
103 + { /* p1 */
104 + 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B,
105 + 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
106 + 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B,
107 + 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
108 + 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54,
109 + 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
110 + 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7,
111 + 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
112 + 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF,
113 + 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
114 + 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D,
115 + 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
116 + 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21,
117 + 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
118 + 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E,
119 + 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
120 + 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44,
121 + 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
122 + 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B,
123 + 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
124 + 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56,
125 + 0x55, 0x09, 0xBE, 0x91
126 + }
127 +};
128 +
129 +static bool TwoFish_MDSready=FALSE;
130 +static u_int32_t TwoFish_MDS[4][256]; /* TwoFish_MDS matrix */
131 +
132 +
133 +#define TwoFish_LFSR1(x) (((x)>>1)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/2:0))
134 +#define TwoFish_LFSR2(x) (((x)>>2)^(((x)&0x02)?TwoFish_MDS_GF_FDBK/2:0)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/4:0))
135 +
136 +#define TwoFish_Mx_1(x) ((u_int32_t)(x)) /* force result to dword so << will work */
137 +#define TwoFish_Mx_X(x) ((u_int32_t)((x)^TwoFish_LFSR2(x))) /* 5B */
138 +#define TwoFish_Mx_Y(x) ((u_int32_t)((x)^TwoFish_LFSR1(x)^TwoFish_LFSR2(x))) /* EF */
139 +#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; }
140 +
141 +/*#define TwoFish__b(x,N) (((u_int8_t *)&x)[((N)&3)^TwoFish_ADDR_XOR])*/ /* pick bytes out of a dword */
142 +
143 +#define TwoFish_b0(x) TwoFish__b(x,0) /* extract LSB of u_int32_t */
144 +#define TwoFish_b1(x) TwoFish__b(x,1)
145 +#define TwoFish_b2(x) TwoFish__b(x,2)
146 +#define TwoFish_b3(x) TwoFish__b(x,3) /* extract MSB of u_int32_t */
147 +
148 +u_int8_t TwoFish__b(u_int32_t x,int n)
149 +{ n&=3;
150 + while(n-->0)
151 + x>>=8;
152 + return (u_int8_t)x;
153 +}
154 +
155 +
156 +/* TwoFish Initialization
157 + *
158 + * This routine generates a global data structure for use with TwoFish,
159 + * initializes important values (such as subkeys, sBoxes), generates subkeys
160 + * and precomputes the MDS matrix if not already done.
161 + *
162 + * Input: User supplied password (will be appended by default password of 'SnortHas2FishEncryptionRoutines!')
163 + *
164 + * Output: Pointer to TWOFISH structure. This data structure contains key dependent data.
165 + * This pointer is used with all other crypt functions.
166 + */
167 +
168 +TWOFISH *TwoFishInit(char *userkey)
169 +{ TWOFISH *tfdata;
170 + int i,x,m;
171 + char tkey[TwoFish_KEY_LENGTH+40];
172 +
173 + tfdata=malloc(sizeof(TWOFISH)); /* allocate the TwoFish structure */
174 + if(tfdata!=NULL)
175 + { if(*userkey)
176 + { strncpy(tkey,userkey,TwoFish_KEY_LENGTH); /* use first 32 chars of user supplied password */
177 + tkey[TwoFish_KEY_LENGTH]=0; /* make sure it wasn't more */
178 + }
179 + else
180 + strcpy(tkey,TwoFish_DEFAULT_PW); /* if no key defined, use default password */
181 + for(i=0,x=0,m=strlen(tkey);i<TwoFish_KEY_LENGTH;i++) /* copy into data structure */
182 + { tfdata->key[i]=tkey[x++]; /* fill the whole keyspace with repeating key. */
183 + if(x==m)
184 + x=0;
185 + }
186 +
187 + if(!TwoFish_MDSready)
188 + _TwoFish_PrecomputeMDSmatrix(); /* "Wake Up, Neo" */
189 + _TwoFish_MakeSubKeys(tfdata); /* generate subkeys */
190 + _TwoFish_ResetCBC(tfdata); /* reset the CBC */
191 + tfdata->output=NULL; /* nothing to output yet */
192 + tfdata->dontflush=FALSE; /* reset decrypt skip block flag */
193 + if(TwoFish_srand)
194 + { TwoFish_srand=FALSE;
195 + srand(time(NULL));
196 + }
197 + }
198 + return tfdata; /* return the data pointer */
199 +}
200 +
201 +
202 +void TwoFishDestroy(TWOFISH *tfdata)
203 +{ if(tfdata!=NULL)
204 + free(tfdata);
205 +}
206 +
207 +
208 +/* en/decryption with CBC mode */
209 +unsigned long _TwoFish_CryptRawCBC(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata)
210 +{ unsigned long rl;
211 +
212 + rl=len; /* remember how much data to crypt. */
213 + while(len>TwoFish_BLOCK_SIZE) /* and now we process block by block. */
214 + { _TwoFish_BlockCrypt(in,out,TwoFish_BLOCK_SIZE,decrypt,tfdata); /* de/encrypt it. */
215 + in+=TwoFish_BLOCK_SIZE; /* adjust pointers. */
216 + out+=TwoFish_BLOCK_SIZE;
217 + len-=TwoFish_BLOCK_SIZE;
218 + }
219 + if(len>0) /* if we have less than a block left... */
220 + _TwoFish_BlockCrypt(in,out,len,decrypt,tfdata); /* ...then we de/encrypt that too. */
221 + if(tfdata->qBlockDefined && !tfdata->dontflush) /* in case len was exactly one block... */
222 + _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); /* ...we need to write the... */
223 + /* ...remaining bytes of the buffer */
224 + return rl;
225 +}
226 +
227 +/* en/decryption on one block only */
228 +unsigned long _TwoFish_CryptRaw16(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata)
229 +{ /* qBlockPlain already zero'ed through ResetCBC */
230 + memcpy(tfdata->qBlockPlain,in,len); /* toss the data into it. */
231 + _TwoFish_BlockCrypt16(tfdata->qBlockPlain,tfdata->qBlockCrypt,decrypt,tfdata); /* encrypt just that block without CBC. */
232 + memcpy(out,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE); /* and return what we got */
233 + return TwoFish_BLOCK_SIZE;
234 +}
235 +
236 +/* en/decryption without reset of CBC and output assignment */
237 +unsigned long _TwoFish_CryptRaw(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata)
238 +{
239 + if(in!=NULL && out!=NULL && len>0 && tfdata!=NULL) /* if we have valid data, then... */
240 + { if(len>TwoFish_BLOCK_SIZE) /* ...check if we have more than one block. */
241 + return _TwoFish_CryptRawCBC(in,out,len,decrypt,tfdata); /* if so, use the CBC routines... */
242 + else
243 + return _TwoFish_CryptRaw16(in,out,len,decrypt,tfdata); /* ...otherwise just do one block. */
244 + }
245 + return 0;
246 +}
247 +
248 +
249 +/* TwoFish Raw Encryption
250 + *
251 + * Does not use header, but does use CBC (if more than one block has to be encrypted).
252 + *
253 + * Input: Pointer to the buffer of the plaintext to be encrypted.
254 + * Pointer to the buffer receiving the ciphertext.
255 + * The length of the plaintext buffer.
256 + * The TwoFish structure.
257 + *
258 + * Output: The amount of bytes encrypted if successful, otherwise 0.
259 + */
260 +
261 +unsigned long TwoFishEncryptRaw(char *in,
262 + char *out,
263 + unsigned long len,
264 + TWOFISH *tfdata)
265 +{ _TwoFish_ResetCBC(tfdata); /* reset CBC flag. */
266 + tfdata->output=out; /* output straight into output buffer. */
267 + return _TwoFish_CryptRaw(in,out,len,FALSE,tfdata); /* and go for it. */
268 +}
269 +
270 +/* TwoFish Raw Decryption
271 + *
272 + * Does not use header, but does use CBC (if more than one block has to be decrypted).
273 + *
274 + * Input: Pointer to the buffer of the ciphertext to be decrypted.
275 + * Pointer to the buffer receiving the plaintext.
276 + * The length of the ciphertext buffer (at least one cipher block).
277 + * The TwoFish structure.
278 + *
279 + * Output: The amount of bytes decrypted if successful, otherwise 0.
280 + */
281 +
282 +unsigned long TwoFishDecryptRaw(char *in,
283 + char *out,
284 + unsigned long len,
285 + TWOFISH *tfdata)
286 +{ _TwoFish_ResetCBC(tfdata); /* reset CBC flag. */
287 + tfdata->output=out; /* output straight into output buffer. */
288 + return _TwoFish_CryptRaw(in,out,len,TRUE,tfdata); /* and go for it. */
289 +}
290 +
291 +/* TwoFish Free
292 + *
293 + * Free's the allocated buffer.
294 + *
295 + * Input: Pointer to the TwoFish structure
296 + *
297 + * Output: (none)
298 + */
299 +
300 +void TwoFishFree(TWOFISH *tfdata)
301 +{ if(tfdata->output!=NULL) /* if a valid buffer is present... */
302 + { free(tfdata->output); /* ...then we free it for you... */
303 + tfdata->output=NULL; /* ...and mark as such. */
304 + }
305 +}
306 +
307 +/* TwoFish Set Output
308 + *
309 + * If you want to allocate the output buffer yourself,
310 + * then you can set it with this function.
311 + *
312 + * Input: Pointer to your output buffer
313 + * Pointer to the TwoFish structure
314 + *
315 + * Output: (none)
316 + */
317 +
318 +void TwoFishSetOutput(char *outp,TWOFISH *tfdata)
319 +{ tfdata->output=outp; /* (do we really need a function for this?) */
320 +}
321 +
322 +/* TwoFish Alloc
323 + *
324 + * Allocates enough memory for the output buffer that would be required
325 + *
326 + * Input: Length of the plaintext.
327 + * Boolean flag for BinHex Output.
328 + * Pointer to the TwoFish structure.
329 + *
330 + * Output: Returns a pointer to the memory allocated.
331 + */
332 +
333 +void *TwoFishAlloc(unsigned long len,bool binhex,bool decrypt,TWOFISH *tfdata)
334 +{
335 +/* TwoFishFree(tfdata); */ /* (don't for now) discard whatever was allocated earlier. */
336 + if(decrypt) /* if decrypting... */
337 + { if(binhex) /* ...and input is binhex encoded... */
338 + len/=2; /* ...use half as much for output. */
339 + len-=TwoFish_BLOCK_SIZE; /* Also, subtract the size of the header. */
340 + }
341 + else
342 + { len+=TwoFish_BLOCK_SIZE; /* the size is just increased by the header... */
343 + if(binhex)
344 + len*=2; /* ...and doubled if output is to be binhexed. */
345 + }
346 + tfdata->output=malloc(len+TwoFish_BLOCK_SIZE);/* grab some memory...plus some extra (it's running over somewhere, crashes without extra padding) */
347 +
348 + return tfdata->output; /* ...and return to caller. */
349 +}
350 +
351 +/* bin2hex and hex2bin conversion */
352 +void _TwoFish_BinHex(u_int8_t *buf,unsigned long len,bool bintohex)
353 +{ u_int8_t *pi,*po,c;
354 +
355 + if(bintohex)
356 + { 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. */
357 + { c=*pi; /* grab value. */
358 + c&=15; /* use lower 4 bits. */
359 + if(c>9) /* convert to ascii. */
360 + c+=('a'-10);
361 + else
362 + c+='0';
363 + *po--=c; /* set the lower nibble. */
364 + c=*pi; /* grab value again. */
365 + c>>=4; /* right shift 4 bits. */
366 + c&=15; /* make sure we only have 4 bits. */
367 + if(c>9) /* convert to ascii. */
368 + c+=('a'-10);
369 + else
370 + c+='0';
371 + *po=c; /* set the higher nibble. */
372 + } /* and keep going. */
373 + }
374 + else
375 + { for(pi=buf,po=buf;len>0;pi++,po++,len-=2) /* let's start from the beginning of the hex block. */
376 + { c=tolower(*pi++)-'0'; /* grab higher nibble. */
377 + if(c>9) /* convert to value. */
378 + c-=('0'-9);
379 + *po=c<<4; /* left shit 4 bits. */
380 + c=tolower(*pi)-'0'; /* grab lower nibble. */
381 + if(c>9) /* convert to value. */
382 + c-=('0'-9);
383 + *po|=c; /* and add to value. */
384 + }
385 + }
386 +}
387 +
388 +
389 +/* TwoFish Encryption
390 + *
391 + * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
392 + * this routine will alloc the memory. In addition, it will include a small 'header'
393 + * containing the magic and some salt. That way the decrypt routine can check if the
394 + * packet got decrypted successfully, and return 0 instead of garbage.
395 + *
396 + * Input: Pointer to the buffer of the plaintext to be encrypted.
397 + * Pointer to the pointer to the buffer receiving the ciphertext.
398 + * The pointer either points to user allocated output buffer space, or to NULL, in which case
399 + * this routine will set the pointer to the buffer allocated through the struct.
400 + * The length of the plaintext buffer.
401 + * Can be -1 if the input is a null terminated string, in which case we'll count for you.
402 + * Boolean flag for BinHex Output (if used, output will be twice as large as input).
403 + * Note: BinHex conversion overwrites (converts) input buffer!
404 + * The TwoFish structure.
405 + *
406 + * Output: The amount of bytes encrypted if successful, otherwise 0.
407 + */
408 +
409 +unsigned long TwoFishEncrypt(char *in,
410 + char **out,
411 + signed long len,
412 + bool binhex,
413 + TWOFISH *tfdata)
414 +{ unsigned long ilen,olen;
415 +
416 +
417 + if(len== -1) /* if we got -1 for len, we'll assume IN is a... */
418 + ilen=strlen(in); /* ...\0 terminated string and figure len out ourselves... */
419 + else
420 + ilen=len; /* ...otherwise we trust you supply a correct length. */
421 +
422 + if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */
423 + { if(*out==NULL) /* if OUT points to a NULL pointer... */
424 + *out=TwoFishAlloc(ilen,binhex,FALSE,tfdata); /* ...we'll (re-)allocate buffer space. */
425 + if(*out!=NULL)
426 + { tfdata->output=*out; /* set output buffer. */
427 + tfdata->header.salt=rand()*65536+rand(); /* toss in some salt. */
428 + tfdata->header.length[0]= (u_int8_t)(ilen);
429 + tfdata->header.length[1]= (u_int8_t)(ilen>>8);
430 + tfdata->header.length[2]= (u_int8_t)(ilen>>16);
431 + tfdata->header.length[3]= (u_int8_t)(ilen>>24);
432 + memcpy(tfdata->header.magic,TwoFish_MAGIC,TwoFish_MAGIC_LEN); /* set the magic. */
433 + olen=TwoFish_BLOCK_SIZE; /* set output counter. */
434 + _TwoFish_ResetCBC(tfdata); /* reset the CBC flag */
435 + _TwoFish_BlockCrypt((u_int8_t *)&(tfdata->header),*out,olen,FALSE,tfdata); /* encrypt first block (without flush on 16 byte boundary). */
436 + olen+=_TwoFish_CryptRawCBC(in,*out+TwoFish_BLOCK_SIZE,ilen,FALSE,tfdata); /* and encrypt the rest (we do not reset the CBC flag). */
437 + if(binhex) /* if binhex... */
438 + { _TwoFish_BinHex(*out,olen,TRUE); /* ...convert output to binhex... */
439 + olen*=2; /* ...and size twice as large. */
440 + }
441 + tfdata->output=*out;
442 + return olen;
443 + }
444 + }
445 + return 0;
446 +}
447 +
448 +/* TwoFish Decryption
449 + *
450 + * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
451 + * this routine will alloc the memory. In addition, it will check the small 'header'
452 + * containing the magic. If magic does not match we return 0. Otherwise we return the
453 + * amount of bytes decrypted (should be the same as the length in the header).
454 + *
455 + * Input: Pointer to the buffer of the ciphertext to be decrypted.
456 + * Pointer to the pointer to the buffer receiving the plaintext.
457 + * The pointer either points to user allocated output buffer space, or to NULL, in which case
458 + * this routine will set the pointer to the buffer allocated through the struct.
459 + * The length of the ciphertext buffer.
460 + * Can be -1 if the input is a null terminated binhex string, in which case we'll count for you.
461 + * Boolean flag for BinHex Input (if used, plaintext will be half as large as input).
462 + * Note: BinHex conversion overwrites (converts) input buffer!
463 + * The TwoFish structure.
464 + *
465 + * Output: The amount of bytes decrypted if successful, otherwise 0.
466 + */
467 +
468 +unsigned long TwoFishDecrypt(char *in,
469 + char **out,
470 + signed long len,
471 + bool binhex,
472 + TWOFISH *tfdata)
473 +{ unsigned long ilen,elen,olen;
474 + const u_int8_t cmagic[TwoFish_MAGIC_LEN]=TwoFish_MAGIC;
475 + u_int8_t *tbuf;
476 +
477 +
478 +
479 + if(len== -1) /* if we got -1 for len, we'll assume IN is... */
480 + ilen=strlen(in); /* ...\0 terminated binhex and figure len out ourselves... */
481 + else
482 + ilen=len; /* ...otherwise we trust you supply a correct length. */
483 +
484 + if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */
485 + { if(*out==NULL) /* if OUT points to a NULL pointer... */
486 + *out=TwoFishAlloc(ilen,binhex,TRUE,tfdata); /* ...we'll (re-)allocate buffer space. */
487 + if(*out!=NULL)
488 + { if(binhex) /* if binhex... */
489 + { _TwoFish_BinHex(in,ilen,FALSE); /* ...convert input to values... */
490 + ilen/=2; /* ...and size half as much. */
491 + }
492 + _TwoFish_ResetCBC(tfdata); /* reset the CBC flag. */
493 +
494 + tbuf=(u_int8_t *)malloc(ilen+TwoFish_BLOCK_SIZE); /* get memory for data and header. */
495 + if(tbuf==NULL)
496 + return 0;
497 + tfdata->output=tbuf; /* set output to temp buffer. */
498 +
499 + olen=_TwoFish_CryptRawCBC(in,tbuf,ilen,TRUE,tfdata)-TwoFish_BLOCK_SIZE; /* decrypt the whole thing. */
500 + memcpy(&(tfdata->header),tbuf,TwoFish_BLOCK_SIZE); /* copy first block into header. */
501 + tfdata->output=*out;
502 + for(elen=0;elen<TwoFish_MAGIC_LEN;elen++) /* compare magic. */
503 + if(tfdata->header.magic[elen]!=cmagic[elen])
504 + break;
505 + if(elen==TwoFish_MAGIC_LEN) /* if magic matches then... */
506 + { elen=(tfdata->header.length[0]) |
507 + (tfdata->header.length[1])<<8 |
508 + (tfdata->header.length[2])<<16 |
509 + (tfdata->header.length[3])<<24; /* .. we know how much to expect. */
510 + if(elen>olen) /* adjust if necessary. */
511 + elen=olen;
512 + memcpy(*out,tbuf+TwoFish_BLOCK_SIZE,elen); /* copy data into intended output. */
513 + free(tbuf);
514 + return elen;
515 + }
516 + free(tbuf);
517 + }
518 + }
519 + return 0;
520 +}
521 +
522 +void _TwoFish_PrecomputeMDSmatrix(void) /* precompute the TwoFish_MDS matrix */
523 +{ u_int32_t m1[2];
524 + u_int32_t mX[2];
525 + u_int32_t mY[2];
526 + u_int32_t i, j;
527 +
528 + for (i = 0; i < 256; i++)
529 + { j = TwoFish_P[0][i] & 0xFF; /* compute all the matrix elements */
530 + m1[0] = j;
531 + mX[0] = TwoFish_Mx_X( j ) & 0xFF;
532 + mY[0] = TwoFish_Mx_Y( j ) & 0xFF;
533 +
534 + j = TwoFish_P[1][i] & 0xFF;
535 + m1[1] = j;
536 + mX[1] = TwoFish_Mx_X( j ) & 0xFF;
537 + mY[1] = TwoFish_Mx_Y( j ) & 0xFF;
538 +
539 + TwoFish_MDS[0][i] = m1[TwoFish_P_00] | /* fill matrix w/ above elements */
540 + mX[TwoFish_P_00] << 8 |
541 + mY[TwoFish_P_00] << 16 |
542 + mY[TwoFish_P_00] << 24;
543 + TwoFish_MDS[1][i] = mY[TwoFish_P_10] |
544 + mY[TwoFish_P_10] << 8 |
545 + mX[TwoFish_P_10] << 16 |
546 + m1[TwoFish_P_10] << 24;
547 + TwoFish_MDS[2][i] = mX[TwoFish_P_20] |
548 + mY[TwoFish_P_20] << 8 |
549 + m1[TwoFish_P_20] << 16 |
550 + mY[TwoFish_P_20] << 24;
551 + TwoFish_MDS[3][i] = mX[TwoFish_P_30] |
552 + m1[TwoFish_P_30] << 8 |
553 + mY[TwoFish_P_30] << 16 |
554 + mX[TwoFish_P_30] << 24;
555 + }
556 + TwoFish_MDSready=TRUE;
557 +}
558 +
559 +
560 +void _TwoFish_MakeSubKeys(TWOFISH *tfdata) /* Expand a user-supplied key material into a session key. */
561 +{ u_int32_t k64Cnt = TwoFish_KEY_LENGTH / 8;
562 + u_int32_t k32e[4]; /* even 32-bit entities */
563 + u_int32_t k32o[4]; /* odd 32-bit entities */
564 + u_int32_t sBoxKey[4];
565 + u_int32_t offset,i,j;
566 + u_int32_t A, B, q=0;
567 + u_int32_t k0,k1,k2,k3;
568 + u_int32_t b0,b1,b2,b3;
569 +
570 + /* split user key material into even and odd 32-bit entities and */
571 + /* compute S-box keys using (12, 8) Reed-Solomon code over GF(256) */
572 +
573 +
574 + for (offset=0,i=0,j=k64Cnt-1;i<4 && offset<TwoFish_KEY_LENGTH;i++,j--)
575 + { k32e[i] = tfdata->key[offset++];
576 + k32e[i]|= tfdata->key[offset++]<<8;
577 + k32e[i]|= tfdata->key[offset++]<<16;
578 + k32e[i]|= tfdata->key[offset++]<<24;
579 + k32o[i] = tfdata->key[offset++];
580 + k32o[i]|= tfdata->key[offset++]<<8;
581 + k32o[i]|= tfdata->key[offset++]<<16;
582 + k32o[i]|= tfdata->key[offset++]<<24;
583 + sBoxKey[j] = _TwoFish_RS_MDS_Encode( k32e[i], k32o[i] ); /* reverse order */
584 + }
585 +
586 + /* compute the round decryption subkeys for PHT. these same subkeys */
587 + /* will be used in encryption but will be applied in reverse order. */
588 + i=0;
589 + while(i < TwoFish_TOTAL_SUBKEYS)
590 + { A = _TwoFish_F32( k64Cnt, q, k32e ); /* A uses even key entities */
591 + q += TwoFish_SK_BUMP;
592 +
593 + B = _TwoFish_F32( k64Cnt, q, k32o ); /* B uses odd key entities */
594 + q += TwoFish_SK_BUMP;
595 +
596 + B = B << 8 | B >> 24;
597 +
598 + A += B;
599 + tfdata->subKeys[i++] = A; /* combine with a PHT */
600 +
601 + A += B;
602 + tfdata->subKeys[i++] = A << TwoFish_SK_ROTL | A >> (32-TwoFish_SK_ROTL);
603 + }
604 +
605 + /* fully expand the table for speed */
606 + k0 = sBoxKey[0];
607 + k1 = sBoxKey[1];
608 + k2 = sBoxKey[2];
609 + k3 = sBoxKey[3];
610 +
611 + for (i = 0; i < 256; i++)
612 + { b0 = b1 = b2 = b3 = i;
613 + switch (k64Cnt & 3)
614 + { case 1: /* 64-bit keys */
615 + tfdata->sBox[ 2*i ] = TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0]) ^ TwoFish_b0(k0)];
616 + tfdata->sBox[ 2*i+1] = TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1]) ^ TwoFish_b1(k0)];
617 + tfdata->sBox[0x200+2*i ] = TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2]) ^ TwoFish_b2(k0)];
618 + tfdata->sBox[0x200+2*i+1] = TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3]) ^ TwoFish_b3(k0)];
619 + break;
620 + case 0: /* 256-bit keys (same as 4) */
621 + b0 = (TwoFish_P[TwoFish_P_04][b0]) ^ TwoFish_b0(k3);
622 + b1 = (TwoFish_P[TwoFish_P_14][b1]) ^ TwoFish_b1(k3);
623 + b2 = (TwoFish_P[TwoFish_P_24][b2]) ^ TwoFish_b2(k3);
624 + b3 = (TwoFish_P[TwoFish_P_34][b3]) ^ TwoFish_b3(k3);
625 + case 3: /* 192-bit keys */
626 + b0 = (TwoFish_P[TwoFish_P_03][b0]) ^ TwoFish_b0(k2);
627 + b1 = (TwoFish_P[TwoFish_P_13][b1]) ^ TwoFish_b1(k2);
628 + b2 = (TwoFish_P[TwoFish_P_23][b2]) ^ TwoFish_b2(k2);
629 + b3 = (TwoFish_P[TwoFish_P_33][b3]) ^ TwoFish_b3(k2);
630 + case 2: /* 128-bit keys */
631 + tfdata->sBox[ 2*i ]=
632 + TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0]) ^
633 + TwoFish_b0(k1)]) ^ TwoFish_b0(k0)];
634 +
635 + tfdata->sBox[ 2*i+1]=
636 + TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1]) ^
637 + TwoFish_b1(k1)]) ^ TwoFish_b1(k0)];
638 +
639 + tfdata->sBox[0x200+2*i ]=
640 + TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2]) ^
641 + TwoFish_b2(k1)]) ^ TwoFish_b2(k0)];
642 +
643 + tfdata->sBox[0x200+2*i+1]=
644 + TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3]) ^
645 + TwoFish_b3(k1)]) ^ TwoFish_b3(k0)];
646 + }
647 + }
648 +}
649 +
650 +
651 +/**
652 + * Encrypt or decrypt exactly one block of plaintext in CBC mode.
653 + * Use "ciphertext stealing" technique described on pg. 196
654 + * of "Applied Cryptography" to encrypt the final partial
655 + * (i.e. <16 byte) block if necessary.
656 + *
657 + * jojo: the "ciphertext stealing" requires we read ahead and have
658 + * special handling for the last two blocks. Because of this, the
659 + * output from the TwoFish algorithm is handled internally here.
660 + * It would be better to have a higher level handle this as well as
661 + * CBC mode. Unfortunately, I've mixed the two together, which is
662 + * pretty crappy... The Java version separates these out correctly.
663 + *
664 + * fknobbe: I have reduced the CBC mode to work on memory buffer only.
665 + * Higher routines should use an intermediate buffer and handle
666 + * their output seperately (mainly so the data can be flushed
667 + * in one chunk, not seperate 16 byte blocks...)
668 + *
669 + * @param in The plaintext.
670 + * @param out The ciphertext
671 + * @param size how much to encrypt
672 + * @param tfdata: Pointer to the global data structure containing session keys.
673 + * @return none
674 + */
675 +void _TwoFish_BlockCrypt(u_int8_t *in,u_int8_t *out,unsigned long size,int decrypt,TWOFISH *tfdata)
676 +{ u_int8_t PnMinusOne[TwoFish_BLOCK_SIZE];
677 + u_int8_t CnMinusOne[TwoFish_BLOCK_SIZE];
678 + u_int8_t CBCplusCprime[TwoFish_BLOCK_SIZE];
679 + u_int8_t Pn[TwoFish_BLOCK_SIZE];
680 + u_int8_t *p,*pout;
681 + unsigned long i;
682 +
683 + /* here is where we implement CBC mode and cipher block stealing */
684 + if(size==TwoFish_BLOCK_SIZE)
685 + { /* if we are encrypting, CBC means we XOR the plain text block with the */
686 + /* previous cipher text block before encrypting */
687 + if(!decrypt && tfdata->qBlockDefined)
688 + { for(p=in,i=0;i<TwoFish_BLOCK_SIZE;i++,p++)
689 + Pn[i]=*p ^ tfdata->qBlockCrypt[i]; /* FK: I'm copying the xor'ed input into Pn... */
690 + }
691 + else
692 + memcpy(Pn,in,TwoFish_BLOCK_SIZE); /* FK: same here. we work of Pn all the time. */
693 +
694 + /* TwoFish block level encryption or decryption */
695 + _TwoFish_BlockCrypt16(Pn,out,decrypt,tfdata);
696 +
697 + /* if we are decrypting, CBC means we XOR the result of the decryption */
698 + /* with the previous cipher text block to get the resulting plain text */
699 + if(decrypt && tfdata->qBlockDefined)
700 + { for (p=out,i=0;i<TwoFish_BLOCK_SIZE;i++,p++)
701 + *p^=tfdata->qBlockPlain[i];
702 + }
703 +
704 + /* save the input and output blocks, since CBC needs these for XOR */
705 + /* operations */
706 + _TwoFish_qBlockPush(Pn,out,tfdata);
707 + }
708 + else
709 + { /* cipher block stealing, we are at Pn, */
710 + /* but since Cn-1 must now be replaced with CnC' */
711 + /* we pop it off, and recalculate Cn-1 */
712 +
713 + if(decrypt)
714 + { /* We are on an odd block, and had to do cipher block stealing, */
715 + /* so the PnMinusOne has to be derived differently. */
716 +
717 + /* First we decrypt it into CBC and C' */
718 + _TwoFish_qBlockPop(CnMinusOne,PnMinusOne,tfdata);
719 + _TwoFish_BlockCrypt16(CnMinusOne,CBCplusCprime,decrypt,tfdata);
720 +
721 + /* we then xor the first few bytes with the "in" bytes (Cn) */
722 + /* to recover Pn, which we put in out */
723 + for(p=in,pout=out,i=0;i<size;i++,p++,pout++)
724 + *pout=*p ^ CBCplusCprime[i];
725 +
726 + /* We now recover the original CnMinusOne, which consists of */
727 + /* the first "size" bytes of "in" data, followed by the */
728 + /* "Cprime" portion of CBCplusCprime */
729 + for(p=in,i=0;i<size;i++,p++)
730 + CnMinusOne[i]=*p;
731 + for(;i<TwoFish_BLOCK_SIZE;i++)
732 + CnMinusOne[i]=CBCplusCprime[i];
733 +
734 + /* we now decrypt CnMinusOne to get PnMinusOne xored with Cn-2 */
735 + _TwoFish_BlockCrypt16(CnMinusOne,PnMinusOne,decrypt,tfdata);
736 +
737 + for(i=0;i<TwoFish_BLOCK_SIZE;i++)
738 + PnMinusOne[i]=PnMinusOne[i] ^ tfdata->prevCipher[i];
739 +
740 + /* So at this point, out has PnMinusOne */
741 + _TwoFish_qBlockPush(CnMinusOne,PnMinusOne,tfdata);
742 + _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata);
743 + _TwoFish_FlushOutput(out,size,tfdata);
744 + }
745 + else
746 + { _TwoFish_qBlockPop(PnMinusOne,CnMinusOne,tfdata);
747 + memset(Pn,0,TwoFish_BLOCK_SIZE);
748 + memcpy(Pn,in,size);
749 + for(i=0;i<TwoFish_BLOCK_SIZE;i++)
750 + Pn[i]^=CnMinusOne[i];
751 + _TwoFish_BlockCrypt16(Pn,out,decrypt,tfdata);
752 + _TwoFish_qBlockPush(Pn,out,tfdata); /* now we officially have Cn-1 */
753 + _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata);
754 + _TwoFish_FlushOutput(CnMinusOne,size,tfdata); /* old Cn-1 becomes new partial Cn */
755 + }
756 + tfdata->qBlockDefined=FALSE;
757 + }
758 +}
759 +
760 +void _TwoFish_qBlockPush(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata)
761 +{ if(tfdata->qBlockDefined)
762 + _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata);
763 + memcpy(tfdata->prevCipher,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE);
764 + memcpy(tfdata->qBlockPlain,p,TwoFish_BLOCK_SIZE);
765 + memcpy(tfdata->qBlockCrypt,c,TwoFish_BLOCK_SIZE);
766 + tfdata->qBlockDefined=TRUE;
767 +}
768 +
769 +void _TwoFish_qBlockPop(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata)
770 +{ memcpy(p,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE );
771 + memcpy(c,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE );
772 + tfdata->qBlockDefined=FALSE;
773 +}
774 +
775 +/* Reset's the CBC flag and zero's PrevCipher (through qBlockPlain) (important) */
776 +void _TwoFish_ResetCBC(TWOFISH *tfdata)
777 +{ tfdata->qBlockDefined=FALSE;
778 + memset(tfdata->qBlockPlain,0,TwoFish_BLOCK_SIZE);
779 +}
780 +
781 +void _TwoFish_FlushOutput(u_int8_t *b,unsigned long len,TWOFISH *tfdata)
782 +{ unsigned long i;
783 +
784 + for(i=0;i<len && !tfdata->dontflush;i++)
785 + *tfdata->output++ = *b++;
786 + tfdata->dontflush=FALSE;
787 +}
788 +
789 +void _TwoFish_BlockCrypt16(u_int8_t *in,u_int8_t *out,bool decrypt,TWOFISH *tfdata)
790 +{ u_int32_t x0,x1,x2,x3;
791 + u_int32_t k,t0,t1,R;
792 +
793 +
794 + x0=*in++;
795 + x0|=(*in++ << 8 );
796 + x0|=(*in++ << 16);
797 + x0|=(*in++ << 24);
798 + x1=*in++;
799 + x1|=(*in++ << 8 );
800 + x1|=(*in++ << 16);
801 + x1|=(*in++ << 24);
802 + x2=*in++;
803 + x2|=(*in++ << 8 );
804 + x2|=(*in++ << 16);
805 + x2|=(*in++ << 24);
806 + x3=*in++;
807 + x3|=(*in++ << 8 );
808 + x3|=(*in++ << 16);
809 + x3|=(*in++ << 24);
810 +
811 + if(decrypt)
812 + { x0 ^= tfdata->subKeys[4]; /* swap input and output whitening keys when decrypting */
813 + x1 ^= tfdata->subKeys[5];
814 + x2 ^= tfdata->subKeys[6];
815 + x3 ^= tfdata->subKeys[7];
816 +
817 + k = 7+(TwoFish_ROUNDS*2);
818 + for (R = 0; R < TwoFish_ROUNDS; R += 2)
819 + { t0 = _TwoFish_Fe320( tfdata->sBox, x0);
820 + t1 = _TwoFish_Fe323( tfdata->sBox, x1);
821 + x3 ^= t0 + (t1<<1) + tfdata->subKeys[k--];
822 + x3 = x3 >> 1 | x3 << 31;
823 + x2 = x2 << 1 | x2 >> 31;
824 + x2 ^= t0 + t1 + tfdata->subKeys[k--];
825 +
826 + t0 = _TwoFish_Fe320( tfdata->sBox, x2);
827 + t1 = _TwoFish_Fe323( tfdata->sBox, x3);
828 + x1 ^= t0 + (t1<<1) + tfdata->subKeys[k--];
829 + x1 = x1 >> 1 | x1 << 31;
830 + x0 = x0 << 1 | x0 >> 31;
831 + x0 ^= t0 + t1 + tfdata->subKeys[k--];
832 + }
833 +
834 + x2 ^= tfdata->subKeys[0];
835 + x3 ^= tfdata->subKeys[1];
836 + x0 ^= tfdata->subKeys[2];
837 + x1 ^= tfdata->subKeys[3];
838 + }
839 + else
840 + { x0 ^= tfdata->subKeys[0];
841 + x1 ^= tfdata->subKeys[1];
842 + x2 ^= tfdata->subKeys[2];
843 + x3 ^= tfdata->subKeys[3];
844 +
845 + k = 8;
846 + for (R = 0; R < TwoFish_ROUNDS; R += 2)
847 + { t0 = _TwoFish_Fe320( tfdata->sBox, x0);
848 + t1 = _TwoFish_Fe323( tfdata->sBox, x1);
849 + x2 ^= t0 + t1 + tfdata->subKeys[k++];
850 + x2 = x2 >> 1 | x2 << 31;
851 + x3 = x3 << 1 | x3 >> 31;
852 + x3 ^= t0 + (t1<<1) + tfdata->subKeys[k++];
853 +
854 + t0 = _TwoFish_Fe320( tfdata->sBox, x2);
855 + t1 = _TwoFish_Fe323( tfdata->sBox, x3);
856 + x0 ^= t0 + t1 + tfdata->subKeys[k++];
857 + x0 = x0 >> 1 | x0 << 31;
858 + x1 = x1 << 1 | x1 >> 31;
859 + x1 ^= t0 + (t1<<1) + tfdata->subKeys[k++];
860 + }
861 +
862 + x2 ^= tfdata->subKeys[4];
863 + x3 ^= tfdata->subKeys[5];
864 + x0 ^= tfdata->subKeys[6];
865 + x1 ^= tfdata->subKeys[7];
866 + }
867 +
868 + *out++ = (u_int8_t)(x2 );
869 + *out++ = (u_int8_t)(x2 >> 8);
870 + *out++ = (u_int8_t)(x2 >> 16);
871 + *out++ = (u_int8_t)(x2 >> 24);
872 +
873 + *out++ = (u_int8_t)(x3 );
874 + *out++ = (u_int8_t)(x3 >> 8);
875 + *out++ = (u_int8_t)(x3 >> 16);
876 + *out++ = (u_int8_t)(x3 >> 24);
877 +
878 + *out++ = (u_int8_t)(x0 );
879 + *out++ = (u_int8_t)(x0 >> 8);
880 + *out++ = (u_int8_t)(x0 >> 16);
881 + *out++ = (u_int8_t)(x0 >> 24);
882 +
883 + *out++ = (u_int8_t)(x1 );
884 + *out++ = (u_int8_t)(x1 >> 8);
885 + *out++ = (u_int8_t)(x1 >> 16);
886 + *out++ = (u_int8_t)(x1 >> 24);
887 +}
888 +
889 +/**
890 + * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box
891 + * 32-bit entity from two key material 32-bit entities.
892 + *
893 + * @param k0 1st 32-bit entity.
894 + * @param k1 2nd 32-bit entity.
895 + * @return Remainder polynomial generated using RS code
896 + */
897 +u_int32_t _TwoFish_RS_MDS_Encode(u_int32_t k0,u_int32_t k1)
898 +{ u_int32_t i,r;
899 +
900 + for(r=k1,i=0;i<4;i++) /* shift 1 byte at a time */
901 + TwoFish_RS_rem(r);
902 + r ^= k0;
903 + for(i=0;i<4;i++)
904 + TwoFish_RS_rem(r);
905 +
906 + return r;
907 +}
908 +
909 +u_int32_t _TwoFish_F32(u_int32_t k64Cnt,u_int32_t x,u_int32_t *k32)
910 +{ u_int8_t b0,b1,b2,b3;
911 + u_int32_t k0,k1,k2,k3,result = 0;
912 +
913 + b0=TwoFish_b0(x);
914 + b1=TwoFish_b1(x);
915 + b2=TwoFish_b2(x);
916 + b3=TwoFish_b3(x);
917 + k0=k32[0];
918 + k1=k32[1];
919 + k2=k32[2];
920 + k3=k32[3];
921 +
922 + switch (k64Cnt & 3)
923 + { case 1: /* 64-bit keys */
924 + result =
925 + TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0] & 0xFF) ^ TwoFish_b0(k0)] ^
926 + TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1] & 0xFF) ^ TwoFish_b1(k0)] ^
927 + TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2] & 0xFF) ^ TwoFish_b2(k0)] ^
928 + TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3] & 0xFF) ^ TwoFish_b3(k0)];
929 + break;
930 + case 0: /* 256-bit keys (same as 4) */
931 + b0 = (TwoFish_P[TwoFish_P_04][b0] & 0xFF) ^ TwoFish_b0(k3);
932 + b1 = (TwoFish_P[TwoFish_P_14][b1] & 0xFF) ^ TwoFish_b1(k3);
933 + b2 = (TwoFish_P[TwoFish_P_24][b2] & 0xFF) ^ TwoFish_b2(k3);
934 + b3 = (TwoFish_P[TwoFish_P_34][b3] & 0xFF) ^ TwoFish_b3(k3);
935 +
936 + case 3: /* 192-bit keys */
937 + b0 = (TwoFish_P[TwoFish_P_03][b0] & 0xFF) ^ TwoFish_b0(k2);
938 + b1 = (TwoFish_P[TwoFish_P_13][b1] & 0xFF) ^ TwoFish_b1(k2);
939 + b2 = (TwoFish_P[TwoFish_P_23][b2] & 0xFF) ^ TwoFish_b2(k2);
940 + b3 = (TwoFish_P[TwoFish_P_33][b3] & 0xFF) ^ TwoFish_b3(k2);
941 + case 2: /* 128-bit keys (optimize for this case) */
942 + result =
943 + TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0] & 0xFF) ^ TwoFish_b0(k1)] & 0xFF) ^ TwoFish_b0(k0)] ^
944 + TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1] & 0xFF) ^ TwoFish_b1(k1)] & 0xFF) ^ TwoFish_b1(k0)] ^
945 + TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2] & 0xFF) ^ TwoFish_b2(k1)] & 0xFF) ^ TwoFish_b2(k0)] ^
946 + TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3] & 0xFF) ^ TwoFish_b3(k1)] & 0xFF) ^ TwoFish_b3(k0)];
947 + break;
948 + }
949 + return result;
950 +}
951 +
952 +u_int32_t _TwoFish_Fe320(u_int32_t *lsBox,u_int32_t x)
953 +{ return lsBox[ TwoFish_b0(x)<<1 ]^
954 + lsBox[ ((TwoFish_b1(x)<<1)|1)]^
955 + lsBox[0x200+ (TwoFish_b2(x)<<1) ]^
956 + lsBox[0x200+((TwoFish_b3(x)<<1)|1)];
957 +}
958 +
959 +u_int32_t _TwoFish_Fe323(u_int32_t *lsBox,u_int32_t x)
960 +{ return lsBox[ (TwoFish_b3(x)<<1) ]^
961 + lsBox[ ((TwoFish_b0(x)<<1)|1)]^
962 + lsBox[0x200+ (TwoFish_b1(x)<<1) ]^
963 + lsBox[0x200+((TwoFish_b2(x)<<1)|1)];
964 +}
965 +
966 +u_int32_t _TwoFish_Fe32(u_int32_t *lsBox,u_int32_t x,u_int32_t R)
967 +{ return lsBox[ 2*TwoFish__b(x,R ) ]^
968 + lsBox[ 2*TwoFish__b(x,R+1)+1]^
969 + lsBox[0x200+2*TwoFish__b(x,R+2) ]^
970 + lsBox[0x200+2*TwoFish__b(x,R+3)+1];
971 +}
972 +
973 +
974 +#endif
975 --- snort-2.9.0/src/twofish.h 1970-01-01 01:00:00.000000000 +0100
976 +++ snort-2.9.0.dlucio/src/twofish.h 2010-10-08 18:05:37.000000000 +0200
977 @@ -0,0 +1,276 @@
978 +/* $Id: twofish.h,v 2.1 2008/12/15 20:36:05 fknobbe Exp $
979 + *
980 + *
981 + * Copyright (C) 1997-2000 The Cryptix Foundation Limited.
982 + * Copyright (C) 2000 Farm9.
983 + * Copyright (C) 2001 Frank Knobbe.
984 + * All rights reserved.
985 + *
986 + * For Cryptix code:
987 + * Use, modification, copying and distribution of this software is subject
988 + * the terms and conditions of the Cryptix General Licence. You should have
989 + * received a copy of the Cryptix General Licence along with this library;
990 + * if not, you can download a copy from http://www.cryptix.org/ .
991 + *
992 + * For Farm9:
993 + * --- jojo@farm9.com, August 2000, converted from Java to C++, added CBC mode and
994 + * ciphertext stealing technique, added AsciiTwofish class for easy encryption
995 + * decryption of text strings
996 + *
997 + * Frank Knobbe <frank@knobbe.us>:
998 + * --- April 2001, converted from C++ to C, prefixed global variables
999 + * with TwoFish, substituted some defines, changed functions to make use of
1000 + * variables supplied in a struct, modified and added routines for modular calls.
1001 + * Cleaned up the code so that defines are used instead of fixed 16's and 32's.
1002 + * Created two general purpose crypt routines for one block and multiple block
1003 + * encryption using Joh's CBC code.
1004 + * Added crypt routines that use a header (with a magic and data length).
1005 + * (Basically a major rewrite).
1006 + *
1007 + * Note: Routines labeled _TwoFish are private and should not be used
1008 + * (or with extreme caution).
1009 + *
1010 + */
1011 +
1012 +#ifndef __TWOFISH_LIBRARY_HEADER__
1013 +#define __TWOFISH_LIBRARY_HEADER__
1014 +
1015 +#ifndef FALSE
1016 +#define FALSE 0
1017 +#endif
1018 +#ifndef TRUE
1019 +#define TRUE !FALSE
1020 +#endif
1021 +#ifndef bool
1022 +#define bool int
1023 +#endif
1024 +
1025 +
1026 +/* Constants */
1027 +
1028 +#define TwoFish_DEFAULT_PW "SnortHas2FishEncryptionRoutines!" /* default password (not more than 32 chars) */
1029 +#define TwoFish_MAGIC "TwoFish" /* to indentify a successful decryption */
1030 +
1031 +enum
1032 +{ TwoFish_KEY_SIZE = 256, /* Valid values: 64, 128, 192, 256 */
1033 + /* User 256, other key sizes have not been tested. */
1034 + /* (But should work. I substituted as much as */
1035 + /* I could with this define.) */
1036 + TwoFish_ROUNDS = 16,
1037 + TwoFish_BLOCK_SIZE = 16, /* bytes in a data-block */
1038 + TwoFish_KEY_LENGTH = TwoFish_KEY_SIZE/8, /* 32= 256-bit key */
1039 + TwoFish_TOTAL_SUBKEYS = 4+4+2*TwoFish_ROUNDS,
1040 + TwoFish_MAGIC_LEN = TwoFish_BLOCK_SIZE-8,
1041 + TwoFish_SK_BUMP = 0x01010101,
1042 + TwoFish_SK_ROTL = 9,
1043 + TwoFish_P_00 = 1,
1044 + TwoFish_P_01 = 0,
1045 + TwoFish_P_02 = 0,
1046 + TwoFish_P_03 = TwoFish_P_01 ^ 1,
1047 + TwoFish_P_04 = 1,
1048 + TwoFish_P_10 = 0,
1049 + TwoFish_P_11 = 0,
1050 + TwoFish_P_12 = 1,
1051 + TwoFish_P_13 = TwoFish_P_11 ^ 1,
1052 + TwoFish_P_14 = 0,
1053 + TwoFish_P_20 = 1,
1054 + TwoFish_P_21 = 1,
1055 + TwoFish_P_22 = 0,
1056 + TwoFish_P_23 = TwoFish_P_21 ^ 1,
1057 + TwoFish_P_24 = 0,
1058 + TwoFish_P_30 = 0,
1059 + TwoFish_P_31 = 1,
1060 + TwoFish_P_32 = 1,
1061 + TwoFish_P_33 = TwoFish_P_31 ^ 1,
1062 + TwoFish_P_34 = 1,
1063 + TwoFish_GF256_FDBK = 0x169,
1064 + TwoFish_GF256_FDBK_2 = 0x169 / 2,
1065 + TwoFish_GF256_FDBK_4 = 0x169 / 4,
1066 + TwoFish_RS_GF_FDBK = 0x14D, /* field generator */
1067 + TwoFish_MDS_GF_FDBK = 0x169 /* primitive polynomial for GF(256) */
1068 +};
1069 +
1070 +
1071 +/* Global data structure for callers */
1072 +
1073 +typedef struct
1074 +{ u_int32_t sBox[4 * 256]; /* Key dependent S-box */
1075 + u_int32_t subKeys[TwoFish_TOTAL_SUBKEYS]; /* Subkeys */
1076 + u_int8_t key[TwoFish_KEY_LENGTH]; /* Encryption Key */
1077 + u_int8_t *output; /* Pointer to output buffer */
1078 + u_int8_t qBlockPlain[TwoFish_BLOCK_SIZE]; /* Used by CBC */
1079 + u_int8_t qBlockCrypt[TwoFish_BLOCK_SIZE];
1080 + u_int8_t prevCipher[TwoFish_BLOCK_SIZE];
1081 + struct /* Header for crypt functions. Has to be at least one block long. */
1082 + { u_int32_t salt; /* Random salt in first block (will salt the rest through CBC) */
1083 + u_int8_t length[4]; /* The amount of data following the header */
1084 + u_int8_t magic[TwoFish_MAGIC_LEN]; /* Magic to identify successful decryption */
1085 + } header;
1086 + bool qBlockDefined;
1087 + bool dontflush;
1088 +} TWOFISH;
1089 +
1090 +#ifndef __TWOFISH_LIBRARY_SOURCE__
1091 +
1092 +extern bool TwoFish_srand; /* if set to TRUE (default), first call of TwoFishInit will seed rand(); */
1093 + /* call of TwoFishInit */
1094 +#endif
1095 +
1096 +
1097 +/**** Public Functions ****/
1098 +
1099 +/* TwoFish Initialization
1100 + *
1101 + * This routine generates a global data structure for use with TwoFish,
1102 + * initializes important values (such as subkeys, sBoxes), generates subkeys
1103 + * and precomputes the MDS matrix if not already done.
1104 + *
1105 + * Input: User supplied password (will be appended by default password of 'SnortHas2FishEncryptionRoutines!')
1106 + *
1107 + * Output: Pointer to TWOFISH structure. This data structure contains key dependent data.
1108 + * This pointer is used with all other crypt functions.
1109 + */
1110 +TWOFISH *TwoFishInit(char *userkey);
1111 +
1112 +
1113 +/* TwoFish Destroy
1114 + *
1115 + * Nothing else but a free...
1116 + *
1117 + * Input: Pointer to the TwoFish structure.
1118 + *
1119 + */
1120 +void TwoFishDestroy(TWOFISH *tfdata);
1121 +
1122 +
1123 +/* TwoFish Alloc
1124 + *
1125 + * Allocates enough memory for the output buffer as required.
1126 + *
1127 + * Input: Length of the plaintext.
1128 + * Boolean flag for BinHex Output.
1129 + * Pointer to the TwoFish structure.
1130 + *
1131 + * Output: Returns a pointer to the memory allocated.
1132 + */
1133 +void *TwoFishAlloc(unsigned long len,bool binhex,bool decrypt,TWOFISH *tfdata);
1134 +
1135 +
1136 +/* TwoFish Free
1137 + *
1138 + * Free's the allocated buffer.
1139 + *
1140 + * Input: Pointer to the TwoFish structure
1141 + *
1142 + * Output: (none)
1143 + */
1144 +void TwoFishFree(TWOFISH *tfdata);
1145 +
1146 +
1147 +/* TwoFish Set Output
1148 + *
1149 + * If you want to allocate the output buffer yourself,
1150 + * then you can set it with this function.
1151 + *
1152 + * Input: Pointer to your output buffer
1153 + * Pointer to the TwoFish structure
1154 + *
1155 + * Output: (none)
1156 + */
1157 +void TwoFishSetOutput(char *outp,TWOFISH *tfdata);
1158 +
1159 +
1160 +/* TwoFish Raw Encryption
1161 + *
1162 + * Does not use header, but does use CBC (if more than one block has to be encrypted).
1163 + *
1164 + * Input: Pointer to the buffer of the plaintext to be encrypted.
1165 + * Pointer to the buffer receiving the ciphertext.
1166 + * The length of the plaintext buffer.
1167 + * The TwoFish structure.
1168 + *
1169 + * Output: The amount of bytes encrypted if successful, otherwise 0.
1170 + */
1171 +unsigned long TwoFishEncryptRaw(char *in,char *out,unsigned long len,TWOFISH *tfdata);
1172 +
1173 +/* TwoFish Raw Decryption
1174 + *
1175 + * Does not use header, but does use CBC (if more than one block has to be decrypted).
1176 + *
1177 + * Input: Pointer to the buffer of the ciphertext to be decrypted.
1178 + * Pointer to the buffer receiving the plaintext.
1179 + * The length of the ciphertext buffer (at least one cipher block).
1180 + * The TwoFish structure.
1181 + *
1182 + * Output: The amount of bytes decrypted if successful, otherwise 0.
1183 + */
1184 +unsigned long TwoFishDecryptRaw(char *in,char *out,unsigned long len,TWOFISH *tfdata);
1185 +
1186 +
1187 +/* TwoFish Encryption
1188 + *
1189 + * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
1190 + * this routine will alloc the memory. In addition, it will include a small 'header'
1191 + * containing the magic and some salt. That way the decrypt routine can check if the
1192 + * packet got decrypted successfully, and return 0 instead of garbage.
1193 + *
1194 + * Input: Pointer to the buffer of the plaintext to be encrypted.
1195 + * Pointer to the pointer to the buffer receiving the ciphertext.
1196 + * The pointer either points to user allocated output buffer space, or to NULL, in which case
1197 + * this routine will set the pointer to the buffer allocated through the struct.
1198 + * The length of the plaintext buffer.
1199 + * Can be -1 if the input is a null terminated string, in which case we'll count for you.
1200 + * Boolean flag for BinHex Output (if used, output will be twice as large as input).
1201 + * Note: BinHex conversion overwrites (converts) input buffer!
1202 + * The TwoFish structure.
1203 + *
1204 + * Output: The amount of bytes encrypted if successful, otherwise 0.
1205 + */
1206 +unsigned long TwoFishEncrypt(char *in,char **out,signed long len,bool binhex,TWOFISH *tfdata);
1207 +
1208 +
1209 +/* TwoFish Decryption
1210 + *
1211 + * Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
1212 + * this routine will alloc the memory. In addition, it will check the small 'header'
1213 + * containing the magic. If magic does not match we return 0. Otherwise we return the
1214 + * amount of bytes decrypted (should be the same as the length in the header).
1215 + *
1216 + * Input: Pointer to the buffer of the ciphertext to be decrypted.
1217 + * Pointer to the pointer to the buffer receiving the plaintext.
1218 + * The pointer either points to user allocated output buffer space, or to NULL, in which case
1219 + * this routine will set the pointer to the buffer allocated through the struct.
1220 + * The length of the ciphertext buffer.
1221 + * Can be -1 if the input is a null terminated binhex string, in which case we'll count for you.
1222 + * Boolean flag for BinHex Input (if used, plaintext will be half as large as input).
1223 + * Note: BinHex conversion overwrites (converts) input buffer!
1224 + * The TwoFish structure.
1225 + *
1226 + * Output: The amount of bytes decrypted if successful, otherwise 0.
1227 + */
1228 +unsigned long TwoFishDecrypt(char *in,char **out,signed long len,bool binhex,TWOFISH *tfdata);
1229 +
1230 +
1231 +/**** Private Functions ****/
1232 +
1233 +u_int8_t TwoFish__b(u_int32_t x,int n);
1234 +void _TwoFish_BinHex(u_int8_t *buf,unsigned long len,bool bintohex);
1235 +unsigned long _TwoFish_CryptRawCBC(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata);
1236 +unsigned long _TwoFish_CryptRaw16(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata);
1237 +unsigned long _TwoFish_CryptRaw(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata);
1238 +void _TwoFish_PrecomputeMDSmatrix(void);
1239 +void _TwoFish_MakeSubKeys(TWOFISH *tfdata);
1240 +void _TwoFish_qBlockPush(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata);
1241 +void _TwoFish_qBlockPop(u_int8_t *p,u_int8_t *c,TWOFISH *tfdata);
1242 +void _TwoFish_ResetCBC(TWOFISH *tfdata);
1243 +void _TwoFish_FlushOutput(u_int8_t *b,unsigned long len,TWOFISH *tfdata);
1244 +void _TwoFish_BlockCrypt(u_int8_t *in,u_int8_t *out,unsigned long size,int decrypt,TWOFISH *tfdata);
1245 +void _TwoFish_BlockCrypt16(u_int8_t *in,u_int8_t *out,bool decrypt,TWOFISH *tfdata);
1246 +u_int32_t _TwoFish_RS_MDS_Encode(u_int32_t k0,u_int32_t k1);
1247 +u_int32_t _TwoFish_F32(u_int32_t k64Cnt,u_int32_t x,u_int32_t *k32);
1248 +u_int32_t _TwoFish_Fe320(u_int32_t *lsBox,u_int32_t x);
1249 +u_int32_t _TwoFish_Fe323(u_int32_t *lsBox,u_int32_t x);
1250 +u_int32_t _TwoFish_Fe32(u_int32_t *lsBox,u_int32_t x,u_int32_t R);
1251 +
1252 +
1253 +#endif
1254 --- snort-2.9.0/src/plugin_enum.h 2010-06-10 00:04:54.000000000 +0200
1255 +++ snort-2.9.0.dlucio/src/plugin_enum.h 2010-10-08 18:08:27.000000000 +0200
1256 @@ -60,6 +60,7 @@
1257 PLUGIN_URILEN_CHECK,
1258 PLUGIN_DYNAMIC,
1259 PLUGIN_FLOWBIT,
1260 + PLUGIN_FWSAM,
1261 PLUGIN_FILE_DATA,
1262 PLUGIN_BASE64_DECODE,
1263 PLUGIN_MAX /* sentinel value */
1264 --- snort-2.9.0/src/fatal.h 1970-01-01 01:00:00.000000000 +0100
1265 +++ snort-2.9.0.dlucio/src/fatal.h 2010-10-08 18:05:37.000000000 +0200
1266 @@ -0,0 +1,40 @@
1267 +/* $Id$ */
1268 +/*
1269 +** Copyright (C) 2002-2008 Sourcefire, Inc.
1270 +** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
1271 +**
1272 +** This program is free software; you can redistribute it and/or modify
1273 +** it under the terms of the GNU General Public License Version 2 as
1274 +** published by the Free Software Foundation. You may not use, modify or
1275 +** distribute this program under any other version of the GNU General
1276 +** Public License.
1277 +**
1278 +** This program is distributed in the hope that it will be useful,
1279 +** but WITHOUT ANY WARRANTY; without even the implied warranty of
1280 +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1281 +** GNU General Public License for more details.
1282 +**
1283 +** You should have received a copy of the GNU General Public License
1284 +** along with this program; if not, write to the Free Software
1285 +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1286 +*/
1287 +
1288 +#ifndef __FATAL_H__
1289 +#define __FATAL_H__
1290 +
1291 +
1292 +/*
1293 + * in debugging mode print out the filename and the line number where the
1294 + * failure have occured
1295 + */
1296 +
1297 +
1298 +#ifdef DEBUG
1299 + #define FATAL(msg) { printf("%s:%d: ", __FILE__, __LINE__); FatalError( (char *) msg); }
1300 +#else
1301 + #define FATAL(msg) FatalError( (char *) msg)
1302 +#endif
1303 +
1304 +
1305 +
1306 +#endif /* __FATAL_H__ */
1307 --- snort-2.9.0/src/output-plugins/spo_alert_fwsam.c 1970-01-01 01:00:00.000000000 +0100
1308 +++ snort-2.9.0.dlucio/src/output-plugins/spo_alert_fwsam.c 2010-10-08 18:05:37.000000000 +0200
1309 @@ -0,0 +1,1380 @@
1310 +/* $id: snortpatchb,v 1.2 2002/10/26 03:32:35 fknobbe Exp $
1311 +**
1312 +** spo_alert_fwsam.c
1313 +**
1314 +** Copyright (c) 2001-2004 Frank Knobbe <frank@knobbe.us>
1315 +**
1316 +** This program is free software; you can redistribute it and/or modify
1317 +** it under the terms of the GNU General Public License as published by
1318 +** the Free Software Foundation; either version 2 of the License, or
1319 +** (at your option) any later version.
1320 +**
1321 +** This program is distributed in the hope that it will be useful,
1322 +** but WITHOUT ANY WARRANTY; without even the implied warranty of
1323 +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1324 +** GNU General Public License for more details.
1325 +**
1326 +** You should have received a copy of the GNU General Public License
1327 +** along with this program; if not, write to the Free Software
1328 +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1329 +*/
1330 +
1331 +/*
1332 + * Purpose:
1333 + *
1334 + * This module sends alerts to a remote service on a host running SnortSam
1335 + * (the agent) which will block the intruding IP address on a variety of
1336 + * host and network firewalls.
1337 + *
1338 + * SnortSam also performs checks against a white-list of never-to-be-blocked IP addresses,
1339 + * can override block durations (for example for known proxies), and can detect attack conditions
1340 + * where too many blocks are received within a defined interval. If an attack is detected
1341 + * it will unblock the last x blocks and wait for the attack to end.
1342 + *
1343 + * See the SnortSam documentation for more information.
1344 + *
1345 + *
1346 + * Output Plugin Parameters:
1347 + ***************************
1348 + *
1349 + * output alert_fwsam: <SnortSam Station>:<port>/<key>
1350 + *
1351 + * <FW Mgmt Station>: The IP address or host name of the host running SnortSam.
1352 + * <port>: The port the remote SnortSam service listens on (default 898).
1353 + * <key>: The key used for authentication (encryption really)
1354 + * of the communication to the remote service.
1355 + *
1356 + * Examples:
1357 + *
1358 + * output alert_fwsam: snortsambox/idspassword
1359 + * output alert_fwsam: fw1.domain.tld:898/mykey
1360 + * output alert_fwsam: 192.168.0.1/borderfw 192.168.1.254/wanfw
1361 + *
1362 + *
1363 + * Rule Options:
1364 + ***************
1365 + *
1366 + * fwsam: who[how],time;
1367 + *
1368 + * who: src, source, dst, dest, destination
1369 + * IP address to be blocked according to snort rule (some rules
1370 + * are reversed, i.e. homenet -> any [and you want to block any]).
1371 + * src denotes IP to the left of -> and dst denotes IP to the right
1372 + *
1373 + * how: Optional. In, out, src, dest, either, both, this, conn, connection
1374 + * Tells FW-1 to block packets INcoming from host, OUTgoing to host,
1375 + * EITHERway, or only THIS connection (IP/Service pair).
1376 + * See 'fw sam' for more information. May be ignored by other plugins.
1377 + *
1378 + * time: Duration of block in seconds. (Accepts 'days', 'months', 'weeks',
1379 + * 'years', 'minutes', 'seconds', 'hours'. Alternatively, a value of
1380 + * 0, or the keyword PERManent, INFinite, or ALWAYS, will block the
1381 + * host permanently. Be careful with this!
1382 + * Tells FW-1 (and others) how long to inhibit packets from the host.
1383 + *
1384 + * Examples:
1385 + *
1386 + * fwsam: src[either],15min;
1387 + * or dst[in], 2 days 4 hours
1388 + * or src, 1 hour
1389 + *
1390 + * (default: src[either],5min)
1391 + *
1392 + *
1393 + * Effect:
1394 + *
1395 + * Alerts are sent to the remote SnortSam services on Firewall-1 Management Stations
1396 + * or other hosts running SnortSam (as required for Cisco Routers and PIX).
1397 + * The remote services will invoke the SAM configuration via the fw sam
1398 + * command line, or by sending a packet to the SAM port 18183, or by using the official
1399 + * OPSEC API calls, or by telnetting into Cisco routers or PIX firewalls.
1400 + * The communication over the network is encrypted using two-fish.
1401 + * (Implementation ripped from CryptCat by Farm9 with permission.)
1402 + *
1403 + * Future Plans:
1404 + *
1405 + * - Custom alert trigger per rule (x alerts in y secs) --> Seems to exist in Snort 1.9 now.
1406 + * - Enable/Allow tagged fwsam: arguments to provide different values to
1407 + * different stations. --> Seems to be accomplished with custom rule-types
1408 + *
1409 + *
1410 + * Comments:
1411 + *
1412 + * It seem that above wishes can be implemented with todays setup. Feedback concerning
1413 + * these is greatly appreciated.
1414 + *
1415 +*/
1416 +
1417 +
1418 +#include "spo_alert_fwsam.h"
1419 +#include "twofish.h"
1420 +/* external globals from rules.c */
1421 +extern char *file_name;
1422 +extern int file_line;
1423 +extern OptTreeNode *otn_tmp;
1424 +extern char *snort_conf_dir; /* extern PV pv; */
1425 +
1426 +
1427 +/* my globals */
1428 +
1429 +FWsamList *FWsamStationList=NULL; /* Global (for all alert-types) list of snortsam stations */
1430 +FWsamOptions *FWsamOptionField=NULL;
1431 +unsigned long FWsamMaxOptions=0;
1432 +
1433 +
1434 +/*
1435 + * Function: AlertFWsamSetup()
1436 + *
1437 + * Purpose: Registers the output plugin keyword and initialization
1438 + * function into the output plugin list. This is the function that
1439 + * gets called from InitOutputPlugins() in plugbase.c.
1440 + * It also registers itself as a plugin in order to parse every rule
1441 + * and to set the appropiate flags from fwsam: option.
1442 + *
1443 + * Arguments: None.
1444 + *
1445 + * Returns: void function
1446 + *
1447 +*/
1448 +void AlertFWsamSetup(void)
1449 +{
1450 + /* link the preprocessor keyword to the init function in
1451 + the preproc list */
1452 + RegisterOutputPlugin("alert_fwsam", OUTPUT_TYPE_FLAG__ALERT, AlertFWsamInit);
1453 + RegisterRuleOption("fwsam", AlertFWsamOptionInit, NULL, OPT_TYPE_ACTION, NULL);
1454 +
1455 +#ifdef FWSAMDEBUG /* This allows debugging of fwsam only */
1456 + LogMessage("DEBUG => [Alert_FWsam](AlertFWsamSetup) Output plugin is plugged in...\n");
1457 +#endif
1458 +}
1459 +
1460 +
1461 +/* This function checks if a given snortsam station is already in
1462 + * a given list.
1463 +*/
1464 +int FWsamStationExists(FWsamStation *who,FWsamList *list)
1465 +{
1466 + while(list)
1467 + {
1468 + if(list->station) {
1469 +// if( who->stationip.s_addr==list->station->stationip.s_addr &&
1470 + if(IP_EQUALITY(&who->stationip, &list->station->stationip) &&
1471 + who->stationport==list->station->stationport)
1472 + return TRUE;
1473 + }
1474 + list=list->next;
1475 + }
1476 + return FALSE;
1477 +}
1478 +
1479 +/*
1480 + * Function: AlertFWsamInit(char *args)
1481 + *
1482 + * Purpose: Calls the argument parsing function, performs final setup on data
1483 + * structs, links the preproc function into the function list.
1484 + *
1485 + * Arguments: args => ptr to argument string
1486 + *
1487 + * Returns: void function
1488 + *
1489 +*/
1490 +void AlertFWsamInit(char *args)
1491 +{ char *ap;
1492 + unsigned long statip,cnt,again,i;
1493 + char *stathost,*statport,*statpass;
1494 + FWsamStation *station;
1495 + FWsamList *fwsamlist=NULL; /* alert-type dependent list of snortsam stations */
1496 + FWsamList *listp,*newlistp;
1497 + struct hostent *hoste;
1498 + char buf[1024]="";
1499 + FILE *fp;
1500 + FWsamOptions tempopt;
1501 +
1502 +#ifdef FWSAMDEBUG
1503 + unsigned long hostcnt=0;
1504 +
1505 +
1506 +
1507 + LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Output plugin initializing...\n");
1508 +#endif
1509 +
1510 + /* pv.alert_plugin_active = 1; */
1511 +
1512 + /* parse the argument list from the rules file */
1513 +
1514 + if(args == NULL)
1515 + FatalError("ERROR %s (%d) => [Alert_FWsam](AlertFWsamInit) No arguments to alert_fwsam preprocessor!\n", file_name, file_line);
1516 +
1517 + if(!FWsamOptionField && !FWsamMaxOptions)
1518 + { strncpy(buf,snort_conf_dir,sizeof(buf)-1);
1519 + strncpy(buf+strlen(buf),SID_MAPFILE,sizeof(buf)-strlen(buf)-1);
1520 +#ifdef FWSAMDEBUG
1521 + LogMessage("DEBUG => [Alert_FWsam](AlertFWsamSetup) Using file: %s\n",buf);
1522 +#endif
1523 + fp=fopen(buf,"rt");
1524 + if(!fp)
1525 + { strncpy(buf,snort_conf_dir,sizeof(buf)-1);
1526 + strncpy(buf+strlen(buf),SID_ALT_MAPFILE,sizeof(buf)-strlen(buf)-1);
1527 + fp=fopen(buf,"rt");
1528 + }
1529 + if(fp) /* Check for presence of map file and read those in, sorted. */
1530 + { LogMessage("INFO => [Alert_FWsam](AlertFWsamSetup) Using sid-map file: %s\n",buf);
1531 +
1532 + while(FWsamReadLine(buf,sizeof(buf),fp))
1533 + if(*buf)
1534 + FWsamMaxOptions++;
1535 + if(FWsamMaxOptions)
1536 + { if((FWsamOptionField=(FWsamOptions *)malloc(sizeof(FWsamOptions)*FWsamMaxOptions))==NULL)
1537 + FatalError("ERROR => [Alert_FWsam](AlertFWsamSetup) malloc failed for OptionField!\n");
1538 + fseek(fp,0,SEEK_SET);
1539 + for(cnt=0;cnt<FWsamMaxOptions;)
1540 + { FWsamReadLine(buf,sizeof(buf),fp);
1541 + if(*buf)
1542 + FWsamParseLine(&(FWsamOptionField[cnt++]),buf);
1543 + }
1544 + if(FWsamMaxOptions>1)
1545 + { for(again=TRUE,cnt=FWsamMaxOptions-1;cnt>=1 && again;cnt--)
1546 + { for(again=FALSE,i=0;i<cnt;i++)
1547 + { if(FWsamOptionField[i].sid>FWsamOptionField[i+1].sid)
1548 + { memcpy(&tempopt,&(FWsamOptionField[i]),sizeof(FWsamOptions));
1549 + memcpy(&(FWsamOptionField[i]),&(FWsamOptionField[i+1]),sizeof(FWsamOptions));
1550 + memcpy(&(FWsamOptionField[i+1]),&tempopt,sizeof(FWsamOptions));
1551 + again=TRUE;
1552 + }
1553 + }
1554 + }
1555 + }
1556 + }
1557 + else
1558 + FWsamMaxOptions=1;
1559 + fclose(fp);
1560 + }
1561 + else
1562 + FWsamMaxOptions=1;
1563 + }
1564 +
1565 +
1566 + ap=args; /* start at the beginning of the argument */
1567 + while(*ap && isspace(*ap)) ap++;
1568 + while(*ap)
1569 + { stathost=ap; /* first argument should be host */
1570 + statport=NULL;
1571 + statpass=NULL;
1572 + while(*ap && *ap!=':' && *ap!='/' && !isspace(*ap)) ap++; /* find token */
1573 + switch(*ap)
1574 + { case ':': *ap++=0; /* grab the port */
1575 + statport=ap;
1576 + while(*ap && *ap!='/' && !isspace(*ap)) ap++;
1577 + if(*ap!='/')
1578 + break;
1579 + case '/': *ap++=0; /* grab the key */
1580 + statpass=ap;
1581 + while(*ap && !isspace(*ap)) ap++;
1582 + default: break;
1583 + }
1584 + if(*ap)
1585 + { *ap++=0;
1586 + while(isspace(*ap)) ap++;
1587 + }
1588 + /* now we have the first host with port and password (key) */
1589 + /* next we check for valid/blank password/port */
1590 + if(statpass!=NULL)
1591 + if(!*statpass)
1592 + statpass=NULL;
1593 + if(statport!=NULL)
1594 + if(!*statport)
1595 + statport=NULL;
1596 + statip=0;
1597 + /* now we check if a valid host was specified */
1598 + if(inet_addr(stathost)==INADDR_NONE)
1599 + { hoste=gethostbyname(stathost);
1600 + if (!hoste)
1601 + LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWsamInit) Unable to resolve host '%s'!\n",file_name,file_line,stathost);
1602 + else
1603 + statip=*(unsigned long *)hoste->h_addr;
1604 + }
1605 + else
1606 + { statip=inet_addr(stathost);
1607 + if(!statip)
1608 + LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWsamInit) Invalid host address '%s'!\n",file_name,file_line,stathost);
1609 + }
1610 + if(statip)
1611 + { /* groovie, a valid host. Let's alloc and assemble the structure for it. */
1612 + if((station=(FWsamStation *)malloc(sizeof(FWsamStation)))==NULL)
1613 + FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for station!\n");
1614 +
1615 +// station->stationip.s_addr=statip; /* the IP address */
1616 + station->stationip.ip32[0] = statip; /* the IP address */
1617 + if(statport!=NULL && atoi(statport)>0) /* if the user specified one */
1618 + station->stationport=atoi(statport); /* use users setting */
1619 + else
1620 + station->stationport=FWSAM_DEFAULTPORT; /* set the default port */
1621 +
1622 + if(statpass!=NULL) /* if specified by user */
1623 + strncpy(station->stationkey,statpass,TwoFish_KEY_LENGTH); /* use defined key */
1624 + else
1625 + station->stationkey[0]=0;
1626 + station->stationkey[TwoFish_KEY_LENGTH]=0; /* make sure it's terminated. (damn strncpy...) */
1627 +
1628 + strcpy(station->initialkey,station->stationkey);
1629 + station->stationfish=TwoFishInit(station->stationkey);
1630 +
1631 + station->localsocketaddr.sin_port=htons(0); /* let's use dynamic ports for now */
1632 + station->localsocketaddr.sin_addr.s_addr=0;
1633 + station->localsocketaddr.sin_family=AF_INET;
1634 + station->stationsocketaddr.sin_port=htons(station->stationport);
1635 + //station->stationsocketaddr.sin_addr=station->stationip;
1636 + station->stationsocketaddr.sin_addr.s_addr=station->stationip.ip32[0];
1637 + station->stationsocketaddr.sin_family=AF_INET; /* load all socket crap and keep for later */
1638 +
1639 + do
1640 + station->myseqno=rand(); /* the seqno this host will use */
1641 + while(station->myseqno<20 || station->myseqno>65500);
1642 + station->mykeymod[0]=rand();
1643 + station->mykeymod[1]=rand();
1644 + station->mykeymod[2]=rand();
1645 + station->mykeymod[3]=rand();
1646 + station->stationseqno=0; /* peer hasn't answered yet. */
1647 +
1648 +
1649 + if(!FWsamStationExists(station,FWsamStationList)) /* If we don't have the station already in global list....*/
1650 + { if(FWsamCheckIn(station)) /* ...and we can talk to the agent... */
1651 + { if((newlistp=(FWsamList *)malloc(sizeof(FWsamList)))==NULL)
1652 + FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for global newlistp!\n");
1653 + newlistp->station=station;
1654 + newlistp->next=NULL;
1655 +
1656 + if(!FWsamStationList) /* ... add it to the global list/ */
1657 + FWsamStationList=newlistp;
1658 + else
1659 + { listp=FWsamStationList;
1660 + while(listp->next)
1661 + listp=listp->next;
1662 + listp->next=newlistp;
1663 + }
1664 + }
1665 + else
1666 + { TwoFishDestroy(station->stationfish); /* if not, we trash it. */
1667 + free(station);
1668 + station=NULL;
1669 + }
1670 + }
1671 +#ifdef FWSAMDEBUG
1672 + else
1673 + LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Host %s:%i already in global list, skipping CheckIn.\n", sfip_ntoa(&station->stationip),station->stationport);
1674 +#endif
1675 +
1676 + if(station)
1677 + { if(!FWsamStationExists(station,fwsamlist)) /* If we don't have the station already in local list....*/
1678 + { if((newlistp=(FWsamList *)malloc(sizeof(FWsamList)))==NULL)
1679 + FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for local newlistp!\n");
1680 + newlistp->station=station;
1681 + newlistp->next=NULL;
1682 +
1683 + if(!fwsamlist) /* ... add it to the local list/ */
1684 + fwsamlist=newlistp;
1685 + else
1686 + { listp=fwsamlist;
1687 + while(listp->next)
1688 + listp=listp->next;
1689 + listp->next=newlistp;
1690 + }
1691 + }
1692 +
1693 +#ifdef FWSAMDEBUG
1694 + else
1695 + LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Host %s:%i already in local list, skipping.\n",sfip_ntoa(&station->stationip),station->stationport);
1696 + LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) #%i: Host %s [%s] port %i password %s\n",++hostcnt,stathost,sfip_ntoa(&station->stationip),station->stationport,station->stationkey);
1697 +#endif
1698 + }
1699 +
1700 + }
1701 + } /* next one */
1702 +
1703 +#ifdef FWSAMDEBUG
1704 + LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Linking fwsam alert function to call list...\n");
1705 +#endif
1706 +
1707 + /* Set the preprocessor function into the function list */
1708 + AddFuncToOutputList(AlertFWsam, OUTPUT_TYPE_FLAG__ALERT, fwsamlist);
1709 + AddFuncToCleanExitList(AlertFWsamCleanExitFunc, fwsamlist);
1710 + AddFuncToRestartList(AlertFWsamRestartFunc, fwsamlist);
1711 +}
1712 +
1713 +
1714 +/* This routine reads in a str from a file, snips white-spaces
1715 + * off the front and back, removes comments, and pretties the
1716 + * string. Returns true or false if a line was read or not.
1717 +*/
1718 +int FWsamReadLine(char *buf,unsigned long bufsize,FILE *fp)
1719 +{ char *p;
1720 +
1721 + if(fgets(buf,bufsize-1,fp))
1722 + { buf[bufsize-1]=0;
1723 +
1724 +#ifdef FWSAMDEBUG_off
1725 + LogMessage("DEBUG => [Alert_FWsam](AlertFWsamReadLine) Line: %s\n",buf);
1726 +#endif
1727 +
1728 + p=buf;
1729 + while(isspace(*p))
1730 + p++;
1731 + if(p>buf);
1732 + strcpy(buf,p);
1733 + if(*buf)
1734 + { p=buf+strlen(buf)-1; /* remove leading and trailing spaces */
1735 + while(isspace(*p))
1736 + *p-- =0;
1737 + }
1738 + p=buf;
1739 + if(*p=='#' || *p==';')
1740 + *p=0;
1741 + else
1742 + p++;
1743 + while(*p) /* remove inline comments (except escaped #'s and ;'s) */
1744 + { if(*p=='#' || *p==';')
1745 + { if(*(p-1)=='\\')
1746 + strcpy(p-1,p);
1747 + else
1748 + *p=0;
1749 + }
1750 + else
1751 + p++;
1752 + }
1753 + return TRUE;
1754 + }
1755 + return FALSE;
1756 +}
1757 +
1758 +
1759 +/* Parses the duration of the argument, recognizing minutes, hours, etc..
1760 +*/
1761 +unsigned long FWsamParseDuration(char *p)
1762 +{ unsigned long dur=0,tdu;
1763 + char *tok,c1,c2;
1764 +
1765 + while(*p)
1766 + { tok=p;
1767 + while(*p && isdigit(*p))
1768 + p++;
1769 + if(*p)
1770 + { c1=tolower(*p);
1771 + *p=0;
1772 + p++;
1773 + if(*p && !isdigit(*p))
1774 + { c2=tolower(*p++);
1775 + while(*p && !isdigit(*p))
1776 + p++;
1777 + }
1778 + else
1779 + c2=0;
1780 + tdu=atol(tok);
1781 + switch(c1)
1782 + { case 'm': if(c2=='o') /* month */
1783 + tdu*=(60*60*24*30); /* use 30 days */
1784 + else
1785 + tdu*=60; /* minutes */
1786 + case 's': break; /* seconds */
1787 + case 'h': tdu*=(60*60); /* hours */
1788 + break;
1789 + case 'd': tdu*=(60*60*24); /* days */
1790 + break;
1791 + case 'w': tdu*=(60*60*24*7); /* week */
1792 + break;
1793 + case 'y': tdu*=(60*60*24*365); /* year */
1794 + break;
1795 + }
1796 + dur+=tdu;
1797 + }
1798 + else
1799 + dur+=atol(tok);
1800 + }
1801 +
1802 + return dur;
1803 +}
1804 +
1805 +
1806 +/* This routine parses an option line. It is called by FWsamParseLine,
1807 + * which parses the sid-block.map file, and also by AlertFWsamOptionInit,
1808 + * which is called by Snort when processing fwsam: options in rules.
1809 + * It returns TRUE it there is a possible option problem, otherwise FALSE.
1810 +*/
1811 +int FWsamParseOption(FWsamOptions *optp,char *ap)
1812 +{ int possprob=FALSE;
1813 +
1814 + /* set defaults */
1815 +
1816 + optp->duration=300; /* default of 5 minute block */
1817 + optp->how=FWSAM_HOW_INOUT; /* inbound and outbound block */
1818 + optp->who=FWSAM_WHO_SRC; /* the source */
1819 + optp->loglevel=FWSAM_LOG_LONGALERT; /* the log level default */
1820 + /* parse the fwsam keywords */
1821 +
1822 +#ifdef FWSAMDEBUG
1823 + LogMessage("DEBUG => [Alert_FWsam](AlertFWamOptionInit) Parse Options Args: %s\n",ap);
1824 +#endif
1825 +
1826 + if(*ap) /* should be dst/src (the WHO) or duration */
1827 + { if(isdigit(*ap))
1828 + optp->duration=FWsamParseDuration(ap);
1829 + else
1830 + { switch(*ap) /* yeah, we're lazy and check only the first character */
1831 + { case 'p': ; /* permanent, perm */
1832 + case 'f': ; /* forever */
1833 + case 'i': optp->duration=0; /* infinite, inf */
1834 + break;
1835 + case 'd': optp->who=FWSAM_WHO_DST; /* destination, dest, dst */
1836 + break;
1837 + case 's': optp->who=FWSAM_WHO_SRC; /* source, src */
1838 + break;
1839 + default: possprob=TRUE;
1840 + }
1841 + while(*ap && *ap!=',' && *ap!='[')
1842 + ap++;
1843 + if(*ap=='[')
1844 + { ap++; /* now we have the HOW */
1845 + switch(*ap)
1846 + { case 'i': ; /* in */
1847 + case 's': optp->how=FWSAM_HOW_IN; /* source, src */
1848 + break;
1849 + case 'o': ; /* out */
1850 + case 'd': optp->how=FWSAM_HOW_OUT; /* destination, dest, dst */
1851 + break;
1852 + case 'b': ; /* both */
1853 + case 'e': optp->how=FWSAM_HOW_INOUT; /* either */
1854 + break;
1855 + case 't': ; /* this */
1856 + case 'c': optp->how=FWSAM_HOW_THIS; /* connection, conn */
1857 + break;
1858 + default: possprob=TRUE;
1859 + }
1860 + while(*ap && *ap!=',')
1861 + ap++;
1862 + }
1863 + if(*ap==',')
1864 + { ap++;
1865 + if(isdigit(*ap)) /* and figure out how long to block */
1866 + optp->duration=FWsamParseDuration(ap);
1867 + else if(*ap=='p' || *ap=='f' || *ap=='i')
1868 + optp->duration=0;
1869 + else
1870 + possprob=TRUE;
1871 + }
1872 + else if(!*ap)
1873 + possprob=TRUE;
1874 + }
1875 + }
1876 + else
1877 + possprob=TRUE;
1878 +
1879 + return possprob;
1880 +}
1881 +
1882 +
1883 +/* This goes through the lines of sid-block.map and sets the
1884 + * options for fwsam if the file is being used.
1885 +*/
1886 +void FWsamParseLine(FWsamOptions *optp,char *buf)
1887 +{ char *ap;
1888 +
1889 + ap=buf; /* start at the beginning of the argument */
1890 +
1891 + while(*ap)
1892 + { if(isspace(*ap)) /* normalize spaces (tabs into space, etc) */
1893 + *ap=' ';
1894 + if(isupper(*ap)) /* and set to lower case */
1895 + *ap=tolower(*ap);
1896 + ap++;
1897 + }
1898 + while((ap=strrchr(buf,' '))!=NULL) /* remove spaces */
1899 + strcpy(ap,ap+1);
1900 +
1901 + ap=buf;
1902 + if(*ap)
1903 + { while(*ap && *ap!=':' && *ap!='|')
1904 + ap++;
1905 + *ap++ =0;
1906 + while(*ap && (*ap==':' || *ap=='|'))
1907 + ap++;
1908 +
1909 + optp->sid=(unsigned long)atol(buf);
1910 +
1911 + if(FWsamParseOption(optp,ap))
1912 + 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);
1913 + }
1914 + else
1915 + optp->sid=0;
1916 +}
1917 +
1918 +
1919 +
1920 +/*
1921 + * Function: AlertFWsamOptionInit(char *data, OptTreeNode *otn, int protocol)
1922 + *
1923 + * Purpose: Parses each rule and sets the option flags in the tree.
1924 + *
1925 + * Arguments: args => ptr to argument string
1926 + *
1927 + * Returns: void function
1928 + *
1929 +*/
1930 +void AlertFWsamOptionInit(char *args,OptTreeNode *otn,int protocol)
1931 +{
1932 + FWsamOptions *optp;
1933 + char *ap;
1934 +
1935 +
1936 +#ifdef FWSAMDEBUG
1937 + LogMessage("DEBUG => [Alert_FWsam](AlertFWamOptionInit) FWsamOptionInit is parsing...\n");
1938 +#endif
1939 +
1940 + if((optp=(FWsamOptions *)malloc(sizeof(FWsamOptions)))==NULL)
1941 + FatalError("ERROR => [Alert_FWsam](AlertFWamOptionInit) malloc failed for opt!\n");
1942 +
1943 +
1944 + ap=args; /* start at the beginning of the argument */
1945 +
1946 + while(*ap)
1947 + { if(isspace(*ap)) /* normalize spaces (tabs into space, etc) */
1948 + *ap=' ';
1949 + if(isupper(*ap)) /* and set to lower case */
1950 + *ap=tolower(*ap);
1951 + ap++;
1952 + }
1953 + while((ap=strrchr(args,' '))!=NULL) /* remove spaces */
1954 + strcpy(ap,ap+1);
1955 +
1956 +
1957 + if(FWsamParseOption(optp,args))
1958 + 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);
1959 +
1960 + otn->ds_list[PLUGIN_FWSAM]=(FWsamOptions *)optp;
1961 +}
1962 +
1963 +
1964 +/* Generates a new encryption key for TwoFish based on seq numbers and a random that
1965 + * the SnortSam agents send on checkin (in protocol)
1966 +*/
1967 +void FWsamNewStationKey(FWsamStation *station,FWsamPacket *packet)
1968 +{
1969 + //unsigned char newkey[TwoFish_KEY_LENGTH+2];
1970 + char newkey[TwoFish_KEY_LENGTH+2];
1971 + int i;
1972 +
1973 + newkey[0]=packet->snortseqno[0]; /* current snort seq # (which both know) */
1974 + newkey[1]=packet->snortseqno[1];
1975 + newkey[2]=packet->fwseqno[0]; /* current SnortSam seq # (which both know) */
1976 + newkey[3]=packet->fwseqno[1];
1977 + newkey[4]=packet->protocol[0]; /* the random SnortSam chose */
1978 + newkey[5]=packet->protocol[1];
1979 +
1980 + strncpy(newkey+6,station->stationkey,TwoFish_KEY_LENGTH-6); /* append old key */
1981 + newkey[TwoFish_KEY_LENGTH]=0;
1982 +
1983 + newkey[0]^=station->mykeymod[0]; /* modify key with key modifiers which were */
1984 + newkey[1]^=station->mykeymod[1]; /* exchanged during the check-in handshake. */
1985 + newkey[2]^=station->mykeymod[2];
1986 + newkey[3]^=station->mykeymod[3];
1987 + newkey[4]^=station->fwkeymod[0];
1988 + newkey[5]^=station->fwkeymod[1];
1989 + newkey[6]^=station->fwkeymod[2];
1990 + newkey[7]^=station->fwkeymod[3];
1991 +
1992 + for(i=0;i<=7;i++)
1993 + if(newkey[i]==0)
1994 + newkey[i]++;
1995 +
1996 + strcpy(station->stationkey,newkey);
1997 + TwoFishDestroy(station->stationfish);
1998 + station->stationfish=TwoFishInit(newkey);
1999 +}
2000 +
2001 +
2002 +/* This routine will search the option list as defined
2003 + * by the sid-block.map file and return a pointer
2004 + * to the matching record.
2005 +*/
2006 +FWsamOptions *FWsamGetOption(unsigned long sid)
2007 +{ signed long i,step,diff,o,o2;
2008 +
2009 +#ifdef FWSAM_FANCYFETCH /* Fancy-fetch jumps in decreasing n/2 steps and takes much less lookups */
2010 + o=o2= -1;
2011 + i=step=FWsamMaxOptions>>1;
2012 + while(i>=0 && i<FWsamMaxOptions && i!=o2)
2013 + { diff=sid-FWsamOptionField[i].sid;
2014 + if(!diff)
2015 + return &(FWsamOptionField[i]);
2016 + if(step>1)
2017 + step=step>>1;
2018 + o2=o;
2019 + o=i;
2020 + if(diff>0)
2021 + i+=step;
2022 + else
2023 + i-=step;
2024 + }
2025 +#else /* This is just a sequential list lookup */
2026 + for(i=0;i<FWsamMaxOptions;i++)
2027 + if(FWsamOptionField[i].sid==sid)
2028 + return &(FWsamOptionField[i]);
2029 +#endif
2030 + return NULL;
2031 +}
2032 +
2033 +
2034 +/****************************************************************************
2035 + *
2036 + * Function: AlertFWsam(Packet *, char *)
2037 + *
2038 + * Purpose: Send the current alert to a remote module on a FW-1 mgmt station
2039 + *
2040 + * Arguments: p => pointer to the packet data struct
2041 + * msg => the message to print in the alert
2042 + *
2043 + * Returns: void function
2044 + *
2045 + ***************************************************************************/
2046 +void AlertFWsam(Packet *p, char *msg, void *arg, Event *event)
2047 +{ FWsamOptions *optp;
2048 + FWsamPacket sampacket;
2049 + FWsamStation *station=NULL;
2050 + FWsamList *fwsamlist;
2051 + SOCKET stationsocket;
2052 + int i,len,deletestation,stationtry=0;
2053 + //unsigned char *encbuf,*decbuf;
2054 + char *encbuf,*decbuf;
2055 + static unsigned long lastbsip[FWSAM_REPET_BLOCKS],lastbdip[FWSAM_REPET_BLOCKS],
2056 + lastbduration[FWSAM_REPET_BLOCKS],lastbtime[FWSAM_REPET_BLOCKS];
2057 + static unsigned short lastbsp[FWSAM_REPET_BLOCKS],lastbdp[FWSAM_REPET_BLOCKS],
2058 + lastbproto[FWSAM_REPET_BLOCKS],lastbpointer;
2059 + static unsigned char lastbmode[FWSAM_REPET_BLOCKS];
2060 + static unsigned long btime=0;
2061 +
2062 +
2063 + if(otn_tmp==NULL)
2064 + {
2065 +#ifdef FWSAMDEBUG
2066 + LogMessage("DEBUG => [Alert_FWsam] NULL otn_tmp!\n");
2067 +#endif
2068 + return;
2069 + }
2070 + if(p == NULL)
2071 + {
2072 +#ifdef FWSAMDEBUG
2073 + LogMessage("DEBUG => [Alert_FWsam] NULL packet!\n");
2074 +#endif
2075 + return;
2076 + }
2077 + if(arg == NULL)
2078 + {
2079 +#ifdef FWSAMDEBUG
2080 + LogMessage("DEBUG => [Alert_FWsam] NULL arg!\n");
2081 +#endif
2082 + return;
2083 + }
2084 +
2085 + /* SnortSam does no IPv6 */
2086 + if (!IS_IP4(p)) {
2087 +#ifdef FWSAMDEBUG
2088 + LogMessage("DEBUG => [Alert_FWsam] not acting on non-IP4 packet!\n");
2089 +#endif
2090 + return;
2091 + }
2092 +
2093 + optp=NULL;
2094 +
2095 + if(FWsamOptionField) /* If using the file (field present), let's use that */
2096 + optp=FWsamGetOption(event->sig_id);
2097 +
2098 + if(!optp) /* If file not present, check if an fwsam option was defined on the triggering rule */
2099 + optp=otn_tmp->ds_list[PLUGIN_FWSAM];
2100 +
2101 + if(optp) /* if options specified for this rule */
2102 + { if(!btime) /* if this is the first time this function is */
2103 + { for(i=0;i<FWSAM_REPET_BLOCKS;i++) /* called, reset the time and protocol to 0. */
2104 + { lastbproto[i]=0;
2105 + lastbtime[i]=0;
2106 + }
2107 + }
2108 +
2109 + fwsamlist=(FWsamList *)arg;
2110 +
2111 +#ifdef FWSAMDEBUG
2112 + LogMessage("DEBUG => [Alert_FWsam] Alert -> Msg=\"%s\"\n",msg);
2113 +
2114 + 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);
2115 +#endif
2116 +
2117 + len=TRUE;
2118 + btime=(unsigned long)time(NULL); /* get current time */
2119 + /* This is a cheap check to see if the blocking request matches any of the previous requests. */
2120 + for(i=0;i<FWSAM_REPET_BLOCKS && len;i++)
2121 + { if( ((optp->how==FWSAM_HOW_THIS)? /* if blocking mode SERVICE, check for src and dst */
2122 + ( lastbsip[i]==p->iph->ip_src.s_addr && lastbdip[i]==p->iph->ip_dst.s_addr &&lastbproto[i]==p->iph->ip_proto &&
2123 + ((p->iph->ip_proto==IPPROTO_TCP || p->iph->ip_proto==IPPROTO_UDP)? /* check port only of TCP or UDP */
2124 +/* ((optp->who==FWSAM_WHO_SRC)?(lastbsp[i]==p->sp):(lastbdp[i]==p->dp)):TRUE) ): */
2125 + lastbdp[i]==p->dp:TRUE) ):
2126 + ((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. */
2127 + lastbduration[i]==optp->duration &&
2128 + (lastbmode[i]&(FWSAM_HOW|FWSAM_WHO))==(optp->how|optp->who) &&
2129 + (btime-lastbtime[i]<((optp->duration>FWSAM_REPET_TIME)?FWSAM_REPET_TIME:optp->duration)))
2130 + { len=FALSE; /* If so, we don't need to block again. */
2131 + }
2132 + }
2133 + if(len)
2134 + { if(++lastbpointer>=FWSAM_REPET_BLOCKS) /* increase repetitive check pointer */
2135 + lastbpointer=0;
2136 + lastbsip[lastbpointer]=p->iph->ip_src.s_addr; /* and note packet details */
2137 + lastbdip[lastbpointer]=p->iph->ip_dst.s_addr;
2138 + lastbduration[lastbpointer]=optp->duration;
2139 + lastbmode[lastbpointer]=optp->how|optp->who|optp->loglevel;
2140 + lastbproto[lastbpointer]=p->iph->ip_proto;
2141 + if(p->iph->ip_proto==IPPROTO_TCP || p->iph->ip_proto==IPPROTO_UDP)
2142 + { lastbsp[lastbpointer]=p->sp; /* set ports if TCP or UDP */
2143 + lastbdp[lastbpointer]=p->dp;
2144 + }
2145 + lastbtime[lastbpointer]=btime;
2146 +
2147 +
2148 + while(fwsamlist!=NULL)
2149 + { station=fwsamlist->station;
2150 + //if(station->stationip.s_addr)
2151 + if(station->stationip.ip32[0])
2152 + { deletestation=FALSE;
2153 + stationtry++; /* first try */
2154 + /* create a socket for the station */
2155 + stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
2156 + if(stationsocket==INVALID_SOCKET)
2157 + FatalError("ERROR => [Alert_FWsam] Funky socket error (socket)!\n");
2158 + if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr)))
2159 + FatalError("ERROR => [Alert_FWsam] Could not bind socket!\n");
2160 +
2161 + /* let's connect to the agent */
2162 + if(connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr)))
2163 + {
2164 + LogMessage("WARNING => [Alert_FWsam] Could not send block to host %s. Will try later.\n",sfip_ntoa(&station->stationip));
2165 +#ifdef WIN32
2166 + closesocket(stationsocket);
2167 +#else
2168 + close(stationsocket);
2169 +#endif
2170 + stationtry=0;
2171 + }
2172 + else
2173 + {
2174 +#ifdef FWSAMDEBUG
2175 + LogMessage("DEBUG => [Alert_FWsam] Connected to host %s.\n",sfip_ntoa(&station->stationip));
2176 +#endif
2177 + /* now build the packet */
2178 + station->myseqno+=station->stationseqno; /* increase my seqno by adding agent seq no */
2179 + sampacket.endiancheck=1; /* This is an endian indicator for Snortsam */
2180 + sampacket.snortseqno[0]=(char)station->myseqno;
2181 + sampacket.snortseqno[1]=(char)(station->myseqno>>8);
2182 + sampacket.fwseqno[0]=(char)station->stationseqno;/* fill station seqno */
2183 + sampacket.fwseqno[1]=(char)(station->stationseqno>>8);
2184 + sampacket.status=FWSAM_STATUS_BLOCK; /* set block mode */
2185 + sampacket.version=FWSAM_PACKETVERSION; /* set packet version */
2186 + sampacket.duration[0]=(char)optp->duration; /* set duration */
2187 + sampacket.duration[1]=(char)(optp->duration>>8);
2188 + sampacket.duration[2]=(char)(optp->duration>>16);
2189 + sampacket.duration[3]=(char)(optp->duration>>24);
2190 + sampacket.fwmode=optp->how|optp->who|optp->loglevel; /* set the mode */
2191 + sampacket.dstip[0]=(char)p->iph->ip_dst.s_addr; /* destination IP */
2192 + sampacket.dstip[1]=(char)(p->iph->ip_dst.s_addr>>8);
2193 + sampacket.dstip[2]=(char)(p->iph->ip_dst.s_addr>>16);
2194 + sampacket.dstip[3]=(char)(p->iph->ip_dst.s_addr>>24);
2195 + sampacket.srcip[0]=(char)p->iph->ip_src.s_addr; /* source IP */
2196 + sampacket.srcip[1]=(char)(p->iph->ip_src.s_addr>>8);
2197 + sampacket.srcip[2]=(char)(p->iph->ip_src.s_addr>>16);
2198 + sampacket.srcip[3]=(char)(p->iph->ip_src.s_addr>>24);
2199 + sampacket.protocol[0]=(char)p->iph->ip_proto; /* protocol */
2200 + sampacket.protocol[1]=(char)(p->iph->ip_proto>>8);/* protocol */
2201 +
2202 + if(p->iph->ip_proto==IPPROTO_TCP || p->iph->ip_proto==IPPROTO_UDP)
2203 + { sampacket.srcport[0]=(char)p->sp; /* set ports */
2204 + sampacket.srcport[1]=(char)(p->sp>>8);
2205 + sampacket.dstport[0]=(char)p->dp;
2206 + sampacket.dstport[1]=(char)(p->dp>>8);
2207 + }
2208 + else
2209 + sampacket.srcport[0]=sampacket.srcport[1]=sampacket.dstport[0]=sampacket.dstport[1]=0;
2210 +
2211 + sampacket.sig_id[0]=(char)event->sig_id; /* set signature ID */
2212 + sampacket.sig_id[1]=(char)(event->sig_id>>8);
2213 + sampacket.sig_id[2]=(char)(event->sig_id>>16);
2214 + sampacket.sig_id[3]=(char)(event->sig_id>>24);
2215 +
2216 +#ifdef FWSAMDEBUG
2217 + LogMessage("DEBUG => [Alert_FWsam] Sending BLOCK\n");
2218 + LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo: %x\n",station->myseqno);
2219 + LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo : %x\n",station->stationseqno);
2220 + LogMessage("DEBUG => [Alert_FWsam] Status : %i\n",FWSAM_STATUS_BLOCK);
2221 + LogMessage("DEBUG => [Alert_FWsam] Mode : %i\n",optp->how|optp->who|optp->loglevel);
2222 + LogMessage("DEBUG => [Alert_FWsam] Duration : %li\n",optp->duration);
2223 + LogMessage("DEBUG => [Alert_FWsam] Protocol : %i\n",GET_IPH_PROTO(p));
2224 +#ifdef SUP_IP6
2225 + LogMessage("DEBUG => [Alert_FWsam] Src IP : %s\n",sfip_ntoa(GET_SRC_IP(p)));
2226 + LogMessage("DEBUG => [Alert_FWsam] Dest IP : %s\n",sfip_ntoa(GET_DST_IP(p)));
2227 +#else
2228 + LogMessage("DEBUG => [Alert_FWsam] Src IP : %s\n",inet_ntoa(p->iph->ip_src));
2229 + LogMessage("DEBUG => [Alert_FWsam] Dest IP : %s\n",inet_ntoa(p->iph->ip_dst));
2230 +#endif
2231 + LogMessage("DEBUG => [Alert_FWsam] Src Port : %i\n",p->sp);
2232 + LogMessage("DEBUG => [Alert_FWsam] Dest Port : %i\n",p->dp);
2233 + LogMessage("DEBUG => [Alert_FWsam] Sig_ID : %lu\n",event->sig_id);
2234 +
2235 +#endif
2236 +
2237 + encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get the encryption buffer */
2238 + len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt the packet with current key */
2239 +
2240 + if(send(stationsocket,encbuf,len,0)!=len) /* weird...could not send */
2241 + { LogMessage("WARNING => [Alert_FWsam] Could not send to host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
2242 +#ifdef WIN32
2243 + closesocket(stationsocket);
2244 +#else
2245 + close(stationsocket);
2246 +#endif
2247 + stationtry=0;
2248 + }
2249 + else
2250 + { i=FWSAM_NETWAIT;
2251 +#ifdef WIN32
2252 + ioctlsocket(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
2253 +#else
2254 + ioctl(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
2255 +#endif
2256 + while(i-- >1) /* the response packet */
2257 + { waitms(10); /* wait for response (default maximum 3 secs */
2258 + if(recv(stationsocket,encbuf,len,0)==len)
2259 + i=0; /* if we received packet we set the counter to 0. */
2260 + /* by the time we check with if, it's already dec'ed to -1 */
2261 + }
2262 + if(!i) /* id we timed out (i was one, then dec'ed)... */
2263 + { LogMessage("WARNING => [Alert_FWsam] Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
2264 +#ifdef WIN32
2265 + closesocket(stationsocket);
2266 +#else
2267 + close(stationsocket);
2268 +#endif
2269 + stationtry=0;
2270 + }
2271 + else /* got a packet */
2272 + { decbuf=(char *)&sampacket; /* get the pointer to the packet struct */
2273 + len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt the packet with current key */
2274 +
2275 + if(len!=sizeof(FWsamPacket)) /* invalid decryption */
2276 + { strcpy(station->stationkey,station->initialkey); /* try the intial key */
2277 + TwoFishDestroy(station->stationfish);
2278 + station->stationfish=TwoFishInit(station->stationkey); /* re-initialize the TwoFish with the intial key */
2279 + len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try again to decrypt */
2280 + LogMessage("INFO => [Alert_FWsam] Had to use initial key!\n");
2281 + }
2282 + if(len==sizeof(FWsamPacket)) /* valid decryption */
2283 + { if(sampacket.version==FWSAM_PACKETVERSION)/* master speaks my language */
2284 + { if(sampacket.status==FWSAM_STATUS_OK || sampacket.status==FWSAM_STATUS_NEWKEY
2285 + || sampacket.status==FWSAM_STATUS_RESYNC || sampacket.status==FWSAM_STATUS_HOLD)
2286 + { station->stationseqno=sampacket.fwseqno[0] | (sampacket.fwseqno[1]<<8); /* get stations seqno */
2287 + station->lastcontact=(unsigned long)time(NULL); /* set the last contact time (not used yet) */
2288 +#ifdef FWSAMDEBUG
2289 + LogMessage("DEBUG => [Alert_FWsam] Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK":
2290 + sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY":
2291 + sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC":
2292 + sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR");
2293 + LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo: %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8));
2294 + LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo : %x\n",station->stationseqno);
2295 + LogMessage("DEBUG => [Alert_FWsam] Status : %i\n",sampacket.status);
2296 + LogMessage("DEBUG => [Alert_FWsam] Version : %i\n",sampacket.version);
2297 +#endif
2298 + if(sampacket.status==FWSAM_STATUS_HOLD)
2299 + { i=FWSAM_NETHOLD; /* Stay on hold for a maximum of 60 secs (default) */
2300 + while(i-- >1) /* the response packet */
2301 + { waitms(10); /* wait for response */
2302 + if(recv(stationsocket,encbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,0)==sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE)
2303 + i=0; /* if we received packet we set the counter to 0. */
2304 + }
2305 + if(!i) /* id we timed out (i was one, then dec'ed)... */
2306 + { LogMessage("WARNING => [Alert_FWsam] Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
2307 + stationtry=0;
2308 + sampacket.status=FWSAM_STATUS_ERROR;
2309 + }
2310 + else /* got a packet */
2311 + { decbuf=(char *)&sampacket; /* get the pointer to the packet struct */
2312 + len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt the packet with current key */
2313 +
2314 + if(len!=sizeof(FWsamPacket)) /* invalid decryption */
2315 + { strcpy(station->stationkey,station->initialkey); /* try the intial key */
2316 + TwoFishDestroy(station->stationfish);
2317 + station->stationfish=TwoFishInit(station->stationkey); /* re-initialize the TwoFish with the intial key */
2318 + len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try again to decrypt */
2319 + LogMessage("INFO => [Alert_FWsam] Had to use initial key again!\n");
2320 + }
2321 +#ifdef FWSAMDEBUG
2322 + LogMessage("DEBUG => [Alert_FWsam] Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK":
2323 + sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY":
2324 + sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC":
2325 + sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR");
2326 + LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo: %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8));
2327 + LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo : %x\n",station->stationseqno);
2328 + LogMessage("DEBUG => [Alert_FWsam] Status : %i\n",sampacket.status);
2329 + LogMessage("DEBUG => [Alert_FWsam] Version : %i\n",sampacket.version);
2330 +#endif
2331 + if(len!=sizeof(FWsamPacket)) /* invalid decryption */
2332 + { ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
2333 + deletestation=TRUE;
2334 + sampacket.status=FWSAM_STATUS_ERROR;
2335 + }
2336 + else if(sampacket.version!=FWSAM_PACKETVERSION) /* invalid protocol version */
2337 + { ErrorMessage("ERROR => [Alert_FWsam] Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
2338 + deletestation=TRUE;
2339 + sampacket.status=FWSAM_STATUS_ERROR;
2340 + }
2341 + else if(sampacket.status!=FWSAM_STATUS_OK && sampacket.status!=FWSAM_STATUS_NEWKEY && sampacket.status!=FWSAM_STATUS_RESYNC)
2342 + { ErrorMessage("ERROR => [Alert_FWsam] Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
2343 + deletestation=TRUE;
2344 + sampacket.status=FWSAM_STATUS_ERROR;
2345 + }
2346 + }
2347 + }
2348 + if(sampacket.status==FWSAM_STATUS_RESYNC) /* if station want's to resync... */
2349 + { strcpy(station->stationkey,station->initialkey); /* ...we use the intial key... */
2350 + memcpy(station->fwkeymod,sampacket.duration,4); /* and note the random key modifier */
2351 + }
2352 + if(sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC)
2353 + {
2354 + FWsamNewStationKey(station,&sampacket); /* generate new TwoFish keys */
2355 +#ifdef FWSAMDEBUG
2356 + LogMessage("DEBUG => [Alert_FWsam] Generated new encryption key...\n");
2357 +#endif
2358 + }
2359 +#ifdef WIN32
2360 + closesocket(stationsocket);
2361 +#else
2362 + close(stationsocket);
2363 +#endif
2364 + stationtry=0;
2365 + }
2366 + else if(sampacket.status==FWSAM_STATUS_ERROR) /* if SnortSam reports an error on second try, */
2367 + {
2368 +#ifdef WIN32
2369 + closesocket(stationsocket); /* something is messed up and ... */
2370 +#else
2371 + close(stationsocket);
2372 +#endif
2373 + if(stationtry>1) /* we ignore that station. */
2374 + { deletestation=TRUE; /* flag for deletion */
2375 + ErrorMessage("ERROR => [Alert_FWsam] Could not renegotiate key! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
2376 + }
2377 + else /* if we get an error on the first try, */
2378 + { if(!FWsamCheckIn(station)) /* we first try to check in again. */
2379 + { deletestation=TRUE;
2380 + ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
2381 + }
2382 + }
2383 + }
2384 + else /* an unknown status means trouble... */
2385 + { ErrorMessage("ERROR => [Alert_FWsam] Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
2386 +#ifdef WIN32
2387 + closesocket(stationsocket);
2388 +#else
2389 + close(stationsocket);
2390 +#endif
2391 + deletestation=TRUE;
2392 + }
2393 + }
2394 + else /* if the SnortSam agent uses a different packet version, we have no choice but to ignore it. */
2395 + { ErrorMessage("ERROR => [Alert_FWsam] Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
2396 +#ifdef WIN32
2397 + closesocket(stationsocket);
2398 +#else
2399 + close(stationsocket);
2400 +#endif
2401 + deletestation=TRUE;
2402 + }
2403 + }
2404 + else /* if the intial key failed to decrypt as well, the keys are not configured the same, and we ignore that SnortSam station. */
2405 + { ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
2406 +#ifdef WIN32
2407 + closesocket(stationsocket);
2408 +#else
2409 + close(stationsocket);
2410 +#endif
2411 + deletestation=TRUE;
2412 + }
2413 + }
2414 + }
2415 + free(encbuf); /* release of the TwoFishAlloc'ed encryption buffer */
2416 + }
2417 + if(stationtry==0 || deletestation) /* if everything went real well, or real bad... */
2418 + { if(deletestation){ /* If it went bad, we remove the station from the list by marking the IP */
2419 +// station->stationip.s_addr=0;
2420 + station->stationip.ip32[0]=0;
2421 + }
2422 + fwsamlist=fwsamlist->next;
2423 + }
2424 + }
2425 + else
2426 + fwsamlist=fwsamlist->next;
2427 + }
2428 + }
2429 + else
2430 + {
2431 +#ifdef FWSAMDEBUG
2432 + LogMessage("DEBUG => [Alert_FWsam] Skipping repetitive block.\n");
2433 +#endif
2434 + }
2435 + }
2436 +}
2437 +
2438 +/* FWsamCheckOut will be called when Snort exists. It de-registeres this snort sensor
2439 + * from the list of sensor that the SnortSam agent keeps.
2440 + */
2441 +void FWsamCheckOut(FWsamStation *station)
2442 +{ FWsamPacket sampacket;
2443 + SOCKET stationsocket;
2444 + int i,len;
2445 + char *encbuf,*decbuf;
2446 + //unsigned char *encbuf,*decbuf;
2447 +
2448 +
2449 + stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
2450 + if(stationsocket==INVALID_SOCKET)
2451 + FatalError("ERROR => [Alert_FWsam](FWsamCheckOut) Funky socket error (socket)!\n");
2452 + if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr)))
2453 + FatalError("ERROR => [Alert_FWsam](FWsamCheckOut) Could not bind socket!\n");
2454 +
2455 + /* let's connect to the agent */
2456 + if(!connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr)))
2457 + { LogMessage("INFO => [Alert_FWsam](FWsamCheckOut) Disconnecting from host %s.\n",sfip_ntoa(&station->stationip));
2458 + /* now build the packet */
2459 + station->myseqno+=station->stationseqno; /* increase my seqno */
2460 + sampacket.endiancheck=1;
2461 + sampacket.snortseqno[0]=(char)station->myseqno;
2462 + sampacket.snortseqno[1]=(char)(station->myseqno>>8);
2463 + sampacket.fwseqno[0]=(char)station->stationseqno; /* fill station seqno */
2464 + sampacket.fwseqno[1]=(char)(station->stationseqno>>8);
2465 + sampacket.status=FWSAM_STATUS_CHECKOUT; /* checking out... */
2466 + sampacket.version=FWSAM_PACKETVERSION;
2467 +
2468 +#ifdef FWSAMDEBUG
2469 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Sending CHECKOUT\n");
2470 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Snort SeqNo: %x\n",station->myseqno);
2471 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Mgmt SeqNo : %x\n",station->stationseqno);
2472 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Status : %i\n",sampacket.status);
2473 +
2474 +#endif
2475 +
2476 + encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get encryption buffer */
2477 + len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt packet with current key */
2478 +
2479 + if(send(stationsocket,encbuf,len,0)==len)
2480 + { i=FWSAM_NETWAIT;
2481 +#ifdef WIN32
2482 + ioctlsocket(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
2483 +#else
2484 + ioctl(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
2485 +#endif
2486 + while(i-- >1)
2487 + { waitms(10); /* ...wait a maximum of 3 secs for response... */
2488 + if(recv(stationsocket,encbuf,len,0)==len) /* ... for the status packet */
2489 + i=0;
2490 + }
2491 + if(i) /* if we got the packet */
2492 + { decbuf=(char *)&sampacket;
2493 + len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish);
2494 +
2495 + if(len!=sizeof(FWsamPacket)) /* invalid decryption */
2496 + { strcpy(station->stationkey,station->initialkey); /* try initial key */
2497 + TwoFishDestroy(station->stationfish); /* toss this fish */
2498 + station->stationfish=TwoFishInit(station->stationkey); /* re-initialze TwoFish with initial key */
2499 + len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* and try to decrypt again */
2500 + LogMessage("INFO => [Alert_FWsam](FWsamCheckOut) Had to use initial key!\n");
2501 + }
2502 + if(len==sizeof(FWsamPacket)) /* valid decryption */
2503 + { if(sampacket.version!=FWSAM_PACKETVERSION) /* but don't really care since we are on the way out */
2504 + ErrorMessage("WARNING => [Alert_FWsam](FWsamCheckOut) Protocol version error! What the hell, we're quitting anyway! :)\n");
2505 + }
2506 + else
2507 + ErrorMessage("WARNING => [Alert_FWsam](FWsamCheckOut) Password mismatch! What the hell, we're quitting anyway! :)\n");
2508 + }
2509 + }
2510 + free(encbuf); /* release TwoFishAlloc'ed buffer */
2511 + }
2512 + else
2513 + LogMessage("WARNING => [Alert_FWsam] Could not connect to host %s for CheckOut. What the hell, we're quitting anyway! :)\n",sfip_ntoa(&station->stationip));
2514 +#ifdef WIN32
2515 + closesocket(stationsocket);
2516 +#else
2517 + close(stationsocket);
2518 +#endif
2519 +}
2520 +
2521 +
2522 +/* FWSamFree: Disconnects all FW-1 management stations,
2523 + * closes sockets, and frees the structures.
2524 + */
2525 +void FWsamFree(FWsamList *list)
2526 +{
2527 + FWsamList *next;
2528 +
2529 + while(list) /* Free pointer list for rule type */
2530 + {
2531 + next=list->next;
2532 + free(list);
2533 + list=next;
2534 + }
2535 + list=FWsamStationList;
2536 +
2537 + while(list) /* Free global pointer list and stations */
2538 + {
2539 + next=list->next;
2540 + if (list->station)
2541 + {
2542 + if(list->station->stationip.ip32[0])
2543 + //if(list->station->stationip.s_addr)
2544 + FWsamCheckOut(list->station); /* Send a Check-Out to SnortSam, */
2545 +
2546 + TwoFishDestroy(list->station->stationfish); /* toss the fish, */
2547 + free(list->station); /* free station, */
2548 + }
2549 + free(list); /* free pointer, */
2550 + list=next; /* and move to next. */
2551 + }
2552 + FWsamStationList=NULL;
2553 + if(FWsamOptionField)
2554 + free(FWsamOptionField);
2555 +}
2556 +
2557 +void AlertFWsamCleanExitFunc(int signal, void *arg)
2558 +{ FWsamList *fwsamlist;
2559 +
2560 +#ifdef FWSAMDEBUG
2561 + LogMessage("DEBUG => [Alert_FWsam](AlertFWsamCleanExitFunc) Exiting...\n");
2562 +#endif
2563 +
2564 + fwsamlist=(FWsamList *)arg;
2565 + FWsamFree(fwsamlist); /* Free all elements */
2566 +}
2567 +
2568 +void AlertFWsamRestartFunc(int signal, void *arg)
2569 +{ FWsamList *fwsamlist;
2570 +
2571 +#ifdef FWSAMDEBUG
2572 + LogMessage("DEBUG => [Alert_FWsam](AlertFWsamRestartFunc) Restarting...\n");
2573 +#endif
2574 +
2575 + fwsamlist=(FWsamList *)arg;
2576 + FWsamFree(fwsamlist); /* Free all elements */
2577 +}
2578 +
2579 +/* This routine registers this Snort sensor with SnortSam.
2580 + * It will also change the encryption key based on some variables.
2581 + */
2582 +int FWsamCheckIn(FWsamStation *station)
2583 +{ int i,len,stationok=TRUE;
2584 + FWsamPacket sampacket;
2585 + char *encbuf,*decbuf;
2586 + //unsigned char *encbuf,*decbuf;
2587 + SOCKET stationsocket;
2588 +
2589 +
2590 + /* create a socket for the station */
2591 + stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
2592 + if(stationsocket==INVALID_SOCKET)
2593 + FatalError("ERROR => [Alert_FWsam](FWsamCheckIn) Funky socket error (socket)!\n");
2594 + if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr)))
2595 + FatalError("ERROR => [Alert_FWsam](FWsamCheckIn) Could not bind socket!\n");
2596 +
2597 + i=TRUE;
2598 + /* let's connect to the agent */
2599 + if(connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr)))
2600 + LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Could not connect to host %s. Will try later.\n",sfip_ntoa(&station->stationip));
2601 + else
2602 + { LogMessage("INFO => [Alert_FWsam](FWsamCheckIn) Connected to host %s.\n",sfip_ntoa(&station->stationip));
2603 + /* now build the packet */
2604 + sampacket.endiancheck=1;
2605 + sampacket.snortseqno[0]=(char)station->myseqno; /* fill my sequence number number */
2606 + sampacket.snortseqno[1]=(char)(station->myseqno>>8); /* fill my sequence number number */
2607 + sampacket.status=FWSAM_STATUS_CHECKIN; /* let's check in */
2608 + sampacket.version=FWSAM_PACKETVERSION; /* set the packet version */
2609 + memcpy(sampacket.duration,station->mykeymod,4); /* we'll send SnortSam our key modifier in the duration slot */
2610 + /* (the checkin packet is just the plain initial key) */
2611 +#ifdef FWSAMDEBUG
2612 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Sending CheckIn\n");
2613 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Snort SeqNo: %x\n",station->myseqno);
2614 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Mode : %i\n",sampacket.status);
2615 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Version : %i\n",sampacket.version);
2616 +#endif
2617 + encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get buffer for encryption */
2618 + len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt with initial key */
2619 + if(send(stationsocket,encbuf,len,0)!=len) /* weird...could not send */
2620 + LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Could not send to host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
2621 + else
2622 + { i=FWSAM_NETWAIT;
2623 +#ifdef WIN32
2624 + ioctlsocket(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
2625 +#else
2626 + ioctl(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
2627 +#endif
2628 + while(i-- >1)
2629 + { waitms(10); /* wait a maximum of 3 secs for response */
2630 + if(recv(stationsocket,encbuf,len,0)==len)
2631 + i=0;
2632 + }
2633 + if(!i) /* time up? */
2634 + LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
2635 + else
2636 + { decbuf=(char *)&sampacket; /* got status packet */
2637 + len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt with initial key */
2638 + if(len==sizeof(FWsamPacket)) /* valid decryption */
2639 + {
2640 +#ifdef FWSAMDEBUG
2641 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK":
2642 + sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY":
2643 + sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC":
2644 + sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR");
2645 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Snort SeqNo: %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8));
2646 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Mgmt SeqNo : %x\n",sampacket.fwseqno[0]|(sampacket.fwseqno[1]<<8));
2647 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Status : %i\n",sampacket.status);
2648 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Version : %i\n",sampacket.version);
2649 +#endif
2650 + if(sampacket.version==FWSAM_PACKETVERSION) /* master speaks my language */
2651 + { if(sampacket.status==FWSAM_STATUS_OK || sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC)
2652 + { station->stationseqno=sampacket.fwseqno[0]|(sampacket.fwseqno[1]<<8); /* get stations seqno */
2653 + station->lastcontact=(unsigned long)time(NULL);
2654 +
2655 + if(sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC) /* generate new keys */
2656 + { memcpy(station->fwkeymod,sampacket.duration,4); /* note the key modifier */
2657 + FWsamNewStationKey(station,&sampacket); /* and generate new TwoFish keys (with key modifiers) */
2658 +#ifdef FWSAMDEBUG
2659 + LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Generated new encryption key...\n");
2660 +#endif
2661 + }
2662 + }
2663 + else /* weird, got a strange status back */
2664 + { ErrorMessage("ERROR => [Alert_FWsam](FWsamCheckIn) Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
2665 + stationok=FALSE;
2666 + }
2667 + }
2668 + else /* packet version does not match */
2669 + { ErrorMessage("ERROR =>[Alert_FWsam](FWsamCheckIn) Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
2670 + stationok=FALSE;
2671 + }
2672 + }
2673 + else /* key does not match */
2674 + { ErrorMessage("ERROR => [Alert_FWsam](FWsamCheckIn) Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
2675 + stationok=FALSE;
2676 + }
2677 + }
2678 + }
2679 + free(encbuf); /* release TwoFishAlloc'ed buffer */
2680 + }
2681 +#ifdef WIN32
2682 + closesocket(stationsocket);
2683 +#else
2684 + close(stationsocket);
2685 +#endif
2686 + return stationok;
2687 +}
2688 +#undef FWSAMDEBUG
2689 +
2690 --- snort-2.9.0/src/output-plugins/spo_alert_fwsam.h 1970-01-01 01:00:00.000000000 +0100
2691 +++ snort-2.9.0.dlucio/src/output-plugins/spo_alert_fwsam.h 2010-10-08 18:05:37.000000000 +0200
2692 @@ -0,0 +1,216 @@
2693 +/* $Id: snortpatchb,v 1.5 2005/10/06 08:50:39 fknobbe Exp $
2694 +**
2695 +** spo_alert_fwsam.h
2696 +**
2697 +** Copyright (c) 2001-2004 Frank Knobbe <frank@knobbe.us>
2698 +**
2699 +** This program is free software; you can redistribute it and/or modify
2700 +** it under the terms of the GNU General Public License as published by
2701 +** the Free Software Foundation; either version 2 of the License, or
2702 +** (at your option) any later version.
2703 +**
2704 +** This program is distributed in the hope that it will be useful,
2705 +** but WITHOUT ANY WARRANTY; without even the implied warranty of
2706 +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2707 +** GNU General Public License for more details.
2708 +**
2709 +** You should have received a copy of the GNU General Public License
2710 +** along with this program; if not, write to the Free Software
2711 +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2712 +*/
2713 +
2714 +/* This file gets included in plugbase.c when it is integrated into the rest
2715 + * of the program.
2716 + *
2717 + * For more info, see the beginning of spo_alert_fwsam.c
2718 + *
2719 + */
2720 +
2721 +#ifndef __SPO_FWSAM_H__
2722 +#define __SPO_FWSAM_H__
2723 +
2724 +#include "snort.h"
2725 +#include "rules.h"
2726 +#include "plugbase.h"
2727 +#include "plugin_enum.h"
2728 +#include "fatal.h"
2729 +#include "util.h"
2730 +#include "twofish.h"
2731 +
2732 +#include <stdlib.h>
2733 +#include <stdio.h>
2734 +#include <time.h>
2735 +#include <string.h>
2736 +#include <ctype.h>
2737 +#include <unistd.h>
2738 +
2739 +
2740 +/* just some compatibility stuff */
2741 +#ifdef WIN32
2742 +#if !defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
2743 +#include <winsock.h>
2744 +#endif
2745 +#define waitms(x) Sleep(x)
2746 +
2747 +#else
2748 +
2749 +#include <sys/socket.h>
2750 +#include <netinet/in.h>
2751 +#include <arpa/inet.h>
2752 +#include <sys/ioctl.h>
2753 +#include <netdb.h>
2754 +
2755 +#ifdef SOLARIS
2756 +#include <sys/filio.h>
2757 +#endif
2758 +
2759 +typedef int SOCKET;
2760 +
2761 +#ifndef INVALID_SOCKET
2762 +#define INVALID_SOCKET -1
2763 +#endif
2764 +
2765 +#define waitms(x) usleep((x)*1000)
2766 +
2767 +#endif
2768 +
2769 +#ifndef FALSE
2770 +#define FALSE 0
2771 +#endif
2772 +#ifndef TRUE
2773 +#define TRUE !FALSE
2774 +#endif
2775 +#ifndef bool
2776 +#define bool int
2777 +#endif
2778 +
2779 +
2780 +#if defined(_DEBUG) || defined(DEBUG)
2781 +#ifndef FWSAMDEBUG
2782 +#define FWSAMDEBUG
2783 +#endif
2784 +#else
2785 +#endif
2786 +
2787 +
2788 +/* Official Snort PlugIn Number has been moved into plugin_enum.h */
2789 +
2790 +
2791 +/* fixed defines */
2792 +
2793 +#define FWSAM_DEFAULTPORT 898 /* Default port if user does not specify one in snort.conf */
2794 + /* (Was unused last time I checked...) */
2795 +#define FWSAM_PACKETVERSION 14 /* version of the packet. Will increase with enhancements. */
2796 +
2797 +#define FWSAM_STATUS_CHECKIN 1 /* snort to fw */
2798 +#define FWSAM_STATUS_CHECKOUT 2
2799 +#define FWSAM_STATUS_BLOCK 3
2800 +#define FWSAM_STATUS_UNBLOCK 9
2801 +
2802 +#define FWSAM_STATUS_OK 4 /* fw to snort */
2803 +#define FWSAM_STATUS_ERROR 5
2804 +#define FWSAM_STATUS_NEWKEY 6
2805 +#define FWSAM_STATUS_RESYNC 7
2806 +#define FWSAM_STATUS_HOLD 8
2807 +
2808 +#define FWSAM_LOG_NONE 0
2809 +#define FWSAM_LOG_SHORTLOG 1
2810 +#define FWSAM_LOG_SHORTALERT 2
2811 +#define FWSAM_LOG_LONGLOG 3
2812 +#define FWSAM_LOG_LONGALERT 4
2813 +#define FWSAM_LOG (FWSAM_LOG_SHORTLOG|FWSAM_LOG_SHORTALERT|FWSAM_LOG_LONGLOG|FWSAM_LOG_LONGALERT)
2814 +#define FWSAM_WHO_DST 8
2815 +#define FWSAM_WHO_SRC 16
2816 +#define FWSAM_WHO (FWSAM_WHO_DST|FWSAM_WHO_SRC)
2817 +#define FWSAM_HOW_IN 32
2818 +#define FWSAM_HOW_OUT 64
2819 +#define FWSAM_HOW_INOUT (FWSAM_HOW_IN|FWSAM_HOW_OUT)
2820 +#define FWSAM_HOW_THIS 128
2821 +#define FWSAM_HOW (FWSAM_HOW_IN|FWSAM_HOW_OUT|FWSAM_HOW_THIS)
2822 +
2823 +
2824 +/* user adjustable defines */
2825 +
2826 +#define FWSAM_REPET_BLOCKS 10 /* Snort remembers this amount of last blocks and... */
2827 +#define FWSAM_REPET_TIME 20 /* ...checks if they fall within this time. If so,... */
2828 + /* ...the blocking request is not send. */
2829 +
2830 +#define FWSAM_NETWAIT 300 /* 100th of a second. 3 sec timeout for network connections */
2831 +#define FWSAM_NETHOLD 6000 /* 100th of a second. 60 sec timeout for holding */
2832 +
2833 +#define SID_MAPFILE "sid-block.map"
2834 +#define SID_ALT_MAPFILE "sid-fwsam.map"
2835 +
2836 +#define FWSAM_FANCYFETCH /* This will invoke a fast sid lookup routine */
2837 +
2838 +
2839 +/* vars */
2840 +
2841 +typedef struct _FWsamstation /* structure of a mgmt station */
2842 +{ unsigned short myseqno;
2843 + unsigned short stationseqno;
2844 + unsigned char mykeymod[4];
2845 + unsigned char fwkeymod[4];
2846 + unsigned short stationport;
2847 + //struct in_addr stationip;
2848 + sfip_t stationip;
2849 + struct sockaddr_in localsocketaddr;
2850 + struct sockaddr_in stationsocketaddr;
2851 + TWOFISH *stationfish;
2852 + char initialkey[TwoFish_KEY_LENGTH+2];
2853 + char stationkey[TwoFish_KEY_LENGTH+2];
2854 + time_t lastcontact;
2855 +/* time_t sleepstart; */
2856 +} FWsamStation;
2857 +
2858 +typedef struct _FWsampacket /* 2 blocks (3rd block is header from TwoFish) */
2859 +{ unsigned short endiancheck; /* 0 */
2860 + unsigned char srcip[4]; /* 2 */
2861 + unsigned char dstip[4]; /* 6 */
2862 + unsigned char duration[4]; /* 10 */
2863 + unsigned char snortseqno[2]; /* 14 */
2864 + unsigned char fwseqno[2]; /* 16 */
2865 + unsigned char srcport[2]; /* 18 */
2866 + unsigned char dstport[2]; /* 20 */
2867 + unsigned char protocol[2]; /* 22 */
2868 + unsigned char fwmode; /* 24 */
2869 + unsigned char version; /* 25 */
2870 + unsigned char status; /* 26 */
2871 + unsigned char sig_id[4]; /* 27 */
2872 + unsigned char fluff; /* 31 */
2873 +} FWsamPacket; /* 32 bytes in size */
2874 +
2875 +typedef struct _FWsamoptions /* snort rule options */
2876 +{ unsigned long sid;
2877 + unsigned long duration;
2878 + unsigned char who;
2879 + unsigned char how;
2880 + unsigned char loglevel;
2881 +} FWsamOptions;
2882 +
2883 +typedef struct _FWsamlistpointer
2884 +{ FWsamStation *station;
2885 + struct _FWsamlistpointer *next;
2886 +} FWsamList;
2887 +
2888 +
2889 +/* functions */
2890 +void AlertFWsamSetup(void);
2891 +void AlertFWsamInit(char *args);
2892 +void AlertFWsamOptionInit(char *args,OptTreeNode *otn,int protocol);
2893 +void AlertFWsamCleanExitFunc(int signal, void *arg);
2894 +void AlertFWsamRestartFunc(int signal, void *arg);
2895 +void AlertFWsam(Packet *p, char *msg, void *arg, Event *event);
2896 +int FWsamCheckIn(FWsamStation *station);
2897 +void FWsamCheckOut(FWsamStation *station);
2898 +void FWsamNewStationKey(FWsamStation *station,FWsamPacket *packet);
2899 +void FWsamFixPacketEndian(FWsamPacket *p);
2900 +unsigned long FWsamParseDuration(char *p);
2901 +void FWsamFree(FWsamList *fwsamlist);
2902 +int FWsamStationExists(FWsamStation *who,FWsamList *list);
2903 +int FWsamReadLine(char *,unsigned long,FILE *);
2904 +void FWsamParseLine(FWsamOptions *,char *);
2905 +FWsamOptions *FWsamGetOption(unsigned long);
2906 +int FWsamParseOption(FWsamOptions *,char *);
2907 +
2908 +#endif /* __SPO_FWSAM_H__ */
2909 --- snort-2.9.0/src/output-plugins/Makefile.am 2010-06-10 00:05:17.000000000 +0200
2910 +++ snort-2.9.0.dlucio/src/output-plugins/Makefile.am 2010-10-08 18:07:33.000000000 +0200
2911 @@ -15,6 +15,7 @@
2912 spo_log_tcpdump.h spo_unified.c spo_unified2.c spo_unified.h spo_unified2.h \
2913 spo_log_ascii.c spo_log_ascii.h spo_alert_sf_socket.h spo_alert_sf_socket.c \
2914 $(PRELUDE_CODE) spo_alert_arubaaction.c spo_alert_arubaaction.h \
2915 +spo_alert_fwsam.c spo_alert_fwsam.h \
2916 spo_alert_test.c spo_alert_test.h
2917
2918 INCLUDES = @INCLUDES@
2919 --- snort-2.9.0/src/plugbase.c 2010-08-25 22:22:38.000000000 +0200
2920 +++ snort-2.9.0.dlucio/src/plugbase.c 2010-10-08 18:05:37.000000000 +0200
2921 @@ -129,6 +129,7 @@
2922 #endif
2923
2924 #include "output-plugins/spo_alert_test.h"
2925 +#include "output-plugins/spo_alert_fwsam.h"
2926
2927 extern ListHead *head_tmp;
2928 extern PreprocConfigFuncNode *preproc_config_funcs;
2929 @@ -1400,6 +1401,7 @@
2930 #endif
2931
2932 AlertTestSetup();
2933 + AlertFWsamSetup();
2934 }
2935
2936 /****************************************************************************
2937 --- snort-2.9.0/src/Makefile.am 2010-06-10 00:04:50.000000000 +0200
2938 +++ snort-2.9.0.dlucio/src/Makefile.am 2010-10-08 18:09:34.000000000 +0200
2939 @@ -60,6 +60,7 @@
2940 rate_filter.c rate_filter.h \
2941 obfuscation.c obfuscation.h \
2942 rule_option_types.h \
2943 +twofish.c twofish.h \
2944 sfdaq.c sfdaq.h
2945
2946 snort_LDADD = output-plugins/libspo.a \
2947 --- snort-2.9.0/autojunk.sh 1970-01-01 01:00:00.000000000 +0100
2948 +++ snort-2.9.0.dlucio/autojunk.sh 2010-10-08 18:05:37.000000000 +0200
2949 @@ -0,0 +1,7 @@
2950 +#!/bin/sh
2951 +# the list of commands that need to run before we do a compile
2952 +libtoolize --automake --copy
2953 +aclocal -I m4
2954 +autoheader
2955 +automake --add-missing --copy
2956 +autoconf
2957 --- snort-2.9.0/etc/snort.conf 2010-09-27 18:16:37.000000000 +0200
2958 +++ snort-2.9.0.dlucio/etc/snort.conf 2010-10-08 18:05:37.000000000 +0200
2959 @@ -354,6 +354,32 @@
2960 # prelude
2961 # output alert_prelude
2962
2963 +# snortsam
2964 +# In order to cause Snort to send a blocking request to the SnortSam agent,
2965 +# that agent has to be listed, including the port it listens on,
2966 +# and the encryption key it is using. The statement for that is:
2967 +#
2968 +# output alert_fwsam: {SnortSam Station}:{port}/{password}
2969 +#
2970 +# {SnortSam Station}: IP address or host name of the host where SnortSam is running.
2971 +# {port}: The port the remote SnortSam agent listens on.
2972 +# {password}: The password, or key, used for encryption of the
2973 +# communication to the remote agent.
2974 +#
2975 +# At the very least, the IP address or host name of the host running SnortSam
2976 +# needs to be specified. If the port is omitted, it defaults to TCP port 898.
2977 +# If the password is omitted, it defaults to a preset password.
2978 +# (In which case it needs to be omitted on the SnortSam agent as well)
2979 +#
2980 +# More than one host can be specified, but has to be done on the same line.
2981 +# Just separate them with one or more spaces.
2982 +#
2983 +# Examples:
2984 +#
2985 +# output alert_fwsam: firewall/idspassword
2986 +# output alert_fwsam: fw1.domain.tld:898/mykey
2987 +# output alert_fwsam: 192.168.0.1/borderfw 192.168.1.254/wanfw
2988 +
2989 # metadata reference data. do not modify these lines
2990 include classification.config
2991 include reference.config

  ViewVC Help
Powered by ViewVC 1.1.30