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