[package] Snort: patch for snortsam support (update for 2.9.2.2)
authorFlorian Fainelli <florian@openwrt.org>
Mon, 13 Aug 2012 14:08:42 +0000 (14:08 +0000)
committerFlorian Fainelli <florian@openwrt.org>
Mon, 13 Aug 2012 14:08:42 +0000 (14:08 +0000)
This patch introduces support for Snort plugin Snortsam. (resend, for snort version 2.9.2.2 - for 2.8.4.1 is located there http://patchwork.openwrt.org/patch/2381/)

Signed-off-by: Jiri Slachta <jiri@slachta.eu>
SVN-Revision: 33170

net/snort/Makefile
net/snort/patches/200-snortsam.patch [new file with mode: 0644]

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