1 /*
2 ** spo_alert_fwsam.c
3 **
4 ** Copyright (c) 2001-2005 Frank Knobbe <frank@knobbe.us>
5 ** Portions Copyright (c) 2012 Ian Firns <firnsy@securixlive.com>
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 /*
23 * Purpose:
24 *
25 * This module sends alerts to a remote service on a host running SnortSam
26 * (the agent) which will block the intruding IP address on a variety of
27 * host and network firewalls.
28 *
29 * SnortSam also performs checks against a white-list of never-to-be-blocked IP addresses,
30 * can override block durations (for example for known proxies), and can detect attack conditions
31 * where too many blocks are received within a defined interval. If an attack is detected
32 * it will unblock the last x blocks and wait for the attack to end.
33 *
34 * See the SnortSam documentation for more information.
35 *
36 *
37 * Output Plugin Parameters:
38 ***************************
39 *
40 * output alert_fwsam: <SnortSam Station>:<port>/<key>
41 *
42 * <FW Mgmt Station>: IP address or host name of the host running SnortSam.
43 * <port>: Port the remote SnortSam service listens on (default 898).
44 * <key>: Key used for authentication (encryption really)
45 * of the communication to the remote service.
46 *
47 * Examples:
48 *
49 * output alert_fwsam: snortsambox/idspassword
50 * output alert_fwsam: fw1.domain.tld:898/mykey
51 * output alert_fwsam: 192.168.0.1/borderfw 192.168.1.254/wanfw
52 *
53 *
54 * sid-fwsam Parameters:
55 ***********************
56 *
57 * <sid>: who[how],time;
58 *
59 * who: src, source, dst, dest, destination
60 * IP address to be blocked according to snort rule (some rules
61 * are reversed, i.e. homenet -> any [and you want to block any]).
62 * src denotes IP to the left of -> and dst denotes IP to the right
63 *
64 * how: Optional. In, out, src, dest, either, both, this, conn, connection
65 * Tells SnortSam to block packets INcoming from host, OUTgoing to host,
66 * EITHERway, or only THIS connection (IP/Service pair).
67 * See 'fw sam' on Firewall-1 for more information.
68 * This option may be ignored by other plugins.
69 *
70 * time: Duration of block in seconds. (Accepts 'days', 'months', 'weeks',
71 * 'years', 'minutes', 'seconds', 'hours'. Alternatively, a value of
72 * 0, or the keyword PERManent, INFinite, or ALWAYS, will block the
73 * host permanently. Be careful with this!
74 * Tells SnortSam how long to inhibit packets from the host.
75 *
76 * Examples:
77 *
78 * 1487: src[either],15min;
79 * 1292: dst[in], 2 days 4 hours
80 * 1638: src, 1 hour
81 *
82 */
83
84 #include <stdlib.h>
85 #include <stdio.h>
86 #include <time.h>
87 #include <string.h>
88 #include <ctype.h>
89 #include <unistd.h>
90
91 #include "barnyard2.h"
92 #include "decode.h"
93 #include "spo_alert_fwsam.h"
94 #include "twofish.h"
95 #include "plugbase.h"
96 #include "unified2.h"
97 #include "util.h"
98
99 /* just some compatibility stuff */
100 #ifdef WIN32
101 #if !defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
102 #include <winsock.h>
103 #endif
104 #define waitms(x) Sleep(x)
105
106 #else
107
108 #include <sys/socket.h>
109 #include <netinet/in.h>
110 #include <arpa/inet.h>
111 #include <sys/ioctl.h>
112 #include <netdb.h>
113
114 #ifdef SOLARIS
115 #include <sys/filio.h>
116 #endif
117
118 //typedef int SOCKET;
119
120 #ifndef INVALID_SOCKET
121 #define INVALID_SOCKET -1
122 #endif
123
124 #define waitms(x) usleep((x)*1000)
125
126 #endif
127
128 #ifndef FALSE
129 #define FALSE 0
130 #endif
131 #ifndef TRUE
132 #define TRUE !FALSE
133 #endif
134 #ifndef bool
135 #define bool int
136 #endif
137
138
139 #if defined(_DEBUG) || defined(DEBUG)
140 #ifndef FWSAMDEBUG
141 #define FWSAMDEBUG
142 #endif
143 #else
144 #endif
145
146
147
148 /* fixed defines */
149
150 #define FWSAM_DEFAULTPORT 898 /* Default port if user does not specify one in barnyard2.conf */
151 /* (Was unused last time I checked...) */
152 #define FWSAM_PACKETVERSION 14 /* version of the packet. Will increase with enhancements. */
153
154 #define FWSAM_STATUS_CHECKIN 1 /* snort to fw */
155 #define FWSAM_STATUS_CHECKOUT 2
156 #define FWSAM_STATUS_BLOCK 3
157 #define FWSAM_STATUS_UNBLOCK 9
158
159 #define FWSAM_STATUS_OK 4 /* fw to snort */
160 #define FWSAM_STATUS_ERROR 5
161 #define FWSAM_STATUS_NEWKEY 6
162 #define FWSAM_STATUS_RESYNC 7
163 #define FWSAM_STATUS_HOLD 8
164
165 #define FWSAM_LOG_NONE 0
166 #define FWSAM_LOG_SHORTLOG 1
167 #define FWSAM_LOG_SHORTALERT 2
168 #define FWSAM_LOG_LONGLOG 3
169 #define FWSAM_LOG_LONGALERT 4
170 #define FWSAM_LOG (FWSAM_LOG_SHORTLOG|FWSAM_LOG_SHORTALERT|FWSAM_LOG_LONGLOG|FWSAM_LOG_LONGALERT)
171 #define FWSAM_WHO_DST 8
172 #define FWSAM_WHO_SRC 16
173 #define FWSAM_WHO (FWSAM_WHO_DST|FWSAM_WHO_SRC)
174 #define FWSAM_HOW_IN 32
175 #define FWSAM_HOW_OUT 64
176 #define FWSAM_HOW_INOUT (FWSAM_HOW_IN|FWSAM_HOW_OUT)
177 #define FWSAM_HOW_THIS 128
178 #define FWSAM_HOW (FWSAM_HOW_IN|FWSAM_HOW_OUT|FWSAM_HOW_THIS)
179
180
181 /* user adjustable defines */
182
183 #define FWSAM_REPET_BLOCKS 10 /* Snort remembers this amount of last blocks and... */
184 #define FWSAM_REPET_TIME 20 /* ...checks if they fall within this time. If so,... */
185 /* ...the blocking request is not send. */
186
187 #define FWSAM_NETWAIT 300 /* 100th of a second. 3 sec timeout for network connections */
188 #define FWSAM_NETHOLD 6000 /* 100th of a second. 60 sec timeout for holding */
189
190 #define SID_MAPFILE "sid-block.map"
191 #define SID_ALT_MAPFILE "sid-fwsam.map"
192
193 #define FWSAM_FANCYFETCH /* This will invoke a fast sid lookup routine */
194
195
196 /* vars */
197
198 typedef struct _FWsamstation /* structure of a mgmt station */
199 {
200 unsigned short myseqno;
201 unsigned short stationseqno;
202 unsigned char mykeymod[4];
203 unsigned char fwkeymod[4];
204 unsigned short stationport;
205 //struct in_addr stationip;
206 sfip_t stationip;
207 struct sockaddr_in localsocketaddr;
208 struct sockaddr_in stationsocketaddr;
209 TWOFISH *stationfish;
210 char initialkey[TwoFish_KEY_LENGTH+2];
211 char stationkey[TwoFish_KEY_LENGTH+2];
212 time_t lastcontact;
213 /* time_t sleepstart; */
214 } FWsamStation;
215
216 typedef struct _FWsampacket /* 2 blocks (3rd block is header from TwoFish) */
217 {
218 unsigned short endiancheck; /* 0 */
219 unsigned char srcip[4]; /* 2 */
220 unsigned char dstip[4]; /* 6 */
221 unsigned char duration[4]; /* 10 */
222 unsigned char snortseqno[2]; /* 14 */
223 unsigned char fwseqno[2]; /* 16 */
224 unsigned char srcport[2]; /* 18 */
225 unsigned char dstport[2]; /* 20 */
226 unsigned char protocol[2]; /* 22 */
227 unsigned char fwmode; /* 24 */
228 unsigned char version; /* 25 */
229 unsigned char status; /* 26 */
230 unsigned char sig_id[4]; /* 27 */
231 unsigned char fluff; /* 31 */
232 } FWsamPacket; /* 32 bytes in size */
233
234 typedef struct _FWsampacket2 /* 4 blocks (3rd block is header from TwoFish) */
235 {
236 unsigned short endiancheck; /* 0 */
237 unsigned char srcip[16]; /* 2 */
238 unsigned char dstip[16]; /* 18 */
239 unsigned char ipver; /* 34 */
240 unsigned char duration[4]; /* 35 */
241 unsigned char snortseqno[2]; /* 39 */
242 unsigned char fwseqno[2]; /* 41 */
243 unsigned char srcport[2]; /* 43 */
244 unsigned char dstport[2]; /* 45 */
245 unsigned char protocol[2]; /* 47 */
246 unsigned char fwmode; /* 49 */
247 unsigned char version; /* 50 */
248 unsigned char status; /* 51 */
249 unsigned char sig_id[4]; /* 52 */
250 unsigned char reserved[7]; /* 56 */
251 } FWsamPacket2; /* 64 bytes in size */
252
253 typedef struct _FWsamoptions /* snort rule options */
254 {
255 unsigned long sid;
256 unsigned long duration;
257 unsigned char who;
258 unsigned char how;
259 unsigned char loglevel;
260 } FWsamOptions;
261
262 typedef struct _FWsamlistpointer
263 {
264 FWsamStation *station;
265 struct _FWsamlistpointer *next;
266 } FWsamList;
267
268 /*
269 ** PROTOTYPES
270 */
271 void AlertFWsamInit(char *args);
272 void AlertFWsamCleanExitFunc(int signal, void *arg);
273 void AlertFWsamRestartFunc(int signal, void *arg);
274 void AlertFWsam(Packet *p, void *event, uint32_t type, void *arg);
275 int FWsamCheckIn(FWsamStation *station);
276 void FWsamCheckOut(FWsamStation *station);
277 void FWsamNewStationKey(FWsamStation *station, FWsamPacket *packet);
278 void FWsamFixPacketEndian(FWsamPacket *p);
279 unsigned long FWsamParseDuration(char *p);
280 void FWsamFree(FWsamList *fwsamlist);
281 int FWsamStationExists(FWsamStation *who, FWsamList *list);
282 int FWsamReadLine(char *, unsigned long, FILE *);
283 void FWsamParseLine(FWsamOptions *, char *);
284 FWsamOptions *FWsamGetOption(unsigned long);
285 int FWsamParseOption(FWsamOptions *, char *);
286
287
288 /*
289 ** GLOBALS
290 */
291
292 /* external globals from rules.c */
293 extern char *file_name;
294 extern int file_line;
295
296 /* external globals from barnyard.c */
297 extern Barnyard2Config *barnyard2_conf;
298
299 FWsamList *FWsamStationList=NULL; /* Global (for all alert-types) list of snortsam stations */
300 FWsamOptions *FWsamOptionField=NULL;
301 unsigned long FWsamMaxOptions=0;
302
303
304 /*
305 * Function: AlertFWsamSetup()
306 *
307 * Purpose: Registers the output plugin keyword and initialization
308 * function into the output plugin list. This is the function that
309 * gets called from InitOutputPlugins() in plugbase.c.
310 * It also registers itself as a plugin in order to parse every rule
311 * and to set the appropiate flags from fwsam: option.
312 *
313 * Arguments: None.
314 *
315 * Returns: void function
316 *
317 */
AlertFWsamSetup(void)318 void AlertFWsamSetup(void)
319 {
320 /* link the preprocessor keyword to the init function in the preproc list */
321 RegisterOutputPlugin("alert_fwsam", OUTPUT_TYPE_FLAG__ALERT, AlertFWsamInit);
322
323 #ifdef FWSAMDEBUG /* This allows debugging of fwsam only */
324 LogMessage("DEBUG => [Alert_FWsam](AlertFWsamSetup) Output plugin is plugged in...\n");
325 #endif
326 }
327
328
329 /*
330 * Function: AlertFWsamInit(char *args)
331 *
332 * Purpose: Calls the argument parsing function, performs final setup on data
333 * structs, links the preproc function into the function list.
334 *
335 * Arguments: args => ptr to argument string
336 *
337 * Returns: void function
338 *
339 */
AlertFWsamInit(char * args)340 void AlertFWsamInit(char *args)
341 {
342 char *ap;
343 unsigned long statip,cnt,again,i;
344 char *stathost, *statport, *statpass;
345 FWsamStation *station;
346 FWsamList *fwsamlist=NULL; /* alert-type dependent list of snortsam stations */
347 FWsamList *listp,*newlistp;
348 struct hostent *hoste;
349 char buf[1024]="";
350 FILE *fp;
351 FWsamOptions tempopt;
352
353 #ifdef FWSAMDEBUG
354 unsigned long hostcnt=0;
355 LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Output plugin initializing...\n");
356 #endif
357
358 /* parse the argument list from the rules file */
359 if(args == NULL)
360 FatalError("[Alert_FWsam](AlertFWsamInit) No arguments to alert_fwsam preprocessor!\n");
361
362 if(!FWsamOptionField && !FWsamMaxOptions)
363 {
364 strncpy(buf, barnyard2_conf->config_dir, sizeof(buf)-1);
365 strncpy(buf+strlen(buf), SID_MAPFILE, sizeof(buf)-strlen(buf)-1);
366 #ifdef FWSAMDEBUG
367 LogMessage("DEBUG => [Alert_FWsam](AlertFWsamSetup) Using file: %s\n",buf);
368 #endif
369 fp=fopen(buf,"rt");
370 if(!fp)
371 {
372 strncpy(buf, barnyard2_conf->config_dir, sizeof(buf)-1);
373 strncpy(buf+strlen(buf), SID_ALT_MAPFILE, sizeof(buf)-strlen(buf)-1);
374 LogMessage("DEBUG => [Alert_FWsam](AlertFWsamSetup) Using alternative file: %s\n",buf);
375 fp=fopen(buf,"rt");
376 }
377
378 if(fp) /* Check for presence of map file and read those in, sorted. */
379 {
380 LogMessage("INFO => [Alert_FWsam](AlertFWsamSetup) Using sid-map file: %s\n",buf);
381 while( FWsamReadLine(buf,sizeof(buf),fp) )
382 if( *buf )
383 FWsamMaxOptions++;
384
385 if( FWsamMaxOptions )
386 {
387 if( (FWsamOptionField=(FWsamOptions *)malloc(sizeof(FWsamOptions)*FWsamMaxOptions)) == NULL )
388 FatalError("ERROR => [Alert_FWsam](AlertFWsamSetup) malloc failed for OptionField!\n");
389
390 fseek(fp,0,SEEK_SET);
391 for(cnt=0; cnt<FWsamMaxOptions; )
392 {
393 FWsamReadLine(buf,sizeof(buf),fp);
394
395 if( *buf )
396 FWsamParseLine(&(FWsamOptionField[cnt++]),buf);
397 }
398
399 if( FWsamMaxOptions>1 )
400 {
401 for(again=TRUE,cnt=FWsamMaxOptions-1; cnt>=1 && again; cnt--)
402 {
403 for(again=FALSE,i=0; i<cnt; i++)
404 {
405 if( FWsamOptionField[i].sid>FWsamOptionField[i+1].sid )
406 { memcpy(&tempopt,&(FWsamOptionField[i]),sizeof(FWsamOptions));
407 memcpy(&(FWsamOptionField[i]),&(FWsamOptionField[i+1]),sizeof(FWsamOptions));
408 memcpy(&(FWsamOptionField[i+1]),&tempopt,sizeof(FWsamOptions));
409 again=TRUE;
410 }
411 }
412 }
413 }
414 }
415 else
416 FWsamMaxOptions=1;
417
418 fclose(fp);
419 }
420 else
421 FWsamMaxOptions=1;
422 }
423
424
425 ap=args; /* start at the beginning of the argument */
426 while(*ap && isspace(*ap)) ap++;
427 while(*ap)
428 {
429 stathost=ap; /* first argument should be host */
430 statport=NULL;
431 statpass=NULL;
432 while(*ap && *ap!=':' && *ap!='/' && !isspace(*ap)) ap++; /* find token */
433 switch(*ap)
434 {
435 case ':':
436 *ap++=0; /* grab the port */
437 statport=ap;
438 while(*ap && *ap!='/' && !isspace(*ap)) ap++;
439 if(*ap!='/')
440 break;
441
442 case '/':
443 *ap++=0; /* grab the key */
444 statpass=ap;
445 while(*ap && !isspace(*ap)) ap++;
446 break;
447
448 default:
449 break;
450 }
451
452 if(*ap)
453 {
454 *ap++=0;
455 while(isspace(*ap)) ap++;
456 }
457
458 /* now we have the first host with port and password (key) */
459 /* next we check for valid/blank password/port */
460 if(statpass!=NULL)
461 if(!*statpass)
462 statpass=NULL;
463
464 if(statport!=NULL)
465 if(!*statport)
466 statport=NULL;
467
468 statip=0;
469 /* now we check if a valid host was specified */
470 if(inet_addr(stathost)==INADDR_NONE)
471 {
472 hoste=gethostbyname(stathost);
473
474 if (!hoste)
475 LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWsamInit) Unable to resolve host '%s'!\n",file_name,file_line,stathost);
476 else
477 statip=*(unsigned long *)hoste->h_addr;
478 }
479 else
480 {
481 statip=inet_addr(stathost);
482 if(!statip)
483 LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWsamInit) Invalid host address '%s'!\n",file_name,file_line,stathost);
484 }
485
486 if(statip)
487 { /* groovie, a valid host. Let's alloc and assemble the structure for it. */
488 if((station=(FWsamStation *)malloc(sizeof(FWsamStation)))==NULL)
489 FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for station!\n");
490
491 station->stationip.ip32[0] = statip; /* the IP address */
492 if(statport!=NULL && atoi(statport)>0) /* if the user specified one */
493 station->stationport=atoi(statport); /* use users setting */
494 else
495 station->stationport=FWSAM_DEFAULTPORT; /* set the default port */
496
497 if(statpass!=NULL) /* if specified by user */
498 strncpy(station->stationkey,statpass,TwoFish_KEY_LENGTH); /* use defined key */
499 else
500 station->stationkey[0]=0;
501
502 station->stationkey[TwoFish_KEY_LENGTH]=0; /* make sure it's terminated. (damn strncpy...) */
503
504 strcpy(station->initialkey,station->stationkey);
505 station->stationfish=TwoFishInit(station->stationkey);
506
507 station->localsocketaddr.sin_port=htons(0); /* let's use dynamic ports for now */
508 station->localsocketaddr.sin_addr.s_addr=0;
509 station->localsocketaddr.sin_family=AF_INET;
510 station->stationsocketaddr.sin_port=htons(station->stationport);
511
512 station->stationsocketaddr.sin_addr.s_addr=station->stationip.ip32[0];
513 station->stationsocketaddr.sin_family=AF_INET; /* load all socket crap and keep for later */
514
515 do
516 station->myseqno=rand(); /* the seqno this host will use */
517 while(station->myseqno<20 || station->myseqno>65500);
518
519 station->mykeymod[0]=rand();
520 station->mykeymod[1]=rand();
521 station->mykeymod[2]=rand();
522 station->mykeymod[3]=rand();
523 station->stationseqno=0; /* peer hasn't answered yet. */
524
525
526 /* If we don't have the station already in global list....*/
527 if(!FWsamStationExists(station,FWsamStationList))
528 {
529 if(FWsamCheckIn(station)) /* ...and we can talk to the agent... */
530 {
531 if((newlistp=(FWsamList *)malloc(sizeof(FWsamList)))==NULL)
532 FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for global newlistp!\n");
533
534 newlistp->station=station;
535 newlistp->next=NULL;
536
537 if(!FWsamStationList) /* ... add it to the global list/ */
538 FWsamStationList=newlistp;
539 else
540 {
541 listp=FWsamStationList;
542 while(listp->next)
543 listp=listp->next;
544 listp->next=newlistp;
545 }
546 }
547 else
548 {
549 TwoFishDestroy(station->stationfish); /* if not, we trash it. */
550 free(station);
551 station=NULL;
552 }
553 }
554 #ifdef FWSAMDEBUG
555 else
556 LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Host %s:%i already in global list, skipping CheckIn.\n", sfip_ntoa(&station->stationip),station->stationport);
557 #endif
558
559 if(station)
560 {
561 /* If we don't have the station already in local list....*/
562 if(!FWsamStationExists(station,fwsamlist))
563 {
564 if((newlistp=(FWsamList *)malloc(sizeof(FWsamList)))==NULL)
565 FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for local newlistp!\n");
566
567 newlistp->station=station;
568 newlistp->next=NULL;
569
570 if(!fwsamlist) /* ... add it to the local list/ */
571 fwsamlist=newlistp;
572 else
573 {
574 listp=fwsamlist;
575 while(listp->next)
576 listp=listp->next;
577 listp->next=newlistp;
578 }
579 }
580
581 #ifdef FWSAMDEBUG
582 else
583 LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Host %s:%i already in local list, skipping.\n",sfip_ntoa(&station->stationip),station->stationport);
584
585 LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) #%i: Host %s [%s] port %i password %s\n",++hostcnt,stathost,sfip_ntoa(&station->stationip),station->stationport,station->stationkey);
586 #endif
587 }
588 }
589 } /* next one */
590
591 #ifdef FWSAMDEBUG
592 LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Linking fwsam alert function to call list...\n");
593 #endif
594
595 /* Set the preprocessor function into the function list */
596 AddFuncToOutputList(AlertFWsam, OUTPUT_TYPE__LOG, fwsamlist);
597 AddFuncToCleanExitList(AlertFWsamCleanExitFunc, fwsamlist);
598 AddFuncToRestartList(AlertFWsamRestartFunc, fwsamlist);
599 }
600
601
602 /* This routine reads in a str from a file, snips white-spaces
603 * off the front and back, removes comments, and pretties the
604 * string. Returns true or false if a line was read or not.
605 */
FWsamReadLine(char * buf,unsigned long bufsize,FILE * fp)606 int FWsamReadLine(char *buf,unsigned long bufsize,FILE *fp)
607 { char *p;
608
609 if(fgets(buf,bufsize-1,fp))
610 {
611 buf[bufsize-1]=0;
612
613 #ifdef FWSAMDEBUG
614 LogMessage("DEBUG => [Alert_FWsam](AlertFWsamReadLine) Line: %s\n",buf);
615 #endif
616
617 p=buf;
618 while(isspace(*p))
619 p++;
620 if(p>buf)
621 ;
622 strcpy(buf,p);
623 if(*buf)
624 {
625 p=buf+strlen(buf)-1; /* remove leading and trailing spaces */
626 while(isspace(*p))
627 *p-- =0;
628 }
629 p=buf;
630 if(*p=='#' || *p==';')
631 *p=0;
632 else
633 p++;
634 while(*p) /* remove inline comments (except escaped #'s and ;'s) */
635 {
636 if(*p=='#' || *p==';')
637 {
638 if(*(p-1)=='\\')
639 strcpy(p-1,p);
640 else
641 *p=0;
642 }
643 else
644 p++;
645 }
646 return TRUE;
647 }
648 return FALSE;
649 }
650
651 /* This function checks if a given snortsam station is already in
652 * a given list.
653 */
FWsamStationExists(FWsamStation * who,FWsamList * list)654 int FWsamStationExists(FWsamStation *who,FWsamList *list)
655 {
656 while(list)
657 {
658 if(list->station)
659 {
660 if( IP_EQUALITY(&who->stationip, &list->station->stationip) &&
661 who->stationport==list->station->stationport )
662 return TRUE;
663 }
664 list=list->next;
665 }
666 return FALSE;
667 }
668
669
670 /* Parses the duration of the argument, recognizing minutes, hours, etc..
671 */
FWsamParseDuration(char * p)672 unsigned long FWsamParseDuration(char *p)
673 { unsigned long dur=0,tdu;
674 char *tok,c1,c2;
675
676 while(*p)
677 {
678 tok=p;
679 while(*p && isdigit(*p))
680 p++;
681 if(*p)
682 {
683 c1=tolower(*p);
684 *p=0;
685 p++;
686 if(*p && !isdigit(*p))
687 {
688 c2=tolower(*p++);
689 while(*p && !isdigit(*p))
690 p++;
691 }
692 else
693 c2=0;
694 tdu=atol(tok);
695 switch(c1)
696 {
697 case 'm':
698 if(c2=='o') /* month */
699 tdu*=(60*60*24*30); /* use 30 days */
700 else
701 tdu*=60; /* minutes */
702 break;
703 case 's':
704 break; /* seconds */
705 case 'h':
706 tdu*=(60*60); /* hours */
707 break;
708 case 'd':
709 tdu*=(60*60*24); /* days */
710 break;
711 case 'w':
712 tdu*=(60*60*24*7); /* week */
713 break;
714 case 'y':
715 tdu*=(60*60*24*365); /* year */
716 break;
717 }
718 dur+=tdu;
719 }
720 else
721 dur+=atol(tok);
722 }
723
724 return dur;
725 }
726
727
728 /* This routine parses an option line. It is called by FWsamParseLine,
729 * which parses the sid-block.map file, and also by AlertFWsamOptionInit,
730 * which is called by Snort when processing fwsam: options in rules.
731 * It returns TRUE it there is a possible option problem, otherwise FALSE.
732 */
FWsamParseOption(FWsamOptions * optp,char * ap)733 int FWsamParseOption(FWsamOptions *optp,char *ap)
734 {
735 int possprob=FALSE;
736
737 /* set defaults */
738
739 optp->duration=300; /* default of 5 minute block */
740 optp->how=FWSAM_HOW_INOUT; /* inbound and outbound block */
741 optp->who=FWSAM_WHO_SRC; /* the source */
742 optp->loglevel=FWSAM_LOG_LONGALERT; /* the log level default */
743 /* parse the fwsam keywords */
744
745 #ifdef FWSAMDEBUG
746 LogMessage("DEBUG => [Alert_FWsam](AlertFWamOptionInit) Parse Options Args: %s\n",ap);
747 #endif
748
749 if(*ap) /* should be dst/src (the WHO) or duration */
750 {
751 if(isdigit(*ap))
752 optp->duration=FWsamParseDuration(ap);
753 else
754 {
755 switch(*ap) /* yeah, we're lazy and check only the first character */
756 {
757 case 'p': /* permanent, perm */
758 case 'f': /* forever */
759 case 'i': /* infinite, inf */
760 optp->duration=0;
761 break;
762 case 'd': /* destination, dest, dst */
763 optp->who=FWSAM_WHO_DST;
764 break;
765 case 's': /* source, src */
766 optp->who=FWSAM_WHO_SRC;
767 break;
768 default:
769 possprob=TRUE;
770 }
771 while(*ap && *ap!=',' && *ap!='[')
772 ap++;
773 if(*ap=='[')
774 { ap++; /* now we have the HOW */
775 switch(*ap)
776 {
777 case 'i': /* in */
778 case 's': /* source, src */
779 optp->how=FWSAM_HOW_IN;
780 break;
781 case 'o': ; /* out */
782 case 'd': /* destination, dest, dst */
783 optp->how=FWSAM_HOW_OUT;
784 break;
785 case 'b': ; /* both */
786 case 'e': /* either */
787 optp->how=FWSAM_HOW_INOUT;
788 break;
789 case 't': ; /* this */
790 case 'c': /* connection, conn */
791 optp->how=FWSAM_HOW_THIS;
792 break;
793 default:
794 possprob=TRUE;
795 }
796 while(*ap && *ap!=',')
797 ap++;
798 }
799 if(*ap==',')
800 {
801 ap++;
802 if(isdigit(*ap)) /* and figure out how long to block */
803 optp->duration=FWsamParseDuration(ap);
804 else if(*ap=='p' || *ap=='f' || *ap=='i')
805 optp->duration=0;
806 else
807 possprob=TRUE;
808 }
809 else if(!*ap)
810 possprob=TRUE;
811 }
812 }
813 else
814 possprob=TRUE;
815
816 return possprob;
817 }
818
819
820 /* This goes through the lines of sid-block.map and sets the
821 * options for fwsam if the file is being used.
822 */
FWsamParseLine(FWsamOptions * optp,char * buf)823 void FWsamParseLine(FWsamOptions *optp,char *buf)
824 {
825 char *ap;
826
827 ap=buf; /* start at the beginning of the argument */
828
829 while(*ap)
830 {
831 if(isspace(*ap)) /* normalize spaces (tabs into space, etc) */
832 *ap=' ';
833 if(isupper(*ap)) /* and set to lower case */
834 *ap=tolower(*ap);
835 ap++;
836 }
837 while((ap=strrchr(buf,' '))!=NULL) /* remove spaces */
838 strcpy(ap,ap+1);
839
840 ap=buf;
841 if(*ap)
842 {
843 while(*ap && *ap!=':' && *ap!='|') ap++;
844 *ap++ =0;
845 while(*ap && (*ap==':' || *ap=='|')) ap++;
846
847 optp->sid=(unsigned long)atol(buf);
848
849 if(FWsamParseOption(optp,ap))
850 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);
851 }
852 else
853 optp->sid=0;
854 }
855
856
857 /* Generates a new encryption key for TwoFish based on seq numbers and a random that
858 * the SnortSam agents send on checkin (in protocol)
859 */
FWsamNewStationKey(FWsamStation * station,FWsamPacket * packet)860 void FWsamNewStationKey(FWsamStation *station,FWsamPacket *packet)
861 {
862 char newkey[TwoFish_KEY_LENGTH+2];
863 int i;
864
865 newkey[0]=packet->snortseqno[0]; /* current snort seq # (which both know) */
866 newkey[1]=packet->snortseqno[1];
867 newkey[2]=packet->fwseqno[0]; /* current SnortSam seq # (which both know) */
868 newkey[3]=packet->fwseqno[1];
869 newkey[4]=packet->protocol[0]; /* the random SnortSam chose */
870 newkey[5]=packet->protocol[1];
871
872 strncpy(newkey+6,station->stationkey,TwoFish_KEY_LENGTH-6); /* append old key */
873 newkey[TwoFish_KEY_LENGTH]=0;
874
875 newkey[0]^=station->mykeymod[0]; /* modify key with key modifiers which were */
876 newkey[1]^=station->mykeymod[1]; /* exchanged during the check-in handshake. */
877 newkey[2]^=station->mykeymod[2];
878 newkey[3]^=station->mykeymod[3];
879 newkey[4]^=station->fwkeymod[0];
880 newkey[5]^=station->fwkeymod[1];
881 newkey[6]^=station->fwkeymod[2];
882 newkey[7]^=station->fwkeymod[3];
883
884 for(i=0;i<=7;i++)
885 if(newkey[i]==0)
886 newkey[i]++;
887
888 strcpy(station->stationkey,newkey);
889 TwoFishDestroy(station->stationfish);
890 station->stationfish=TwoFishInit(newkey);
891 }
892
893
894 #ifdef FWSAMDEBUG
895 /* This does nothing else than inet_ntoa, but it keeps 4 results in a static string
896 * unlike inet_ntoa which keeps only one. This is used for (s)printf's were two IP
897 * addresses are printed.
898 */
inettoa(unsigned long ip)899 char *inettoa(unsigned long ip)
900 {
901 struct in_addr ips;
902 static char addr[4][20];
903 static unsigned char toggle;
904
905 ips.s_addr=ip;
906 toggle=(toggle+1)&3;
907 strncpy(addr[toggle],inet_ntoa(ips),18);
908 return addr[toggle];
909 }
910 #endif
911
912
913 /* This routing will search the option list as defined
914 * by the sid-block.map file and return a pointer
915 * to the matching record.
916 */
FWsamGetOption(unsigned long sid)917 FWsamOptions *FWsamGetOption(unsigned long sid)
918 {
919 signed long i,step,diff,o,o2;
920
921 #ifdef FWSAM_FANCYFETCH /* Fancy-fetch jumps in decreasing n/2 steps and takes much less lookups */
922 o=o2= -1;
923 i=step=FWsamMaxOptions>>1;
924 while(i>=0 && i<FWsamMaxOptions && i!=o2)
925 {
926 diff=sid-FWsamOptionField[i].sid;
927 if(!diff)
928 return &(FWsamOptionField[i]);
929 if(step>1)
930 step=step>>1;
931 o2=o;
932 o=i;
933 if(diff>0)
934 i+=step;
935 else
936 i-=step;
937 }
938 #else /* This is just a sequential list lookup */
939 for(i=0;i<FWsamMaxOptions;i++)
940 if(FWsamOptionField[i].sid==sid)
941 return &(FWsamOptionField[i]);
942 #endif
943 return NULL;
944 }
945
946
947 /****************************************************************************
948 *
949 * Function: AlertFWsam(Packet *, char *)
950 *
951 * Purpose: Send the current alert to a remote module on a FW-1 mgmt station
952 *
953 * Arguments: p => pointer to the packet data struct
954 * msg => the message to print in the alert
955 *
956 * Returns: void function
957 *
958 ***************************************************************************/
AlertFWsam(Packet * p,void * event,uint32_t event_type,void * arg)959 void AlertFWsam(Packet *p, void *event, uint32_t event_type, void *arg)
960 {
961 FWsamOptions *optp;
962 FWsamPacket sampacket;
963 FWsamStation *station=NULL;
964 FWsamList *fwsamlist;
965 int stationsocket;
966 int i,len,deletestation,stationtry=0;
967 char *encbuf,*decbuf;
968 static unsigned long lastbsip[FWSAM_REPET_BLOCKS];
969 static unsigned long lastbdip[FWSAM_REPET_BLOCKS];
970 static unsigned long lastbduration[FWSAM_REPET_BLOCKS];
971 static unsigned long lastbtime[FWSAM_REPET_BLOCKS];
972 static unsigned short lastbsp[FWSAM_REPET_BLOCKS];
973 static unsigned short lastbdp[FWSAM_REPET_BLOCKS];
974 static unsigned short lastbproto[FWSAM_REPET_BLOCKS];
975 static unsigned short lastbpointer;
976 static unsigned char lastbmode[FWSAM_REPET_BLOCKS];
977 static unsigned long btime=0;
978
979 SigNode *sn = NULL;
980 ClassType *cn = NULL;
981
982 /*
983 ** Remove Compiler warning.
984 ReferenceNode *rn = NULL;
985 */
986
987 if(event==NULL)
988 {
989 #ifdef FWSAMDEBUG
990 LogMessage("DEBUG => [Alert_FWsam] NULL event!\n");
991 #endif
992 return;
993 }
994
995 if(p == NULL)
996 {
997 #ifdef FWSAMDEBUG
998 LogMessage("DEBUG => [Alert_FWsam] NULL packet!\n");
999 #endif
1000 return;
1001 }
1002
1003 if(arg == NULL)
1004 {
1005 #ifdef FWSAMDEBUG
1006 LogMessage("DEBUG => [Alert_FWsam] NULL arg!\n");
1007 #endif
1008 return;
1009 }
1010
1011 /* SnortSam does no IPv6 */
1012 if (!IS_IP4(p)) {
1013 #ifdef FWSAMDEBUG
1014 LogMessage("DEBUG => [Alert_FWsam] not acting on non-IP4 packet!\n");
1015 #endif
1016 return;
1017 }
1018
1019 optp=NULL;
1020 sn = GetSigByGidSid(ntohl(((Unified2EventCommon *)event)->generator_id),
1021 ntohl(((Unified2EventCommon *)event)->signature_id),
1022 ntohl(((Unified2EventCommon *)event)->signature_revision));
1023
1024 cn = ClassTypeLookupById(barnyard2_conf, ntohl(((Unified2EventCommon *)event)->classification_id));
1025
1026 if(FWsamOptionField) /* If using the file (field present), let's use that */
1027 optp=FWsamGetOption(ntohl(((Unified2EventCommon *)event)->signature_id));
1028
1029 if(optp) /* if options specified for this rule */
1030 {
1031 if(!btime) /* if this is the first time this function is */
1032 {
1033 for(i=0;i<FWSAM_REPET_BLOCKS;i++) /* called, reset the time and protocol to 0. */
1034 {
1035 lastbproto[i]=0;
1036 lastbtime[i]=0;
1037 }
1038 }
1039
1040 fwsamlist=(FWsamList *)arg;
1041
1042 #ifdef FWSAMDEBUG
1043 LogMessage("DEBUG => [Alert_FWsam] Alert -> Msg=\"%s\"\n",sn->msg);
1044 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);
1045 #endif
1046
1047 len=TRUE;
1048 btime=(unsigned long)time(NULL); /* get current time */
1049 /* This is a cheap check to see if the blocking request matches any of the previous requests. */
1050 for(i=0; i<FWSAM_REPET_BLOCKS && len; i++)
1051 {
1052 if( ( ( optp->how==FWSAM_HOW_THIS ) ? /* if blocking mode SERVICE, check for src and dst */
1053 ( lastbsip[i]==(unsigned long)GET_SRC_IP(p) && lastbdip[i]==(unsigned long)GET_DST_IP(p) && lastbproto[i]==GET_IPH_PROTO(p) &&
1054 ( IP_HAS_PORTS(p) ? /* check port only of TCP or UDP */
1055 /* ((optp->who==FWSAM_WHO_SRC)?(lastbsp[i]==record->sp):(lastbdp[i]==record->dp)):TRUE) ): */
1056 lastbdp[i]==p->dp : TRUE
1057 )
1058 ) :
1059 (
1060 ( optp->who==FWSAM_WHO_SRC) ?
1061 ( lastbsip[i]==(unsigned long)GET_SRC_IP(p) ) :
1062 ( lastbdip[i]==(unsigned long)GET_DST_IP(p) )
1063 )
1064 ) && /* otherwise if we block source, only compare source. Same for dest. */
1065 lastbduration[i]==optp->duration &&
1066 (lastbmode[i] & (FWSAM_HOW|FWSAM_WHO))==(optp->how|optp->who) &&
1067 ( btime-lastbtime[i]<((optp->duration>FWSAM_REPET_TIME) ? FWSAM_REPET_TIME : optp->duration))
1068 )
1069 {
1070 len=FALSE; /* If so, we don't need to block again. */
1071 }
1072 }
1073
1074 if(len)
1075 {
1076 if(++lastbpointer>=FWSAM_REPET_BLOCKS) /* increase repetitive check pointer */
1077 lastbpointer=0;
1078
1079 lastbsip[lastbpointer]=(unsigned long)GET_SRC_IP(p); /* and note packet details */
1080 lastbdip[lastbpointer]=(unsigned long)GET_DST_IP(p);
1081 lastbduration[lastbpointer]=optp->duration;
1082 lastbmode[lastbpointer]=optp->how|optp->who|optp->loglevel;
1083 lastbproto[lastbpointer]=GET_IPH_PROTO(p);
1084 if(IP_HAS_PORTS(p))
1085 {
1086 lastbsp[lastbpointer]=p->sp; /* set ports if TCP or UDP */
1087 lastbdp[lastbpointer]=p->dp;
1088 }
1089 lastbtime[lastbpointer]=btime;
1090
1091
1092 while(fwsamlist!=NULL)
1093 {
1094 station=fwsamlist->station;
1095 //if(station->stationip.s_addr)
1096 if(station->stationip.ip32[0])
1097 {
1098 deletestation=FALSE;
1099 stationtry++; /* first try */
1100 /* create a socket for the station */
1101 stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
1102 if(stationsocket==INVALID_SOCKET)
1103 FatalError("ERROR => [Alert_FWsam] Funky socket error (socket)!\n");
1104 if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr)))
1105 FatalError("ERROR => [Alert_FWsam] Could not bind socket!\n");
1106
1107 /* let's connect to the agent */
1108 if(connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr)))
1109 {
1110 LogMessage("WARNING => [Alert_FWsam] Could not send block to host %s. Will try later.\n",sfip_ntoa(&station->stationip));
1111 #ifdef WIN32
1112 closesocket(stationsocket);
1113 #else
1114 close(stationsocket);
1115 #endif
1116 stationtry=0;
1117 }
1118 else
1119 {
1120 #ifdef FWSAMDEBUG
1121 LogMessage("DEBUG => [Alert_FWsam] Connected to host %s.\n",sfip_ntoa(&station->stationip));
1122 #endif
1123 /* now build the packet */
1124 station->myseqno+=station->stationseqno; /* increase my seqno by adding agent seq no */
1125 sampacket.endiancheck=1; /* This is an endian indicator for Snortsam */
1126 sampacket.snortseqno[0]=(char)station->myseqno;
1127 sampacket.snortseqno[1]=(char)(station->myseqno>>8);
1128 sampacket.fwseqno[0]=(char)station->stationseqno;/* fill station seqno */
1129 sampacket.fwseqno[1]=(char)(station->stationseqno>>8);
1130 sampacket.status=FWSAM_STATUS_BLOCK; /* set block mode */
1131 sampacket.version=FWSAM_PACKETVERSION; /* set packet version */
1132 sampacket.duration[0]=(char)optp->duration; /* set duration */
1133 sampacket.duration[1]=(char)(optp->duration>>8);
1134 sampacket.duration[2]=(char)(optp->duration>>16);
1135 sampacket.duration[3]=(char)(optp->duration>>24);
1136 sampacket.fwmode=optp->how|optp->who|optp->loglevel; /* set the mode */
1137 sampacket.dstip[0]=(char)p->iph->ip_dst.s_addr; /* destination IP */
1138 sampacket.dstip[1]=(char)(p->iph->ip_dst.s_addr>>8);
1139 sampacket.dstip[2]=(char)(p->iph->ip_dst.s_addr>>16);
1140 sampacket.dstip[3]=(char)(p->iph->ip_dst.s_addr>>24);
1141 sampacket.srcip[0]=(char)p->iph->ip_src.s_addr; /* source IP */
1142 sampacket.srcip[1]=(char)(p->iph->ip_src.s_addr>>8);
1143 sampacket.srcip[2]=(char)(p->iph->ip_src.s_addr>>16);
1144 sampacket.srcip[3]=(char)(p->iph->ip_src.s_addr>>24);
1145 sampacket.protocol[0]=(char)p->iph->ip_proto; /* protocol */
1146 sampacket.protocol[1]=(char)(p->iph->ip_proto>>8);/* protocol */
1147
1148 if(IP_HAS_PORTS(p))
1149 { sampacket.srcport[0]=(char)p->sp; /* set ports */
1150 sampacket.srcport[1]=(char)(p->sp>>8);
1151 sampacket.dstport[0]=(char)p->dp;
1152 sampacket.dstport[1]=(char)(p->dp>>8);
1153 }
1154 else
1155 sampacket.srcport[0]=sampacket.srcport[1]=sampacket.dstport[0]=sampacket.dstport[1]=0;
1156
1157 uint32_t sig_id = ntohl(((Unified2EventCommon *)event)->signature_id);
1158 sampacket.sig_id[0]=(char)sig_id; /* set signature ID */
1159 sampacket.sig_id[1]=(char)(sig_id>>8);
1160 sampacket.sig_id[2]=(char)(sig_id>>16);
1161 sampacket.sig_id[3]=(char)(sig_id>>24);
1162
1163 #ifdef FWSAMDEBUG
1164 LogMessage("DEBUG => [Alert_FWsam] Sending BLOCK\n");
1165 LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo: %x\n",station->myseqno);
1166 LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo : %x\n",station->stationseqno);
1167 LogMessage("DEBUG => [Alert_FWsam] Status : %i\n",FWSAM_STATUS_BLOCK);
1168 LogMessage("DEBUG => [Alert_FWsam] Mode : %i\n",optp->how|optp->who|optp->loglevel);
1169 LogMessage("DEBUG => [Alert_FWsam] Duration : %li\n",optp->duration);
1170 LogMessage("DEBUG => [Alert_FWsam] Protocol : %i\n",GET_IPH_PROTO(p));
1171 #ifdef SUP_IP6
1172 LogMessage("DEBUG => [Alert_FWsam] Src IP : %s\n",sfip_ntoa(GET_SRC_IP(p)));
1173 LogMessage("DEBUG => [Alert_FWsam] Dest IP : %s\n",sfip_ntoa(GET_DST_IP(p)));
1174 #else
1175 LogMessage("DEBUG => [Alert_FWsam] Src IP : %s\n",inet_ntoa(GET_SRC_ADDR(p)));
1176 LogMessage("DEBUG => [Alert_FWsam] Dest IP : %s\n",inet_ntoa(GET_DST_ADDR(p)));
1177 #endif
1178 LogMessage("DEBUG => [Alert_FWsam] Src Port : %i\n",p->sp);
1179 LogMessage("DEBUG => [Alert_FWsam] Dest Port : %i\n",p->dp);
1180 LogMessage("DEBUG => [Alert_FWsam] Sig_ID : %lu\n",ntohl(((Unified2EventCommon *)event)->signature_id));
1181
1182 #endif
1183
1184 encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get the encryption buffer */
1185 len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt the packet with current key */
1186
1187 if(send(stationsocket,encbuf,len,0)!=len) /* weird...could not send */
1188 { LogMessage("WARNING => [Alert_FWsam] Could not send to host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
1189 #ifdef WIN32
1190 closesocket(stationsocket);
1191 #else
1192 close(stationsocket);
1193 #endif
1194 stationtry=0;
1195 }
1196 else
1197 { i=FWSAM_NETWAIT;
1198 #ifdef WIN32
1199 ioctlsocket(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
1200 #else
1201 ioctl(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
1202 #endif
1203 while(i-- >1) /* the response packet */
1204 { waitms(10); /* wait for response (default maximum 3 secs */
1205 if(recv(stationsocket,encbuf,len,0)==len)
1206 i=0; /* if we received packet we set the counter to 0. */
1207 /* by the time we check with if, it's already dec'ed to -1 */
1208 }
1209 if(!i) /* id we timed out (i was one, then dec'ed)... */
1210 { LogMessage("WARNING => [Alert_FWsam] Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
1211 #ifdef WIN32
1212 closesocket(stationsocket);
1213 #else
1214 close(stationsocket);
1215 #endif
1216 stationtry=0;
1217 }
1218 else /* got a packet */
1219 { decbuf=(char *)&sampacket; /* get the pointer to the packet struct */
1220 len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt the packet with current key */
1221
1222 if(len!=sizeof(FWsamPacket)) /* invalid decryption */
1223 { strcpy(station->stationkey,station->initialkey); /* try the intial key */
1224 TwoFishDestroy(station->stationfish);
1225 station->stationfish=TwoFishInit(station->stationkey); /* re-initialize the TwoFish with the intial key */
1226 len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try again to decrypt */
1227 LogMessage("INFO => [Alert_FWsam] Had to use initial key!\n");
1228 }
1229 if(len==sizeof(FWsamPacket)) /* valid decryption */
1230 { if(sampacket.version==FWSAM_PACKETVERSION)/* master speaks my language */
1231 { if(sampacket.status==FWSAM_STATUS_OK || sampacket.status==FWSAM_STATUS_NEWKEY
1232 || sampacket.status==FWSAM_STATUS_RESYNC || sampacket.status==FWSAM_STATUS_HOLD)
1233 { station->stationseqno=sampacket.fwseqno[0] | (sampacket.fwseqno[1]<<8); /* get stations seqno */
1234 station->lastcontact=(unsigned long)time(NULL); /* set the last contact time (not used yet) */
1235 #ifdef FWSAMDEBUG
1236 LogMessage("DEBUG => [Alert_FWsam] Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK":
1237 sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY":
1238 sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC":
1239 sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR");
1240 LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo: %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8));
1241 LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo : %x\n",station->stationseqno);
1242 LogMessage("DEBUG => [Alert_FWsam] Status : %i\n",sampacket.status);
1243 LogMessage("DEBUG => [Alert_FWsam] Version : %i\n",sampacket.version);
1244 #endif
1245 if(sampacket.status==FWSAM_STATUS_HOLD)
1246 { i=FWSAM_NETHOLD; /* Stay on hold for a maximum of 60 secs (default) */
1247 while(i-- >1) /* the response packet */
1248 { waitms(10); /* wait for response */
1249 if(recv(stationsocket,encbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,0)==sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE)
1250 i=0; /* if we received packet we set the counter to 0. */
1251 }
1252 if(!i) /* id we timed out (i was one, then dec'ed)... */
1253 { LogMessage("WARNING => [Alert_FWsam] Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
1254 stationtry=0;
1255 sampacket.status=FWSAM_STATUS_ERROR;
1256 }
1257 else /* got a packet */
1258 { decbuf=(char *)&sampacket; /* get the pointer to the packet struct */
1259 len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt the packet with current key */
1260
1261 if(len!=sizeof(FWsamPacket)) /* invalid decryption */
1262 { strcpy(station->stationkey,station->initialkey); /* try the intial key */
1263 TwoFishDestroy(station->stationfish);
1264 station->stationfish=TwoFishInit(station->stationkey); /* re-initialize the TwoFish with the intial key */
1265 len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try again to decrypt */
1266 LogMessage("INFO => [Alert_FWsam] Had to use initial key again!\n");
1267 }
1268 #ifdef FWSAMDEBUG
1269 LogMessage("DEBUG => [Alert_FWsam] Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK":
1270 sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY":
1271 sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC":
1272 sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR");
1273 LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo: %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8));
1274 LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo : %x\n",station->stationseqno);
1275 LogMessage("DEBUG => [Alert_FWsam] Status : %i\n",sampacket.status);
1276 LogMessage("DEBUG => [Alert_FWsam] Version : %i\n",sampacket.version);
1277 #endif
1278 if(len!=sizeof(FWsamPacket)) /* invalid decryption */
1279 { ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1280 deletestation=TRUE;
1281 sampacket.status=FWSAM_STATUS_ERROR;
1282 }
1283 else if(sampacket.version!=FWSAM_PACKETVERSION) /* invalid protocol version */
1284 { ErrorMessage("ERROR => [Alert_FWsam] Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1285 deletestation=TRUE;
1286 sampacket.status=FWSAM_STATUS_ERROR;
1287 }
1288 else if(sampacket.status!=FWSAM_STATUS_OK && sampacket.status!=FWSAM_STATUS_NEWKEY && sampacket.status!=FWSAM_STATUS_RESYNC)
1289 { ErrorMessage("ERROR => [Alert_FWsam] Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1290 deletestation=TRUE;
1291 sampacket.status=FWSAM_STATUS_ERROR;
1292 }
1293 }
1294 }
1295 if(sampacket.status==FWSAM_STATUS_RESYNC) /* if station want's to resync... */
1296 { strcpy(station->stationkey,station->initialkey); /* ...we use the intial key... */
1297 memcpy(station->fwkeymod,sampacket.duration,4); /* and note the random key modifier */
1298 }
1299 if(sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC)
1300 {
1301 FWsamNewStationKey(station,&sampacket); /* generate new TwoFish keys */
1302 #ifdef FWSAMDEBUG
1303 LogMessage("DEBUG => [Alert_FWsam] Generated new encryption key...\n");
1304 #endif
1305 }
1306 #ifdef WIN32
1307 closesocket(stationsocket);
1308 #else
1309 close(stationsocket);
1310 #endif
1311 stationtry=0;
1312 }
1313 else if(sampacket.status==FWSAM_STATUS_ERROR) /* if SnortSam reports an error on second try, */
1314 {
1315 #ifdef WIN32
1316 closesocket(stationsocket); /* something is messed up and ... */
1317 #else
1318 close(stationsocket);
1319 #endif
1320 if(stationtry>1) /* we ignore that station. */
1321 { deletestation=TRUE; /* flag for deletion */
1322 ErrorMessage("ERROR => [Alert_FWsam] Could not renegotiate key! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1323 }
1324 else /* if we get an error on the first try, */
1325 { if(!FWsamCheckIn(station)) /* we first try to check in again. */
1326 { deletestation=TRUE;
1327 ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1328 }
1329 }
1330 }
1331 else /* an unknown status means trouble... */
1332 { ErrorMessage("ERROR => [Alert_FWsam] Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1333 #ifdef WIN32
1334 closesocket(stationsocket);
1335 #else
1336 close(stationsocket);
1337 #endif
1338 deletestation=TRUE;
1339 }
1340 }
1341 else /* if the SnortSam agent uses a different packet version, we have no choice but to ignore it. */
1342 { ErrorMessage("ERROR => [Alert_FWsam] Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1343 #ifdef WIN32
1344 closesocket(stationsocket);
1345 #else
1346 close(stationsocket);
1347 #endif
1348 deletestation=TRUE;
1349 }
1350 }
1351 else /* if the intial key failed to decrypt as well, the keys are not configured the same, and we ignore that SnortSam station. */
1352 { ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1353 #ifdef WIN32
1354 closesocket(stationsocket);
1355 #else
1356 close(stationsocket);
1357 #endif
1358 deletestation=TRUE;
1359 }
1360 }
1361 }
1362 free(encbuf); /* release of the TwoFishAlloc'ed encryption buffer */
1363 }
1364 if(stationtry==0 || deletestation) /* if everything went real well, or real bad... */
1365 { if(deletestation){ /* If it went bad, we remove the station from the list by marking the IP */
1366 // station->stationip.s_addr=0;
1367 station->stationip.ip32[0]=0;
1368 }
1369 fwsamlist=fwsamlist->next;
1370 }
1371 }
1372 else
1373 fwsamlist=fwsamlist->next;
1374 }
1375 }
1376 else
1377 {
1378 #ifdef FWSAMDEBUG
1379 LogMessage("DEBUG => [Alert_FWsam] Skipping repetitive block.\n");
1380 #endif
1381 }
1382 }
1383 }
1384
1385 /* FWsamCheckOut will be called when Snort exists. It de-registeres this snort sensor
1386 * from the list of sensor that the SnortSam agent keeps.
1387 */
FWsamCheckOut(FWsamStation * station)1388 void FWsamCheckOut(FWsamStation *station)
1389 {
1390 FWsamPacket sampacket;
1391 int stationsocket;
1392 int i,len;
1393 char *encbuf,*decbuf;
1394
1395
1396 stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
1397 if(stationsocket==INVALID_SOCKET)
1398 FatalError("ERROR => [Alert_FWsam](FWsamCheckOut) Funky socket error (socket)!\n");
1399 if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr)))
1400 FatalError("ERROR => [Alert_FWsam](FWsamCheckOut) Could not bind socket!\n");
1401
1402 /* let's connect to the agent */
1403 if(!connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr)))
1404 {
1405 LogMessage("INFO => [Alert_FWsam](FWsamCheckOut) Disconnecting from host %s.\n",sfip_ntoa(&station->stationip));
1406 /* now build the packet */
1407 station->myseqno+=station->stationseqno; /* increase my seqno */
1408 sampacket.endiancheck=1;
1409 sampacket.snortseqno[0]=(char)station->myseqno;
1410 sampacket.snortseqno[1]=(char)(station->myseqno>>8);
1411 sampacket.fwseqno[0]=(char)station->stationseqno; /* fill station seqno */
1412 sampacket.fwseqno[1]=(char)(station->stationseqno>>8);
1413 sampacket.status=FWSAM_STATUS_CHECKOUT; /* checking out... */
1414 sampacket.version=FWSAM_PACKETVERSION;
1415
1416 #ifdef FWSAMDEBUG
1417 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Sending CHECKOUT\n");
1418 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Snort SeqNo: %x\n",station->myseqno);
1419 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Mgmt SeqNo : %x\n",station->stationseqno);
1420 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Status : %i\n",sampacket.status);
1421
1422 #endif
1423
1424 encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get encryption buffer */
1425 len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt packet with current key */
1426
1427 if(send(stationsocket,encbuf,len,0)==len)
1428 {
1429 i=FWSAM_NETWAIT;
1430 #ifdef WIN32
1431 ioctlsocket(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
1432 #else
1433 ioctl(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
1434 #endif
1435 while(i-- >1)
1436 {
1437 waitms(10); /* ...wait a maximum of 3 secs for response... */
1438 if(recv(stationsocket,encbuf,len,0)==len) /* ... for the status packet */
1439 i=0;
1440 }
1441
1442 if(i) /* if we got the packet */
1443 {
1444 decbuf=(char *)&sampacket;
1445 len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish);
1446
1447 if(len!=sizeof(FWsamPacket)) /* invalid decryption */
1448 { strcpy(station->stationkey,station->initialkey); /* try initial key */
1449 TwoFishDestroy(station->stationfish); /* toss this fish */
1450 station->stationfish=TwoFishInit(station->stationkey); /* re-initialze TwoFish with initial key */
1451 len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* and try to decrypt again */
1452 LogMessage("INFO => [Alert_FWsam](FWsamCheckOut) Had to use initial key!\n");
1453 }
1454 if(len==sizeof(FWsamPacket)) /* valid decryption */
1455 { if(sampacket.version!=FWSAM_PACKETVERSION) /* but don't really care since we are on the way out */
1456 ErrorMessage("WARNING => [Alert_FWsam](FWsamCheckOut) Protocol version error! What the hell, we're quitting anyway! :)\n");
1457 }
1458 else
1459 ErrorMessage("WARNING => [Alert_FWsam](FWsamCheckOut) Password mismatch! What the hell, we're quitting anyway! :)\n");
1460 }
1461 }
1462 free(encbuf); /* release TwoFishAlloc'ed buffer */
1463 }
1464 else
1465 LogMessage("WARNING => [Alert_FWsam] Could not connect to host %s for CheckOut. What the hell, we're quitting anyway! :)\n",sfip_ntoa(&station->stationip));
1466 #ifdef WIN32
1467 closesocket(stationsocket);
1468 #else
1469 close(stationsocket);
1470 #endif
1471 }
1472
1473
1474
1475 /* FWSamFree: Disconnects all FW-1 management stations,
1476 * closes sockets, and frees the structures.
1477 */
FWsamFree(FWsamList * list)1478 void FWsamFree(FWsamList *list)
1479 {
1480 FWsamList *next;
1481
1482 while(list) /* Free pointer list for rule type */
1483 {
1484 next=list->next;
1485 free(list);
1486 list=next;
1487 }
1488 list=FWsamStationList;
1489
1490 while(list) /* Free global pointer list and stations */
1491 {
1492 next=list->next;
1493 if (list->station)
1494 {
1495 if(list->station->stationip.ip32[0])
1496 //if(list->station->stationip.s_addr)
1497 FWsamCheckOut(list->station); /* Send a Check-Out to SnortSam, */
1498
1499 TwoFishDestroy(list->station->stationfish); /* toss the fish, */
1500 free(list->station); /* free station, */
1501 }
1502 free(list); /* free pointer, */
1503 list=next; /* and move to next. */
1504 }
1505 FWsamStationList=NULL;
1506 if(FWsamOptionField)
1507 free(FWsamOptionField);
1508 }
1509
AlertFWsamCleanExitFunc(int signal,void * arg)1510 void AlertFWsamCleanExitFunc(int signal, void *arg)
1511 {
1512 FWsamList *fwsamlist;
1513
1514 #ifdef FWSAMDEBUG
1515 LogMessage("DEBUG => [Alert_FWsam](AlertFWsamCleanExitFunc) Exiting...\n");
1516 #endif
1517
1518 fwsamlist=(FWsamList *)arg;
1519 FWsamFree(fwsamlist); /* Free all elements */
1520 }
1521
AlertFWsamRestartFunc(int signal,void * arg)1522 void AlertFWsamRestartFunc(int signal, void *arg)
1523 {
1524 FWsamList *fwsamlist;
1525
1526 #ifdef FWSAMDEBUG
1527 LogMessage("DEBUG => [Alert_FWsam](AlertFWsamRestartFunc) Restarting...\n");
1528 #endif
1529
1530 fwsamlist=(FWsamList *)arg;
1531 FWsamFree(fwsamlist); /* Free all elements */
1532 }
1533
1534 /* This routine registers this Snort sensor with SnortSam.
1535 * It will also change the encryption key based on some variables.
1536 */
FWsamCheckIn(FWsamStation * station)1537 int FWsamCheckIn(FWsamStation *station)
1538 {
1539 int i,len,stationok=TRUE;
1540 FWsamPacket sampacket;
1541 char *encbuf,*decbuf;
1542 int stationsocket;
1543
1544
1545 /* create a socket for the station */
1546 stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
1547
1548 if(stationsocket==INVALID_SOCKET)
1549 FatalError("ERROR => [Alert_FWsam](FWsamCheckIn) Funky socket error (socket)!\n");
1550 if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr)))
1551 FatalError("ERROR => [Alert_FWsam](FWsamCheckIn) Could not bind socket!\n");
1552
1553 i=TRUE;
1554 /* let's connect to the agent */
1555 if(connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr)))
1556 LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Could not connect to host %s. Will try later.\n",sfip_ntoa(&station->stationip));
1557 else
1558 {
1559 LogMessage("INFO => [Alert_FWsam](FWsamCheckIn) Connected to host %s.\n",sfip_ntoa(&station->stationip));
1560 /* now build the packet */
1561 sampacket.endiancheck=1;
1562 sampacket.snortseqno[0]=(char)station->myseqno; /* fill my sequence number number */
1563 sampacket.snortseqno[1]=(char)(station->myseqno>>8); /* fill my sequence number number */
1564 sampacket.status=FWSAM_STATUS_CHECKIN; /* let's check in */
1565 sampacket.version=FWSAM_PACKETVERSION; /* set the packet version */
1566 memcpy(sampacket.duration,station->mykeymod,4); /* we'll send SnortSam our key modifier in the duration slot */
1567 /* (the checkin packet is just the plain initial key) */
1568 #ifdef FWSAMDEBUG
1569 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Sending CheckIn\n");
1570 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Snort SeqNo: %x\n",station->myseqno);
1571 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Mode : %i\n",sampacket.status);
1572 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Version : %i\n",sampacket.version);
1573 #endif
1574 encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get buffer for encryption */
1575 len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt with initial key */
1576 if(send(stationsocket,encbuf,len,0)!=len) /* weird...could not send */
1577 LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Could not send to host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
1578 else
1579 {
1580 i=FWSAM_NETWAIT;
1581 #ifdef WIN32
1582 ioctlsocket(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
1583 #else
1584 ioctl(stationsocket,FIONBIO,&i); /* set non blocking and wait for */
1585 #endif
1586 while(i-- >1)
1587 {
1588 waitms(10); /* wait a maximum of 3 secs for response */
1589 if(recv(stationsocket,encbuf,len,0)==len)
1590 i=0;
1591 }
1592 if(!i) /* time up? */
1593 LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
1594 else
1595 {
1596 decbuf=(char *)&sampacket; /* got status packet */
1597 len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt with initial key */
1598 if(len==sizeof(FWsamPacket)) /* valid decryption */
1599 {
1600 #ifdef FWSAMDEBUG
1601 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK":
1602 sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY":
1603 sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC":
1604 sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR");
1605 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Snort SeqNo: %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8));
1606 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Mgmt SeqNo : %x\n",sampacket.fwseqno[0]|(sampacket.fwseqno[1]<<8));
1607 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Status : %i\n",sampacket.status);
1608 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Version : %i\n",sampacket.version);
1609 #endif
1610 if(sampacket.version==FWSAM_PACKETVERSION) /* master speaks my language */
1611 {
1612 if(sampacket.status==FWSAM_STATUS_OK || sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC)
1613 {
1614 station->stationseqno=sampacket.fwseqno[0]|(sampacket.fwseqno[1]<<8); /* get stations seqno */
1615 station->lastcontact=(unsigned long)time(NULL);
1616
1617 if(sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC) /* generate new keys */
1618 {
1619 memcpy(station->fwkeymod,sampacket.duration,4); /* note the key modifier */
1620 FWsamNewStationKey(station,&sampacket); /* and generate new TwoFish keys (with key modifiers) */
1621 #ifdef FWSAMDEBUG
1622 LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Generated new encryption key...\n");
1623 #endif
1624 }
1625 }
1626 else /* weird, got a strange status back */
1627 {
1628 ErrorMessage("ERROR => [Alert_FWsam](FWsamCheckIn) Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1629 stationok=FALSE;
1630 }
1631 }
1632 else /* packet version does not match */
1633 {
1634 ErrorMessage("ERROR =>[Alert_FWsam](FWsamCheckIn) Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1635 stationok=FALSE;
1636 }
1637 }
1638 else /* key does not match */
1639 {
1640 ErrorMessage("ERROR => [Alert_FWsam](FWsamCheckIn) Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1641 stationok=FALSE;
1642 }
1643 }
1644 }
1645 free(encbuf); /* release TwoFishAlloc'ed buffer */
1646 }
1647 #ifdef WIN32
1648 closesocket(stationsocket);
1649 #else
1650 close(stationsocket);
1651 #endif
1652 return stationok;
1653 }
1654 #undef FWSAMDEBUG
1655
1656