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