Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 172325 Details for
Bug 245752
net-analyzer/snort-2.8.3.1: Fix local use-flag descriptions.
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
snortsam patch
snortsam-2.8.3.diff (text/plain), 168.79 KB, created by
Antixrict
on 2008-11-18 23:17:26 UTC
(
hide
)
Description:
snortsam patch
Filename:
MIME Type:
Creator:
Antixrict
Created:
2008-11-18 23:17:26 UTC
Size:
168.79 KB
patch
obsolete
>diff -uNr snort-2.8.3.1/autojunk.sh snortsam-2.8.3.1/autojunk.sh >--- snort-2.8.3.1/autojunk.sh 1969-12-31 18:00:00.000000000 -0600 >+++ snortsam-2.8.3.1/autojunk.sh 2008-11-05 19:08:29.000000000 -0600 >@@ -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 -uNr snort-2.8.3.1/src/Makefile.am snortsam-2.8.3.1/src/Makefile.am >--- snort-2.8.3.1/src/Makefile.am 2007-11-12 17:10:30.000000000 -0600 >+++ snortsam-2.8.3.1/src/Makefile.am 2008-11-05 19:09:15.000000000 -0600 >@@ -53,7 +53,8 @@ > pcap_pkthdr32.h \ > cpuclock.h \ > sf_types.h \ >-log_text.c log_text.h >+log_text.c log_text.h \ >+twofish.c twofish.h > > snort_LDADD = output-plugins/libspo.a \ > detection-plugins/libspd.a \ >diff -uNr snort-2.8.3.1/src/Makefile.am.orig snortsam-2.8.3.1/src/Makefile.am.orig >--- snort-2.8.3.1/src/Makefile.am.orig 1969-12-31 18:00:00.000000000 -0600 >+++ snortsam-2.8.3.1/src/Makefile.am.orig 2007-11-12 17:10:30.000000000 -0600 >@@ -0,0 +1,74 @@ >+## $Id$ >+AUTOMAKE_OPTIONS=foreign no-dependencies >+ >+bin_PROGRAMS = snort >+ >+snort_SOURCES = cdefs.h \ >+event.h \ >+fatal.h \ >+generators.h \ >+prototypes.h \ >+plugin_enum.h \ >+rules.h \ >+sys_include.h \ >+checksum.h \ >+codes.c codes.h \ >+debug.c debug.h \ >+decode.c decode.h \ >+log.c log.h \ >+mstring.c mstring.h \ >+parser.c parser.h \ >+profiler.c profiler.h \ >+plugbase.c plugbase.h \ >+preprocids.h \ >+snort.c snort.h \ >+build.h \ >+snprintf.c snprintf.h \ >+strlcatu.c strlcatu.h \ >+strlcpyu.c strlcpyu.h \ >+tag.c tag.h \ >+ubi_BinTree.c ubi_BinTree.h \ >+ubi_SplayTree.c ubi_SplayTree.h \ >+util.c util.h \ >+detect.c detect.h \ >+signature.c signature.h \ >+mempool.c mempool.h \ >+sf_sdlist.c sf_sdlist.h \ >+fpcreate.c fpcreate.h \ >+fpdetect.c fpdetect.h \ >+pcrm.c pcrm.h \ >+bounds.h \ >+byte_extract.c \ >+byte_extract.h \ >+timersub.h \ >+spo_plugbase.h \ >+sfthreshold.c sfthreshold.h \ >+packet_time.c packet_time.h \ >+event_wrapper.c event_wrapper.h \ >+smalloc.h \ >+event_queue.c event_queue.h \ >+inline.c inline.h \ >+ipv6_port.h \ >+ppm.c ppm.h \ >+pcap_pkthdr32.h \ >+cpuclock.h \ >+sf_types.h \ >+log_text.c log_text.h >+ >+snort_LDADD = output-plugins/libspo.a \ >+detection-plugins/libspd.a \ >+dynamic-plugins/libdynamic.a \ >+preprocessors/libspp.a \ >+preprocessors/flow/portscan/libportscan.a \ >+preprocessors/flow/libflow.a \ >+parser/libparser.a \ >+target-based/libtarget_based.a \ >+preprocessors/HttpInspect/libhttp_inspect.a \ >+preprocessors/Stream5/libstream5.a \ >+sfutil/libsfutil.a >+ >+EXAMPLES_DIR = dynamic-examples >+ >+SUBDIRS = sfutil win32 output-plugins detection-plugins dynamic-plugins preprocessors parser dynamic-preprocessors target-based $(EXAMPLES_DIR) >+ >+INCLUDES = @INCLUDES@ >diff -uNr snort-2.8.3.1/src/output-plugins/Makefile.am snortsam-2.8.3.1/src/output-plugins/Makefile.am >--- snort-2.8.3.1/src/output-plugins/Makefile.am 2007-08-20 12:26:04.000000000 -0500 >+++ snortsam-2.8.3.1/src/output-plugins/Makefile.am 2008-11-05 19:08:29.000000000 -0600 >@@ -11,6 +11,7 @@ > spo_log_tcpdump.h spo_unified.c spo_unified2.c spo_unified.h spo_unified2.h \ > spo_log_ascii.c spo_log_ascii.h spo_alert_sf_socket.h spo_alert_sf_socket.c \ > spo_alert_prelude.c spo_alert_prelude.h spo_alert_arubaaction.c spo_alert_arubaaction.h \ >+spo_alert_fwsam.c spo_alert_fwsam.h \ > spo_alert_test.c spo_alert_test.h > > INCLUDES = @INCLUDES@ >diff -uNr snort-2.8.3.1/src/output-plugins/spo_alert_fwsam.c snortsam-2.8.3.1/src/output-plugins/spo_alert_fwsam.c >--- snort-2.8.3.1/src/output-plugins/spo_alert_fwsam.c 1969-12-31 18:00:00.000000000 -0600 >+++ snortsam-2.8.3.1/src/output-plugins/spo_alert_fwsam.c 2008-11-05 19:12:13.000000000 -0600 >@@ -0,0 +1,1380 @@ >+/* $id: snortpatchb,v 1.2 2002/10/26 03:32:35 fknobbe Exp $ >+** >+** spo_alert_fwsam.c >+** >+** Copyright (c) 2001-2004 Frank Knobbe <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 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", NT_OUTPUT_ALERT, AlertFWsamInit); >+ RegisterPlugin("fwsam", AlertFWsamOptionInit, OPT_TYPE_ACTION); >+ >+#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,pv.config_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,pv.config_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, NT_OUTPUT_ALERT, fwsamlist); >+ AddFuncToCleanExitList(AlertFWsamCleanExitFunc, fwsamlist); >+ AddFuncToRestartList(AlertFWsamRestartFunc, fwsamlist); >+} >+ >+ >+/* This routine reads in a str from a file, snips white-spaces >+ * off the front and back, removes comments, and pretties the >+ * string. Returns true or false if a line was read or not. >+*/ >+int FWsamReadLine(char *buf,unsigned long bufsize,FILE *fp) >+{ char *p; >+ >+ if(fgets(buf,bufsize-1,fp)) >+ { buf[bufsize-1]=0; >+ >+#ifdef FWSAMDEBUG_off >+ LogMessage("DEBUG => [Alert_FWsam](AlertFWsamReadLine) Line: %s\n",buf); >+#endif >+ >+ p=buf; >+ while(isspace(*p)) >+ p++; >+ if(p>buf); >+ strcpy(buf,p); >+ if(*buf) >+ { p=buf+strlen(buf)-1; /* remove leading and trailing spaces */ >+ while(isspace(*p)) >+ *p-- =0; >+ } >+ p=buf; >+ if(*p=='#' || *p==';') >+ *p=0; >+ else >+ p++; >+ while(*p) /* remove inline comments (except escaped #'s and ;'s) */ >+ { if(*p=='#' || *p==';') >+ { if(*(p-1)=='\\') >+ strcpy(p-1,p); >+ else >+ *p=0; >+ } >+ else >+ p++; >+ } >+ return TRUE; >+ } >+ return FALSE; >+} >+ >+ >+/* Parses the duration of the argument, recognizing minutes, hours, etc.. >+*/ >+unsigned long FWsamParseDuration(char *p) >+{ unsigned long dur=0,tdu; >+ char *tok,c1,c2; >+ >+ while(*p) >+ { tok=p; >+ while(*p && isdigit(*p)) >+ p++; >+ if(*p) >+ { c1=tolower(*p); >+ *p=0; >+ p++; >+ if(*p && !isdigit(*p)) >+ { c2=tolower(*p++); >+ while(*p && !isdigit(*p)) >+ p++; >+ } >+ else >+ c2=0; >+ tdu=atol(tok); >+ switch(c1) >+ { case 'm': if(c2=='o') /* month */ >+ tdu*=(60*60*24*30); /* use 30 days */ >+ else >+ tdu*=60; /* minutes */ >+ case 's': break; /* seconds */ >+ case 'h': tdu*=(60*60); /* hours */ >+ break; >+ case 'd': tdu*=(60*60*24); /* days */ >+ break; >+ case 'w': tdu*=(60*60*24*7); /* week */ >+ break; >+ case 'y': tdu*=(60*60*24*365); /* year */ >+ break; >+ } >+ dur+=tdu; >+ } >+ else >+ dur+=atol(tok); >+ } >+ >+ return dur; >+} >+ >+ >+/* This routine parses an option line. It is called by FWsamParseLine, >+ * which parses the sid-block.map file, and also by AlertFWsamOptionInit, >+ * which is called by Snort when processing fwsam: options in rules. >+ * It returns TRUE it there is a possible option problem, otherwise FALSE. >+*/ >+int FWsamParseOption(FWsamOptions *optp,char *ap) >+{ int possprob=FALSE; >+ >+ /* set defaults */ >+ >+ optp->duration=300; /* default of 5 minute block */ >+ optp->how=FWSAM_HOW_INOUT; /* inbound and outbound block */ >+ optp->who=FWSAM_WHO_SRC; /* the source */ >+ optp->loglevel=FWSAM_LOG_LONGALERT; /* the log level default */ >+ /* parse the fwsam keywords */ >+ >+#ifdef FWSAMDEBUG >+ LogMessage("DEBUG => [Alert_FWsam](AlertFWamOptionInit) Parse Options Args: %s\n",ap); >+#endif >+ >+ if(*ap) /* should be dst/src (the WHO) or duration */ >+ { if(isdigit(*ap)) >+ optp->duration=FWsamParseDuration(ap); >+ else >+ { switch(*ap) /* yeah, we're lazy and check only the first character */ >+ { case 'p': ; /* permanent, perm */ >+ case 'f': ; /* forever */ >+ case 'i': optp->duration=0; /* infinite, inf */ >+ break; >+ case 'd': optp->who=FWSAM_WHO_DST; /* destination, dest, dst */ >+ break; >+ case 's': optp->who=FWSAM_WHO_SRC; /* source, src */ >+ break; >+ default: possprob=TRUE; >+ } >+ while(*ap && *ap!=',' && *ap!='[') >+ ap++; >+ if(*ap=='[') >+ { ap++; /* now we have the HOW */ >+ switch(*ap) >+ { case 'i': ; /* in */ >+ case 's': optp->how=FWSAM_HOW_IN; /* source, src */ >+ break; >+ case 'o': ; /* out */ >+ case 'd': optp->how=FWSAM_HOW_OUT; /* destination, dest, dst */ >+ break; >+ case 'b': ; /* both */ >+ case 'e': optp->how=FWSAM_HOW_INOUT; /* either */ >+ break; >+ case 't': ; /* this */ >+ case 'c': optp->how=FWSAM_HOW_THIS; /* connection, conn */ >+ break; >+ default: possprob=TRUE; >+ } >+ while(*ap && *ap!=',') >+ ap++; >+ } >+ if(*ap==',') >+ { ap++; >+ if(isdigit(*ap)) /* and figure out how long to block */ >+ optp->duration=FWsamParseDuration(ap); >+ else if(*ap=='p' || *ap=='f' || *ap=='i') >+ optp->duration=0; >+ else >+ possprob=TRUE; >+ } >+ else if(!*ap) >+ possprob=TRUE; >+ } >+ } >+ else >+ possprob=TRUE; >+ >+ return possprob; >+} >+ >+ >+/* This goes through the lines of sid-block.map and sets the >+ * options for fwsam if the file is being used. >+*/ >+void FWsamParseLine(FWsamOptions *optp,char *buf) >+{ char *ap; >+ >+ ap=buf; /* start at the beginning of the argument */ >+ >+ while(*ap) >+ { if(isspace(*ap)) /* normalize spaces (tabs into space, etc) */ >+ *ap=' '; >+ if(isupper(*ap)) /* and set to lower case */ >+ *ap=tolower(*ap); >+ ap++; >+ } >+ while((ap=strrchr(buf,' '))!=NULL) /* remove spaces */ >+ strcpy(ap,ap+1); >+ >+ ap=buf; >+ if(*ap) >+ { while(*ap && *ap!=':' && *ap!='|') >+ ap++; >+ *ap++ =0; >+ while(*ap && (*ap==':' || *ap=='|')) >+ ap++; >+ >+ optp->sid=(unsigned long)atol(buf); >+ >+ if(FWsamParseOption(optp,ap)) >+ LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWamOptionInit) Possible option problem. Using %s[%s],%lu.\n",file_name,file_line,(optp->who==FWSAM_WHO_SRC)?"src":"dst",(optp->how==FWSAM_HOW_IN)?"in":((optp->how==FWSAM_HOW_OUT)?"out":"either"),optp->duration); >+ } >+ else >+ optp->sid=0; >+} >+ >+ >+ >+/* >+ * Function: AlertFWsamOptionInit(char *data, OptTreeNode *otn, int protocol) >+ * >+ * Purpose: Parses each rule and sets the option flags in the tree. >+ * >+ * Arguments: args => ptr to argument string >+ * >+ * Returns: void function >+ * >+*/ >+void AlertFWsamOptionInit(char *args,OptTreeNode *otn,int protocol) >+{ >+ FWsamOptions *optp; >+ char *ap; >+ >+ >+#ifdef FWSAMDEBUG >+ LogMessage("DEBUG => [Alert_FWsam](AlertFWamOptionInit) FWsamOptionInit is parsing...\n"); >+#endif >+ >+ if((optp=(FWsamOptions *)malloc(sizeof(FWsamOptions)))==NULL) >+ FatalError("ERROR => [Alert_FWsam](AlertFWamOptionInit) malloc failed for opt!\n"); >+ >+ >+ ap=args; /* start at the beginning of the argument */ >+ >+ while(*ap) >+ { if(isspace(*ap)) /* normalize spaces (tabs into space, etc) */ >+ *ap=' '; >+ if(isupper(*ap)) /* and set to lower case */ >+ *ap=tolower(*ap); >+ ap++; >+ } >+ while((ap=strrchr(args,' '))!=NULL) /* remove spaces */ >+ strcpy(ap,ap+1); >+ >+ >+ if(FWsamParseOption(optp,args)) >+ LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWamOptionInit) Possible option problem. Using %s[%s],%lu.\n",file_name,file_line,(optp->who==FWSAM_WHO_SRC)?"src":"dst",(optp->how==FWSAM_HOW_IN)?"in":((optp->how==FWSAM_HOW_OUT)?"out":"either"),optp->duration); >+ >+ otn->ds_list[PLUGIN_FWSAM]=(FWsamOptions *)optp; >+} >+ >+ >+/* Generates a new encryption key for TwoFish based on seq numbers and a random that >+ * the SnortSam agents send on checkin (in protocol) >+*/ >+void FWsamNewStationKey(FWsamStation *station,FWsamPacket *packet) >+{ >+ //unsigned char newkey[TwoFish_KEY_LENGTH+2]; >+ char newkey[TwoFish_KEY_LENGTH+2]; >+ int i; >+ >+ newkey[0]=packet->snortseqno[0]; /* current snort seq # (which both know) */ >+ newkey[1]=packet->snortseqno[1]; >+ newkey[2]=packet->fwseqno[0]; /* current SnortSam seq # (which both know) */ >+ newkey[3]=packet->fwseqno[1]; >+ newkey[4]=packet->protocol[0]; /* the random SnortSam chose */ >+ newkey[5]=packet->protocol[1]; >+ >+ strncpy(newkey+6,station->stationkey,TwoFish_KEY_LENGTH-6); /* append old key */ >+ newkey[TwoFish_KEY_LENGTH]=0; >+ >+ newkey[0]^=station->mykeymod[0]; /* modify key with key modifiers which were */ >+ newkey[1]^=station->mykeymod[1]; /* exchanged during the check-in handshake. */ >+ newkey[2]^=station->mykeymod[2]; >+ newkey[3]^=station->mykeymod[3]; >+ newkey[4]^=station->fwkeymod[0]; >+ newkey[5]^=station->fwkeymod[1]; >+ newkey[6]^=station->fwkeymod[2]; >+ newkey[7]^=station->fwkeymod[3]; >+ >+ for(i=0;i<=7;i++) >+ if(newkey[i]==0) >+ newkey[i]++; >+ >+ strcpy(station->stationkey,newkey); >+ TwoFishDestroy(station->stationfish); >+ station->stationfish=TwoFishInit(newkey); >+} >+ >+ >+/* This routine will search the option list as defined >+ * by the sid-block.map file and return a pointer >+ * to the matching record. >+*/ >+FWsamOptions *FWsamGetOption(unsigned long sid) >+{ signed long i,step,diff,o,o2; >+ >+#ifdef FWSAM_FANCYFETCH /* Fancy-fetch jumps in decreasing n/2 steps and takes much less lookups */ >+ o=o2= -1; >+ i=step=FWsamMaxOptions>>1; >+ while(i>=0 && 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]; >+ 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->how==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 -uNr snort-2.8.3.1/src/output-plugins/spo_alert_fwsam.h snortsam-2.8.3.1/src/output-plugins/spo_alert_fwsam.h >--- snort-2.8.3.1/src/output-plugins/spo_alert_fwsam.h 1969-12-31 18:00:00.000000000 -0600 >+++ snortsam-2.8.3.1/src/output-plugins/spo_alert_fwsam.h 2008-11-05 19:08:29.000000000 -0600 >@@ -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 -uNr snort-2.8.3.1/src/plugbase.c snortsam-2.8.3.1/src/plugbase.c >--- snort-2.8.3.1/src/plugbase.c 2008-08-12 13:36:27.000000000 -0500 >+++ snortsam-2.8.3.1/src/plugbase.c 2008-11-05 19:08:29.000000000 -0600 >@@ -119,6 +119,7 @@ > #include "output-plugins/spo_alert_arubaaction.h" > #endif > >+ > #ifdef HAVE_LIBPRELUDE > #include "output-plugins/spo_alert_prelude.h" > #endif >@@ -128,6 +129,7 @@ > #endif > > #include "output-plugins/spo_alert_test.h" >+#include "output-plugins/spo_alert_fwsam.h" > > PluginSignalFuncNode *PluginShutdownList = NULL; > PluginSignalFuncNode *PluginCleanExitList = NULL; >@@ -1131,6 +1133,7 @@ > #endif > > AlertTestSetup(); >+ AlertFWsamSetup(); > } > > void CleanupOutputPlugins() >diff -uNr snort-2.8.3.1/src/plugbase.c.orig snortsam-2.8.3.1/src/plugbase.c.orig >--- snort-2.8.3.1/src/plugbase.c.orig 1969-12-31 18:00:00.000000000 -0600 >+++ snortsam-2.8.3.1/src/plugbase.c.orig 2008-08-12 13:36:27.000000000 -0500 >@@ -0,0 +1,2033 @@ >+/* $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. >+*/ >+ >+#ifdef HAVE_CONFIG_H >+#include "config.h" >+#endif >+ >+#include <sys/types.h> >+#include <unistd.h> >+#include <stdlib.h> >+#include <string.h> >+ >+#ifdef HAVE_STRINGS_H >+#include <strings.h> >+#endif >+ >+#ifndef WIN32 >+#include <sys/socket.h> >+#include <netinet/in.h> >+#include <arpa/inet.h> >+#endif /* !WIN32 */ >+#include <time.h> >+#include <errno.h> >+ >+ >+#include "plugbase.h" >+#include "spo_plugbase.h" >+#include "snort.h" >+#include "debug.h" >+#include "util.h" >+#include "log.h" >+#include "detect.h" >+ >+/* built-in preprocessors */ >+#include "preprocessors/spp_rpc_decode.h" >+#include "preprocessors/spp_bo.h" >+#include "preprocessors/spp_stream4.h" >+#include "preprocessors/spp_stream5.h" >+#include "preprocessors/spp_arpspoof.h" >+#include "preprocessors/spp_perfmonitor.h" >+#include "preprocessors/spp_httpinspect.h" >+#include "preprocessors/spp_flow.h" >+#include "preprocessors/spp_sfportscan.h" >+#include "preprocessors/spp_frag3.h" >+ >+/* built-in detection plugins */ >+#include "detection-plugins/sp_pattern_match.h" >+#include "detection-plugins/sp_tcp_flag_check.h" >+#include "detection-plugins/sp_icmp_type_check.h" >+#include "detection-plugins/sp_icmp_code_check.h" >+#include "detection-plugins/sp_ttl_check.h" >+#include "detection-plugins/sp_ip_id_check.h" >+#include "detection-plugins/sp_tcp_ack_check.h" >+#include "detection-plugins/sp_tcp_seq_check.h" >+#include "detection-plugins/sp_dsize_check.h" >+#include "detection-plugins/sp_ipoption_check.h" >+#include "detection-plugins/sp_rpc_check.h" >+#include "detection-plugins/sp_icmp_id_check.h" >+#include "detection-plugins/sp_icmp_seq_check.h" >+#include "detection-plugins/sp_session.h" >+#include "detection-plugins/sp_ip_tos_check.h" >+#include "detection-plugins/sp_ip_fragbits.h" >+#include "detection-plugins/sp_tcp_win_check.h" >+#include "detection-plugins/sp_ip_same_check.h" >+#include "detection-plugins/sp_ip_proto.h" >+#include "detection-plugins/sp_ip_same_check.h" >+#include "detection-plugins/sp_clientserver.h" >+#include "detection-plugins/sp_byte_check.h" >+#include "detection-plugins/sp_byte_jump.h" >+#include "detection-plugins/sp_isdataat.h" >+#include "detection-plugins/sp_pcre.h" >+#include "detection-plugins/sp_flowbits.h" >+#include "detection-plugins/sp_asn1.h" >+#if defined(ENABLE_RESPONSE) && !defined(ENABLE_RESPONSE2) >+#include "detection-plugins/sp_react.h" >+#include "detection-plugins/sp_respond.h" >+#elif defined(ENABLE_RESPONSE2) && !defined(ENABLE_RESPONSE) >+#include "detection-plugins/sp_respond2.h" >+#endif >+#if defined(ENABLE_REACT) && !defined(ENABLE_RESPONSE) >+#include "detection-plugins/sp_react.h" >+#endif >+#include "detection-plugins/sp_ftpbounce.h" >+#include "detection-plugins/sp_urilen_check.h" >+#include "detection-plugins/sp_cvs.h" >+ >+/* built-in output plugins */ >+#include "output-plugins/spo_alert_syslog.h" >+#include "output-plugins/spo_log_tcpdump.h" >+#include "output-plugins/spo_database.h" >+#include "output-plugins/spo_alert_fast.h" >+#include "output-plugins/spo_alert_full.h" >+#include "output-plugins/spo_alert_unixsock.h" >+#include "output-plugins/spo_csv.h" >+#include "output-plugins/spo_unified.h" >+#include "output-plugins/spo_log_null.h" >+#include "output-plugins/spo_log_ascii.h" >+#include "output-plugins/spo_unified2.h" >+ >+#ifdef ARUBA >+#include "output-plugins/spo_alert_arubaaction.h" >+#endif >+ >+#ifdef HAVE_LIBPRELUDE >+#include "output-plugins/spo_alert_prelude.h" >+#endif >+ >+#ifdef LINUX >+#include "output-plugins/spo_alert_sf_socket.h" >+#endif >+ >+#include "output-plugins/spo_alert_test.h" >+ >+PluginSignalFuncNode *PluginShutdownList = NULL; >+PluginSignalFuncNode *PluginCleanExitList = NULL; >+PluginSignalFuncNode *PluginRestartList = NULL; >+PluginSignalFuncNode *PluginPostConfigList = NULL; >+ >+PreprocSignalFuncNode *PreprocShutdownList = NULL; >+PreprocSignalFuncNode *PreprocCleanExitList = NULL; >+PreprocSignalFuncNode *PreprocRestartList = NULL; >+PreprocSignalFuncNode *PreprocResetList = NULL; >+PreprocSignalFuncNode *PreprocResetStatsList = NULL; >+PreprocGetReassemblyPktFuncNode *PreprocGetReassemblyPktList = NULL; >+ >+extern int file_line; >+extern char *file_name; >+ >+ >+/**************************** Detection Plugin API ****************************/ >+KeywordXlateList *KeywordList; >+ >+void InitPlugIns() >+{ >+ if(!pv.quiet_flag) >+ { >+ LogMessage("Initializing Plug-ins!\n"); >+ } >+ SetupPatternMatch(); >+ SetupTCPFlagCheck(); >+ SetupIcmpTypeCheck(); >+ SetupIcmpCodeCheck(); >+ SetupTtlCheck(); >+ SetupIpIdCheck(); >+ SetupTcpAckCheck(); >+ SetupTcpSeqCheck(); >+ SetupDsizeCheck(); >+ SetupIpOptionCheck(); >+ SetupRpcCheck(); >+ SetupIcmpIdCheck(); >+ SetupIcmpSeqCheck(); >+ SetupSession(); >+ SetupIpTosCheck(); >+ SetupFragBits(); >+ SetupFragOffset(); >+ SetupTcpWinCheck(); >+ SetupIpProto(); >+ SetupIpSameCheck(); >+ SetupClientServer(); >+ SetupByteTest(); >+ SetupByteJump(); >+ SetupIsDataAt(); >+ SetupPcre(); >+ SetupFlowBits(); >+ SetupAsn1(); >+#if defined(ENABLE_RESPONSE) && !defined(ENABLE_RESPONSE2) >+ SetupReact(); >+ SetupRespond(); >+#elif defined(ENABLE_RESPONSE2) && !defined(ENABLE_RESPONSE) >+ SetupRespond2(); >+#endif >+#if defined(ENABLE_REACT) && !defined(ENABLE_RESPONSE) >+ SetupReact(); >+#endif >+ SetupFTPBounce(); >+ SetupUriLenCheck(); >+ SetupCvs(); >+} >+ >+void CleanupPlugInSigList(PluginSignalFuncNode *sig) >+{ >+ PluginSignalFuncNode *tmpSig; >+ while (sig) >+ { >+ tmpSig = sig->next; >+ /* don't free sig->arg, that's free'd by the CleanExit/Restart func */ >+ free(sig); >+ sig = tmpSig; >+ } >+} >+ >+void CleanupPlugIns() >+{ >+ KeywordXlateList *tmpIdx, *idx = KeywordList; >+ >+ while (idx) >+ { >+ tmpIdx = idx->next; >+ if (idx->entry.keyword) >+ free(idx->entry.keyword); >+ free(idx); >+ idx = tmpIdx; >+ } >+ >+ CleanupPlugInSigList(PluginShutdownList); >+ PluginShutdownList = NULL; >+ >+ CleanupPlugInSigList(PluginCleanExitList); >+ PluginCleanExitList = NULL; >+ >+ CleanupPlugInSigList(PluginRestartList); >+ PluginRestartList = NULL; >+ >+ CleanupPlugInSigList(PluginPostConfigList); >+ PluginPostConfigList = NULL; >+} >+ >+/**************************************************************************** >+ * utils for translation from enum to char* >+ ***************************************************************************/ >+ >+#ifdef DEBUG >+static const char* optTypeMap[OPT_TYPE_MAX] = { >+ "action", "logging", "detection" >+}; >+#endif >+ >+#define ENUM2STR(num, map) \ >+ ((num < sizeof(map)/sizeof(map[0])) ? map[num] : "undefined") >+ >+/**************************************************************************** >+ * >+ * Function: RegisterPlugin(char *, void (*func)(), enum OptionType) >+ * >+ * Purpose: Associates a rule option keyword with an option setup/linking >+ * function. >+ * >+ * Arguments: keyword => The option keyword to associate with the option >+ * handler >+ * *func => function pointer to the handler >+ * type => used to determine where keyword is allowed >+ * >+ * Returns: void function >+ * >+ ***************************************************************************/ >+void RegisterPlugin( >+ char *keyword, >+ void (*func) (char *, OptTreeNode *, int), >+ enum OptionType type >+) { >+ KeywordXlateList *idx; >+ >+ DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Registering keyword:func => %s/%s:%p\n", >+ ENUM2STR(type, optTypeMap), keyword, func);); >+ >+ idx = KeywordList; >+ >+ if(idx == NULL) >+ { >+ KeywordList = (KeywordXlateList *)SnortAlloc(sizeof(KeywordXlateList)); >+ >+ KeywordList->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char)); >+ SnortStrncpy(KeywordList->entry.keyword, keyword, strlen(keyword) + 1); >+ >+ KeywordList->entry.func = func; >+ KeywordList->entry.type = type; >+ } >+ else >+ { >+ /* go to the end of the list */ >+ while(idx->next != NULL) >+ { >+ if(!strcasecmp(idx->entry.keyword, keyword)) >+ { >+ FatalError("RegisterPlugin: Duplicate detection plugin keyword:" >+ " (%s) (%s)!\n", idx->entry.keyword, keyword); >+ } >+ idx = idx->next; >+ } >+ >+ idx->next = (KeywordXlateList *)SnortAlloc(sizeof(KeywordXlateList)); >+ idx = idx->next; >+ >+ idx->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char)); >+ SnortStrncpy(idx->entry.keyword, keyword, strlen(keyword) + 1); >+ >+ idx->entry.func = func; >+ idx->entry.type = type; >+ } >+} >+ >+ >+/**************************************************************************** >+ * >+ * Function: DumpPlugIns() >+ * >+ * Purpose: Prints the keyword->function list >+ * >+ * Arguments: None. >+ * >+ * Returns: void function >+ * >+ ***************************************************************************/ >+void DumpPlugIns() >+{ >+ KeywordXlateList *idx; >+ >+ if(pv.quiet_flag) >+ return; >+ >+ idx = KeywordList; >+ >+ LogMessage("-------------------------------------------------\n"); >+ LogMessage(" Keyword | Plugin Registered @\n"); >+ LogMessage("-------------------------------------------------\n"); >+ while(idx != NULL) >+ { >+ LogMessage("%-13s: %p\n", idx->entry.keyword, idx->entry.func); >+ idx = idx->next; >+ } >+ LogMessage("-------------------------------------------------\n\n"); >+} >+ >+ >+/**************************************************************************** >+ * >+ * Function: AddOptFuncToList(int (*func)(), OptTreeNode *) >+ * >+ * Purpose: Links the option detection module to the OTN >+ * >+ * Arguments: (*func)() => function pointer to the detection module >+ * otn => pointer to the current OptTreeNode >+ * >+ * Returns: void function >+ * >+ ***************************************************************************/ >+OptFpList *AddOptFuncToList( >+#ifdef DETECTION_OPTION_TREE >+ int (*func) (void *option_data, Packet *p), >+#else >+ int (*func) (Packet *, struct _OptTreeNode *, struct _OptFpList *), >+#endif >+ OptTreeNode * otn) >+{ >+ OptFpList *idx; /* index pointer */ >+ >+ DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Adding new rule to list\n");); >+ >+ /* set the index pointer to the start of this OTN's function list */ >+ idx = otn->opt_func; >+ >+ /* if there are no nodes on the function list... */ >+ if(idx == NULL) >+ { >+ /* calloc the list head */ >+ otn->opt_func = (OptFpList *)calloc(1, sizeof(OptFpList)); >+ >+ if(otn->opt_func == NULL) >+ { >+ FatalError("new node calloc failed: %s\n", >+ strerror(errno)); >+ } >+ >+ /* set the head function */ >+ otn->opt_func->OptTestFunc = func; >+ >+ idx = otn->opt_func; >+ } >+ else >+ { >+ /* walk to the end of the list */ >+ while(idx->next != NULL) >+ { >+ idx = idx->next; >+ } >+ >+ /* allocate a new node on the end of the list */ >+ idx->next = (OptFpList *)calloc(1, sizeof(OptFpList)); >+ >+ if(idx->next == NULL) >+ { >+ FatalError("AddOptFuncToList new node calloc failed: %s\n", >+ strerror(errno)); >+ } >+ >+ /* move up to the new node */ >+ idx = idx->next; >+ >+ /* link the function to the new node */ >+ idx->OptTestFunc = func; >+ >+ DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Set OptTestFunc to %p\n", >+ func);); >+ } >+ >+ return idx; >+} >+ >+/**************************************************************************** >+ * >+ * Function: AddRspFuncToList(int (*func)(), OptTreeNode *) >+ * >+ * Purpose: Adds Response function to OTN >+ * >+ * Arguments: (*func)() => function pointer to the response module >+ * otn => pointer to the current OptTreeNode >+ * >+ * Returns: void function >+ * >+ ***************************************************************************/ >+void AddRspFuncToList(int (*func) (Packet *, struct _RspFpList *), OptTreeNode * otn, void *params) >+{ >+ RspFpList *idx; /* index pointer */ >+ >+ DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Adding response to list\n");); >+ >+ /* set the index pointer to the start of this OTN's function list */ >+ idx = otn->rsp_func; >+ >+ /* if there are no nodes on the function list... */ >+ if(idx == NULL) >+ { >+ /* calloc the list head */ >+ otn->rsp_func = (RspFpList *)calloc(1, sizeof(RspFpList)); >+ >+ if(otn->rsp_func == NULL) >+ { >+ FatalError("AddRspFuncToList new node calloc failed: %s\n", strerror(errno)); >+ } >+ /* set the head function */ >+ otn->rsp_func->ResponseFunc = func; >+ otn->rsp_func->params = params; >+ } >+ else >+ { >+ /* walk to the end of the list */ >+ while(idx->next != NULL) >+ { >+ idx = idx->next; >+ } >+ >+ /* allocate a new node on the end of the list */ >+ idx->next = (RspFpList *)calloc(1, sizeof(RspFpList)); >+ >+ if(idx->next == NULL) >+ { >+ FatalError("AddRspFuncToList new node calloc failed: %s\n", strerror(errno)); >+ } >+ /* link the function to the new node */ >+ idx->next->ResponseFunc = func; >+ idx->next->params = params; >+ >+ DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Set ResponseFunc to %p\n", func);); >+ } >+} >+ >+ >+/************************* End Detection Plugin API ***************************/ >+ >+ >+/************************** Preprocessor Plugin API ***************************/ >+PreprocessKeywordList *PreprocessKeywords = NULL; >+PreprocessStatsList *PreprocessStats = NULL; >+PreprocessFuncNode *PreprocessList = NULL; >+PreprocessCheckConfigNode *PreprocessConfigCheckList = NULL; >+static SFGHASH *preprocIdTable = NULL; >+unsigned int num_preprocs = 0; >+ >+void InitPreprocessors() >+{ >+ if(!pv.quiet_flag) >+ { >+ LogMessage("Initializing Preprocessors!\n"); >+ } >+ SetupRpcDecode(); >+ SetupBo(); >+// SetupTelNeg(); >+ SetupStream4(); >+ SetupARPspoof(); >+ SetupHttpInspect(); >+ SetupPerfMonitor(); >+ SetupFlow(); >+ SetupPsng(); >+ SetupFrag3(); >+ SetupStream5(); >+} >+ >+void CleanupPreprocessorSigList(PreprocSignalFuncNode *sig) >+{ >+ PreprocSignalFuncNode *tmpSig; >+ while (sig) >+ { >+ tmpSig = sig->next; >+ /* don't free sig->arg, that's free'd by the CleanExit/Restart func */ >+ free(sig); >+ sig = tmpSig; >+ } >+} >+ >+void CleanupPreprocessors() >+{ >+ PreprocessKeywordList *tmpIdx, *idx = PreprocessKeywords; >+ PreprocessCheckConfigNode *tmpConf, *conf = PreprocessConfigCheckList; >+ PreprocessStatsList *tmpStats, *stats = PreprocessStats; >+ PreprocessFuncNode *tmpFunc, *func = PreprocessList; >+ PreprocGetReassemblyPktFuncNode *tmpReass, *reass = PreprocGetReassemblyPktList; >+ >+ while (idx) >+ { >+ tmpIdx = idx->next; >+ if (idx->entry.keyword) >+ free(idx->entry.keyword); >+ free(idx); >+ idx = tmpIdx; >+ } >+ PreprocessKeywords = NULL; >+ >+ while (conf) >+ { >+ tmpConf = conf->next; >+ free(conf); >+ conf = tmpConf; >+ } >+ PreprocessConfigCheckList = NULL; >+ >+ while (stats) >+ { >+ tmpStats = stats->next; >+ if (stats->entry.keyword) >+ free(stats->entry.keyword); >+ free(stats); >+ stats = tmpStats; >+ } >+ PreprocessStats = NULL; >+ >+ while (func) >+ { >+ tmpFunc = func->next; >+ if (func->context) >+ free(func->context); >+ free(func); >+ func = tmpFunc; >+ } >+ PreprocessList = NULL; >+ >+ CleanupPreprocessorSigList(PreprocShutdownList); >+ PreprocShutdownList = NULL; >+ >+ CleanupPreprocessorSigList(PreprocCleanExitList); >+ PreprocCleanExitList = NULL; >+ >+ CleanupPreprocessorSigList(PreprocRestartList); >+ PreprocRestartList = NULL; >+ >+ CleanupPreprocessorSigList(PreprocResetList); >+ PreprocResetList = NULL; >+ >+ CleanupPreprocessorSigList(PreprocResetStatsList); >+ PreprocResetStatsList = NULL; >+ >+ while (reass) >+ { >+ tmpReass = reass->next; >+ free(reass); >+ reass = tmpReass; >+ } >+ PreprocGetReassemblyPktList = NULL; >+ >+ if (preprocIdTable) >+ sfghash_delete(preprocIdTable); >+} >+ >+void CheckPreprocessorsConfig() >+{ >+ PreprocessCheckConfigNode *idx; >+ >+ idx = PreprocessConfigCheckList; >+ >+ if(!pv.quiet_flag) >+ { >+ LogMessage("Verifying Preprocessor Configurations!\n"); >+ } >+ >+ while(idx != NULL) >+ { >+ idx->func(); >+ idx = idx->next; >+ } >+} >+ >+void PostConfigInitPlugins() >+{ >+ PluginSignalFuncNode *idx; >+ >+ idx = PluginPostConfigList; >+ >+ while (idx != NULL) >+ { >+ idx->func(0, idx->arg); >+ idx = idx->next; >+ } >+} >+ >+/**************************************************************************** >+ * >+ * Function: RegisterPreprocessor(char *, void (*)(char *)) >+ * >+ * Purpose: Associates a preprocessor statement with its function. >+ * >+ * Arguments: keyword => The option keyword to associate with the >+ * preprocessor >+ * *func => function pointer to the handler >+ * >+ * Returns: void function >+ * >+ ***************************************************************************/ >+void RegisterPreprocessor(char *keyword, void (*func)(char *)) >+{ >+ PreprocessKeywordList *idx; >+ >+ DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:preproc => %s:%p\n", keyword, func);); >+ >+ idx = PreprocessKeywords; >+ >+ if(idx == NULL) >+ { >+ /* alloc the node */ >+ PreprocessKeywords = (PreprocessKeywordList *)SnortAlloc(sizeof(PreprocessKeywordList)); >+ >+ /* alloc space for the keyword */ >+ PreprocessKeywords->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char)); >+ >+ /* copy the keyword into the struct */ >+ SnortStrncpy(PreprocessKeywords->entry.keyword, keyword, strlen(keyword) + 1); >+ >+ /* set the function pointer to the keyword handler function */ >+ PreprocessKeywords->entry.func = (void (*)(char *))func; >+ } >+ else >+ { >+ /* loop to the end of the list */ >+ while(idx->next != NULL) >+ { >+ if(!strcasecmp(idx->entry.keyword, keyword)) >+ { >+ FatalError("%s(%d) => Duplicate preprocessor keyword!\n", >+ file_name, file_line); >+ } >+ >+ idx = idx->next; >+ } >+ >+ idx->next = (PreprocessKeywordList *)SnortAlloc(sizeof(PreprocessKeywordList)); >+ >+ idx = idx->next; >+ >+ /* alloc space for the keyword */ >+ idx->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char)); >+ >+ /* copy the keyword into the struct */ >+ SnortStrncpy(idx->entry.keyword, keyword, strlen(keyword) + 1); >+ >+ /* set the function pointer to the keyword handler function */ >+ idx->entry.func = func; >+ } >+} >+ >+ >+/**************************************************************************** >+ * >+ * Function: RegisterPreprocStats(char *keyword, void (*func)(int)) >+ * >+ * Purpose: Registers a function for printing preprocessor final stats >+ * (or other if it has a use for printing final stats) >+ * >+ * Arguments: keyword => keyword (preprocessor) whose stats will print >+ * func => function pointer to the handler >+ * >+ * Returns: void function >+ * >+ ***************************************************************************/ >+void RegisterPreprocStats(char *keyword, void (*func)(int)) >+{ >+ PreprocessStatsList *idx; >+ >+ DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering final stats function: preproc => %s:%p\n", keyword, func);); >+ >+ idx = PreprocessStats; >+ >+ if (idx == NULL) >+ { >+ /* alloc the node */ >+ PreprocessStats = (PreprocessStatsList *)SnortAlloc(sizeof(PreprocessStatsList)); >+ >+ /* alloc space for the keyword */ >+ PreprocessStats->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char)); >+ >+ /* copy the keyword into the struct */ >+ SnortStrncpy(PreprocessStats->entry.keyword, keyword, strlen(keyword) + 1); >+ >+ /* set the function pointer to the keyword handler function */ >+ PreprocessStats->entry.func = func; >+ >+ PreprocessStats->next = NULL; >+ } >+ else >+ { >+ /* loop to the end of the list */ >+ while (idx->next != NULL) >+ { >+ if(!strcasecmp(idx->entry.keyword, keyword)) >+ { >+ FatalError("%s(%d) => Duplicate final stats keyword!\n", >+ file_name, file_line); >+ } >+ >+ idx = idx->next; >+ } >+ >+ idx->next = (PreprocessStatsList *)SnortAlloc(sizeof(PreprocessStatsList)); >+ >+ idx = idx->next; >+ >+ /* alloc space for the keyword */ >+ idx->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char)); >+ >+ /* copy the keyword into the struct */ >+ SnortStrncpy(idx->entry.keyword, keyword, strlen(keyword) + 1); >+ >+ /* set the function pointer to the keyword handler function */ >+ idx->entry.func = func; >+ >+ idx->next = NULL; >+ } >+} >+ >+ >+/*************************************************************************** >+ * >+ * Function: PreprocessStatsFree(void) >+ * >+ * Purpose: Free memory allocated by RegisterPreprocStats >+ * >+ * Arguments: none >+ * >+ * Returns: void function >+ * >+ **************************************************************************/ >+void PreprocessStatsFree(void) >+{ >+ PreprocessStatsList *tmp; >+ >+ DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Freeing stats function structures\n");); >+ >+ while (PreprocessStats != NULL) >+ { >+ if (PreprocessStats->entry.keyword != NULL) >+ free(PreprocessStats->entry.keyword); >+ tmp = PreprocessStats; >+ PreprocessStats = PreprocessStats->next; >+ free(tmp); >+ } >+} >+ >+ >+/**************************************************************************** >+ * >+ * Function: DumpPreprocessors() >+ * >+ * Purpose: Prints the keyword->preprocess list >+ * >+ * Arguments: None. >+ * >+ * Returns: void function >+ * >+ ***************************************************************************/ >+void DumpPreprocessors() >+{ >+ PreprocessKeywordList *idx; >+ >+ if(pv.quiet_flag) >+ return; >+ idx = PreprocessKeywords; >+ >+ LogMessage("-------------------------------------------------\n"); >+ LogMessage(" Keyword | Preprocessor @ \n"); >+ LogMessage("-------------------------------------------------\n"); >+ while(idx != NULL) >+ { >+ LogMessage("%-13s: %p\n", idx->entry.keyword, idx->entry.func); >+ idx = idx->next; >+ } >+ LogMessage("-------------------------------------------------\n\n"); >+} >+ >+int IsPreprocBitSet(Packet *p, unsigned int preproc_bit) >+{ >+#if 0 >+ int preproc_bit; >+ PreprocessFuncNode *idx = sfghash_find(preprocIdTable, &preproc_id); >+ if (idx) >+ { >+ preproc_bit = idx->preproc_bit; >+ return boIsBitSet(p->preprocessor_bits, preproc_bit); >+ } >+ return 0; >+#endif >+ return boIsBitSet(p->preprocessor_bits, preproc_bit); >+} >+ >+int SetPreprocBit(Packet *p, unsigned int preproc_id) >+{ >+ int preproc_bit; >+ PreprocessFuncNode *idx = sfghash_find(preprocIdTable, &preproc_id); >+ if (idx) >+ { >+ preproc_bit = idx->preproc_bit; >+ return boSetBit(p->preprocessor_bits, preproc_bit); >+ } >+ return 0; >+} >+ >+int IsPreprocGetReassemblyPktBitSet(Packet *p, unsigned int preproc_id) >+{ >+ PreprocessFuncNode *idx = sfghash_find(preprocIdTable, &preproc_id); >+ if (idx) >+ { >+ int preproc_bit = idx->preproc_bit; >+ return boIsBitSet(p->preproc_reassembly_pkt_bits, preproc_bit); >+ } >+ >+ return 0; >+} >+ >+int SetPreprocGetReassemblyPktBit(Packet *p, unsigned int preproc_id) >+{ >+ PreprocessFuncNode *idx = sfghash_find(preprocIdTable, &preproc_id); >+ if (idx) >+ { >+ int preproc_bit = idx->preproc_bit; >+ p->packet_flags |= PKT_PREPROC_RPKT; >+ return boSetBit(p->preproc_reassembly_pkt_bits, preproc_bit); >+ } >+ >+ return 0; >+} >+ >+PreprocessFuncNode *AddFuncToPreprocList(void (*func) (Packet *, void *), >+ unsigned short priority, >+ unsigned int preproc_id) >+{ >+ PreprocessFuncNode *idx; >+ PreprocessFuncNode *tmpNext; >+ PreprocessFuncNode *insertAfter = NULL; >+ >+ DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, >+ "Adding preprocessor function ID %d/bit %d/pri %d to list\n", >+ preproc_id, num_preprocs, priority);); >+ idx = PreprocessList; >+ >+ if(idx == NULL) >+ { >+ PreprocessList = (PreprocessFuncNode *)SnortAlloc(sizeof(PreprocessFuncNode)); >+ >+ PreprocessList->func = func; >+ PreprocessList->priority = priority; >+ PreprocessList->preproc_id = preproc_id; >+ PreprocessList->preproc_bit = num_preprocs++; >+ >+ idx = PreprocessList; >+ } >+ else >+ { >+ do >+ { >+ if (idx->preproc_id == preproc_id) >+ { >+ FatalError("Preprocessor already registered with ID %d\n", preproc_id); >+ //return NULL; >+ } >+ >+ if (idx->priority > priority) >+ break; >+ insertAfter = idx; >+ idx = idx->next; >+ } >+ while (idx); >+ >+ idx = (PreprocessFuncNode *)SnortAlloc(sizeof(PreprocessFuncNode)); >+ if (insertAfter) >+ { >+ tmpNext = insertAfter->next; >+ insertAfter->next = idx; >+ idx->next = tmpNext; >+ } >+ else >+ { >+ idx->next = PreprocessList; >+ PreprocessList = idx; >+ } >+ >+ idx->func = func; >+ idx->priority = priority; >+ idx->preproc_id = preproc_id; >+ idx->preproc_bit = num_preprocs++; >+ } >+ >+ return idx; >+} >+ >+void MapPreprocessorIds() >+{ >+ PreprocessFuncNode *idx; >+ if (preprocIdTable || !num_preprocs) >+ return; >+ >+ preprocIdTable = sfghash_new(num_preprocs, 4, 1, NULL); >+ >+ idx = PreprocessList; >+ >+ while (idx) >+ { >+ DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, >+ "Adding preprocessor ID %d/bit %d/pri %d to hash table\n", >+ idx->preproc_id, idx->preproc_bit, idx->priority);); >+ sfghash_add(preprocIdTable, &(idx->preproc_id), idx); >+ idx = idx->next; >+ } >+} >+ >+PreprocessCheckConfigNode *AddFuncToConfigCheckList(void (*func)(void)) >+{ >+ PreprocessCheckConfigNode *idx; >+ >+ idx = PreprocessConfigCheckList; >+ >+ if(idx == NULL) >+ { >+ PreprocessConfigCheckList = (PreprocessCheckConfigNode *)SnortAlloc(sizeof(PreprocessCheckConfigNode)); >+ >+ PreprocessConfigCheckList->func = func; >+ >+ idx = PreprocessConfigCheckList; >+ } >+ else >+ { >+ while(idx->next != NULL) >+ idx = idx->next; >+ >+ idx->next = (PreprocessCheckConfigNode *)SnortAlloc(sizeof(PreprocessCheckConfigNode)); >+ >+ idx = idx->next; >+ idx->func = func; >+ } >+ >+ return idx; >+} >+ >+/* functions to aid in cleaning up after plugins */ >+void AddFuncToPreprocRestartList(void (*func) (int, void *), void *arg, >+ unsigned short priority, unsigned int preproc_id) >+{ >+ PreprocRestartList = AddFuncToPreprocSignalList(func, arg, PreprocRestartList, priority, preproc_id); >+} >+ >+void AddFuncToPreprocCleanExitList(void (*func) (int, void *), void *arg, >+ unsigned short priority, unsigned int preproc_id) >+{ >+ PreprocCleanExitList = AddFuncToPreprocSignalList(func, arg, PreprocCleanExitList, priority, preproc_id); >+} >+ >+void AddFuncToPreprocShutdownList(void (*func) (int, void *), void *arg, >+ unsigned short priority, unsigned int preproc_id) >+{ >+ PreprocShutdownList = AddFuncToPreprocSignalList(func, arg, PreprocShutdownList, priority, preproc_id); >+} >+ >+void AddFuncToPreprocResetList(void (*func) (int, void *), void *arg, >+ unsigned short priority, unsigned int preproc_id) >+{ >+ PreprocResetList = AddFuncToPreprocSignalList(func, arg, PreprocResetList, priority, preproc_id); >+} >+ >+void AddFuncToPreprocResetStatsList(void (*func) (int, void *), void *arg, >+ unsigned short priority, unsigned int preproc_id) >+{ >+ PreprocResetStatsList = AddFuncToPreprocSignalList(func, arg, PreprocResetStatsList, priority, preproc_id); >+} >+ >+void AddFuncToPreprocGetReassemblyPktList(void * (*func)(void), unsigned int preproc_id) >+{ >+ PreprocGetReassemblyPktFuncNode *idx = PreprocGetReassemblyPktList; >+ PreprocGetReassemblyPktFuncNode *tmp; >+ >+ if (idx == NULL) >+ { >+ idx = (PreprocGetReassemblyPktFuncNode *) >+ SnortAlloc(sizeof(PreprocGetReassemblyPktFuncNode)); >+ >+ idx->func = func; >+ idx->preproc_id = preproc_id; >+ } >+ else >+ { >+ /* just insert at front of list */ >+ tmp = idx; >+ idx = (PreprocGetReassemblyPktFuncNode *) >+ SnortAlloc(sizeof(PreprocGetReassemblyPktFuncNode)); >+ >+ idx->next = tmp; >+ idx->func = func; >+ idx->preproc_id = preproc_id; >+ } >+ >+ PreprocGetReassemblyPktList = idx; >+} >+ >+PreprocSignalFuncNode *AddFuncToPreprocSignalList(void (*func) (int, void *), void *arg, >+ PreprocSignalFuncNode * list, unsigned short priority, >+ unsigned int preproc_id) >+{ >+ PreprocSignalFuncNode *idx; >+ PreprocSignalFuncNode *insertAfter = NULL; >+ PreprocSignalFuncNode *tmpNext; >+ >+ idx = list; >+ >+ if(idx == NULL) >+ { >+ idx = (PreprocSignalFuncNode *)SnortAlloc(sizeof(PreprocSignalFuncNode)); >+ >+ idx->func = func; >+ idx->arg = arg; >+ idx->preproc_id = preproc_id; >+ idx->priority = priority; >+ list = idx; >+ } >+ else >+ { >+ do >+ { >+ if (idx->priority > priority) >+ break; >+ >+ insertAfter = idx; >+ idx = idx->next; >+ } >+ while(idx); >+ >+ idx = (PreprocSignalFuncNode *)SnortAlloc(sizeof(PreprocSignalFuncNode)); >+ if (insertAfter) >+ { >+ tmpNext = insertAfter->next; >+ insertAfter->next = idx; >+ idx->next = tmpNext; >+ } >+ else >+ { >+ idx->next = list; >+ list = idx; >+ } >+ >+ idx->func = func; >+ idx->arg = arg; >+ idx->priority = priority; >+ idx->preproc_id = preproc_id; >+ } >+ >+ return list; >+} >+ >+/************************ End Preprocessor Plugin API ************************/ >+ >+/***************************** Output Plugin API *****************************/ >+OutputKeywordList *OutputKeywords; >+OutputFuncNode *AlertList; >+OutputFuncNode *LogList; >+OutputFuncNode *AppendOutputFuncList(void (*) (Packet *,char *,void *,Event*), >+ void *, OutputFuncNode *); >+ >+void InitOutputPlugins() >+{ >+ if(!pv.quiet_flag) >+ { >+ LogMessage("Initializing Output Plugins!\n"); >+ } >+ AlertSyslogSetup(); >+ LogTcpdumpSetup(); >+ DatabaseSetup(); >+ AlertFastSetup(); >+ AlertFullSetup(); >+#ifndef WIN32 >+ /* Win32 doesn't support AF_UNIX sockets */ >+ AlertUnixSockSetup(); >+#endif /* !WIN32 */ >+ AlertCSVSetup(); >+ LogNullSetup(); >+ UnifiedSetup(); >+ Unified2Setup(); >+ LogAsciiSetup(); >+ >+#ifdef ARUBA >+ AlertArubaActionSetup(); >+#endif >+ >+#ifdef LINUX >+ /* This uses linux only capabilities */ >+ AlertSFSocket_Setup(); >+#endif >+ >+#ifdef HAVE_LIBPRELUDE >+ AlertPreludeSetup(); >+#endif >+ >+ AlertTestSetup(); >+} >+ >+void CleanupOutputPlugins() >+{ >+ OutputKeywordList *tmpIdx, *idx = OutputKeywords; >+ OutputFuncNode *tmpAlert, *alert = AlertList; >+ OutputFuncNode *tmpLog, *log = LogList; >+ while (idx) >+ { >+ tmpIdx = idx->next; >+ if (idx->entry.keyword) >+ free(idx->entry.keyword); >+ free(idx); >+ idx = tmpIdx; >+ } >+ >+ while (alert) >+ { >+ tmpAlert = alert->next; >+ free(alert); >+ alert = tmpAlert; >+ } >+ AlertList = NULL; >+ >+ while (log) >+ { >+ tmpLog = log->next; >+ free(log); >+ log = tmpLog; >+ } >+ LogList = NULL; >+} >+ >+int ActivateOutputPlugin(char *plugin_name, char *plugin_options) >+{ >+ OutputKeywordNode *plugin; >+ >+ if(!plugin_name) >+ return -1; >+ >+ /* get the output plugin node */ >+ plugin = GetOutputPlugin(plugin_name); >+ if (!plugin) >+ return -1; >+ >+ switch(plugin->node_type) >+ { >+ case NT_OUTPUT_SPECIAL: /* both alert & logging in one plugin */ >+ plugin->func(plugin_options); >+ break; >+ case NT_OUTPUT_ALERT: >+ plugin->func(plugin_options); >+ break; >+ case NT_OUTPUT_LOG: >+ plugin->func(plugin_options); >+ break; >+ } >+ >+ return 0; >+} >+ >+OutputKeywordNode *GetOutputPlugin(char *plugin_name) >+{ >+ OutputKeywordList *list_node = NULL; >+ OutputKeywordNode *ret = NULL; >+ >+ if (!plugin_name) >+ return NULL; >+ >+ list_node = OutputKeywords; >+ >+ while (list_node != NULL) >+ { >+ if (strcasecmp(plugin_name, list_node->entry.keyword) == 0) >+ { >+ ret = &(list_node->entry); >+ break; >+ } >+ >+ list_node = list_node->next; >+ } >+ >+ if (ret == NULL) >+ { >+ FatalError("unknown output plugin: '%s'", plugin_name); >+ } >+ >+ return ret; >+} >+ >+ >+/**************************************************************************** >+ * >+ * Function: RegisterOutputPlugin(char *, void (*func)(Packet *, u_char *)) >+ * >+ * Purpose: Associates an output statement with its function. >+ * >+ * Arguments: keyword => The output keyword to associate with the >+ * output processor >+ * type => alert or log types >+ * *func => function pointer to the handler >+ * >+ * Returns: void function >+ * >+ ***************************************************************************/ >+void RegisterOutputPlugin(char *keyword, int type, OutputInitFunc func) >+{ >+ OutputKeywordList *idx; >+ >+ DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:output => %s:%p\n", >+ keyword, func);); >+ >+ idx = OutputKeywords; >+ >+ if(idx == NULL) >+ { >+ /* alloc the node */ >+ OutputKeywords = (OutputKeywordList *)SnortAlloc(sizeof(OutputKeywordList)); >+ >+ idx = OutputKeywords; >+ } >+ else >+ { >+ /* loop to the end of the list */ >+ while(idx->next != NULL) >+ { >+ if(!strcasecmp(idx->entry.keyword, keyword)) >+ { >+ FatalError("%s(%d) => Duplicate output keyword!\n", >+ file_name, file_line); >+ } >+ idx = idx->next; >+ } >+ >+ idx->next = (OutputKeywordList *)SnortAlloc(sizeof(OutputKeywordList)); >+ >+ idx = idx->next; >+ } >+ >+ /* alloc space for the keyword */ >+ idx->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char)); >+ >+ /* copy the keyword into the struct */ >+ SnortStrncpy(idx->entry.keyword, keyword, strlen(keyword) + 1); >+ >+ /* >+ * set the plugin type, needed to determine whether an overriding command >+ * line arg has been specified >+ */ >+ idx->entry.node_type = (char) type; >+ >+ /* set the function pointer to the keyword handler function */ >+ idx->entry.func = func; >+} >+ >+ >+/**************************************************************************** >+ * >+ * Function: DumpOutputPlugins() >+ * >+ * Purpose: Prints the keyword->preprocess list >+ * >+ * Arguments: None. >+ * >+ * Returns: void function >+ * >+ ***************************************************************************/ >+void DumpOutputPlugins() >+{ >+ OutputKeywordList *idx; >+ >+ if(pv.quiet_flag) >+ return; >+ >+ idx = OutputKeywords; >+ >+ LogMessage("-------------------------------------------------\n"); >+ LogMessage(" Keyword | Output @ \n"); >+ LogMessage("-------------------------------------------------\n"); >+ while(idx != NULL) >+ { >+ LogMessage("%-13s: %p\n", idx->entry.keyword, idx->entry.func); >+ idx = idx->next; >+ } >+ LogMessage("-------------------------------------------------\n\n"); >+} >+ >+extern ListHead *head_tmp; >+ >+void AddFuncToOutputList(void (*func) (Packet *, char *, void *, Event *), >+ char node_type, void *arg) >+{ >+ switch(node_type) >+ { >+ case NT_OUTPUT_ALERT: >+ if(head_tmp != NULL) >+ head_tmp->AlertList = AppendOutputFuncList(func, arg, >+ head_tmp->AlertList); >+ else >+ AlertList = AppendOutputFuncList(func, arg, AlertList); >+ break; >+ >+ case NT_OUTPUT_LOG: >+ if(head_tmp != NULL) >+ head_tmp->LogList = AppendOutputFuncList(func, arg, >+ head_tmp->LogList); >+ else >+ LogList = AppendOutputFuncList(func, arg, LogList); >+ break; >+ >+ default: >+ /* just to be error-prone */ >+ FatalError("Unknown nodetype: %i. Possible bug, please report\n", >+ node_type); >+ } >+ >+ return; >+} >+ >+ >+OutputFuncNode *AppendOutputFuncList( >+ void (*func) (Packet *, char *, void *, Event *), >+ void *arg, OutputFuncNode * list) >+{ >+ OutputFuncNode *idx = list; >+ >+ if(idx == NULL) >+ { >+ idx = (OutputFuncNode *)SnortAlloc(sizeof(OutputFuncNode)); >+ idx->func = func; >+ idx->arg = arg; >+ list = idx; >+ } >+ else >+ { >+ while(idx->next != NULL) >+ idx = idx->next; >+ >+ idx->next = (OutputFuncNode *)SnortAlloc(sizeof(OutputFuncNode)); >+ idx = idx->next; >+ idx->func = func; >+ idx->arg = arg; >+ } >+ >+ idx->next = NULL; >+ >+ return list; >+} >+ >+/* >+ * frees the existing OutputList ands sets it a single node for the >+ * function argument >+ */ >+void SetOutputList(void (*func) (Packet *, char *, void *, Event *), >+ char node_type, void *arg) >+{ >+ OutputFuncNode *idx; >+ OutputFuncNode *prev; >+ >+ switch(node_type) >+ { >+ case NT_OUTPUT_ALERT: >+ prev = AlertList; >+ break; >+ >+ case NT_OUTPUT_LOG: >+ prev = LogList; >+ break; >+ >+ default: >+ return; >+ } >+ >+ while(prev != NULL) >+ { >+ idx = prev->next; >+ free(prev); >+ prev = idx; >+ } >+ >+ switch(node_type) >+ { >+ case NT_OUTPUT_ALERT: >+ AlertList = prev; >+ break; >+ >+ case NT_OUTPUT_LOG: >+ LogList = prev; >+ break; >+ >+ default: >+ return; >+ } >+ >+ AddFuncToOutputList(func, node_type, arg); >+ >+ return; >+} >+ >+ >+ >+/*************************** End Output Plugin API ***************************/ >+ >+ >+/************************** Miscellaneous Functions **************************/ >+ >+int PacketIsIP(Packet * p) >+{ >+ if(IPH_IS_VALID(p)) >+ return 1; >+ >+ return 0; >+} >+ >+ >+ >+int PacketIsTCP(Packet * p) >+{ >+ if(IPH_IS_VALID(p) && p->tcph != NULL) >+ return 1; >+ >+ return 0; >+} >+ >+ >+ >+int PacketIsUDP(Packet * p) >+{ >+ if(IPH_IS_VALID(p) && p->udph != NULL) >+ return 1; >+ >+ return 0; >+} >+ >+ >+ >+int PacketIsICMP(Packet * p) >+{ >+ if(IPH_IS_VALID(p) && p->icmph != NULL) >+ return 1; >+ >+ return 0; >+} >+ >+ >+ >+int DestinationIpIsHomenet(Packet * p) >+{ >+#ifdef SUP_IP6 >+ if(sfip_contains(&pv.homenet, GET_DST_IP(p)) == SFIP_CONTAINS) >+#else >+ if((p->iph->ip_dst.s_addr & pv.netmask) == pv.homenet) >+#endif >+ { >+ return 1; >+ } >+ return 0; >+} >+ >+ >+ >+int SourceIpIsHomenet(Packet * p) >+{ >+#ifdef SUP_IP6 >+ if(sfip_contains(&pv.homenet, GET_SRC_IP(p)) == SFIP_CONTAINS) >+#else >+ if((p->iph->ip_src.s_addr & pv.netmask) == pv.homenet) >+#endif >+ { >+ return 1; >+ } >+ return 0; >+} >+ >+int CheckNet(struct in_addr * compare, struct in_addr * compare2) >+{ >+ if(compare->s_addr == compare2->s_addr) >+ { >+ return 1; >+ } >+ return 0; >+} >+ >+/* functions to aid in cleaning up after plugins */ >+void AddFuncToRestartList(void (*func) (int, void *), void *arg) >+{ >+ PluginRestartList = AddFuncToSignalList(func, arg, PluginRestartList); >+} >+ >+void AddFuncToCleanExitList(void (*func) (int, void *), void *arg) >+{ >+ PluginCleanExitList = AddFuncToSignalList(func, arg, PluginCleanExitList); >+} >+ >+void AddFuncToShutdownList(void (*func) (int, void *), void *arg) >+{ >+ PluginShutdownList = AddFuncToSignalList(func, arg, PluginShutdownList); >+} >+ >+void AddFuncToPostConfigList(void (*func)(int, void *), void *arg) >+{ >+ PluginPostConfigList = AddFuncToSignalList(func, arg, PluginPostConfigList); >+} >+ >+PluginSignalFuncNode *AddFuncToSignalList(void (*func) (int, void *), void *arg, >+ PluginSignalFuncNode * list) >+{ >+ PluginSignalFuncNode *idx; >+ >+ idx = list; >+ >+ if(idx == NULL) >+ { >+ idx = (PluginSignalFuncNode *)SnortAlloc(sizeof(PluginSignalFuncNode)); >+ >+ idx->func = func; >+ idx->arg = arg; >+ list = idx; >+ } >+ else >+ { >+ while(idx->next != NULL) >+ idx = idx->next; >+ >+ idx->next = (PluginSignalFuncNode *)SnortAlloc(sizeof(PluginSignalFuncNode)); >+ >+ idx = idx->next; >+ idx->func = func; >+ idx->arg = arg; >+ } >+ idx->next = NULL; >+ >+ return list; >+} >+ >+ >+/**************************************************************************** >+ * >+ * Function: GetUniqueName(char * iface) >+ * >+ * Purpose: To return a string that has a high probability of being unique >+ * for a given sensor. >+ * >+ * Arguments: char * iface - The network interface you are sniffing >+ * >+ * Returns: A char * -- its a static char * so you should not free it >+ * >+ ***************************************************************************/ >+char *GetUniqueName(char * iface) >+{ >+ char * rptr; >+ static char uniq_name[256]; >+ >+ if (iface == NULL) LogMessage("Interface is NULL. Name may not be unique for the host\n"); >+#ifndef WIN32 >+ rptr = GetIP(iface); >+ if(rptr == NULL || !strcmp(rptr, "unknown")) >+#endif >+ { >+ SnortSnprintf(uniq_name, 255, "%s:%s\n",GetHostname(),iface); >+ rptr = uniq_name; >+ } >+ if (pv.verbose_flag) LogMessage("Node unique name is: %s\n", rptr); >+ return rptr; >+} >+ >+/**************************************************************************** >+ * >+ * Function: GetIP(char * iface) >+ * >+ * Purpose: To return a string representing the IP address for an interface >+ * >+ * Arguments: char * iface - The network interface you want to find an IP >+ * address for. >+ * >+ * Returns: A char * -- make sure you call free on this when you are done >+ * with it. >+ * >+ ***************************************************************************/ >+char *GetIP(char * iface) >+{ >+ struct ifreq ifr; >+ struct sockaddr_in *addr; >+ int s; >+#ifdef SUP_IP6 >+ sfip_t ret; >+#endif >+ >+ if(iface) >+ { >+ /* Set up a dummy socket just so we can use ioctl to find the >+ ip address of the interface */ >+ s = socket(PF_INET, SOCK_DGRAM, 0); >+ if(s == -1) >+ { >+ FatalError("Problem establishing socket to find IP address for interface: %s\n", iface); >+ } >+ >+ SnortStrncpy(ifr.ifr_name, iface, strlen(iface) + 1); >+ >+#ifndef WIN32 >+ if(ioctl(s, SIOCGIFADDR, &ifr) < 0) return NULL; >+ else >+#endif >+ { >+ addr = (struct sockaddr_in *) &ifr.ifr_broadaddr; >+ } >+ close(s); >+ >+#ifdef SUP_IP6 >+// XXX-IPv6 uses ioctl to populate a sockaddr_in structure ... but what if the interface only has an IPv6 address? >+ sfip_set_raw(&ret, addr, AF_INET); >+ return SnortStrdup(sfip_ntoa(&ret)); >+#else >+ return SnortStrdup(inet_ntoa(addr->sin_addr)); >+#endif >+ } >+ else >+ { >+ return "unknown"; >+ } >+} >+ >+/**************************************************************************** >+ * >+ * Function: GetHostname() >+ * >+ * Purpose: To return a string representing the hostname >+ * >+ * Arguments: None >+ * >+ * Returns: A static char * representing the hostname. >+ * >+ ***************************************************************************/ >+char *GetHostname() >+{ >+#ifdef WIN32 >+ DWORD bufflen = 256; >+ static char buff[256]; >+ GetComputerName(buff, &bufflen); >+ return buff; >+#else >+ char * error = "unknown"; >+ if(getenv("HOSTNAME")) return getenv("HOSTNAME"); >+ else if(getenv("HOST")) return getenv("HOST"); >+ else return error; >+#endif >+} >+ >+/**************************************************************************** >+ * >+ * Function: GetTimestamp(register const struct timeval *tvp, int tz) >+ * >+ * Purpose: Get an ISO-8601 formatted timestamp for tvp within the tz >+ * timezone. >+ * >+ * Arguments: tvp is a timeval pointer. tz is a timezone. >+ * >+ * Returns: char * -- You must free this char * when you are done with it. >+ * >+ ***************************************************************************/ >+char *GetTimestamp(register const struct timeval *tvp, int tz) >+{ >+ struct tm *lt; /* localtime */ >+ char * buf; >+ int msec; >+ >+ buf = (char *)SnortAlloc(SMALLBUFFER * sizeof(char)); >+ >+ msec = tvp->tv_usec / 1000; >+ >+ if(pv.use_utc == 1) >+ { >+ lt = gmtime((time_t *)&tvp->tv_sec); >+ SnortSnprintf(buf, SMALLBUFFER, "%04i-%02i-%02i %02i:%02i:%02i.%03i", >+ 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday, >+ lt->tm_hour, lt->tm_min, lt->tm_sec, msec); >+ } >+ else >+ { >+ lt = localtime((time_t *)&tvp->tv_sec); >+ SnortSnprintf(buf, SMALLBUFFER, >+ "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i", >+ 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday, >+ lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tz); >+ } >+ >+ return buf; >+} >+ >+/**************************************************************************** >+ * >+ * Function: GetLocalTimezone() >+ * >+ * Purpose: Find the offset from GMT for current host >+ * >+ * Arguments: none >+ * >+ * Returns: int representing the offset from GMT >+ * >+ ***************************************************************************/ >+int GetLocalTimezone() >+{ >+ time_t ut; >+ struct tm * ltm; >+ long seconds_away_from_utc; >+ >+ time(&ut); >+ ltm = localtime(&ut); >+ >+#if defined(WIN32) || defined(SOLARIS) || defined(AIX) >+ /* localtime() sets the global timezone variable, >+ which is defined in <time.h> */ >+ seconds_away_from_utc = timezone; >+#else >+ seconds_away_from_utc = ltm->tm_gmtoff; >+#endif >+ >+ return seconds_away_from_utc/3600; >+} >+ >+/**************************************************************************** >+ * >+ * Function: GetCurrentTimestamp() >+ * >+ * Purpose: Generate an ISO-8601 formatted timestamp for the current time. >+ * >+ * Arguments: none >+ * >+ * Returns: char * -- You must free this char * when you are done with it. >+ * >+ ***************************************************************************/ >+char *GetCurrentTimestamp() >+{ >+ struct tm *lt; >+ struct timezone tz; >+ struct timeval tv; >+ struct timeval *tvp; >+ char * buf; >+ int tzone; >+ int msec; >+ >+ buf = (char *)SnortAlloc(SMALLBUFFER * sizeof(char)); >+ >+ bzero((char *)&tz,sizeof(tz)); >+ gettimeofday(&tv,&tz); >+ tvp = &tv; >+ >+ msec = tvp->tv_usec/1000; >+ >+ if(pv.use_utc == 1) >+ { >+ lt = gmtime((time_t *)&tvp->tv_sec); >+ SnortSnprintf(buf, SMALLBUFFER, "%04i-%02i-%02i %02i:%02i:%02i.%03i", >+ 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday, >+ lt->tm_hour, lt->tm_min, lt->tm_sec, msec); >+ } >+ else >+ { >+ lt = localtime((time_t *)&tvp->tv_sec); >+ >+ tzone = GetLocalTimezone(); >+ >+ SnortSnprintf(buf, SMALLBUFFER, >+ "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i", >+ 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday, >+ lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tzone); >+ } >+ >+ return buf; >+} >+ >+/**************************************************************************** >+ * Function: base64(char * xdata, int length) >+ * >+ * Purpose: Insert data into the database >+ * >+ * Arguments: xdata => pointer to data to base64 encode >+ * length => how much data to encode >+ * >+ * Make sure you allocate memory for the output before you pass >+ * the output pointer into this function. You should allocate >+ * (1.5 * length) bytes to be safe. >+ * >+ * Returns: data base64 encoded as a char * >+ * >+ ***************************************************************************/ >+char * base64(const u_char * xdata, int length) >+{ >+ int count, cols, bits, c, char_count; >+ unsigned char alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* 64 bytes */ >+ char * payloadptr; >+ char * output; >+ char_count = 0; >+ bits = 0; >+ cols = 0; >+ >+ output = (char *)SnortAlloc( ((unsigned int) (length * 1.5 + 4)) * sizeof(char) ); >+ >+ payloadptr = output; >+ >+ for(count = 0; count < length; count++) >+ { >+ c = xdata[count]; >+ >+ if(c > 255) >+ { >+ ErrorMessage("plugbase.c->base64(): encountered char > 255 (decimal %d)\n If you see this error message a char is more than one byte on your machine\n This means your base64 results can not be trusted", c); >+ } >+ >+ bits += c; >+ char_count++; >+ >+ if(char_count == 3) >+ { >+ *output = alpha[bits >> 18]; output++; >+ *output = alpha[(bits >> 12) & 0x3f]; output++; >+ *output = alpha[(bits >> 6) & 0x3f]; output++; >+ *output = alpha[bits & 0x3f]; output++; >+ cols += 4; >+ if(cols == 72) >+ { >+ *output = '\n'; output++; >+ cols = 0; >+ } >+ bits = 0; >+ char_count = 0; >+ } >+ else >+ { >+ bits <<= 8; >+ } >+ } >+ >+ if(char_count != 0) >+ { >+ bits <<= 16 - (8 * char_count); >+ *output = alpha[bits >> 18]; output++; >+ *output = alpha[(bits >> 12) & 0x3f]; output++; >+ if(char_count == 1) >+ { >+ *output = '='; output++; >+ *output = '='; output++; >+ } >+ else >+ { >+ *output = alpha[(bits >> 6) & 0x3f]; >+ output++; *output = '='; >+ output++; >+ } >+ } >+ *output = '\0'; >+ return payloadptr; >+} >+ >+/**************************************************************************** >+ * >+ * Function: ascii(u_char *xdata, int length) >+ * >+ * Purpose: This function takes takes a buffer "xdata" and its length then >+ * returns a string of only the printible ASCII characters. >+ * >+ * Arguments: xdata is the buffer, length is the length of the buffer in >+ * bytes >+ * >+ * Returns: char * -- You must free this char * when you are done with it. >+ * >+ ***************************************************************************/ >+char *ascii(const u_char *xdata, int length) >+{ >+ char *d_ptr, *ret_val; >+ int i,count = 0; >+ int size; >+ >+ if(xdata == NULL) >+ { >+ return NULL; >+ } >+ >+ for(i=0;i<length;i++) >+ { >+ if(xdata[i] == '<') >+ count+=4; /* < */ >+ else if(xdata[i] == '&') >+ count+=5; /* & */ >+ else if(xdata[i] == '>') /* > */ >+ count += 4; >+ } >+ >+ size = length + count + 1; >+ ret_val = (char *) calloc(1,size); >+ >+ if(ret_val == NULL) >+ { >+ LogMessage("plugbase.c: ascii(): Out of memory, can't log anything!\n"); >+ return NULL; >+ } >+ >+ d_ptr = ret_val; >+ >+ for(i=0;i<length;i++) >+ { >+ if((xdata[i] > 0x1F) && (xdata[i] < 0x7F)) >+ { >+ if(xdata[i] == '<') >+ { >+ SnortStrncpy(d_ptr, "<", size - (d_ptr - ret_val)); >+ d_ptr+=4; >+ } >+ else if(xdata[i] == '&') >+ { >+ SnortStrncpy(d_ptr, "&", size - (d_ptr - ret_val)); >+ d_ptr += 5; >+ } >+ else if(xdata[i] == '>') >+ { >+ SnortStrncpy(d_ptr, ">", size - (d_ptr - ret_val)); >+ d_ptr += 4; >+ } >+ else >+ { >+ *d_ptr++ = xdata[i]; >+ } >+ } >+ else >+ { >+ *d_ptr++ = '.'; >+ } >+ } >+ >+ *d_ptr++ = '\0'; >+ >+ return ret_val; >+} >+ >+/**************************************************************************** >+ * >+ * Function: hex(u_char *xdata, int length) >+ * >+ * Purpose: This function takes takes a buffer "xdata" and its length then >+ * returns a string of hex with no spaces >+ * >+ * Arguments: xdata is the buffer, length is the length of the buffer in >+ * bytes >+ * >+ * Returns: char * -- You must free this char * when you are done with it. >+ * >+ ***************************************************************************/ >+char *hex(const u_char *xdata, int length) >+{ >+ int x; >+ char *rval = NULL; >+ char *buf = NULL; >+ >+ if (xdata == NULL) >+ return NULL; >+ >+ buf = (char *)calloc((length * 2) + 1, sizeof(char)); >+ >+ if (buf != NULL) >+ { >+ rval = buf; >+ >+ for (x = 0; x < length; x++) >+ { >+ SnortSnprintf(buf, 3, "%02X", xdata[x]); >+ buf += 2; >+ } >+ >+ rval[length * 2] = '\0'; >+ } >+ >+ return rval; >+} >+ >+ >+ >+char *fasthex(const u_char *xdata, int length) >+{ >+ char conv[] = "0123456789ABCDEF"; >+ char *retbuf = NULL; >+ const u_char *index; >+ const u_char *end; >+ char *ridx; >+ >+ index = xdata; >+ end = xdata + length; >+ retbuf = (char *)SnortAlloc(((length * 2) + 1) * sizeof(char)); >+ ridx = retbuf; >+ >+ while(index < end) >+ { >+ *ridx++ = conv[((*index & 0xFF)>>4)]; >+ *ridx++ = conv[((*index & 0xFF)&0x0F)]; >+ index++; >+ } >+ >+ return retbuf; >+} >+ >diff -uNr snort-2.8.3.1/src/plugin_enum.h snortsam-2.8.3.1/src/plugin_enum.h >--- snort-2.8.3.1/src/plugin_enum.h 2008-02-25 13:27:42.000000000 -0600 >+++ snortsam-2.8.3.1/src/plugin_enum.h 2008-11-05 19:10:36.000000000 -0600 >@@ -60,6 +60,7 @@ > PLUGIN_URILEN_CHECK, > PLUGIN_DYNAMIC, > PLUGIN_FLOWBIT, >+ PLUGIN_FWSAM, > PLUGIN_MAX /* sentinel value */ > }; > >diff -uNr snort-2.8.3.1/src/plugin_enum.h.orig snortsam-2.8.3.1/src/plugin_enum.h.orig >--- snort-2.8.3.1/src/plugin_enum.h.orig 1969-12-31 18:00:00.000000000 -0600 >+++ snortsam-2.8.3.1/src/plugin_enum.h.orig 2008-02-25 13:27:42.000000000 -0600 >@@ -0,0 +1,67 @@ >+/* $Id$ */ >+/**************************************************************************** >+ * >+ * Copyright (C) 2003-2008 Sourcefire, Inc. >+ * >+ * 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. >+ * >+ ****************************************************************************/ >+ >+/* >+ Purpose: Enumerate all the various detection plugins entries for >+ otn->ds_list[] >+ >+ No more grepping to make your own plugin! >+*/ >+ >+#ifndef _PLUGIN_ENUM_H >+#define _PLUGIN_ENUM_H >+ >+enum { >+ PLUGIN_CLIENTSERVER, >+ PLUGIN_DSIZE_CHECK, >+ PLUGIN_FRAG_BITS, >+ PLUGIN_FRAG_OFFSET, >+ PLUGIN_ICMP_CODE, >+ PLUGIN_ICMP_ID_CHECK, >+ PLUGIN_ICMP_SEQ_CHECK, >+ PLUGIN_ICMP_TYPE, >+ PLUGIN_IPOPTION_CHECK, >+ PLUGIN_IP_ID_CHECK, >+ PLUGIN_IP_PROTO_CHECK, >+ PLUGIN_IP_SAME_CHECK, >+ PLUGIN_IP_TOS_CHECK, >+ PLUGIN_PATTERN_MATCH, /* AND match */ >+ PLUGIN_PATTERN_MATCH_OR, >+ PLUGIN_PATTERN_MATCH_URI, >+ PLUGIN_RESPOND, >+ PLUGIN_RPC_CHECK, >+ PLUGIN_SESSION, >+ PLUGIN_TCP_ACK_CHECK, >+ PLUGIN_TCP_FLAG_CHECK, >+ PLUGIN_TCP_SEQ_CHECK, >+ PLUGIN_TCP_WIN_CHECK, >+ PLUGIN_TTL_CHECK, >+ PLUGIN_BYTE_TEST, >+ PLUGIN_PCRE, >+ PLUGIN_URILEN_CHECK, >+ PLUGIN_DYNAMIC, >+ PLUGIN_FLOWBIT, >+ PLUGIN_MAX /* sentinel value */ >+}; >+ >+#endif /* _PLUGIN_ENUM_H */ >+ >diff -uNr snort-2.8.3.1/src/twofish.c snortsam-2.8.3.1/src/twofish.c >--- snort-2.8.3.1/src/twofish.c 1969-12-31 18:00:00.000000000 -0600 >+++ snortsam-2.8.3.1/src/twofish.c 2008-11-05 19:08:29.000000000 -0600 >@@ -0,0 +1,946 @@ >+/* $Id: snortpatchb,v 1.5 2005/10/06 08:50:39 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 "twofish.h" >+ >+ >+bool TwoFish_srand=TRUE; /* if TRUE, first call of TwoFishInit will seed rand(); */ >+ /* of TwoFishInit */ >+ >+/* Fixed 8x8 permutation S-boxes */ >+static const unsigned char 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 unsigned long 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) ((unsigned long)(x)) /* force result to dword so << will work */ >+#define TwoFish_Mx_X(x) ((unsigned long)((x)^TwoFish_LFSR2(x))) /* 5B */ >+#define TwoFish_Mx_Y(x) ((unsigned long)((x)^TwoFish_LFSR1(x)^TwoFish_LFSR2(x))) /* EF */ >+#define TwoFish_RS_rem(x) { unsigned char b=(unsigned char)(x>>24); unsigned long g2=((b<<1)^((b&0x80)?TwoFish_RS_GF_FDBK:0))&0xFF; unsigned long 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) (((unsigned char *)&x)[((N)&3)^TwoFish_ADDR_XOR])*/ /* pick bytes out of a dword */ >+ >+#define TwoFish_b0(x) TwoFish__b(x,0) /* extract LSB of unsigned long */ >+#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 unsigned long */ >+ >+unsigned char TwoFish__b(unsigned long x,int n) >+{ n&=3; >+ while(n-->0) >+ x>>=8; >+ return (unsigned char)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(unsigned char *buf,unsigned long len,bool bintohex) >+{ unsigned char *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]= (unsigned char)(ilen); >+ tfdata->header.length[1]= (unsigned char)(ilen>>8); >+ tfdata->header.length[2]= (unsigned char)(ilen>>16); >+ tfdata->header.length[3]= (unsigned char)(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((unsigned char *)&(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 unsigned char cmagic[TwoFish_MAGIC_LEN]=TwoFish_MAGIC; >+ unsigned char *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=(unsigned char *)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 */ >+{ unsigned long m1[2]; >+ unsigned long mX[2]; >+ unsigned long mY[2]; >+ unsigned long 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. */ >+{ unsigned long k64Cnt = TwoFish_KEY_LENGTH / 8; >+ unsigned long k32e[4]; /* even 32-bit entities */ >+ unsigned long k32o[4]; /* odd 32-bit entities */ >+ unsigned long sBoxKey[4]; >+ unsigned long offset,i,j; >+ unsigned long A, B, q=0; >+ unsigned long k0,k1,k2,k3; >+ unsigned long 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(unsigned char *in,unsigned char *out,unsigned long size,int decrypt,TWOFISH *tfdata) >+{ unsigned char PnMinusOne[TwoFish_BLOCK_SIZE]; >+ unsigned char CnMinusOne[TwoFish_BLOCK_SIZE]; >+ unsigned char CBCplusCprime[TwoFish_BLOCK_SIZE]; >+ unsigned char Pn[TwoFish_BLOCK_SIZE]; >+ unsigned char *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(unsigned char *p,unsigned char *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(unsigned char *p,unsigned char *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(unsigned char *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(unsigned char *in,unsigned char *out,bool decrypt,TWOFISH *tfdata) >+{ unsigned long x0,x1,x2,x3; >+ unsigned long 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++ = (unsigned char)(x2 ); >+ *out++ = (unsigned char)(x2 >> 8); >+ *out++ = (unsigned char)(x2 >> 16); >+ *out++ = (unsigned char)(x2 >> 24); >+ >+ *out++ = (unsigned char)(x3 ); >+ *out++ = (unsigned char)(x3 >> 8); >+ *out++ = (unsigned char)(x3 >> 16); >+ *out++ = (unsigned char)(x3 >> 24); >+ >+ *out++ = (unsigned char)(x0 ); >+ *out++ = (unsigned char)(x0 >> 8); >+ *out++ = (unsigned char)(x0 >> 16); >+ *out++ = (unsigned char)(x0 >> 24); >+ >+ *out++ = (unsigned char)(x1 ); >+ *out++ = (unsigned char)(x1 >> 8); >+ *out++ = (unsigned char)(x1 >> 16); >+ *out++ = (unsigned char)(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 >+ */ >+unsigned long _TwoFish_RS_MDS_Encode(unsigned long k0,unsigned long k1) >+{ unsigned long 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; >+} >+ >+unsigned long _TwoFish_F32(unsigned long k64Cnt,unsigned long x,unsigned long *k32) >+{ unsigned char b0,b1,b2,b3; >+ unsigned long 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; >+} >+ >+unsigned long _TwoFish_Fe320(unsigned long *lsBox,unsigned long 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)]; >+} >+ >+unsigned long _TwoFish_Fe323(unsigned long *lsBox,unsigned long 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)]; >+} >+ >+unsigned long _TwoFish_Fe32(unsigned long *lsBox,unsigned long x,unsigned long 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 -uNr snort-2.8.3.1/src/twofish.h snortsam-2.8.3.1/src/twofish.h >--- snort-2.8.3.1/src/twofish.h 1969-12-31 18:00:00.000000000 -0600 >+++ snortsam-2.8.3.1/src/twofish.h 2008-11-05 19:08:29.000000000 -0600 >@@ -0,0 +1,276 @@ >+/* $Id: snortpatchb,v 1.5 2005/10/06 08:50:39 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 substitutes 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 >+{ unsigned long sBox[4 * 256]; /* Key dependent S-box */ >+ unsigned long subKeys[TwoFish_TOTAL_SUBKEYS]; /* Subkeys */ >+ unsigned char key[TwoFish_KEY_LENGTH]; /* Encryption Key */ >+ unsigned char *output; /* Pointer to output buffer */ >+ unsigned char qBlockPlain[TwoFish_BLOCK_SIZE]; /* Used by CBC */ >+ unsigned char qBlockCrypt[TwoFish_BLOCK_SIZE]; >+ unsigned char prevCipher[TwoFish_BLOCK_SIZE]; >+ struct /* Header for crypt functions. Has to be at least one block long. */ >+ { unsigned long salt; /* Random salt in first block (will salt the rest through CBC) */ >+ unsigned char length[4]; /* The amount of data following the header */ >+ unsigned char 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 ****/ >+ >+unsigned char TwoFish__b(unsigned long x,int n); >+void _TwoFish_BinHex(unsigned char *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(unsigned char *p,unsigned char *c,TWOFISH *tfdata); >+void _TwoFish_qBlockPop(unsigned char *p,unsigned char *c,TWOFISH *tfdata); >+void _TwoFish_ResetCBC(TWOFISH *tfdata); >+void _TwoFish_FlushOutput(unsigned char *b,unsigned long len,TWOFISH *tfdata); >+void _TwoFish_BlockCrypt(unsigned char *in,unsigned char *out,unsigned long size,int decrypt,TWOFISH *tfdata); >+void _TwoFish_BlockCrypt16(unsigned char *in,unsigned char *out,bool decrypt,TWOFISH *tfdata); >+unsigned long _TwoFish_RS_MDS_Encode(unsigned long k0,unsigned long k1); >+unsigned long _TwoFish_F32(unsigned long k64Cnt,unsigned long x,unsigned long *k32); >+unsigned long _TwoFish_Fe320(unsigned long *lsBox,unsigned long x); >+unsigned long _TwoFish_Fe323(unsigned long *lsBox,unsigned long x); >+unsigned long _TwoFish_Fe32(unsigned long *lsBox,unsigned long x,unsigned long R); >+ >+ >+#endif >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 245752
:
170845
|
170846
|
170848
|
170851
|
172325
|
172329