Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 245752 | Differences between
and this patch

Collapse All | Expand All

(-)snort-2.8.3.1/autojunk.sh (+7 lines)
Line 0 Link Here
1
#!/bin/sh
2
# the list of commands that need to run before we do a compile
3
libtoolize --automake --copy
4
aclocal -I m4
5
autoheader
6
automake --add-missing --copy
7
autoconf
(-)snort-2.8.3.1/src/Makefile.am (-1 / +2 lines)
Lines 53-59 Link Here
53
pcap_pkthdr32.h \
53
pcap_pkthdr32.h \
54
cpuclock.h \
54
cpuclock.h \
55
sf_types.h \
55
sf_types.h \
56
log_text.c log_text.h
56
log_text.c log_text.h \
57
twofish.c twofish.h
57
58
58
snort_LDADD = output-plugins/libspo.a \
59
snort_LDADD = output-plugins/libspo.a \
59
detection-plugins/libspd.a            \
60
detection-plugins/libspd.a            \
(-)snort-2.8.3.1/src/Makefile.am.orig (+74 lines)
Line 0 Link Here
1
## $Id$
2
AUTOMAKE_OPTIONS=foreign no-dependencies
3
4
bin_PROGRAMS = snort
5
6
snort_SOURCES = cdefs.h \
7
event.h \
8
fatal.h \
9
generators.h \
10
prototypes.h \
11
plugin_enum.h \
12
rules.h \
13
sys_include.h \
14
checksum.h \
15
codes.c codes.h \
16
debug.c debug.h \
17
decode.c decode.h \
18
log.c log.h \
19
mstring.c mstring.h \
20
parser.c parser.h \
21
profiler.c profiler.h \
22
plugbase.c plugbase.h \
23
preprocids.h \
24
snort.c snort.h \
25
build.h \
26
snprintf.c snprintf.h \
27
strlcatu.c strlcatu.h \
28
strlcpyu.c strlcpyu.h \
29
tag.c tag.h \
30
ubi_BinTree.c ubi_BinTree.h \
31
ubi_SplayTree.c ubi_SplayTree.h \
32
util.c util.h \
33
detect.c detect.h \
34
signature.c signature.h \
35
mempool.c mempool.h \
36
sf_sdlist.c sf_sdlist.h \
37
fpcreate.c fpcreate.h \
38
fpdetect.c fpdetect.h \
39
pcrm.c pcrm.h \
40
bounds.h \
41
byte_extract.c \
42
byte_extract.h \
43
timersub.h \
44
spo_plugbase.h \
45
sfthreshold.c sfthreshold.h \
46
packet_time.c packet_time.h \
47
event_wrapper.c event_wrapper.h \
48
smalloc.h \
49
event_queue.c event_queue.h \
50
inline.c inline.h \
51
ipv6_port.h \
52
ppm.c ppm.h \
53
pcap_pkthdr32.h \
54
cpuclock.h \
55
sf_types.h \
56
log_text.c log_text.h
57
58
snort_LDADD = output-plugins/libspo.a \
59
detection-plugins/libspd.a            \
60
dynamic-plugins/libdynamic.a            \
61
preprocessors/libspp.a                \
62
preprocessors/flow/portscan/libportscan.a \
63
preprocessors/flow/libflow.a \
64
parser/libparser.a \
65
target-based/libtarget_based.a \
66
preprocessors/HttpInspect/libhttp_inspect.a \
67
preprocessors/Stream5/libstream5.a \
68
sfutil/libsfutil.a
69
70
EXAMPLES_DIR = dynamic-examples
71
72
SUBDIRS = sfutil win32 output-plugins detection-plugins dynamic-plugins preprocessors parser dynamic-preprocessors target-based $(EXAMPLES_DIR)
73
74
INCLUDES = @INCLUDES@
(-)snort-2.8.3.1/src/output-plugins/Makefile.am (+1 lines)
Lines 11-16 Link Here
11
spo_log_tcpdump.h spo_unified.c spo_unified2.c spo_unified.h spo_unified2.h \
11
spo_log_tcpdump.h spo_unified.c spo_unified2.c spo_unified.h spo_unified2.h \
12
spo_log_ascii.c spo_log_ascii.h spo_alert_sf_socket.h spo_alert_sf_socket.c \
12
spo_log_ascii.c spo_log_ascii.h spo_alert_sf_socket.h spo_alert_sf_socket.c \
13
spo_alert_prelude.c spo_alert_prelude.h spo_alert_arubaaction.c spo_alert_arubaaction.h \
13
spo_alert_prelude.c spo_alert_prelude.h spo_alert_arubaaction.c spo_alert_arubaaction.h \
14
spo_alert_fwsam.c spo_alert_fwsam.h \
14
spo_alert_test.c spo_alert_test.h
15
spo_alert_test.c spo_alert_test.h
15
16
16
INCLUDES = @INCLUDES@
17
INCLUDES = @INCLUDES@
(-)snort-2.8.3.1/src/output-plugins/spo_alert_fwsam.c (+1380 lines)
Line 0 Link Here
1
/* $id: snortpatchb,v 1.2 2002/10/26 03:32:35 fknobbe Exp $
2
**
3
** spo_alert_fwsam.c
4
**
5
** Copyright (c) 2001-2004 Frank Knobbe <frank@knobbe.us>
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>:	The IP address or host name of the host running SnortSam.
43
 *	<port>:			The port the remote SnortSam service listens on (default 898).
44
 *	<key>:			The 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
 * Rule Options:
55
 ***************
56
 *
57
 * fwsam:	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 FW-1 to block packets INcoming from host, OUTgoing to host,
66
 *			EITHERway, or only THIS connection (IP/Service pair).
67
 *			See 'fw sam' for more information. May be ignored by other plugins.
68
 *
69
 * time: Duration of block in seconds. (Accepts 'days', 'months', 'weeks',
70
 *		 'years', 'minutes', 'seconds', 'hours'. Alternatively, a value of
71
 *		 0, or the keyword PERManent, INFinite, or ALWAYS, will block the 
72
 *		 host permanently. Be careful with this!
73
 *			Tells FW-1 (and others) how long to inhibit packets from the host.
74
 *
75
 * Examples:
76
 *
77
 * fwsam:  src[either],15min;
78
 *     or  dst[in], 2 days 4 hours
79
 *     or  src, 1 hour
80
 *
81
 *         (default: src[either],5min)
82
 *
83
 *
84
 * Effect:
85
 *
86
 * Alerts are sent to the remote SnortSam services on Firewall-1 Management Stations
87
 * or other hosts running SnortSam (as required for Cisco Routers and PIX).
88
 * The remote services will invoke the SAM configuration via the fw sam
89
 * command line, or by sending a packet to the SAM port 18183, or by using the official
90
 * OPSEC API calls, or by telnetting into Cisco routers or PIX firewalls.
91
 * The communication over the network is encrypted using two-fish.
92
 * (Implementation ripped from CryptCat by Farm9 with permission.)
93
 *
94
 * Future Plans:
95
 *
96
 * - Custom alert trigger per rule (x alerts in y secs) --> Seems to exist in Snort 1.9 now.
97
 * - Enable/Allow tagged fwsam: arguments to provide different values to
98
 *        different stations.  --> Seems to be accomplished with custom rule-types
99
 *
100
 *
101
 * Comments:
102
 * 
103
 * It seem that above wishes can be implemented with todays setup. Feedback concerning
104
 * these is greatly appreciated.
105
 *
106
*/
107
108
109
#include "spo_alert_fwsam.h"
110
#include "twofish.h"
111
/* external globals from rules.c  */
112
extern char *file_name;
113
extern int file_line;
114
extern OptTreeNode *otn_tmp;
115
extern PV pv;
116
117
118
/* my globals  */
119
120
FWsamList *FWsamStationList=NULL;			/* Global (for all alert-types) list of snortsam stations */
121
FWsamOptions *FWsamOptionField=NULL;
122
unsigned long FWsamMaxOptions=0;
123
124
125
/*
126
 * Function: AlertFWsamSetup()
127
 *
128
 * Purpose: Registers the output plugin keyword and initialization 
129
 *          function into the output plugin list.  This is the function that
130
 *          gets called from InitOutputPlugins() in plugbase.c.
131
 *			It also registers itself as a plugin in order to parse every rule 
132
 *			and to set the appropiate flags from fwsam: option.
133
 *
134
 * Arguments: None.
135
 *
136
 * Returns: void function
137
 *
138
*/
139
void AlertFWsamSetup(void)
140
{
141
    /* link the preprocessor keyword to the init function in 
142
       the preproc list */
143
    RegisterOutputPlugin("alert_fwsam", NT_OUTPUT_ALERT, AlertFWsamInit);
144
    RegisterPlugin("fwsam", AlertFWsamOptionInit, OPT_TYPE_ACTION);
145
	
146
#ifdef FWSAMDEBUG   /* This allows debugging of fwsam only */
147
    LogMessage("DEBUG => [Alert_FWsam](AlertFWsamSetup) Output plugin is plugged in...\n");
148
#endif
149
}
150
151
152
/*	This function checks if a given snortsam station is already in
153
 *	a given list.
154
*/
155
int FWsamStationExists(FWsamStation *who,FWsamList *list)
156
{
157
    while(list)
158
    {
159
        if(list->station) {
160
//			if(	who->stationip.s_addr==list->station->stationip.s_addr && 
161
            if(IP_EQUALITY(&who->stationip, &list->station->stationip) &&
162
            who->stationport==list->station->stationport)
163
            return TRUE;
164
        }
165
        list=list->next;
166
    }
167
    return FALSE;
168
}
169
170
/*
171
 * Function: AlertFWsamInit(char *args)
172
 *
173
 * Purpose: Calls the argument parsing function, performs final setup on data
174
 *          structs, links the preproc function into the function list.
175
 *
176
 * Arguments: args => ptr to argument string
177
 *
178
 * Returns: void function
179
 *
180
*/
181
void AlertFWsamInit(char *args)
182
{	char *ap;
183
	unsigned long statip,cnt,again,i;
184
	char *stathost,*statport,*statpass;
185
	FWsamStation *station;
186
	FWsamList *fwsamlist=NULL;	/* alert-type dependent list of snortsam stations  */
187
	FWsamList *listp,*newlistp;
188
	struct hostent *hoste;
189
	char buf[1024]="";
190
	FILE *fp;
191
	FWsamOptions tempopt;
192
193
#ifdef FWSAMDEBUG
194
	unsigned long hostcnt=0;
195
	
196
197
198
    LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Output plugin initializing...\n");
199
#endif
200
201
    pv.alert_plugin_active = 1;
202
203
    /* parse the argument list from the rules file */
204
205
	if(args == NULL)
206
		FatalError("ERROR %s (%d) => [Alert_FWsam](AlertFWsamInit) No arguments to alert_fwsam preprocessor!\n", file_name, file_line);
207
208
	if(!FWsamOptionField && !FWsamMaxOptions)
209
	{	strncpy(buf,pv.config_dir,sizeof(buf)-1);
210
		strncpy(buf+strlen(buf),SID_MAPFILE,sizeof(buf)-strlen(buf)-1);
211
#ifdef FWSAMDEBUG
212
		LogMessage("DEBUG => [Alert_FWsam](AlertFWsamSetup) Using file: %s\n",buf);
213
#endif
214
		fp=fopen(buf,"rt");
215
		if(!fp)
216
		{	strncpy(buf,pv.config_dir,sizeof(buf)-1);
217
			strncpy(buf+strlen(buf),SID_ALT_MAPFILE,sizeof(buf)-strlen(buf)-1);
218
			fp=fopen(buf,"rt");
219
		}
220
		if(fp)  /* Check for presence of map file and read those in, sorted. */
221
		{   LogMessage("INFO => [Alert_FWsam](AlertFWsamSetup) Using sid-map file: %s\n",buf);
222
223
			while(FWsamReadLine(buf,sizeof(buf),fp))
224
				if(*buf)
225
					FWsamMaxOptions++;
226
			if(FWsamMaxOptions)
227
			{   if((FWsamOptionField=(FWsamOptions *)malloc(sizeof(FWsamOptions)*FWsamMaxOptions))==NULL)
228
					FatalError("ERROR => [Alert_FWsam](AlertFWsamSetup) malloc failed for OptionField!\n");
229
				fseek(fp,0,SEEK_SET);
230
				for(cnt=0;cnt<FWsamMaxOptions;)
231
				{	FWsamReadLine(buf,sizeof(buf),fp);
232
					if(*buf)
233
						FWsamParseLine(&(FWsamOptionField[cnt++]),buf);
234
				}
235
				if(FWsamMaxOptions>1)
236
				{	for(again=TRUE,cnt=FWsamMaxOptions-1;cnt>=1 && again;cnt--)
237
					{	for(again=FALSE,i=0;i<cnt;i++)
238
						{	if(FWsamOptionField[i].sid>FWsamOptionField[i+1].sid)
239
							{	memcpy(&tempopt,&(FWsamOptionField[i]),sizeof(FWsamOptions));
240
								memcpy(&(FWsamOptionField[i]),&(FWsamOptionField[i+1]),sizeof(FWsamOptions));
241
								memcpy(&(FWsamOptionField[i+1]),&tempopt,sizeof(FWsamOptions));
242
								again=TRUE;
243
							}
244
						}
245
					}
246
				}
247
			}
248
			else
249
				FWsamMaxOptions=1;
250
			fclose(fp);
251
		}
252
		else
253
			FWsamMaxOptions=1;
254
	}
255
256
257
	ap=args; /* start at the beginning of the argument */
258
	while(*ap && isspace(*ap)) ap++;
259
	while(*ap)
260
	{	stathost=ap; /* first argument should be host */
261
		statport=NULL; 
262
		statpass=NULL;
263
		while(*ap && *ap!=':' && *ap!='/' && !isspace(*ap)) ap++; /* find token */
264
		switch(*ap)
265
		{	case ':':	*ap++=0; /* grab the port */
266
						statport=ap;
267
						while(*ap && *ap!='/' && !isspace(*ap)) ap++;
268
						if(*ap!='/')
269
							break;
270
			case '/':	*ap++=0; /* grab the key */
271
						statpass=ap;
272
						while(*ap && !isspace(*ap)) ap++;
273
			default:	break;
274
		}	
275
		if(*ap)
276
		{	*ap++=0;
277
			while(isspace(*ap)) ap++;
278
		}
279
		/* now we have the first host with port and password (key) */
280
		/* next we check for valid/blank password/port */
281
		if(statpass!=NULL)
282
			if(!*statpass)
283
				statpass=NULL;
284
		if(statport!=NULL)
285
			if(!*statport)
286
				statport=NULL;
287
		statip=0;
288
		/* now we check if a valid host was specified */
289
		if(inet_addr(stathost)==INADDR_NONE)
290
		{	hoste=gethostbyname(stathost);
291
			if (!hoste) 
292
				LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWsamInit) Unable to resolve host '%s'!\n",file_name,file_line,stathost);
293
			else
294
				statip=*(unsigned long *)hoste->h_addr;
295
		} 
296
		else
297
		{	statip=inet_addr(stathost);
298
			if(!statip)
299
				LogMessage("WARNING %s (%d) => [Alert_FWsam](AlertFWsamInit) Invalid host address '%s'!\n",file_name,file_line,stathost);
300
		}
301
		if(statip)
302
		{	/* groovie, a valid host. Let's alloc and assemble the structure for it. */
303
			if((station=(FWsamStation *)malloc(sizeof(FWsamStation)))==NULL)
304
				FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for station!\n");
305
306
//			station->stationip.s_addr=statip; /* the IP address */
307
			station->stationip.ip32[0] = statip; /* the IP address */
308
			if(statport!=NULL && atoi(statport)>0) /* if the user specified one */
309
				station->stationport=atoi(statport); /* use users setting */
310
			else
311
				station->stationport=FWSAM_DEFAULTPORT; /* set the default port */
312
313
			if(statpass!=NULL) /* if specified by user */
314
				strncpy(station->stationkey,statpass,TwoFish_KEY_LENGTH); /* use defined key */
315
			else
316
				station->stationkey[0]=0;
317
			station->stationkey[TwoFish_KEY_LENGTH]=0; /* make sure it's terminated. (damn strncpy...) */
318
319
			strcpy(station->initialkey,station->stationkey);
320
			station->stationfish=TwoFishInit(station->stationkey);
321
322
			station->localsocketaddr.sin_port=htons(0); /* let's use dynamic ports for now */
323
			station->localsocketaddr.sin_addr.s_addr=0;
324
			station->localsocketaddr.sin_family=AF_INET;
325
			station->stationsocketaddr.sin_port=htons(station->stationport);
326
			//station->stationsocketaddr.sin_addr=station->stationip;
327
			station->stationsocketaddr.sin_addr.s_addr=station->stationip.ip32[0];
328
			station->stationsocketaddr.sin_family=AF_INET; /* load all socket crap and keep for later */
329
330
			do
331
				station->myseqno=rand(); /* the seqno this host will use */
332
			while(station->myseqno<20 || station->myseqno>65500);
333
			station->mykeymod[0]=rand();
334
			station->mykeymod[1]=rand();
335
			station->mykeymod[2]=rand();
336
			station->mykeymod[3]=rand();
337
			station->stationseqno=0;				/* peer hasn't answered yet. */
338
			
339
			
340
			if(!FWsamStationExists(station,FWsamStationList))	/* If we don't have the station already in global list....*/
341
			{	if(FWsamCheckIn(station))			/* ...and we can talk to the agent...  */
342
				{	if((newlistp=(FWsamList *)malloc(sizeof(FWsamList)))==NULL)
343
						FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for global newlistp!\n");
344
					newlistp->station=station;
345
					newlistp->next=NULL;
346
					
347
					if(!FWsamStationList)				/* ... add it to the global list/ */
348
						FWsamStationList=newlistp;
349
					else
350
					{	listp=FWsamStationList;
351
						while(listp->next)
352
							listp=listp->next;
353
						listp->next=newlistp;
354
					}
355
				}
356
				else
357
				{	TwoFishDestroy(station->stationfish); /* if not, we trash it. */
358
					free(station);
359
					station=NULL;
360
				}
361
			}
362
#ifdef FWSAMDEBUG
363
			else
364
				LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Host %s:%i already in global list, skipping CheckIn.\n", sfip_ntoa(&station->stationip),station->stationport);
365
#endif
366
				
367
			if(station)
368
			{	if(!FWsamStationExists(station,fwsamlist))	/* If we don't have the station already in local list....*/
369
				{	if((newlistp=(FWsamList *)malloc(sizeof(FWsamList)))==NULL)
370
						FatalError("ERROR => [Alert_FWsam](AlertFWsamInit) malloc failed for local newlistp!\n");
371
					newlistp->station=station;
372
					newlistp->next=NULL;
373
					
374
					if(!fwsamlist)				/* ... add it to the local list/ */
375
						fwsamlist=newlistp;
376
					else
377
					{	listp=fwsamlist;
378
						while(listp->next)
379
							listp=listp->next;
380
						listp->next=newlistp;
381
					}
382
				}
383
384
#ifdef FWSAMDEBUG
385
				else
386
					LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Host %s:%i already in local list, skipping.\n",sfip_ntoa(&station->stationip),station->stationport);
387
				LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) #%i: Host %s [%s] port %i password %s\n",++hostcnt,stathost,sfip_ntoa(&station->stationip),station->stationport,station->stationkey);
388
#endif
389
			}
390
391
		}
392
	}	/* next one */
393
394
#ifdef FWSAMDEBUG
395
    LogMessage("DEBUG => [Alert_FWsam](AlertFWsamInit) Linking fwsam alert function to call list...\n");
396
#endif
397
398
    /* Set the preprocessor function into the function list */
399
    AddFuncToOutputList(AlertFWsam, NT_OUTPUT_ALERT, fwsamlist);
400
    AddFuncToCleanExitList(AlertFWsamCleanExitFunc, fwsamlist);
401
    AddFuncToRestartList(AlertFWsamRestartFunc, fwsamlist);
402
}
403
404
405
/*	This routine reads in a str from a file, snips white-spaces
406
 *	off the front and back, removes comments, and pretties the
407
 *	string. Returns true or false if a line was read or not.
408
*/
409
int FWsamReadLine(char *buf,unsigned long bufsize,FILE *fp)
410
{	char *p;
411
412
	if(fgets(buf,bufsize-1,fp))
413
	{	buf[bufsize-1]=0;
414
415
#ifdef FWSAMDEBUG_off
416
		LogMessage("DEBUG => [Alert_FWsam](AlertFWsamReadLine) Line: %s\n",buf);
417
#endif
418
419
		p=buf;
420
		while(isspace(*p))
421
		  p++;
422
		if(p>buf);
423
			strcpy(buf,p);			
424
		if(*buf)
425
		{	p=buf+strlen(buf)-1;	/* remove leading and trailing spaces */
426
			while(isspace(*p))
427
				*p-- =0;
428
		}
429
		p=buf;
430
		if(*p=='#' || *p==';')
431
			*p=0;
432
		else
433
			p++;
434
		while(*p)					/* remove inline comments (except escaped #'s and ;'s) */
435
		{	if(*p=='#' || *p==';')
436
			{	if(*(p-1)=='\\')
437
					strcpy(p-1,p);
438
				else
439
					*p=0;
440
			}
441
			else
442
				p++;
443
		}
444
		return TRUE;
445
	}
446
	return FALSE;
447
}
448
449
450
/* Parses the duration of the argument, recognizing minutes, hours, etc.. 
451
*/
452
unsigned long FWsamParseDuration(char *p)
453
{	unsigned long dur=0,tdu;
454
	char *tok,c1,c2;
455
456
	while(*p)
457
	{	tok=p;
458
		while(*p && isdigit(*p))
459
			p++;
460
		if(*p)
461
		{	c1=tolower(*p);
462
			*p=0;
463
			p++;
464
			if(*p && !isdigit(*p))
465
			{	c2=tolower(*p++);
466
				while(*p && !isdigit(*p))
467
					p++;
468
			}
469
			else
470
				c2=0;
471
			tdu=atol(tok);
472
			switch(c1)
473
			{	case 'm':	if(c2=='o')				/* month */
474
								tdu*=(60*60*24*30);	/* use 30 days */
475
							else
476
								tdu*=60;			/* minutes */
477
				case 's':	break;					/* seconds */
478
				case 'h':	tdu*=(60*60);			/* hours */
479
							break;
480
				case 'd':	tdu*=(60*60*24);		/* days */
481
							break;
482
				case 'w':	tdu*=(60*60*24*7);		/* week */
483
							break;
484
				case 'y':	tdu*=(60*60*24*365);	/* year */
485
							break;
486
			}
487
			dur+=tdu;
488
		}
489
		else
490
			dur+=atol(tok);
491
	}
492
493
	return dur;
494
}
495
496
497
/*  This routine parses an option line. It is called by FWsamParseLine,
498
 *  which parses the sid-block.map file, and also by AlertFWsamOptionInit,
499
 *  which is called by Snort when processing fwsam: options in rules.
500
 *  It returns TRUE it there is a possible option problem, otherwise FALSE.
501
*/
502
int FWsamParseOption(FWsamOptions *optp,char *ap)
503
{   int possprob=FALSE;
504
505
	/* set defaults */
506
507
	optp->duration=300;					/* default of 5 minute block */
508
	optp->how=FWSAM_HOW_INOUT;			/* inbound and outbound block */
509
	optp->who=FWSAM_WHO_SRC;			/* the source  */
510
    optp->loglevel=FWSAM_LOG_LONGALERT; /* the log level default */
511
	/* parse the fwsam keywords */
512
513
#ifdef FWSAMDEBUG
514
	LogMessage("DEBUG => [Alert_FWsam](AlertFWamOptionInit) Parse Options Args: %s\n",ap);
515
#endif
516
517
	if(*ap)		/* should be dst/src (the WHO) or duration */
518
	{	if(isdigit(*ap))
519
			optp->duration=FWsamParseDuration(ap);
520
		else 
521
		{	switch(*ap)			/* yeah, we're lazy and check only the first character */
522
			{	case 'p':	;								/* permanent, perm */
523
				case 'f':	;								/* forever */
524
				case 'i':	optp->duration=0;				/* infinite, inf */
525
							break;
526
				case 'd':	optp->who=FWSAM_WHO_DST;		/* destination, dest, dst */
527
							break;
528
				case 's':	optp->who=FWSAM_WHO_SRC;		/* source, src */
529
							break;
530
				default:	possprob=TRUE;
531
			}
532
			while(*ap && *ap!=',' && *ap!='[')
533
				ap++;
534
			if(*ap=='[')  
535
			{	ap++;		/* now we have the HOW */
536
				switch(*ap)
537
				{	case 'i':	;							/* in */
538
					case 's':	optp->how=FWSAM_HOW_IN;		/* source, src */
539
								break;
540
					case 'o':	;							/* out */
541
					case 'd':	optp->how=FWSAM_HOW_OUT;	/* destination, dest, dst */
542
								break;
543
					case 'b':	;							/* both */
544
					case 'e':	optp->how=FWSAM_HOW_INOUT;	/* either */
545
								break;
546
					case 't':	;							/* this */
547
					case 'c':	optp->how=FWSAM_HOW_THIS;	/* connection, conn */
548
								break;
549
					default:	possprob=TRUE;
550
				}
551
				while(*ap && *ap!=',')
552
					ap++;
553
			}
554
			if(*ap==',')
555
			{	ap++;  
556
				if(isdigit(*ap))  /* and figure out how long to block */
557
					optp->duration=FWsamParseDuration(ap);
558
				else if(*ap=='p' || *ap=='f' || *ap=='i')
559
					optp->duration=0;
560
				else
561
					possprob=TRUE;
562
			}
563
			else if(!*ap)
564
				possprob=TRUE;
565
		}
566
	}
567
	else
568
		possprob=TRUE;
569
570
	return possprob;
571
}
572
573
574
/*	This goes through the lines of sid-block.map and sets the 
575
 *	options for fwsam if the file is being used.
576
*/
577
void FWsamParseLine(FWsamOptions *optp,char *buf)
578
{   char *ap;
579
580
	ap=buf; /* start at the beginning of the argument */
581
582
	while(*ap)
583
	{	if(isspace(*ap))		/* normalize spaces (tabs into space, etc) */
584
			*ap=' ';
585
		if(isupper(*ap))		/* and set to lower case */
586
			*ap=tolower(*ap);
587
		ap++;
588
	}
589
	while((ap=strrchr(buf,' '))!=NULL)	/* remove spaces */
590
		strcpy(ap,ap+1);
591
592
	ap=buf;
593
	if(*ap)
594
	{	while(*ap && *ap!=':' && *ap!='|')
595
			ap++;
596
		*ap++ =0;
597
		while(*ap && (*ap==':' || *ap=='|'))
598
			ap++;
599
600
		optp->sid=(unsigned long)atol(buf);
601
602
		if(FWsamParseOption(optp,ap))
603
			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);
604
	}
605
	else
606
		optp->sid=0;
607
}
608
609
610
611
/*
612
 * Function: AlertFWsamOptionInit(char *data, OptTreeNode *otn, int protocol)
613
 *
614
 * Purpose: Parses each rule and sets the option flags in the tree.
615
 *
616
 * Arguments: args => ptr to argument string
617
 *
618
 * Returns: void function
619
 *
620
*/
621
void AlertFWsamOptionInit(char *args,OptTreeNode *otn,int protocol)
622
{
623
    FWsamOptions *optp;
624
	char *ap;
625
626
627
#ifdef FWSAMDEBUG
628
    LogMessage("DEBUG => [Alert_FWsam](AlertFWamOptionInit) FWsamOptionInit is parsing...\n");
629
#endif
630
631
    if((optp=(FWsamOptions *)malloc(sizeof(FWsamOptions)))==NULL)
632
		FatalError("ERROR => [Alert_FWsam](AlertFWamOptionInit) malloc failed for opt!\n");
633
634
635
	ap=args; /* start at the beginning of the argument */
636
637
	while(*ap)
638
	{	if(isspace(*ap))		/* normalize spaces (tabs into space, etc) */
639
			*ap=' ';
640
		if(isupper(*ap))		/* and set to lower case */
641
			*ap=tolower(*ap);
642
		ap++;
643
	}
644
	while((ap=strrchr(args,' '))!=NULL)	/* remove spaces */
645
		strcpy(ap,ap+1);
646
647
	
648
	if(FWsamParseOption(optp,args))
649
		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);
650
651
	otn->ds_list[PLUGIN_FWSAM]=(FWsamOptions *)optp;
652
}
653
654
655
/* Generates a new encryption key for TwoFish based on seq numbers and a random that
656
 * the SnortSam agents send on checkin (in protocol)
657
*/
658
void FWsamNewStationKey(FWsamStation *station,FWsamPacket *packet)
659
{
660
    //unsigned char newkey[TwoFish_KEY_LENGTH+2];
661
    char newkey[TwoFish_KEY_LENGTH+2];
662
	int i;
663
664
	newkey[0]=packet->snortseqno[0];		/* current snort seq # (which both know) */
665
	newkey[1]=packet->snortseqno[1];			
666
	newkey[2]=packet->fwseqno[0];			/* current SnortSam seq # (which both know) */
667
	newkey[3]=packet->fwseqno[1];
668
	newkey[4]=packet->protocol[0];		/* the random SnortSam chose */
669
	newkey[5]=packet->protocol[1];
670
671
	strncpy(newkey+6,station->stationkey,TwoFish_KEY_LENGTH-6); /* append old key */
672
	newkey[TwoFish_KEY_LENGTH]=0;
673
674
	newkey[0]^=station->mykeymod[0];		/* modify key with key modifiers which were */
675
	newkey[1]^=station->mykeymod[1];		/* exchanged during the check-in handshake. */
676
	newkey[2]^=station->mykeymod[2];
677
	newkey[3]^=station->mykeymod[3];
678
	newkey[4]^=station->fwkeymod[0];
679
	newkey[5]^=station->fwkeymod[1];
680
	newkey[6]^=station->fwkeymod[2];
681
	newkey[7]^=station->fwkeymod[3];
682
683
	for(i=0;i<=7;i++)
684
		if(newkey[i]==0)
685
			newkey[i]++;
686
687
	strcpy(station->stationkey,newkey);
688
	TwoFishDestroy(station->stationfish);
689
	station->stationfish=TwoFishInit(newkey);
690
}
691
692
693
/*	This routine will search the option list as defined
694
 *	by the sid-block.map file and return a pointer
695
 *	to the matching record.
696
*/
697
FWsamOptions *FWsamGetOption(unsigned long sid)
698
{	signed long i,step,diff,o,o2;
699
700
#ifdef FWSAM_FANCYFETCH       /* Fancy-fetch jumps in decreasing n/2 steps and takes much less lookups */
701
	o=o2= -1;
702
	i=step=FWsamMaxOptions>>1;
703
	while(i>=0 && i<FWsamMaxOptions && i!=o2)
704
	{	diff=sid-FWsamOptionField[i].sid;
705
		if(!diff)
706
			return &(FWsamOptionField[i]);
707
		if(step>1)
708
			step=step>>1;
709
		o2=o;
710
		o=i;
711
		if(diff>0)
712
			i+=step;
713
		else
714
			i-=step;
715
	}
716
#else						/* This is just a sequential list lookup */
717
	for(i=0;i<FWsamMaxOptions;i++)
718
		if(FWsamOptionField[i].sid==sid)
719
			return &(FWsamOptionField[i]);
720
#endif
721
	return NULL;
722
}
723
724
725
/****************************************************************************
726
 *
727
 * Function: AlertFWsam(Packet *, char *)
728
 *
729
 * Purpose: Send the current alert to a remote module on a FW-1 mgmt station
730
 *
731
 * Arguments: p => pointer to the packet data struct
732
 *            msg => the message to print in the alert
733
 *
734
 * Returns: void function
735
 *
736
 ***************************************************************************/
737
void AlertFWsam(Packet *p, char *msg, void *arg, Event *event)
738
{	FWsamOptions *optp;
739
	FWsamPacket sampacket;
740
	FWsamStation *station=NULL;
741
	FWsamList *fwsamlist;
742
	SOCKET stationsocket;
743
	int i,len,deletestation,stationtry=0;
744
	//unsigned char *encbuf,*decbuf;
745
    char *encbuf,*decbuf;
746
	static unsigned long lastbsip[FWSAM_REPET_BLOCKS],lastbdip[FWSAM_REPET_BLOCKS],
747
						 lastbduration[FWSAM_REPET_BLOCKS],lastbtime[FWSAM_REPET_BLOCKS];
748
	static unsigned short lastbsp[FWSAM_REPET_BLOCKS],lastbdp[FWSAM_REPET_BLOCKS],
749
						  lastbproto[FWSAM_REPET_BLOCKS],lastbpointer;
750
	static unsigned char lastbmode[FWSAM_REPET_BLOCKS];
751
	unsigned long btime=0;
752
753
754
	if(otn_tmp==NULL)
755
    {
756
#ifdef FWSAMDEBUG
757
        LogMessage("DEBUG => [Alert_FWsam] NULL otn_tmp!\n");
758
#endif
759
        return;
760
    }
761
    if(p == NULL)
762
    {
763
#ifdef FWSAMDEBUG
764
        LogMessage("DEBUG => [Alert_FWsam] NULL packet!\n");
765
#endif
766
        return;
767
    }
768
    if(arg == NULL)
769
    {
770
#ifdef FWSAMDEBUG
771
        LogMessage("DEBUG => [Alert_FWsam] NULL arg!\n");
772
#endif
773
        return;
774
    }
775
776
    /* SnortSam does no IPv6 */
777
    if (!IS_IP4(p)) {
778
#ifdef FWSAMDEBUG
779
        LogMessage("DEBUG => [Alert_FWsam] not acting on non-IP4 packet!\n");
780
#endif
781
        return;
782
    }
783
784
	optp=NULL;
785
786
	if(FWsamOptionField)            /* If using the file (field present), let's use that */
787
		optp=FWsamGetOption(event->sig_id);
788
789
	if(!optp)                       /* If file not present, check if an fwsam option was defined on the triggering rule */
790
		optp=otn_tmp->ds_list[PLUGIN_FWSAM];
791
792
	if(optp)	/* if options specified for this rule */
793
	{	if(!btime)			/* if this is the first time this function is */
794
		{	for(i=0;i<FWSAM_REPET_BLOCKS;i++)	/*  called, reset the time and protocol to 0. */
795
			{	lastbproto[i]=0;
796
				lastbtime[i]=0;
797
			}
798
		}	
799
	
800
		fwsamlist=(FWsamList *)arg;
801
802
#ifdef FWSAMDEBUG
803
		LogMessage("DEBUG => [Alert_FWsam] Alert -> Msg=\"%s\"\n",msg);
804
805
		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);
806
#endif 
807
808
		len=TRUE;
809
		btime=(unsigned long)time(NULL);	/* get current time */
810
		/* This is a cheap check to see if the blocking request matches any of the previous requests. */
811
		for(i=0;i<FWSAM_REPET_BLOCKS && len;i++) 
812
		{	if( ((optp->how==FWSAM_HOW_THIS)?	/* if blocking mode SERVICE, check for src and dst	  */
813
				( lastbsip[i]==p->iph->ip_src.s_addr && lastbdip[i]==p->iph->ip_dst.s_addr &&lastbproto[i]==p->iph->ip_proto &&
814
				  ((p->iph->ip_proto==IPPROTO_TCP || p->iph->ip_proto==IPPROTO_UDP)? /* check port only of TCP or UDP */
815
/*					((optp->who==FWSAM_WHO_SRC)?(lastbsp[i]==p->sp):(lastbdp[i]==p->dp)):TRUE) ): */
816
					lastbdp[i]==p->dp:TRUE) ):
817
				((optp->how==FWSAM_WHO_SRC)?(lastbsip[i]==p->iph->ip_src.s_addr):(lastbdip[i]==p->iph->ip_dst.s_addr))) && /* otherwise if we block source, only compare source. Same for dest. */
818
				lastbduration[i]==optp->duration &&
819
				(lastbmode[i]&(FWSAM_HOW|FWSAM_WHO))==(optp->how|optp->who) &&
820
				(btime-lastbtime[i]<((optp->duration>FWSAM_REPET_TIME)?FWSAM_REPET_TIME:optp->duration)))
821
			{	len=FALSE;		/* If so, we don't need to block again. */
822
			}
823
		}
824
		if(len)
825
		{	if(++lastbpointer>=FWSAM_REPET_BLOCKS)		/* increase repetitive check pointer */
826
				lastbpointer=0;
827
			lastbsip[lastbpointer]=p->iph->ip_src.s_addr;		/* and note packet details */
828
			lastbdip[lastbpointer]=p->iph->ip_dst.s_addr;
829
			lastbduration[lastbpointer]=optp->duration;	
830
			lastbmode[lastbpointer]=optp->how|optp->who|optp->loglevel; 
831
			lastbproto[lastbpointer]=p->iph->ip_proto;			
832
			if(p->iph->ip_proto==IPPROTO_TCP || p->iph->ip_proto==IPPROTO_UDP)
833
			{	lastbsp[lastbpointer]=p->sp;					/* set ports if TCP or UDP */
834
				lastbdp[lastbpointer]=p->dp;
835
			}
836
			lastbtime[lastbpointer]=btime;
837
838
839
			while(fwsamlist!=NULL)
840
			{	station=fwsamlist->station;
841
				//if(station->stationip.s_addr)
842
				if(station->stationip.ip32[0])
843
				{	deletestation=FALSE;
844
					stationtry++;				/* first try */
845
					/* create a socket for the station */
846
					stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); 
847
					if(stationsocket==INVALID_SOCKET)
848
						FatalError("ERROR => [Alert_FWsam] Funky socket error (socket)!\n");
849
					if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr)))
850
						FatalError("ERROR => [Alert_FWsam] Could not bind socket!\n");
851
	
852
					/* let's connect to the agent */
853
					if(connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr)))
854
					{
855
						LogMessage("WARNING => [Alert_FWsam] Could not send block to host %s. Will try later.\n",sfip_ntoa(&station->stationip));
856
#ifdef WIN32
857
						closesocket(stationsocket);
858
#else
859
						close(stationsocket);
860
#endif
861
						stationtry=0;
862
					}
863
					else
864
					{	
865
#ifdef FWSAMDEBUG
866
						LogMessage("DEBUG => [Alert_FWsam] Connected to host %s.\n",sfip_ntoa(&station->stationip));
867
#endif
868
						/* now build the packet */
869
						station->myseqno+=station->stationseqno; /* increase my seqno by adding agent seq no */
870
						sampacket.endiancheck=1;						/* This is an endian indicator for Snortsam */
871
						sampacket.snortseqno[0]=(char)station->myseqno;
872
						sampacket.snortseqno[1]=(char)(station->myseqno>>8);
873
						sampacket.fwseqno[0]=(char)station->stationseqno;/* fill station seqno */
874
						sampacket.fwseqno[1]=(char)(station->stationseqno>>8);	
875
						sampacket.status=FWSAM_STATUS_BLOCK;			/* set block mode */
876
						sampacket.version=FWSAM_PACKETVERSION;			/* set packet version */
877
						sampacket.duration[0]=(char)optp->duration;		/* set duration */
878
						sampacket.duration[1]=(char)(optp->duration>>8);
879
						sampacket.duration[2]=(char)(optp->duration>>16);
880
						sampacket.duration[3]=(char)(optp->duration>>24);
881
						sampacket.fwmode=optp->how|optp->who|optp->loglevel; /* set the mode */
882
						sampacket.dstip[0]=(char)p->iph->ip_dst.s_addr; /* destination IP */
883
						sampacket.dstip[1]=(char)(p->iph->ip_dst.s_addr>>8);
884
						sampacket.dstip[2]=(char)(p->iph->ip_dst.s_addr>>16);
885
						sampacket.dstip[3]=(char)(p->iph->ip_dst.s_addr>>24);
886
						sampacket.srcip[0]=(char)p->iph->ip_src.s_addr;	/* source IP */
887
						sampacket.srcip[1]=(char)(p->iph->ip_src.s_addr>>8);
888
						sampacket.srcip[2]=(char)(p->iph->ip_src.s_addr>>16);
889
						sampacket.srcip[3]=(char)(p->iph->ip_src.s_addr>>24);
890
						sampacket.protocol[0]=(char)p->iph->ip_proto;	/* protocol */
891
						sampacket.protocol[1]=(char)(p->iph->ip_proto>>8);/* protocol */
892
893
						if(p->iph->ip_proto==IPPROTO_TCP || p->iph->ip_proto==IPPROTO_UDP)
894
						{	sampacket.srcport[0]=(char)p->sp;	/* set ports */
895
							sampacket.srcport[1]=(char)(p->sp>>8);
896
							sampacket.dstport[0]=(char)p->dp;
897
							sampacket.dstport[1]=(char)(p->dp>>8);
898
						} 
899
						else
900
							sampacket.srcport[0]=sampacket.srcport[1]=sampacket.dstport[0]=sampacket.dstport[1]=0;
901
902
						sampacket.sig_id[0]=(char)event->sig_id;		/* set signature ID */
903
						sampacket.sig_id[1]=(char)(event->sig_id>>8);
904
						sampacket.sig_id[2]=(char)(event->sig_id>>16);
905
						sampacket.sig_id[3]=(char)(event->sig_id>>24);
906
907
#ifdef FWSAMDEBUG
908
						LogMessage("DEBUG => [Alert_FWsam] Sending BLOCK\n");
909
						LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo:  %x\n",station->myseqno);
910
						LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo :  %x\n",station->stationseqno);
911
						LogMessage("DEBUG => [Alert_FWsam] Status     :  %i\n",FWSAM_STATUS_BLOCK);
912
						LogMessage("DEBUG => [Alert_FWsam] Mode       :  %i\n",optp->how|optp->who|optp->loglevel);
913
						LogMessage("DEBUG => [Alert_FWsam] Duration   :  %li\n",optp->duration);
914
						LogMessage("DEBUG => [Alert_FWsam] Protocol   :  %i\n",GET_IPH_PROTO(p));
915
#ifdef SUP_IP6
916
						LogMessage("DEBUG => [Alert_FWsam] Src IP     :  %s\n",sfip_ntoa(GET_SRC_IP(p)));
917
						LogMessage("DEBUG => [Alert_FWsam] Dest IP    :  %s\n",sfip_ntoa(GET_DST_IP(p)));
918
#else
919
						LogMessage("DEBUG => [Alert_FWsam] Src IP     :  %s\n",inet_ntoa(p->iph->ip_src));
920
						LogMessage("DEBUG => [Alert_FWsam] Dest IP    :  %s\n",inet_ntoa(p->iph->ip_dst));
921
#endif
922
						LogMessage("DEBUG => [Alert_FWsam] Src Port   :  %i\n",p->sp);
923
						LogMessage("DEBUG => [Alert_FWsam] Dest Port  :  %i\n",p->dp);
924
						LogMessage("DEBUG => [Alert_FWsam] Sig_ID     :  %lu\n",event->sig_id);
925
926
#endif
927
928
						encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get the encryption buffer */
929
						len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt the packet with current key */
930
931
						if(send(stationsocket,encbuf,len,0)!=len) /* weird...could not send */
932
						{	LogMessage("WARNING => [Alert_FWsam] Could not send to host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
933
#ifdef WIN32
934
							closesocket(stationsocket);
935
#else
936
							close(stationsocket);
937
#endif
938
							stationtry=0;
939
						}
940
						else
941
						{	i=FWSAM_NETWAIT;
942
#ifdef WIN32
943
							ioctlsocket(stationsocket,FIONBIO,&i);	/* set non blocking and wait for  */
944
#else
945
							ioctl(stationsocket,FIONBIO,&i);		/* set non blocking and wait for  */
946
#endif
947
							while(i-- >1)							/* the response packet	 */
948
							{	waitms(10); /* wait for response (default maximum 3 secs */
949
								if(recv(stationsocket,encbuf,len,0)==len)
950
									i=0; /* if we received packet we set the counter to 0. */
951
										 /* by the time we check with if, it's already dec'ed to -1 */
952
							}
953
							if(!i) /* id we timed out (i was one, then dec'ed)... */
954
							{	LogMessage("WARNING => [Alert_FWsam] Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
955
#ifdef WIN32
956
								closesocket(stationsocket);
957
#else
958
								close(stationsocket);
959
#endif
960
								stationtry=0;
961
							}
962
							else /* got a packet */
963
							{	decbuf=(char *)&sampacket; /* get the pointer to the packet struct */
964
								len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt the packet with current key */
965
966
								if(len!=sizeof(FWsamPacket)) /* invalid decryption */
967
								{	strcpy(station->stationkey,station->initialkey); /* try the intial key */
968
									TwoFishDestroy(station->stationfish);
969
									station->stationfish=TwoFishInit(station->stationkey); /* re-initialize the TwoFish with the intial key */
970
									len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try again to decrypt */
971
									LogMessage("INFO => [Alert_FWsam] Had to use initial key!\n");
972
								}
973
								if(len==sizeof(FWsamPacket)) /* valid decryption */
974
								{	if(sampacket.version==FWSAM_PACKETVERSION)/* master speaks my language */
975
									{	if(sampacket.status==FWSAM_STATUS_OK || sampacket.status==FWSAM_STATUS_NEWKEY 
976
										|| sampacket.status==FWSAM_STATUS_RESYNC || sampacket.status==FWSAM_STATUS_HOLD) 
977
										{	station->stationseqno=sampacket.fwseqno[0] | (sampacket.fwseqno[1]<<8); /* get stations seqno */
978
											station->lastcontact=(unsigned long)time(NULL); /* set the last contact time (not used yet) */
979
#ifdef FWSAMDEBUG
980
									LogMessage("DEBUG => [Alert_FWsam] Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK":
981
																		   sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY":
982
																		   sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC":
983
																		   sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR");
984
									LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo:  %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8));
985
									LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo :  %x\n",station->stationseqno);
986
									LogMessage("DEBUG => [Alert_FWsam] Status     :  %i\n",sampacket.status);
987
									LogMessage("DEBUG => [Alert_FWsam] Version    :  %i\n",sampacket.version);
988
#endif
989
											if(sampacket.status==FWSAM_STATUS_HOLD)
990
											{	i=FWSAM_NETHOLD;			/* Stay on hold for a maximum of 60 secs (default) */
991
												while(i-- >1)							/* the response packet	 */
992
												{	waitms(10); /* wait for response  */
993
													if(recv(stationsocket,encbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,0)==sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE)
994
													  i=0; /* if we received packet we set the counter to 0. */
995
										 		}
996
												if(!i) /* id we timed out (i was one, then dec'ed)... */
997
												{	LogMessage("WARNING => [Alert_FWsam] Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
998
													stationtry=0;
999
													sampacket.status=FWSAM_STATUS_ERROR;
1000
												}
1001
												else /* got a packet */
1002
												{	decbuf=(char *)&sampacket; /* get the pointer to the packet struct */
1003
													len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt the packet with current key */
1004
1005
													if(len!=sizeof(FWsamPacket)) /* invalid decryption */
1006
													{	strcpy(station->stationkey,station->initialkey); /* try the intial key */
1007
														TwoFishDestroy(station->stationfish);
1008
														station->stationfish=TwoFishInit(station->stationkey); /* re-initialize the TwoFish with the intial key */
1009
														len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try again to decrypt */
1010
														LogMessage("INFO => [Alert_FWsam] Had to use initial key again!\n");
1011
													}
1012
#ifdef FWSAMDEBUG
1013
									LogMessage("DEBUG => [Alert_FWsam] Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK":
1014
																		   sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY":
1015
																		   sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC":
1016
																		   sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR");
1017
									LogMessage("DEBUG => [Alert_FWsam] Snort SeqNo:  %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8));
1018
									LogMessage("DEBUG => [Alert_FWsam] Mgmt SeqNo :  %x\n",station->stationseqno);
1019
									LogMessage("DEBUG => [Alert_FWsam] Status     :  %i\n",sampacket.status);
1020
									LogMessage("DEBUG => [Alert_FWsam] Version    :  %i\n",sampacket.version);
1021
#endif
1022
													if(len!=sizeof(FWsamPacket)) /* invalid decryption */
1023
													{	ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1024
														deletestation=TRUE;
1025
														sampacket.status=FWSAM_STATUS_ERROR;
1026
													}
1027
													else if(sampacket.version!=FWSAM_PACKETVERSION) /* invalid protocol version */
1028
													{	ErrorMessage("ERROR => [Alert_FWsam] Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1029
														deletestation=TRUE;
1030
														sampacket.status=FWSAM_STATUS_ERROR;
1031
													}
1032
													else if(sampacket.status!=FWSAM_STATUS_OK && sampacket.status!=FWSAM_STATUS_NEWKEY && sampacket.status!=FWSAM_STATUS_RESYNC) 
1033
													{	ErrorMessage("ERROR => [Alert_FWsam] Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1034
														deletestation=TRUE;
1035
														sampacket.status=FWSAM_STATUS_ERROR;
1036
													}
1037
												}
1038
											}
1039
											if(sampacket.status==FWSAM_STATUS_RESYNC)  /* if station want's to resync... */
1040
											{	strcpy(station->stationkey,station->initialkey); /* ...we use the intial key... */
1041
												memcpy(station->fwkeymod,sampacket.duration,4);	 /* and note the random key modifier */
1042
											}
1043
											if(sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC)	
1044
											{	
1045
												FWsamNewStationKey(station,&sampacket); /* generate new TwoFish keys */
1046
#ifdef FWSAMDEBUG
1047
													LogMessage("DEBUG => [Alert_FWsam] Generated new encryption key...\n");
1048
#endif
1049
											}
1050
#ifdef WIN32
1051
											closesocket(stationsocket);
1052
#else
1053
											close(stationsocket);
1054
#endif
1055
											stationtry=0;
1056
										}
1057
										else if(sampacket.status==FWSAM_STATUS_ERROR) /* if SnortSam reports an error on second try, */
1058
										{	
1059
#ifdef WIN32
1060
											closesocket(stationsocket);				  /* something is messed up and ... */
1061
#else
1062
											close(stationsocket);
1063
#endif
1064
											if(stationtry>1)						  /* we ignore that station. */
1065
											{	deletestation=TRUE;					  /* flag for deletion */
1066
												ErrorMessage("ERROR => [Alert_FWsam] Could not renegotiate key! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1067
											}
1068
											else							/* if we get an error on the first try, */
1069
											{	if(!FWsamCheckIn(station))	/* we first try to check in again. */
1070
												{	deletestation=TRUE;
1071
													ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1072
												}
1073
											}
1074
										}
1075
										else /* an unknown status means trouble... */
1076
										{	ErrorMessage("ERROR => [Alert_FWsam] Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1077
#ifdef WIN32
1078
											closesocket(stationsocket);
1079
#else
1080
											close(stationsocket);
1081
#endif
1082
											deletestation=TRUE;
1083
										}
1084
									}
1085
									else   /* if the SnortSam agent uses a different packet version, we have no choice but to ignore it. */
1086
									{	ErrorMessage("ERROR => [Alert_FWsam] Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1087
#ifdef WIN32
1088
										closesocket(stationsocket);
1089
#else
1090
										close(stationsocket);
1091
#endif
1092
										deletestation=TRUE;
1093
									}
1094
								}
1095
								else /* if the intial key failed to decrypt as well, the keys are not configured the same, and we ignore that SnortSam station. */
1096
								{	ErrorMessage("ERROR => [Alert_FWsam] Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1097
#ifdef WIN32
1098
									closesocket(stationsocket);
1099
#else
1100
									close(stationsocket);
1101
#endif
1102
									deletestation=TRUE;
1103
								}
1104
							}
1105
						}
1106
						free(encbuf); /* release of the TwoFishAlloc'ed encryption buffer */
1107
					}
1108
					if(stationtry==0 || deletestation)		/* if everything went real well, or real bad... */
1109
					{	if(deletestation){					/* If it went bad, we remove the station from the list by marking the IP */
1110
//							station->stationip.s_addr=0;
1111
							station->stationip.ip32[0]=0;
1112
                                                }
1113
						fwsamlist=fwsamlist->next;
1114
					}
1115
				}
1116
				else
1117
					fwsamlist=fwsamlist->next;
1118
			}
1119
		}
1120
		else
1121
		{
1122
#ifdef FWSAMDEBUG
1123
			LogMessage("DEBUG => [Alert_FWsam] Skipping repetitive block.\n");
1124
#endif
1125
		}
1126
	}
1127
}
1128
1129
/*  FWsamCheckOut will be called when Snort exists. It de-registeres this snort sensor 
1130
 *  from the list of sensor that the SnortSam agent keeps. 
1131
 */
1132
void FWsamCheckOut(FWsamStation *station)
1133
{	FWsamPacket sampacket;
1134
	SOCKET stationsocket;
1135
	int i,len;
1136
    char *encbuf,*decbuf;
1137
	//unsigned char *encbuf,*decbuf;
1138
1139
1140
	stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); 
1141
	if(stationsocket==INVALID_SOCKET)
1142
		FatalError("ERROR => [Alert_FWsam](FWsamCheckOut) Funky socket error (socket)!\n");
1143
	if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr)))
1144
		FatalError("ERROR => [Alert_FWsam](FWsamCheckOut) Could not bind socket!\n");
1145
1146
	/* let's connect to the agent */
1147
	if(!connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr)))
1148
	{	LogMessage("INFO => [Alert_FWsam](FWsamCheckOut) Disconnecting from host %s.\n",sfip_ntoa(&station->stationip));
1149
		/* now build the packet */
1150
		station->myseqno+=station->stationseqno; /* increase my seqno */
1151
		sampacket.endiancheck=1;
1152
		sampacket.snortseqno[0]=(char)station->myseqno;
1153
		sampacket.snortseqno[1]=(char)(station->myseqno>>8);
1154
		sampacket.fwseqno[0]=(char)station->stationseqno; /* fill station seqno */
1155
		sampacket.fwseqno[1]=(char)(station->stationseqno>>8);
1156
		sampacket.status=FWSAM_STATUS_CHECKOUT;  /* checking out... */
1157
		sampacket.version=FWSAM_PACKETVERSION;
1158
1159
#ifdef FWSAMDEBUG
1160
			LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Sending CHECKOUT\n");
1161
			LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Snort SeqNo:  %x\n",station->myseqno);
1162
			LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Mgmt SeqNo :  %x\n",station->stationseqno);
1163
			LogMessage("DEBUG => [Alert_FWsam](FWsamCheckOut) Status     :  %i\n",sampacket.status);
1164
1165
#endif
1166
1167
		encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get encryption buffer */
1168
		len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt packet with current key */
1169
1170
		if(send(stationsocket,encbuf,len,0)==len)
1171
		{	i=FWSAM_NETWAIT;
1172
#ifdef WIN32
1173
			ioctlsocket(stationsocket,FIONBIO,&i);	/* set non blocking and wait for  */
1174
#else
1175
			ioctl(stationsocket,FIONBIO,&i);		/* set non blocking and wait for  */
1176
#endif
1177
			while(i-- >1)
1178
			{	waitms(10);					/* ...wait a maximum of 3 secs for response... */
1179
				if(recv(stationsocket,encbuf,len,0)==len) /* ... for the status packet */
1180
					i=0;
1181
			}
1182
			if(i) /* if we got the packet */
1183
			{	decbuf=(char *)&sampacket;
1184
				len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish);
1185
1186
				if(len!=sizeof(FWsamPacket)) /* invalid decryption */
1187
				{	strcpy(station->stationkey,station->initialkey); /* try initial key */
1188
					TwoFishDestroy(station->stationfish);			 /* toss this fish */
1189
					station->stationfish=TwoFishInit(station->stationkey); /* re-initialze TwoFish with initial key */
1190
					len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* and try to decrypt again */
1191
					LogMessage("INFO => [Alert_FWsam](FWsamCheckOut) Had to use initial key!\n");
1192
				}
1193
				if(len==sizeof(FWsamPacket)) /* valid decryption */
1194
				{	if(sampacket.version!=FWSAM_PACKETVERSION) /* but don't really care since we are on the way out */
1195
						ErrorMessage("WARNING => [Alert_FWsam](FWsamCheckOut) Protocol version error! What the hell, we're quitting anyway! :)\n");
1196
				}
1197
				else
1198
					ErrorMessage("WARNING => [Alert_FWsam](FWsamCheckOut) Password mismatch! What the hell, we're quitting anyway! :)\n");
1199
			}
1200
		}
1201
		free(encbuf); /* release TwoFishAlloc'ed buffer */
1202
	}
1203
	else
1204
		LogMessage("WARNING => [Alert_FWsam] Could not connect to host %s for CheckOut. What the hell, we're quitting anyway! :)\n",sfip_ntoa(&station->stationip));
1205
#ifdef WIN32
1206
	closesocket(stationsocket);
1207
#else
1208
	close(stationsocket);
1209
#endif
1210
}
1211
1212
1213
/*   FWSamFree: Disconnects all FW-1 management stations,
1214
 *   closes sockets, and frees the structures.
1215
 */
1216
void FWsamFree(FWsamList *list)	
1217
{
1218
    FWsamList *next;
1219
1220
    while(list)	/* Free pointer list for rule type */
1221
    {
1222
        next=list->next;
1223
        free(list);
1224
        list=next;
1225
    }
1226
    list=FWsamStationList;
1227
1228
    while(list) /* Free global pointer list and stations */
1229
    {
1230
        next=list->next;
1231
        if (list->station)
1232
        {
1233
            if(list->station->stationip.ip32[0])
1234
            //if(list->station->stationip.s_addr)
1235
                FWsamCheckOut(list->station); /* Send a Check-Out to SnortSam, */
1236
1237
            TwoFishDestroy(list->station->stationfish);	/* toss the fish, */
1238
            free(list->station); /* free station, */
1239
        } 
1240
        free(list); /* free pointer, */
1241
        list=next; /* and move to next. */
1242
    }
1243
    FWsamStationList=NULL;
1244
    if(FWsamOptionField)
1245
        free(FWsamOptionField);
1246
}
1247
1248
void AlertFWsamCleanExitFunc(int signal, void *arg)
1249
{	FWsamList *fwsamlist;
1250
1251
#ifdef FWSAMDEBUG
1252
    LogMessage("DEBUG => [Alert_FWsam](AlertFWsamCleanExitFunc) Exiting...\n");
1253
#endif
1254
1255
	fwsamlist=(FWsamList *)arg;
1256
	FWsamFree(fwsamlist); /* Free all elements */
1257
}
1258
1259
void AlertFWsamRestartFunc(int signal, void *arg)
1260
{	FWsamList *fwsamlist;
1261
1262
#ifdef FWSAMDEBUG
1263
    LogMessage("DEBUG => [Alert_FWsam](AlertFWsamRestartFunc) Restarting...\n");
1264
#endif
1265
1266
	fwsamlist=(FWsamList *)arg;
1267
	FWsamFree(fwsamlist); /* Free all elements */
1268
}
1269
1270
/*  This routine registers this Snort sensor with SnortSam.
1271
 *  It will also change the encryption key based on some variables.
1272
 */
1273
int FWsamCheckIn(FWsamStation *station)
1274
{	int i,len,stationok=TRUE;
1275
	FWsamPacket sampacket;
1276
    char *encbuf,*decbuf;
1277
	//unsigned char *encbuf,*decbuf;
1278
	SOCKET stationsocket;
1279
1280
1281
	/* create a socket for the station */
1282
	stationsocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); 
1283
	if(stationsocket==INVALID_SOCKET)
1284
		FatalError("ERROR => [Alert_FWsam](FWsamCheckIn) Funky socket error (socket)!\n");
1285
	if(bind(stationsocket,(struct sockaddr *)&(station->localsocketaddr),sizeof(struct sockaddr)))
1286
		FatalError("ERROR => [Alert_FWsam](FWsamCheckIn) Could not bind socket!\n");
1287
1288
	i=TRUE;
1289
	/* let's connect to the agent */
1290
	if(connect(stationsocket,(struct sockaddr *)&station->stationsocketaddr,sizeof(struct sockaddr)))
1291
		LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Could not connect to host %s. Will try later.\n",sfip_ntoa(&station->stationip));
1292
	else
1293
	{	LogMessage("INFO => [Alert_FWsam](FWsamCheckIn) Connected to host %s.\n",sfip_ntoa(&station->stationip));
1294
		/* now build the packet */
1295
		sampacket.endiancheck=1;
1296
		sampacket.snortseqno[0]=(char)station->myseqno; /* fill my sequence number number */
1297
		sampacket.snortseqno[1]=(char)(station->myseqno>>8); /* fill my sequence number number */
1298
		sampacket.status=FWSAM_STATUS_CHECKIN; /* let's check in */
1299
		sampacket.version=FWSAM_PACKETVERSION; /* set the packet version */
1300
		memcpy(sampacket.duration,station->mykeymod,4);  /* we'll send SnortSam our key modifier in the duration slot */
1301
											   /* (the checkin packet is just the plain initial key) */
1302
#ifdef FWSAMDEBUG
1303
			LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Sending CheckIn\n");
1304
			LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Snort SeqNo:  %x\n",station->myseqno);
1305
			LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Mode       :  %i\n",sampacket.status);
1306
			LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Version    :  %i\n",sampacket.version);
1307
#endif
1308
		encbuf=TwoFishAlloc(sizeof(FWsamPacket),FALSE,FALSE,station->stationfish); /* get buffer for encryption */
1309
		len=TwoFishEncrypt((char *)&sampacket,&encbuf,sizeof(FWsamPacket),FALSE,station->stationfish); /* encrypt with initial key */
1310
		if(send(stationsocket,encbuf,len,0)!=len) /* weird...could not send */
1311
			LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Could not send to host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
1312
		else
1313
		{	i=FWSAM_NETWAIT;
1314
#ifdef WIN32
1315
			ioctlsocket(stationsocket,FIONBIO,&i);	/* set non blocking and wait for  */
1316
#else
1317
			ioctl(stationsocket,FIONBIO,&i);		/* set non blocking and wait for  */
1318
#endif
1319
			while(i-- >1)
1320
			{	waitms(10); /* wait a maximum of 3 secs for response */
1321
				if(recv(stationsocket,encbuf,len,0)==len)
1322
					i=0;
1323
			}
1324
			if(!i) /* time up? */
1325
				LogMessage("WARNING => [Alert_FWsam](FWsamCheckIn) Did not receive response from host %s. Will try again later.\n",sfip_ntoa(&station->stationip));
1326
			else
1327
			{	decbuf=(char *)&sampacket; /* got status packet */
1328
				len=TwoFishDecrypt(encbuf,&decbuf,sizeof(FWsamPacket)+TwoFish_BLOCK_SIZE,FALSE,station->stationfish); /* try to decrypt with initial key */
1329
				if(len==sizeof(FWsamPacket)) /* valid decryption */
1330
				{	
1331
#ifdef FWSAMDEBUG
1332
					LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Received %s\n",sampacket.status==FWSAM_STATUS_OK?"OK":
1333
															   sampacket.status==FWSAM_STATUS_NEWKEY?"NEWKEY":
1334
															   sampacket.status==FWSAM_STATUS_RESYNC?"RESYNC":
1335
															   sampacket.status==FWSAM_STATUS_HOLD?"HOLD":"ERROR");
1336
					LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Snort SeqNo:  %x\n",sampacket.snortseqno[0]|(sampacket.snortseqno[1]<<8));
1337
					LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Mgmt SeqNo :  %x\n",sampacket.fwseqno[0]|(sampacket.fwseqno[1]<<8));
1338
					LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Status     :  %i\n",sampacket.status);
1339
					LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Version    :  %i\n",sampacket.version);
1340
#endif
1341
					if(sampacket.version==FWSAM_PACKETVERSION) /* master speaks my language */
1342
					{	if(sampacket.status==FWSAM_STATUS_OK || sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC) 
1343
						{	station->stationseqno=sampacket.fwseqno[0]|(sampacket.fwseqno[1]<<8); /* get stations seqno */
1344
							station->lastcontact=(unsigned long)time(NULL);
1345
							
1346
							if(sampacket.status==FWSAM_STATUS_NEWKEY || sampacket.status==FWSAM_STATUS_RESYNC)	/* generate new keys */
1347
							{	memcpy(station->fwkeymod,sampacket.duration,4); /* note the key modifier */
1348
								FWsamNewStationKey(station,&sampacket); /* and generate new TwoFish keys (with key modifiers) */
1349
#ifdef FWSAMDEBUG
1350
				LogMessage("DEBUG => [Alert_FWsam](FWsamCheckIn) Generated new encryption key...\n");
1351
#endif
1352
							}
1353
						}
1354
						else /* weird, got a strange status back */
1355
						{	ErrorMessage("ERROR => [Alert_FWsam](FWsamCheckIn) Funky handshake error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1356
							stationok=FALSE;
1357
						}
1358
					}
1359
					else /* packet version does not match */
1360
					{	ErrorMessage("ERROR =>[Alert_FWsam](FWsamCheckIn) Protocol version error! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1361
						stationok=FALSE;
1362
					}
1363
				}
1364
				else /* key does not match */
1365
				{	ErrorMessage("ERROR => [Alert_FWsam](FWsamCheckIn) Password mismatch! Ignoring host %s.\n",sfip_ntoa(&station->stationip));
1366
					stationok=FALSE;
1367
				}
1368
			}
1369
		}
1370
		free(encbuf); /* release TwoFishAlloc'ed buffer */
1371
	}
1372
#ifdef WIN32
1373
	closesocket(stationsocket);
1374
#else
1375
	close(stationsocket);
1376
#endif
1377
	return stationok;
1378
}
1379
#undef FWSAMDEBUG
1380
(-)snort-2.8.3.1/src/output-plugins/spo_alert_fwsam.h (+216 lines)
Line 0 Link Here
1
/* $Id: snortpatchb,v 1.5 2005/10/06 08:50:39 fknobbe Exp $
2
**
3
** spo_alert_fwsam.h
4
**
5
** Copyright (c) 2001-2004 Frank Knobbe <frank@knobbe.us>
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
/* This file gets included in plugbase.c when it is integrated into the rest 
23
 * of the program.
24
 *
25
 * For more info, see the beginning of spo_alert_fwsam.c
26
 *
27
 */
28
29
#ifndef __SPO_FWSAM_H__
30
#define __SPO_FWSAM_H__
31
32
#include "snort.h"
33
#include "rules.h"
34
#include "plugbase.h"
35
#include "plugin_enum.h"
36
#include "fatal.h"
37
#include "util.h"
38
#include "twofish.h"
39
40
#include <stdlib.h>
41
#include <stdio.h>
42
#include <time.h>
43
#include <string.h>
44
#include <ctype.h>
45
#include <unistd.h>
46
47
48
/* just some compatibility stuff */
49
#ifdef WIN32
50
#if !defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
51
#include <winsock.h>
52
#endif
53
#define	waitms(x)				Sleep(x)
54
55
#else
56
57
#include <sys/socket.h>
58
#include <netinet/in.h>
59
#include <arpa/inet.h>
60
#include <sys/ioctl.h>		
61
#include <netdb.h>
62
63
#ifdef SOLARIS
64
#include <sys/filio.h>
65
#endif
66
67
typedef int SOCKET;
68
69
#ifndef INVALID_SOCKET
70
#define INVALID_SOCKET	-1
71
#endif
72
73
#define	waitms(x)				usleep((x)*1000)
74
75
#endif
76
77
#ifndef	FALSE
78
#define FALSE	0
79
#endif
80
#ifndef	TRUE
81
#define	TRUE	!FALSE
82
#endif
83
#ifndef	bool
84
#define	bool	int
85
#endif
86
87
88
#if defined(_DEBUG) || defined(DEBUG)
89
#ifndef FWSAMDEBUG
90
#define FWSAMDEBUG
91
#endif
92
#else
93
#endif
94
95
96
/* Official Snort PlugIn Number has been moved into plugin_enum.h */
97
98
99
/* fixed defines */
100
101
#define FWSAM_DEFAULTPORT		898	/* Default port if user does not specify one in snort.conf */
102
									/* (Was unused last time I checked...) */
103
#define FWSAM_PACKETVERSION		14	/* version of the packet. Will increase with enhancements. */
104
105
#define FWSAM_STATUS_CHECKIN	1	/* snort to fw */
106
#define FWSAM_STATUS_CHECKOUT	2
107
#define FWSAM_STATUS_BLOCK		3
108
#define FWSAM_STATUS_UNBLOCK	9
109
110
#define FWSAM_STATUS_OK			4	/* fw to snort */
111
#define FWSAM_STATUS_ERROR		5
112
#define FWSAM_STATUS_NEWKEY		6
113
#define FWSAM_STATUS_RESYNC		7
114
#define FWSAM_STATUS_HOLD		8
115
116
#define FWSAM_LOG_NONE			0
117
#define FWSAM_LOG_SHORTLOG		1
118
#define FWSAM_LOG_SHORTALERT	2
119
#define FWSAM_LOG_LONGLOG		3
120
#define FWSAM_LOG_LONGALERT		4
121
#define FWSAM_LOG				(FWSAM_LOG_SHORTLOG|FWSAM_LOG_SHORTALERT|FWSAM_LOG_LONGLOG|FWSAM_LOG_LONGALERT)
122
#define	FWSAM_WHO_DST			8
123
#define FWSAM_WHO_SRC			16
124
#define FWSAM_WHO				(FWSAM_WHO_DST|FWSAM_WHO_SRC)
125
#define FWSAM_HOW_IN			32
126
#define FWSAM_HOW_OUT			64
127
#define FWSAM_HOW_INOUT			(FWSAM_HOW_IN|FWSAM_HOW_OUT)
128
#define FWSAM_HOW_THIS			128
129
#define FWSAM_HOW				(FWSAM_HOW_IN|FWSAM_HOW_OUT|FWSAM_HOW_THIS)
130
131
132
/* user adjustable defines */
133
 
134
#define FWSAM_REPET_BLOCKS		10	/* Snort remembers this amount of last blocks and... */
135
#define FWSAM_REPET_TIME		20	/* ...checks if they fall within this time. If so,... */
136
									/* ...the blocking request is not send. */
137
138
#define FWSAM_NETWAIT			300		/* 100th of a second. 3 sec timeout for network connections */
139
#define FWSAM_NETHOLD			6000	/* 100th of a second. 60 sec timeout for holding */
140
141
#define SID_MAPFILE				"sid-block.map"
142
#define SID_ALT_MAPFILE			"sid-fwsam.map"
143
144
#define FWSAM_FANCYFETCH        /* This will invoke a fast sid lookup routine */
145
146
147
/* vars */
148
149
typedef struct _FWsamstation		/* structure of a mgmt station */
150
{	unsigned short 		myseqno;
151
	unsigned short 		stationseqno;
152
	unsigned char		mykeymod[4];
153
	unsigned char		fwkeymod[4];
154
	unsigned short		stationport;
155
	//struct in_addr		stationip;
156
	sfip_t			stationip;
157
	struct sockaddr_in	localsocketaddr;
158
	struct sockaddr_in	stationsocketaddr;
159
	TWOFISH			*stationfish;
160
	char			initialkey[TwoFish_KEY_LENGTH+2];
161
	char			stationkey[TwoFish_KEY_LENGTH+2];
162
	time_t			lastcontact;
163
/*	time_t			sleepstart; */
164
}	FWsamStation;
165
166
typedef struct _FWsampacket			/* 2 blocks (3rd block is header from TwoFish) */
167
{	unsigned short		endiancheck;	/* 0  */
168
	unsigned char		srcip[4];		/* 2  */
169
	unsigned char		dstip[4];		/* 6  */
170
	unsigned char		duration[4];	/* 10 */
171
	unsigned char		snortseqno[2];	/* 14 */
172
	unsigned char		fwseqno[2];		/* 16 */
173
	unsigned char		srcport[2];		/* 18 */
174
	unsigned char		dstport[2];		/* 20 */
175
	unsigned char		protocol[2];	/* 22 */
176
	unsigned char		fwmode;			/* 24 */
177
	unsigned char		version;		/* 25 */
178
	unsigned char		status;			/* 26 */
179
	unsigned char		sig_id[4];		/* 27 */
180
	unsigned char		fluff;			/* 31 */
181
}	FWsamPacket;						/* 32 bytes in size */
182
183
typedef struct _FWsamoptions	/* snort rule options */
184
{	unsigned long	sid;
185
    unsigned long	duration;
186
	unsigned char	who;
187
	unsigned char	how;
188
	unsigned char	loglevel;
189
}	FWsamOptions;
190
191
typedef struct _FWsamlistpointer
192
{	FWsamStation *station;
193
	struct _FWsamlistpointer *next;
194
}	FWsamList;
195
196
197
/* functions */
198
void AlertFWsamSetup(void);
199
void AlertFWsamInit(char *args);
200
void AlertFWsamOptionInit(char *args,OptTreeNode *otn,int protocol);
201
void AlertFWsamCleanExitFunc(int signal, void *arg);
202
void AlertFWsamRestartFunc(int signal, void *arg);
203
void AlertFWsam(Packet *p, char *msg, void *arg, Event *event);
204
int FWsamCheckIn(FWsamStation *station);
205
void FWsamCheckOut(FWsamStation *station);
206
void FWsamNewStationKey(FWsamStation *station,FWsamPacket *packet);
207
void FWsamFixPacketEndian(FWsamPacket *p);
208
unsigned long FWsamParseDuration(char *p);
209
void FWsamFree(FWsamList *fwsamlist);
210
int FWsamStationExists(FWsamStation *who,FWsamList *list);
211
int FWsamReadLine(char *,unsigned long,FILE *);
212
void FWsamParseLine(FWsamOptions *,char *);
213
FWsamOptions *FWsamGetOption(unsigned long);
214
int FWsamParseOption(FWsamOptions *,char *);
215
216
#endif  /* __SPO_FWSAM_H__ */
(-)snort-2.8.3.1/src/plugbase.c (+3 lines)
Lines 119-124 Link Here
119
#include "output-plugins/spo_alert_arubaaction.h"
119
#include "output-plugins/spo_alert_arubaaction.h"
120
#endif
120
#endif
121
121
122
122
#ifdef HAVE_LIBPRELUDE
123
#ifdef HAVE_LIBPRELUDE
123
#include "output-plugins/spo_alert_prelude.h"
124
#include "output-plugins/spo_alert_prelude.h"
124
#endif
125
#endif
Lines 128-133 Link Here
128
#endif
129
#endif
129
130
130
#include "output-plugins/spo_alert_test.h"
131
#include "output-plugins/spo_alert_test.h"
132
#include "output-plugins/spo_alert_fwsam.h"
131
133
132
PluginSignalFuncNode *PluginShutdownList = NULL;
134
PluginSignalFuncNode *PluginShutdownList = NULL;
133
PluginSignalFuncNode *PluginCleanExitList = NULL;
135
PluginSignalFuncNode *PluginCleanExitList = NULL;
Lines 1131-1136 Link Here
1131
#endif
1133
#endif
1132
1134
1133
    AlertTestSetup();
1135
    AlertTestSetup();
1136
    AlertFWsamSetup();
1134
}
1137
}
1135
1138
1136
void CleanupOutputPlugins()
1139
void CleanupOutputPlugins()
(-)snort-2.8.3.1/src/plugbase.c.orig (+2033 lines)
Line 0 Link Here
1
/* $Id$ */
2
/*
3
** Copyright (C) 2002-2008 Sourcefire, Inc.
4
** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
5
**
6
** This program is free software; you can redistribute it and/or modify
7
** it under the terms of the GNU General Public License Version 2 as
8
** published by the Free Software Foundation.  You may not use, modify or
9
** distribute this program under any other version of the GNU General
10
** Public License.
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
#ifdef HAVE_CONFIG_H
23
#include "config.h"
24
#endif
25
26
#include <sys/types.h>
27
#include <unistd.h>
28
#include <stdlib.h>
29
#include <string.h>
30
31
#ifdef HAVE_STRINGS_H
32
#include <strings.h>
33
#endif
34
35
#ifndef WIN32
36
#include <sys/socket.h>
37
#include <netinet/in.h>
38
#include <arpa/inet.h>
39
#endif /* !WIN32 */
40
#include <time.h>
41
#include <errno.h>
42
43
44
#include "plugbase.h"
45
#include "spo_plugbase.h"
46
#include "snort.h"
47
#include "debug.h"
48
#include "util.h"
49
#include "log.h"
50
#include "detect.h"
51
52
/* built-in preprocessors */
53
#include "preprocessors/spp_rpc_decode.h"
54
#include "preprocessors/spp_bo.h"
55
#include "preprocessors/spp_stream4.h"
56
#include "preprocessors/spp_stream5.h"
57
#include "preprocessors/spp_arpspoof.h"
58
#include "preprocessors/spp_perfmonitor.h"
59
#include "preprocessors/spp_httpinspect.h"
60
#include "preprocessors/spp_flow.h"
61
#include "preprocessors/spp_sfportscan.h"
62
#include "preprocessors/spp_frag3.h"
63
64
/* built-in detection plugins */
65
#include "detection-plugins/sp_pattern_match.h"
66
#include "detection-plugins/sp_tcp_flag_check.h"
67
#include "detection-plugins/sp_icmp_type_check.h"
68
#include "detection-plugins/sp_icmp_code_check.h"
69
#include "detection-plugins/sp_ttl_check.h"
70
#include "detection-plugins/sp_ip_id_check.h"
71
#include "detection-plugins/sp_tcp_ack_check.h"
72
#include "detection-plugins/sp_tcp_seq_check.h"
73
#include "detection-plugins/sp_dsize_check.h"
74
#include "detection-plugins/sp_ipoption_check.h"
75
#include "detection-plugins/sp_rpc_check.h"
76
#include "detection-plugins/sp_icmp_id_check.h"
77
#include "detection-plugins/sp_icmp_seq_check.h"
78
#include "detection-plugins/sp_session.h"
79
#include "detection-plugins/sp_ip_tos_check.h"
80
#include "detection-plugins/sp_ip_fragbits.h"
81
#include "detection-plugins/sp_tcp_win_check.h"
82
#include "detection-plugins/sp_ip_same_check.h"
83
#include "detection-plugins/sp_ip_proto.h"
84
#include "detection-plugins/sp_ip_same_check.h"
85
#include "detection-plugins/sp_clientserver.h"
86
#include "detection-plugins/sp_byte_check.h"
87
#include "detection-plugins/sp_byte_jump.h"
88
#include "detection-plugins/sp_isdataat.h"
89
#include "detection-plugins/sp_pcre.h"
90
#include "detection-plugins/sp_flowbits.h"
91
#include "detection-plugins/sp_asn1.h"
92
#if defined(ENABLE_RESPONSE) && !defined(ENABLE_RESPONSE2)
93
#include "detection-plugins/sp_react.h"
94
#include "detection-plugins/sp_respond.h"
95
#elif defined(ENABLE_RESPONSE2) && !defined(ENABLE_RESPONSE)
96
#include "detection-plugins/sp_respond2.h"
97
#endif
98
#if defined(ENABLE_REACT) && !defined(ENABLE_RESPONSE)
99
#include "detection-plugins/sp_react.h"
100
#endif
101
#include "detection-plugins/sp_ftpbounce.h"
102
#include "detection-plugins/sp_urilen_check.h"
103
#include "detection-plugins/sp_cvs.h"
104
105
/* built-in output plugins */
106
#include "output-plugins/spo_alert_syslog.h"
107
#include "output-plugins/spo_log_tcpdump.h"
108
#include "output-plugins/spo_database.h"
109
#include "output-plugins/spo_alert_fast.h"
110
#include "output-plugins/spo_alert_full.h"
111
#include "output-plugins/spo_alert_unixsock.h"
112
#include "output-plugins/spo_csv.h"
113
#include "output-plugins/spo_unified.h"
114
#include "output-plugins/spo_log_null.h"
115
#include "output-plugins/spo_log_ascii.h"
116
#include "output-plugins/spo_unified2.h"
117
118
#ifdef ARUBA
119
#include "output-plugins/spo_alert_arubaaction.h"
120
#endif
121
122
#ifdef HAVE_LIBPRELUDE
123
#include "output-plugins/spo_alert_prelude.h"
124
#endif
125
126
#ifdef LINUX
127
#include "output-plugins/spo_alert_sf_socket.h"
128
#endif
129
130
#include "output-plugins/spo_alert_test.h"
131
132
PluginSignalFuncNode *PluginShutdownList = NULL;
133
PluginSignalFuncNode *PluginCleanExitList = NULL;
134
PluginSignalFuncNode *PluginRestartList = NULL;
135
PluginSignalFuncNode *PluginPostConfigList = NULL;
136
137
PreprocSignalFuncNode *PreprocShutdownList = NULL;
138
PreprocSignalFuncNode *PreprocCleanExitList = NULL;
139
PreprocSignalFuncNode *PreprocRestartList = NULL;
140
PreprocSignalFuncNode *PreprocResetList = NULL;
141
PreprocSignalFuncNode *PreprocResetStatsList = NULL;
142
PreprocGetReassemblyPktFuncNode *PreprocGetReassemblyPktList = NULL;
143
144
extern int file_line;
145
extern char *file_name;
146
147
148
/**************************** Detection Plugin API ****************************/
149
KeywordXlateList *KeywordList;
150
151
void InitPlugIns()
152
{
153
    if(!pv.quiet_flag)
154
    {
155
        LogMessage("Initializing Plug-ins!\n");
156
    }
157
    SetupPatternMatch();
158
    SetupTCPFlagCheck();
159
    SetupIcmpTypeCheck();
160
    SetupIcmpCodeCheck();
161
    SetupTtlCheck();
162
    SetupIpIdCheck();
163
    SetupTcpAckCheck();
164
    SetupTcpSeqCheck();
165
    SetupDsizeCheck();
166
    SetupIpOptionCheck();
167
    SetupRpcCheck();
168
    SetupIcmpIdCheck();
169
    SetupIcmpSeqCheck();
170
    SetupSession();
171
    SetupIpTosCheck();
172
    SetupFragBits();
173
    SetupFragOffset();
174
    SetupTcpWinCheck();
175
    SetupIpProto();
176
    SetupIpSameCheck();
177
    SetupClientServer();
178
    SetupByteTest();
179
    SetupByteJump();
180
    SetupIsDataAt();
181
    SetupPcre();
182
    SetupFlowBits();
183
    SetupAsn1();
184
#if defined(ENABLE_RESPONSE) && !defined(ENABLE_RESPONSE2)
185
    SetupReact();
186
    SetupRespond();
187
#elif defined(ENABLE_RESPONSE2) && !defined(ENABLE_RESPONSE)
188
    SetupRespond2();
189
#endif
190
#if defined(ENABLE_REACT) && !defined(ENABLE_RESPONSE)
191
    SetupReact();
192
#endif
193
    SetupFTPBounce();
194
    SetupUriLenCheck();
195
    SetupCvs();
196
}
197
198
void CleanupPlugInSigList(PluginSignalFuncNode *sig)
199
{
200
    PluginSignalFuncNode *tmpSig;
201
    while (sig)
202
    {
203
        tmpSig = sig->next;
204
        /* don't free sig->arg, that's free'd by the CleanExit/Restart func */
205
        free(sig);
206
        sig = tmpSig;
207
    }
208
}
209
210
void CleanupPlugIns()
211
{
212
    KeywordXlateList *tmpIdx, *idx = KeywordList;
213
214
    while (idx)
215
    {
216
        tmpIdx = idx->next;
217
        if (idx->entry.keyword)
218
            free(idx->entry.keyword);
219
        free(idx);
220
        idx = tmpIdx;
221
    }
222
223
    CleanupPlugInSigList(PluginShutdownList);
224
    PluginShutdownList = NULL;
225
226
    CleanupPlugInSigList(PluginCleanExitList);
227
    PluginCleanExitList = NULL;
228
229
    CleanupPlugInSigList(PluginRestartList);
230
    PluginRestartList = NULL;
231
232
    CleanupPlugInSigList(PluginPostConfigList);
233
    PluginPostConfigList = NULL;
234
}
235
236
/****************************************************************************
237
 * utils for translation from enum to char*
238
 ***************************************************************************/
239
240
#ifdef DEBUG
241
static const char* optTypeMap[OPT_TYPE_MAX] = {
242
    "action", "logging", "detection"
243
};
244
#endif
245
246
#define ENUM2STR(num, map) \
247
    ((num < sizeof(map)/sizeof(map[0])) ? map[num] : "undefined")
248
    
249
/****************************************************************************
250
 *
251
 * Function: RegisterPlugin(char *, void (*func)(), enum OptionType)
252
 *
253
 * Purpose:  Associates a rule option keyword with an option setup/linking
254
 *           function.
255
 *
256
 * Arguments: keyword => The option keyword to associate with the option
257
 *                       handler
258
 *            *func => function pointer to the handler
259
 *            type => used to determine where keyword is allowed
260
 *
261
 * Returns: void function
262
 *
263
 ***************************************************************************/
264
void RegisterPlugin(
265
    char *keyword,
266
    void (*func) (char *, OptTreeNode *, int),
267
    enum OptionType type
268
) {
269
    KeywordXlateList *idx;
270
271
    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Registering keyword:func => %s/%s:%p\n",
272
               ENUM2STR(type, optTypeMap), keyword, func););
273
274
    idx = KeywordList;
275
276
    if(idx == NULL)
277
    {
278
        KeywordList = (KeywordXlateList *)SnortAlloc(sizeof(KeywordXlateList));
279
280
        KeywordList->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char));
281
        SnortStrncpy(KeywordList->entry.keyword, keyword, strlen(keyword) + 1);
282
283
        KeywordList->entry.func = func;
284
        KeywordList->entry.type = type;
285
    }
286
    else
287
    {
288
        /* go to the end of the list */
289
        while(idx->next != NULL)
290
        {
291
            if(!strcasecmp(idx->entry.keyword, keyword))
292
            {
293
                FatalError("RegisterPlugin: Duplicate detection plugin keyword:"
294
                        " (%s) (%s)!\n", idx->entry.keyword, keyword);
295
            }
296
            idx = idx->next;
297
        }
298
299
        idx->next = (KeywordXlateList *)SnortAlloc(sizeof(KeywordXlateList));
300
        idx = idx->next;
301
302
        idx->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char));
303
        SnortStrncpy(idx->entry.keyword, keyword, strlen(keyword) + 1);
304
        
305
        idx->entry.func = func;
306
        idx->entry.type = type;
307
    }
308
}
309
310
311
/****************************************************************************
312
 *
313
 * Function: DumpPlugIns()
314
 *
315
 * Purpose:  Prints the keyword->function list
316
 *
317
 * Arguments: None.
318
 *
319
 * Returns: void function
320
 *
321
 ***************************************************************************/
322
void DumpPlugIns()
323
{
324
    KeywordXlateList *idx;
325
326
    if(pv.quiet_flag)
327
        return;
328
329
    idx = KeywordList;
330
331
    LogMessage("-------------------------------------------------\n");
332
    LogMessage(" Keyword     |      Plugin Registered @\n");
333
    LogMessage("-------------------------------------------------\n");
334
    while(idx != NULL)
335
    {
336
        LogMessage("%-13s:      %p\n", idx->entry.keyword, idx->entry.func);
337
        idx = idx->next;
338
    }
339
    LogMessage("-------------------------------------------------\n\n");
340
}
341
342
343
/****************************************************************************
344
 * 
345
 * Function: AddOptFuncToList(int (*func)(), OptTreeNode *)
346
 *
347
 * Purpose: Links the option detection module to the OTN
348
 *
349
 * Arguments: (*func)() => function pointer to the detection module
350
 *            otn =>  pointer to the current OptTreeNode
351
 *
352
 * Returns: void function
353
 *
354
 ***************************************************************************/
355
OptFpList *AddOptFuncToList(
356
#ifdef DETECTION_OPTION_TREE
357
            int (*func) (void *option_data, Packet *p), 
358
#else
359
            int (*func) (Packet *, struct _OptTreeNode *, struct _OptFpList *), 
360
#endif
361
            OptTreeNode * otn)
362
{
363
    OptFpList *idx;     /* index pointer */
364
365
    DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Adding new rule to list\n"););
366
367
    /* set the index pointer to the start of this OTN's function list */
368
    idx = otn->opt_func;
369
370
    /* if there are no nodes on the function list... */
371
    if(idx == NULL)
372
    {
373
        /* calloc the list head */
374
        otn->opt_func = (OptFpList *)calloc(1, sizeof(OptFpList));
375
376
        if(otn->opt_func == NULL)
377
        {
378
            FatalError("new node calloc failed: %s\n",
379
                       strerror(errno));
380
        }
381
382
        /* set the head function */
383
        otn->opt_func->OptTestFunc = func;
384
385
        idx = otn->opt_func;
386
    }
387
    else
388
    {
389
        /* walk to the end of the list */
390
        while(idx->next != NULL)
391
        {
392
            idx = idx->next;
393
        }
394
395
        /* allocate a new node on the end of the list */
396
        idx->next = (OptFpList *)calloc(1, sizeof(OptFpList));
397
398
        if(idx->next == NULL)
399
        {
400
            FatalError("AddOptFuncToList new node calloc failed: %s\n",
401
                       strerror(errno));
402
        }
403
404
        /* move up to the new node */
405
        idx = idx->next;
406
407
        /* link the function to the new node */
408
        idx->OptTestFunc = func;
409
410
        DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Set OptTestFunc to %p\n", 
411
                    func););
412
    }
413
414
    return idx;
415
}
416
417
/****************************************************************************
418
 *
419
 * Function: AddRspFuncToList(int (*func)(), OptTreeNode *)
420
 *
421
 * Purpose: Adds Response function to OTN
422
 *
423
 * Arguments: (*func)() => function pointer to the response module
424
 *            otn =>  pointer to the current OptTreeNode
425
 *
426
 * Returns: void function
427
 *
428
 ***************************************************************************/
429
void AddRspFuncToList(int (*func) (Packet *, struct _RspFpList *), OptTreeNode * otn, void *params)
430
{
431
    RspFpList *idx;     /* index pointer */
432
433
    DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Adding response to list\n"););
434
435
    /* set the index pointer to the start of this OTN's function list */
436
    idx = otn->rsp_func;
437
438
    /* if there are no nodes on the function list... */
439
    if(idx == NULL)
440
    {
441
        /* calloc the list head */
442
        otn->rsp_func = (RspFpList *)calloc(1, sizeof(RspFpList));
443
444
        if(otn->rsp_func == NULL)
445
        {
446
            FatalError("AddRspFuncToList new node calloc failed: %s\n", strerror(errno));
447
        }
448
        /* set the head function */
449
        otn->rsp_func->ResponseFunc = func;
450
        otn->rsp_func->params = params;
451
    }
452
    else
453
    {
454
        /* walk to the end of the list */
455
        while(idx->next != NULL)
456
        {
457
            idx = idx->next;
458
        }
459
460
        /* allocate a new node on the end of the list */
461
        idx->next = (RspFpList *)calloc(1, sizeof(RspFpList));
462
463
        if(idx->next == NULL)
464
        {
465
            FatalError("AddRspFuncToList new node calloc failed: %s\n", strerror(errno));
466
        }
467
        /* link the function to the new node */
468
        idx->next->ResponseFunc = func;
469
        idx->next->params = params;
470
471
        DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Set ResponseFunc to %p\n", func););
472
    }
473
}
474
475
476
/************************* End Detection Plugin API ***************************/
477
478
479
/************************** Preprocessor Plugin API ***************************/
480
PreprocessKeywordList *PreprocessKeywords = NULL;
481
PreprocessStatsList *PreprocessStats = NULL;
482
PreprocessFuncNode *PreprocessList = NULL;
483
PreprocessCheckConfigNode *PreprocessConfigCheckList = NULL;
484
static SFGHASH *preprocIdTable = NULL;
485
unsigned int num_preprocs = 0;
486
487
void InitPreprocessors()
488
{
489
    if(!pv.quiet_flag)
490
    {
491
        LogMessage("Initializing Preprocessors!\n");
492
    }
493
    SetupRpcDecode();
494
    SetupBo();
495
//    SetupTelNeg();
496
    SetupStream4();
497
    SetupARPspoof();
498
    SetupHttpInspect();
499
    SetupPerfMonitor();
500
    SetupFlow();
501
    SetupPsng();
502
    SetupFrag3();
503
    SetupStream5();
504
}
505
506
void CleanupPreprocessorSigList(PreprocSignalFuncNode *sig)
507
{
508
    PreprocSignalFuncNode *tmpSig;
509
    while (sig)
510
    {
511
        tmpSig = sig->next;
512
        /* don't free sig->arg, that's free'd by the CleanExit/Restart func */
513
        free(sig);
514
        sig = tmpSig;
515
    }
516
}
517
518
void CleanupPreprocessors()
519
{
520
    PreprocessKeywordList *tmpIdx, *idx = PreprocessKeywords;
521
    PreprocessCheckConfigNode *tmpConf, *conf = PreprocessConfigCheckList;
522
    PreprocessStatsList *tmpStats, *stats = PreprocessStats;
523
    PreprocessFuncNode *tmpFunc, *func = PreprocessList;
524
    PreprocGetReassemblyPktFuncNode *tmpReass, *reass = PreprocGetReassemblyPktList;
525
526
    while (idx)
527
    {
528
        tmpIdx = idx->next;
529
        if (idx->entry.keyword)
530
            free(idx->entry.keyword);
531
        free(idx);
532
        idx = tmpIdx;
533
    }
534
    PreprocessKeywords = NULL;
535
536
    while (conf)
537
    {
538
        tmpConf = conf->next;
539
        free(conf);
540
        conf = tmpConf;
541
    }
542
    PreprocessConfigCheckList = NULL;
543
544
    while (stats)
545
    {
546
        tmpStats = stats->next;
547
        if (stats->entry.keyword)
548
            free(stats->entry.keyword);
549
        free(stats);
550
        stats = tmpStats;
551
    }
552
    PreprocessStats = NULL;
553
554
    while (func)
555
    {
556
        tmpFunc = func->next;
557
        if (func->context)
558
            free(func->context);
559
        free(func);
560
        func = tmpFunc;
561
    }
562
    PreprocessList = NULL;
563
564
    CleanupPreprocessorSigList(PreprocShutdownList);
565
    PreprocShutdownList = NULL;
566
567
    CleanupPreprocessorSigList(PreprocCleanExitList);
568
    PreprocCleanExitList = NULL;
569
570
    CleanupPreprocessorSigList(PreprocRestartList);
571
    PreprocRestartList = NULL;
572
573
    CleanupPreprocessorSigList(PreprocResetList);
574
    PreprocResetList = NULL;
575
576
    CleanupPreprocessorSigList(PreprocResetStatsList);
577
    PreprocResetStatsList = NULL;
578
579
    while (reass)
580
    {
581
        tmpReass = reass->next;
582
        free(reass);
583
        reass = tmpReass;
584
    }
585
    PreprocGetReassemblyPktList = NULL;
586
587
    if (preprocIdTable)
588
        sfghash_delete(preprocIdTable);
589
}
590
591
void CheckPreprocessorsConfig()
592
{
593
    PreprocessCheckConfigNode *idx;
594
595
    idx = PreprocessConfigCheckList;
596
597
    if(!pv.quiet_flag)
598
    {
599
        LogMessage("Verifying Preprocessor Configurations!\n");
600
    }
601
602
    while(idx != NULL)
603
    {
604
        idx->func();
605
        idx = idx->next;
606
    }
607
}
608
609
void PostConfigInitPlugins()
610
{
611
    PluginSignalFuncNode *idx;
612
613
    idx = PluginPostConfigList;
614
615
    while (idx != NULL)
616
    {
617
        idx->func(0, idx->arg);
618
        idx = idx->next;
619
    }
620
}
621
622
/****************************************************************************
623
 *
624
 * Function: RegisterPreprocessor(char *, void (*)(char *))
625
 *
626
 * Purpose:  Associates a preprocessor statement with its function.
627
 *
628
 * Arguments: keyword => The option keyword to associate with the
629
 *                       preprocessor
630
 *            *func => function pointer to the handler
631
 *
632
 * Returns: void function
633
 *
634
 ***************************************************************************/
635
void RegisterPreprocessor(char *keyword, void (*func)(char *))
636
{
637
    PreprocessKeywordList *idx;
638
639
    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:preproc => %s:%p\n", keyword, func););
640
641
    idx = PreprocessKeywords;
642
643
    if(idx == NULL)
644
    {
645
        /* alloc the node */
646
        PreprocessKeywords = (PreprocessKeywordList *)SnortAlloc(sizeof(PreprocessKeywordList));
647
648
        /* alloc space for the keyword */
649
        PreprocessKeywords->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char));
650
651
        /* copy the keyword into the struct */
652
        SnortStrncpy(PreprocessKeywords->entry.keyword, keyword, strlen(keyword) + 1);
653
654
        /* set the function pointer to the keyword handler function */
655
        PreprocessKeywords->entry.func = (void (*)(char *))func;
656
    }
657
    else
658
    {
659
        /* loop to the end of the list */
660
        while(idx->next != NULL)
661
        {
662
            if(!strcasecmp(idx->entry.keyword, keyword))
663
            {
664
                FatalError("%s(%d) => Duplicate preprocessor keyword!\n",
665
                           file_name, file_line);
666
            }
667
668
            idx = idx->next;
669
        }
670
671
        idx->next = (PreprocessKeywordList *)SnortAlloc(sizeof(PreprocessKeywordList));
672
673
        idx = idx->next;
674
675
        /* alloc space for the keyword */
676
        idx->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char));
677
678
        /* copy the keyword into the struct */
679
        SnortStrncpy(idx->entry.keyword, keyword, strlen(keyword) + 1);
680
681
        /* set the function pointer to the keyword handler function */
682
        idx->entry.func = func;
683
    }
684
}
685
686
687
/****************************************************************************
688
 *
689
 * Function: RegisterPreprocStats(char *keyword, void (*func)(int))
690
 *
691
 * Purpose: Registers a function for printing preprocessor final stats
692
 *          (or other if it has a use for printing final stats)
693
 *
694
 * Arguments: keyword => keyword (preprocessor) whose stats will print
695
 *            func => function pointer to the handler
696
 *
697
 * Returns: void function
698
 *
699
 ***************************************************************************/
700
void RegisterPreprocStats(char *keyword, void (*func)(int))
701
{
702
    PreprocessStatsList *idx;
703
704
    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering final stats function: preproc => %s:%p\n", keyword, func););
705
706
    idx = PreprocessStats;
707
708
    if (idx == NULL)
709
    {
710
        /* alloc the node */
711
        PreprocessStats = (PreprocessStatsList *)SnortAlloc(sizeof(PreprocessStatsList));
712
713
        /* alloc space for the keyword */
714
        PreprocessStats->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char));
715
716
        /* copy the keyword into the struct */
717
        SnortStrncpy(PreprocessStats->entry.keyword, keyword, strlen(keyword) + 1);
718
719
        /* set the function pointer to the keyword handler function */
720
        PreprocessStats->entry.func = func;
721
722
        PreprocessStats->next = NULL;
723
    }
724
    else
725
    {
726
        /* loop to the end of the list */
727
        while (idx->next != NULL)
728
        {
729
            if(!strcasecmp(idx->entry.keyword, keyword))
730
            {
731
                FatalError("%s(%d) => Duplicate final stats keyword!\n",
732
                           file_name, file_line);
733
            }
734
735
            idx = idx->next;
736
        }
737
738
        idx->next = (PreprocessStatsList *)SnortAlloc(sizeof(PreprocessStatsList));
739
740
        idx = idx->next;
741
742
        /* alloc space for the keyword */
743
        idx->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char));
744
745
        /* copy the keyword into the struct */
746
        SnortStrncpy(idx->entry.keyword, keyword, strlen(keyword) + 1);
747
748
        /* set the function pointer to the keyword handler function */
749
        idx->entry.func = func;
750
751
        idx->next = NULL;
752
    }
753
}
754
755
756
/***************************************************************************
757
 *
758
 * Function: PreprocessStatsFree(void)
759
 *
760
 * Purpose: Free memory allocated by RegisterPreprocStats
761
 *
762
 * Arguments: none
763
 *
764
 * Returns: void function
765
 *
766
 **************************************************************************/
767
void PreprocessStatsFree(void)
768
{
769
    PreprocessStatsList *tmp;
770
771
    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Freeing stats function structures\n"););
772
773
    while (PreprocessStats != NULL)
774
    {
775
        if (PreprocessStats->entry.keyword != NULL)
776
            free(PreprocessStats->entry.keyword);
777
        tmp = PreprocessStats;
778
        PreprocessStats = PreprocessStats->next;
779
        free(tmp);
780
    }
781
}
782
783
784
/****************************************************************************
785
 *
786
 * Function: DumpPreprocessors()
787
 *
788
 * Purpose:  Prints the keyword->preprocess list
789
 *
790
 * Arguments: None.
791
 *
792
 * Returns: void function
793
 *
794
 ***************************************************************************/
795
void DumpPreprocessors()
796
{
797
    PreprocessKeywordList *idx;
798
799
    if(pv.quiet_flag)
800
        return;
801
    idx = PreprocessKeywords;
802
803
    LogMessage("-------------------------------------------------\n");
804
    LogMessage(" Keyword     |       Preprocessor @ \n");
805
    LogMessage("-------------------------------------------------\n");
806
    while(idx != NULL)
807
    {
808
        LogMessage("%-13s:       %p\n", idx->entry.keyword, idx->entry.func);
809
        idx = idx->next;
810
    }
811
    LogMessage("-------------------------------------------------\n\n");
812
}
813
814
int IsPreprocBitSet(Packet *p, unsigned int preproc_bit)
815
{
816
#if 0
817
    int preproc_bit;
818
    PreprocessFuncNode *idx = sfghash_find(preprocIdTable, &preproc_id);
819
    if (idx)
820
    {
821
        preproc_bit = idx->preproc_bit;
822
        return boIsBitSet(p->preprocessor_bits, preproc_bit);
823
    }
824
    return 0;
825
#endif
826
    return boIsBitSet(p->preprocessor_bits, preproc_bit);
827
}
828
829
int SetPreprocBit(Packet *p, unsigned int preproc_id)
830
{
831
    int preproc_bit;
832
    PreprocessFuncNode *idx = sfghash_find(preprocIdTable, &preproc_id);
833
    if (idx)
834
    {
835
        preproc_bit = idx->preproc_bit;
836
        return boSetBit(p->preprocessor_bits, preproc_bit);
837
    }
838
    return 0;
839
}
840
841
int IsPreprocGetReassemblyPktBitSet(Packet *p, unsigned int preproc_id)
842
{
843
    PreprocessFuncNode *idx = sfghash_find(preprocIdTable, &preproc_id);
844
    if (idx)
845
    {
846
        int preproc_bit = idx->preproc_bit;
847
        return boIsBitSet(p->preproc_reassembly_pkt_bits, preproc_bit);
848
    }
849
850
    return 0;
851
}
852
853
int SetPreprocGetReassemblyPktBit(Packet *p, unsigned int preproc_id)
854
{
855
    PreprocessFuncNode *idx = sfghash_find(preprocIdTable, &preproc_id);
856
    if (idx)
857
    {
858
        int preproc_bit = idx->preproc_bit;
859
        p->packet_flags |= PKT_PREPROC_RPKT;
860
        return boSetBit(p->preproc_reassembly_pkt_bits, preproc_bit);
861
    }
862
    
863
    return 0;
864
}
865
866
PreprocessFuncNode *AddFuncToPreprocList(void (*func) (Packet *, void *),
867
        unsigned short priority,
868
        unsigned int preproc_id)
869
{
870
    PreprocessFuncNode *idx;
871
    PreprocessFuncNode *tmpNext;
872
    PreprocessFuncNode *insertAfter = NULL;
873
874
    DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
875
        "Adding preprocessor function ID %d/bit %d/pri %d to list\n",
876
         preproc_id, num_preprocs, priority););
877
    idx = PreprocessList;
878
879
    if(idx == NULL)
880
    {
881
        PreprocessList = (PreprocessFuncNode *)SnortAlloc(sizeof(PreprocessFuncNode));
882
883
        PreprocessList->func = func;
884
        PreprocessList->priority = priority;
885
        PreprocessList->preproc_id = preproc_id;
886
        PreprocessList->preproc_bit = num_preprocs++;
887
888
        idx = PreprocessList;
889
    }
890
    else
891
    {
892
        do
893
        {
894
            if (idx->preproc_id == preproc_id)
895
            {
896
                FatalError("Preprocessor already registered with ID %d\n", preproc_id);
897
                //return NULL;
898
            }
899
            
900
            if (idx->priority > priority)
901
                break;
902
            insertAfter = idx;
903
            idx = idx->next;
904
        }
905
        while (idx);
906
907
        idx = (PreprocessFuncNode *)SnortAlloc(sizeof(PreprocessFuncNode));
908
        if (insertAfter)
909
        {
910
            tmpNext = insertAfter->next;
911
            insertAfter->next = idx;
912
            idx->next = tmpNext;
913
        }
914
        else
915
        {
916
            idx->next = PreprocessList;
917
            PreprocessList = idx;
918
        }
919
920
        idx->func = func;
921
        idx->priority = priority;
922
        idx->preproc_id = preproc_id;
923
        idx->preproc_bit = num_preprocs++;
924
    }
925
926
    return idx;
927
}
928
929
void MapPreprocessorIds()
930
{
931
    PreprocessFuncNode *idx;
932
    if (preprocIdTable || !num_preprocs)
933
        return;
934
935
    preprocIdTable = sfghash_new(num_preprocs, 4, 1, NULL);
936
937
    idx = PreprocessList;
938
939
    while (idx)
940
    {
941
        DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
942
                   "Adding preprocessor ID %d/bit %d/pri %d to hash table\n",
943
                   idx->preproc_id, idx->preproc_bit, idx->priority););
944
        sfghash_add(preprocIdTable, &(idx->preproc_id), idx);
945
        idx = idx->next;
946
    }
947
}
948
949
PreprocessCheckConfigNode *AddFuncToConfigCheckList(void (*func)(void))
950
{
951
    PreprocessCheckConfigNode *idx;
952
953
    idx = PreprocessConfigCheckList;
954
955
    if(idx == NULL)
956
    {
957
        PreprocessConfigCheckList = (PreprocessCheckConfigNode *)SnortAlloc(sizeof(PreprocessCheckConfigNode));
958
959
        PreprocessConfigCheckList->func = func;
960
961
        idx = PreprocessConfigCheckList;
962
    }
963
    else
964
    {
965
        while(idx->next != NULL)
966
            idx = idx->next;
967
968
        idx->next = (PreprocessCheckConfigNode *)SnortAlloc(sizeof(PreprocessCheckConfigNode));
969
970
        idx = idx->next;
971
        idx->func = func;
972
    }
973
974
    return idx;
975
}
976
977
/* functions to aid in cleaning up after plugins */
978
void AddFuncToPreprocRestartList(void (*func) (int, void *), void *arg,
979
                                 unsigned short priority, unsigned int preproc_id)
980
{
981
    PreprocRestartList = AddFuncToPreprocSignalList(func, arg, PreprocRestartList, priority, preproc_id);
982
}
983
984
void AddFuncToPreprocCleanExitList(void (*func) (int, void *), void *arg,
985
                                   unsigned short priority, unsigned int preproc_id)
986
{
987
    PreprocCleanExitList = AddFuncToPreprocSignalList(func, arg, PreprocCleanExitList, priority, preproc_id);
988
}
989
990
void AddFuncToPreprocShutdownList(void (*func) (int, void *), void *arg,
991
                                  unsigned short priority, unsigned int preproc_id)
992
{
993
    PreprocShutdownList = AddFuncToPreprocSignalList(func, arg, PreprocShutdownList, priority, preproc_id);
994
}
995
996
void AddFuncToPreprocResetList(void (*func) (int, void *), void *arg,
997
                               unsigned short priority, unsigned int preproc_id)
998
{
999
    PreprocResetList = AddFuncToPreprocSignalList(func, arg, PreprocResetList, priority, preproc_id);
1000
}
1001
1002
void AddFuncToPreprocResetStatsList(void (*func) (int, void *), void *arg,
1003
                                    unsigned short priority, unsigned int preproc_id)
1004
{
1005
    PreprocResetStatsList = AddFuncToPreprocSignalList(func, arg, PreprocResetStatsList, priority, preproc_id);
1006
}
1007
1008
void AddFuncToPreprocGetReassemblyPktList(void * (*func)(void), unsigned int preproc_id)
1009
{
1010
    PreprocGetReassemblyPktFuncNode *idx = PreprocGetReassemblyPktList;
1011
    PreprocGetReassemblyPktFuncNode *tmp;
1012
1013
    if (idx == NULL)
1014
    {
1015
        idx = (PreprocGetReassemblyPktFuncNode *)
1016
            SnortAlloc(sizeof(PreprocGetReassemblyPktFuncNode));
1017
1018
        idx->func = func;
1019
        idx->preproc_id = preproc_id;
1020
    }
1021
    else
1022
    {
1023
        /* just insert at front of list */
1024
        tmp = idx;
1025
        idx = (PreprocGetReassemblyPktFuncNode *)
1026
            SnortAlloc(sizeof(PreprocGetReassemblyPktFuncNode));
1027
1028
        idx->next = tmp;
1029
        idx->func = func;
1030
        idx->preproc_id = preproc_id;
1031
    }
1032
1033
    PreprocGetReassemblyPktList = idx;
1034
}
1035
1036
PreprocSignalFuncNode *AddFuncToPreprocSignalList(void (*func) (int, void *), void *arg,
1037
                                                  PreprocSignalFuncNode * list, unsigned short priority,
1038
                                                  unsigned int preproc_id)
1039
{
1040
    PreprocSignalFuncNode *idx;
1041
    PreprocSignalFuncNode *insertAfter = NULL;
1042
    PreprocSignalFuncNode *tmpNext;
1043
1044
    idx = list;
1045
1046
    if(idx == NULL)
1047
    {
1048
        idx = (PreprocSignalFuncNode *)SnortAlloc(sizeof(PreprocSignalFuncNode));
1049
1050
        idx->func = func;
1051
        idx->arg = arg;
1052
        idx->preproc_id = preproc_id;
1053
        idx->priority = priority;
1054
        list = idx;
1055
    }
1056
    else
1057
    {
1058
        do
1059
        {
1060
            if (idx->priority > priority)
1061
                break;
1062
1063
            insertAfter = idx;
1064
            idx = idx->next;
1065
        }
1066
        while(idx);
1067
1068
        idx = (PreprocSignalFuncNode *)SnortAlloc(sizeof(PreprocSignalFuncNode));
1069
        if (insertAfter)
1070
        {
1071
            tmpNext = insertAfter->next;
1072
            insertAfter->next = idx;
1073
            idx->next = tmpNext;
1074
        }
1075
        else
1076
        {
1077
            idx->next = list;
1078
            list = idx;
1079
        }
1080
1081
        idx->func = func;
1082
        idx->arg = arg;
1083
        idx->priority = priority;
1084
        idx->preproc_id = preproc_id;
1085
    }
1086
1087
    return list;
1088
}
1089
1090
/************************ End Preprocessor Plugin API  ************************/
1091
1092
/***************************** Output Plugin API  *****************************/
1093
OutputKeywordList *OutputKeywords;
1094
OutputFuncNode *AlertList;
1095
OutputFuncNode *LogList;
1096
OutputFuncNode *AppendOutputFuncList(void (*) (Packet *,char *,void *,Event*),
1097
                void *, OutputFuncNode *);
1098
1099
void InitOutputPlugins()
1100
{
1101
    if(!pv.quiet_flag)
1102
    {
1103
        LogMessage("Initializing Output Plugins!\n");
1104
    }
1105
    AlertSyslogSetup();
1106
    LogTcpdumpSetup();
1107
    DatabaseSetup();
1108
    AlertFastSetup();
1109
    AlertFullSetup();
1110
#ifndef WIN32
1111
    /* Win32 doesn't support AF_UNIX sockets */
1112
    AlertUnixSockSetup();
1113
#endif /* !WIN32 */
1114
    AlertCSVSetup();
1115
    LogNullSetup();
1116
    UnifiedSetup();
1117
    Unified2Setup();
1118
    LogAsciiSetup();
1119
1120
#ifdef ARUBA
1121
    AlertArubaActionSetup();
1122
#endif
1123
1124
#ifdef LINUX
1125
    /* This uses linux only capabilities */
1126
    AlertSFSocket_Setup();
1127
#endif
1128
1129
#ifdef HAVE_LIBPRELUDE
1130
    AlertPreludeSetup();
1131
#endif
1132
1133
    AlertTestSetup();
1134
}
1135
1136
void CleanupOutputPlugins()
1137
{
1138
    OutputKeywordList *tmpIdx, *idx = OutputKeywords;
1139
    OutputFuncNode *tmpAlert, *alert = AlertList;
1140
    OutputFuncNode *tmpLog, *log = LogList;
1141
    while (idx)
1142
    {
1143
        tmpIdx = idx->next;
1144
        if (idx->entry.keyword)
1145
            free(idx->entry.keyword);
1146
        free(idx);
1147
        idx = tmpIdx;
1148
    }
1149
1150
    while (alert)
1151
    {
1152
        tmpAlert = alert->next;
1153
        free(alert);
1154
        alert = tmpAlert;
1155
    }
1156
    AlertList = NULL;
1157
1158
    while (log)
1159
    {
1160
        tmpLog = log->next;
1161
        free(log);
1162
        log = tmpLog;
1163
    }
1164
    LogList = NULL;
1165
}
1166
1167
int ActivateOutputPlugin(char *plugin_name, char *plugin_options)
1168
{
1169
    OutputKeywordNode *plugin;
1170
    
1171
    if(!plugin_name)
1172
        return -1;
1173
    
1174
    /* get the output plugin node */
1175
    plugin = GetOutputPlugin(plugin_name);
1176
    if (!plugin)
1177
        return -1;
1178
1179
    switch(plugin->node_type)
1180
    {
1181
        case NT_OUTPUT_SPECIAL: /* both alert & logging in one plugin */
1182
            plugin->func(plugin_options);
1183
            break;
1184
        case NT_OUTPUT_ALERT:
1185
            plugin->func(plugin_options);
1186
            break;
1187
        case NT_OUTPUT_LOG:
1188
            plugin->func(plugin_options);
1189
            break;
1190
    }
1191
1192
    return 0;
1193
}
1194
1195
OutputKeywordNode *GetOutputPlugin(char *plugin_name)
1196
{
1197
    OutputKeywordList *list_node = NULL;
1198
    OutputKeywordNode *ret = NULL;
1199
1200
    if (!plugin_name)
1201
        return NULL;
1202
1203
    list_node = OutputKeywords;
1204
1205
    while (list_node != NULL)
1206
    {
1207
        if (strcasecmp(plugin_name, list_node->entry.keyword) == 0)
1208
        {
1209
            ret = &(list_node->entry);
1210
            break;
1211
        }
1212
1213
        list_node = list_node->next;
1214
    }
1215
1216
    if (ret == NULL)
1217
    {
1218
        FatalError("unknown output plugin: '%s'", plugin_name);
1219
    }
1220
1221
    return ret;
1222
}
1223
1224
1225
/****************************************************************************
1226
 *
1227
 * Function: RegisterOutputPlugin(char *, void (*func)(Packet *, u_char *))
1228
 *
1229
 * Purpose:  Associates an output statement with its function.
1230
 *
1231
 * Arguments: keyword => The output keyword to associate with the
1232
 *                       output processor
1233
 *            type => alert or log types
1234
 *            *func => function pointer to the handler
1235
 *
1236
 * Returns: void function
1237
 *
1238
 ***************************************************************************/
1239
void RegisterOutputPlugin(char *keyword, int type, OutputInitFunc func)
1240
{
1241
    OutputKeywordList *idx;
1242
1243
    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:output => %s:%p\n", 
1244
                keyword, func););
1245
1246
    idx = OutputKeywords;
1247
1248
    if(idx == NULL)
1249
    {
1250
        /* alloc the node */
1251
        OutputKeywords = (OutputKeywordList *)SnortAlloc(sizeof(OutputKeywordList));
1252
1253
        idx = OutputKeywords;
1254
    }
1255
    else
1256
    {
1257
        /* loop to the end of the list */
1258
        while(idx->next != NULL)
1259
        {
1260
            if(!strcasecmp(idx->entry.keyword, keyword))
1261
            {
1262
                FatalError("%s(%d) => Duplicate output keyword!\n", 
1263
                        file_name, file_line);
1264
            }
1265
            idx = idx->next;
1266
        }
1267
1268
        idx->next = (OutputKeywordList *)SnortAlloc(sizeof(OutputKeywordList));
1269
1270
        idx = idx->next;
1271
    }
1272
1273
    /* alloc space for the keyword */
1274
    idx->entry.keyword = (char *)SnortAlloc((strlen(keyword) + 1) * sizeof(char));
1275
1276
    /* copy the keyword into the struct */
1277
    SnortStrncpy(idx->entry.keyword, keyword, strlen(keyword) + 1);
1278
1279
    /*
1280
     * set the plugin type, needed to determine whether an overriding command
1281
     * line arg has been specified
1282
     */
1283
    idx->entry.node_type = (char) type;
1284
1285
    /* set the function pointer to the keyword handler function */
1286
    idx->entry.func = func;
1287
}
1288
1289
1290
/****************************************************************************
1291
 *
1292
 * Function: DumpOutputPlugins()
1293
 *
1294
 * Purpose:  Prints the keyword->preprocess list
1295
 *
1296
 * Arguments: None.
1297
 *
1298
 * Returns: void function
1299
 *
1300
 ***************************************************************************/
1301
void DumpOutputPlugins()
1302
{
1303
    OutputKeywordList *idx;
1304
1305
    if(pv.quiet_flag)
1306
        return;
1307
1308
    idx = OutputKeywords;
1309
1310
    LogMessage("-------------------------------------------------\n");
1311
    LogMessage(" Keyword     |          Output @ \n");
1312
    LogMessage("-------------------------------------------------\n");
1313
    while(idx != NULL)
1314
    {
1315
        LogMessage("%-13s:       %p\n", idx->entry.keyword, idx->entry.func);
1316
        idx = idx->next;
1317
    }
1318
    LogMessage("-------------------------------------------------\n\n");
1319
}
1320
1321
extern ListHead *head_tmp;
1322
1323
void AddFuncToOutputList(void (*func) (Packet *, char *, void *, Event *),
1324
        char node_type, void *arg)
1325
{
1326
    switch(node_type)
1327
    {
1328
        case NT_OUTPUT_ALERT:
1329
            if(head_tmp != NULL)
1330
                head_tmp->AlertList = AppendOutputFuncList(func, arg,
1331
                        head_tmp->AlertList);
1332
            else
1333
                AlertList = AppendOutputFuncList(func, arg, AlertList);
1334
            break;
1335
1336
        case NT_OUTPUT_LOG:
1337
            if(head_tmp != NULL)
1338
                head_tmp->LogList = AppendOutputFuncList(func, arg,
1339
                        head_tmp->LogList);
1340
            else
1341
                LogList = AppendOutputFuncList(func, arg, LogList);
1342
            break;
1343
1344
        default:
1345
            /* just to be error-prone */
1346
            FatalError("Unknown nodetype: %i. Possible bug, please report\n",
1347
                    node_type);
1348
    }
1349
1350
    return;
1351
}
1352
1353
1354
OutputFuncNode *AppendOutputFuncList(
1355
        void (*func) (Packet *, char *, void *, Event *),
1356
        void *arg, OutputFuncNode * list)
1357
{
1358
    OutputFuncNode *idx = list;
1359
1360
    if(idx == NULL)
1361
    {
1362
        idx = (OutputFuncNode *)SnortAlloc(sizeof(OutputFuncNode));
1363
        idx->func = func;
1364
        idx->arg = arg;
1365
        list = idx;
1366
    }
1367
    else
1368
    {
1369
        while(idx->next != NULL)
1370
            idx = idx->next;
1371
1372
        idx->next = (OutputFuncNode *)SnortAlloc(sizeof(OutputFuncNode));
1373
        idx = idx->next;
1374
        idx->func = func;
1375
        idx->arg = arg;
1376
    }
1377
1378
    idx->next = NULL;
1379
1380
    return list;
1381
}
1382
1383
/*
1384
 * frees the existing OutputList ands sets it a single node for the
1385
 * function argument
1386
 */
1387
void SetOutputList(void (*func) (Packet *, char *, void *, Event *),
1388
        char node_type, void *arg)
1389
{
1390
    OutputFuncNode *idx;
1391
    OutputFuncNode *prev;
1392
1393
    switch(node_type)
1394
    {
1395
        case NT_OUTPUT_ALERT:
1396
            prev = AlertList;
1397
            break;
1398
1399
        case NT_OUTPUT_LOG:
1400
            prev = LogList;
1401
            break;
1402
1403
        default:
1404
            return;
1405
    }
1406
1407
    while(prev != NULL)
1408
    {
1409
        idx = prev->next;
1410
        free(prev);
1411
        prev = idx;
1412
    }
1413
1414
    switch(node_type)
1415
    {
1416
        case NT_OUTPUT_ALERT:
1417
            AlertList = prev;
1418
            break;
1419
1420
        case NT_OUTPUT_LOG:
1421
            LogList = prev;
1422
            break;
1423
1424
        default:
1425
            return;
1426
    }
1427
1428
    AddFuncToOutputList(func, node_type, arg);
1429
1430
    return;
1431
}
1432
1433
1434
1435
/*************************** End Output Plugin API  ***************************/
1436
1437
1438
/************************** Miscellaneous Functions  **************************/
1439
1440
int PacketIsIP(Packet * p)
1441
{
1442
    if(IPH_IS_VALID(p))
1443
        return 1;
1444
1445
    return 0;
1446
}
1447
1448
1449
1450
int PacketIsTCP(Packet * p)
1451
{
1452
    if(IPH_IS_VALID(p) && p->tcph != NULL)
1453
        return 1;
1454
1455
    return 0;
1456
}
1457
1458
1459
1460
int PacketIsUDP(Packet * p)
1461
{
1462
    if(IPH_IS_VALID(p) && p->udph != NULL)
1463
        return 1;
1464
1465
    return 0;
1466
}
1467
1468
1469
1470
int PacketIsICMP(Packet * p)
1471
{
1472
    if(IPH_IS_VALID(p) && p->icmph != NULL)
1473
        return 1;
1474
1475
    return 0;
1476
}
1477
1478
1479
1480
int DestinationIpIsHomenet(Packet * p)
1481
{
1482
#ifdef SUP_IP6
1483
    if(sfip_contains(&pv.homenet, GET_DST_IP(p)) == SFIP_CONTAINS)
1484
#else
1485
    if((p->iph->ip_dst.s_addr & pv.netmask) == pv.homenet)
1486
#endif
1487
    {
1488
        return 1;
1489
    }
1490
    return 0;
1491
}
1492
1493
1494
1495
int SourceIpIsHomenet(Packet * p)
1496
{
1497
#ifdef SUP_IP6
1498
    if(sfip_contains(&pv.homenet, GET_SRC_IP(p)) == SFIP_CONTAINS)
1499
#else
1500
    if((p->iph->ip_src.s_addr & pv.netmask) == pv.homenet)
1501
#endif
1502
    {
1503
        return 1;
1504
    }
1505
    return 0;
1506
}
1507
1508
int CheckNet(struct in_addr * compare, struct in_addr * compare2)
1509
{
1510
    if(compare->s_addr == compare2->s_addr)
1511
    {
1512
        return 1;
1513
    }
1514
    return 0;
1515
}
1516
1517
/* functions to aid in cleaning up after plugins */
1518
void AddFuncToRestartList(void (*func) (int, void *), void *arg)
1519
{
1520
    PluginRestartList = AddFuncToSignalList(func, arg, PluginRestartList);
1521
}
1522
1523
void AddFuncToCleanExitList(void (*func) (int, void *), void *arg)
1524
{
1525
    PluginCleanExitList = AddFuncToSignalList(func, arg, PluginCleanExitList);
1526
}
1527
1528
void AddFuncToShutdownList(void (*func) (int, void *), void *arg)
1529
{
1530
    PluginShutdownList = AddFuncToSignalList(func, arg, PluginShutdownList);
1531
}
1532
1533
void AddFuncToPostConfigList(void (*func)(int, void *), void *arg)
1534
{
1535
    PluginPostConfigList = AddFuncToSignalList(func, arg, PluginPostConfigList);
1536
}
1537
1538
PluginSignalFuncNode *AddFuncToSignalList(void (*func) (int, void *), void *arg,
1539
                                          PluginSignalFuncNode * list)
1540
{
1541
    PluginSignalFuncNode *idx;
1542
1543
    idx = list;
1544
1545
    if(idx == NULL)
1546
    {
1547
        idx = (PluginSignalFuncNode *)SnortAlloc(sizeof(PluginSignalFuncNode));
1548
1549
        idx->func = func;
1550
        idx->arg = arg;
1551
        list = idx;
1552
    }
1553
    else
1554
    {
1555
        while(idx->next != NULL)
1556
            idx = idx->next;
1557
1558
        idx->next = (PluginSignalFuncNode *)SnortAlloc(sizeof(PluginSignalFuncNode));
1559
1560
        idx = idx->next;
1561
        idx->func = func;
1562
        idx->arg = arg;
1563
    }
1564
    idx->next = NULL;
1565
1566
    return list;
1567
}
1568
1569
1570
/****************************************************************************
1571
 *
1572
 * Function: GetUniqueName(char * iface)
1573
 *
1574
 * Purpose: To return a string that has a high probability of being unique
1575
 *          for a given sensor.
1576
 *
1577
 * Arguments: char * iface - The network interface you are sniffing
1578
 *
1579
 * Returns: A char * -- its a static char * so you should not free it
1580
 *
1581
 ***************************************************************************/
1582
char *GetUniqueName(char * iface)
1583
{
1584
    char * rptr;
1585
    static char uniq_name[256];
1586
1587
    if (iface == NULL) LogMessage("Interface is NULL. Name may not be unique for the host\n");
1588
#ifndef WIN32
1589
    rptr = GetIP(iface); 
1590
    if(rptr == NULL || !strcmp(rptr, "unknown"))
1591
#endif
1592
    {
1593
        SnortSnprintf(uniq_name, 255, "%s:%s\n",GetHostname(),iface);
1594
        rptr = uniq_name; 
1595
    }
1596
    if (pv.verbose_flag) LogMessage("Node unique name is: %s\n", rptr);
1597
    return rptr;
1598
}    
1599
1600
/****************************************************************************
1601
 *
1602
 * Function: GetIP(char * iface)
1603
 *
1604
 * Purpose: To return a string representing the IP address for an interface
1605
 *
1606
 * Arguments: char * iface - The network interface you want to find an IP
1607
 *            address for.
1608
 *
1609
 * Returns: A char * -- make sure you call free on this when you are done
1610
 *          with it.
1611
 *
1612
 ***************************************************************************/
1613
char *GetIP(char * iface)
1614
{
1615
    struct ifreq ifr;
1616
    struct sockaddr_in *addr;
1617
    int s;
1618
#ifdef SUP_IP6
1619
    sfip_t ret;
1620
#endif
1621
1622
    if(iface)
1623
    {
1624
        /* Set up a dummy socket just so we can use ioctl to find the
1625
           ip address of the interface */
1626
        s = socket(PF_INET, SOCK_DGRAM, 0);
1627
        if(s == -1)
1628
        {
1629
            FatalError("Problem establishing socket to find IP address for interface: %s\n", iface);
1630
        }
1631
1632
        SnortStrncpy(ifr.ifr_name, iface, strlen(iface) + 1);
1633
1634
#ifndef WIN32
1635
        if(ioctl(s, SIOCGIFADDR, &ifr) < 0) return NULL;
1636
        else
1637
#endif
1638
        {
1639
            addr = (struct sockaddr_in *) &ifr.ifr_broadaddr;
1640
        }
1641
        close(s);
1642
1643
#ifdef SUP_IP6
1644
// XXX-IPv6 uses ioctl to populate a sockaddr_in structure ... but what if the interface only has an IPv6 address?
1645
        sfip_set_raw(&ret, addr, AF_INET); 
1646
        return SnortStrdup(sfip_ntoa(&ret));
1647
#else
1648
        return SnortStrdup(inet_ntoa(addr->sin_addr));
1649
#endif
1650
    }
1651
    else
1652
    {
1653
        return "unknown";
1654
    }
1655
}
1656
1657
/****************************************************************************
1658
 *
1659
 * Function: GetHostname()
1660
 *
1661
 * Purpose: To return a string representing the hostname
1662
 *
1663
 * Arguments: None
1664
 *
1665
 * Returns: A static char * representing the hostname. 
1666
 *
1667
 ***************************************************************************/
1668
char *GetHostname()
1669
{
1670
#ifdef WIN32
1671
    DWORD bufflen = 256;
1672
    static char buff[256];
1673
    GetComputerName(buff, &bufflen);
1674
    return buff;
1675
#else
1676
    char * error = "unknown";
1677
    if(getenv("HOSTNAME")) return getenv("HOSTNAME");
1678
    else if(getenv("HOST")) return getenv("HOST");
1679
    else return error;
1680
#endif
1681
}
1682
1683
/****************************************************************************
1684
 *
1685
 * Function: GetTimestamp(register const struct timeval *tvp, int tz)
1686
 *
1687
 * Purpose: Get an ISO-8601 formatted timestamp for tvp within the tz
1688
 *          timezone. 
1689
 *
1690
 * Arguments: tvp is a timeval pointer. tz is a timezone. 
1691
 *
1692
 * Returns: char * -- You must free this char * when you are done with it.
1693
 *
1694
 ***************************************************************************/
1695
char *GetTimestamp(register const struct timeval *tvp, int tz)
1696
{
1697
    struct tm *lt;  /* localtime */
1698
    char * buf;
1699
    int msec;
1700
1701
    buf = (char *)SnortAlloc(SMALLBUFFER * sizeof(char));
1702
1703
    msec = tvp->tv_usec / 1000;
1704
1705
    if(pv.use_utc == 1)
1706
    {
1707
        lt = gmtime((time_t *)&tvp->tv_sec);
1708
        SnortSnprintf(buf, SMALLBUFFER, "%04i-%02i-%02i %02i:%02i:%02i.%03i",
1709
                1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
1710
                lt->tm_hour, lt->tm_min, lt->tm_sec, msec);
1711
    }
1712
    else
1713
    {
1714
        lt = localtime((time_t *)&tvp->tv_sec);
1715
        SnortSnprintf(buf, SMALLBUFFER,
1716
                "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i",
1717
                1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
1718
                lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tz);
1719
    }
1720
1721
    return buf;
1722
}
1723
1724
/****************************************************************************
1725
 *
1726
 * Function: GetLocalTimezone()
1727
 *
1728
 * Purpose: Find the offset from GMT for current host
1729
 *
1730
 * Arguments: none 
1731
 *
1732
 * Returns: int representing the offset from GMT
1733
 *
1734
 ***************************************************************************/
1735
int GetLocalTimezone()
1736
{
1737
    time_t      ut;
1738
    struct tm * ltm;
1739
    long        seconds_away_from_utc;
1740
1741
    time(&ut);
1742
    ltm = localtime(&ut);
1743
1744
#if defined(WIN32) || defined(SOLARIS) || defined(AIX)
1745
    /* localtime() sets the global timezone variable,
1746
       which is defined in <time.h> */
1747
    seconds_away_from_utc = timezone;
1748
#else
1749
    seconds_away_from_utc = ltm->tm_gmtoff;
1750
#endif
1751
1752
    return  seconds_away_from_utc/3600;
1753
}
1754
1755
/****************************************************************************
1756
 *
1757
 * Function: GetCurrentTimestamp()
1758
 *
1759
 * Purpose: Generate an ISO-8601 formatted timestamp for the current time.
1760
 *
1761
 * Arguments: none 
1762
 *
1763
 * Returns: char * -- You must free this char * when you are done with it.
1764
 *
1765
 ***************************************************************************/
1766
char *GetCurrentTimestamp()
1767
{
1768
    struct tm *lt;
1769
    struct timezone tz;
1770
    struct timeval tv;
1771
    struct timeval *tvp;
1772
    char * buf;
1773
    int tzone;
1774
    int msec;
1775
1776
    buf = (char *)SnortAlloc(SMALLBUFFER * sizeof(char));
1777
1778
    bzero((char *)&tz,sizeof(tz));
1779
    gettimeofday(&tv,&tz);
1780
    tvp = &tv;
1781
1782
    msec = tvp->tv_usec/1000;
1783
1784
    if(pv.use_utc == 1)
1785
    {
1786
        lt = gmtime((time_t *)&tvp->tv_sec);
1787
        SnortSnprintf(buf, SMALLBUFFER, "%04i-%02i-%02i %02i:%02i:%02i.%03i",
1788
                1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
1789
                lt->tm_hour, lt->tm_min, lt->tm_sec, msec);
1790
    }
1791
    else
1792
    {
1793
        lt = localtime((time_t *)&tvp->tv_sec);
1794
1795
        tzone = GetLocalTimezone();
1796
1797
        SnortSnprintf(buf, SMALLBUFFER,
1798
                "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i",
1799
                1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
1800
                lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tzone);
1801
    }
1802
1803
    return buf;
1804
}
1805
1806
/****************************************************************************
1807
 * Function: base64(char * xdata, int length)
1808
 *
1809
 * Purpose: Insert data into the database
1810
 *
1811
 * Arguments: xdata  => pointer to data to base64 encode
1812
 *            length => how much data to encode 
1813
 *
1814
 * Make sure you allocate memory for the output before you pass
1815
 * the output pointer into this function. You should allocate 
1816
 * (1.5 * length) bytes to be safe.
1817
 *
1818
 * Returns: data base64 encoded as a char *
1819
 *
1820
 ***************************************************************************/
1821
char * base64(const u_char * xdata, int length)
1822
{
1823
    int count, cols, bits, c, char_count;
1824
    unsigned char alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  /* 64 bytes */
1825
    char * payloadptr;
1826
    char * output;
1827
    char_count = 0;
1828
    bits = 0;
1829
    cols = 0;
1830
1831
    output = (char *)SnortAlloc( ((unsigned int) (length * 1.5 + 4)) * sizeof(char) );
1832
1833
    payloadptr = output;
1834
1835
    for(count = 0; count < length; count++)
1836
    {
1837
        c = xdata[count];
1838
1839
        if(c > 255)
1840
        {
1841
            ErrorMessage("plugbase.c->base64(): encountered char > 255 (decimal %d)\n If you see this error message a char is more than one byte on your machine\n This means your base64 results can not be trusted", c);
1842
        }
1843
1844
        bits += c;
1845
        char_count++;
1846
1847
        if(char_count == 3)
1848
        {
1849
            *output = alpha[bits >> 18]; output++;
1850
            *output = alpha[(bits >> 12) & 0x3f]; output++;
1851
            *output = alpha[(bits >> 6) & 0x3f]; output++;
1852
            *output = alpha[bits & 0x3f]; output++; 
1853
            cols += 4;
1854
            if(cols == 72)
1855
            {
1856
                *output = '\n'; output++;
1857
                cols = 0;
1858
            }
1859
            bits = 0;
1860
            char_count = 0;
1861
        }
1862
        else
1863
        {
1864
            bits <<= 8;
1865
        }
1866
    }
1867
1868
    if(char_count != 0)
1869
    {
1870
        bits <<= 16 - (8 * char_count);
1871
        *output = alpha[bits >> 18]; output++;
1872
        *output = alpha[(bits >> 12) & 0x3f]; output++;
1873
        if(char_count == 1)
1874
        {
1875
            *output = '='; output++;
1876
            *output = '='; output++;
1877
        }
1878
        else
1879
        {
1880
            *output = alpha[(bits >> 6) & 0x3f]; 
1881
            output++; *output = '='; 
1882
            output++;
1883
        }
1884
    }
1885
    *output = '\0';
1886
    return payloadptr;
1887
} 
1888
1889
/****************************************************************************
1890
 *
1891
 * Function: ascii(u_char *xdata, int length)
1892
 *
1893
 * Purpose: This function takes takes a buffer "xdata" and its length then
1894
 *          returns a string of only the printible ASCII characters.
1895
 *
1896
 * Arguments: xdata is the buffer, length is the length of the buffer in
1897
 *            bytes
1898
 *
1899
 * Returns: char * -- You must free this char * when you are done with it.
1900
 *
1901
 ***************************************************************************/
1902
char *ascii(const u_char *xdata, int length)
1903
{
1904
     char *d_ptr, *ret_val;
1905
     int i,count = 0;
1906
     int size;
1907
     
1908
     if(xdata == NULL)
1909
     {
1910
         return NULL;         
1911
     }
1912
     
1913
     for(i=0;i<length;i++)
1914
     {
1915
         if(xdata[i] == '<')
1916
             count+=4;              /* &lt; */
1917
         else if(xdata[i] == '&')
1918
             count+=5;              /* &amp; */
1919
         else if(xdata[i] == '>')   /* &gt;  */
1920
             count += 4;
1921
     }
1922
1923
     size = length + count + 1;
1924
     ret_val = (char *) calloc(1,size);
1925
     
1926
     if(ret_val == NULL)
1927
     {
1928
         LogMessage("plugbase.c: ascii(): Out of memory, can't log anything!\n");
1929
         return NULL;
1930
     }
1931
     
1932
     d_ptr = ret_val; 
1933
     
1934
     for(i=0;i<length;i++)
1935
     {
1936
         if((xdata[i] > 0x1F) && (xdata[i] < 0x7F))
1937
         {
1938
             if(xdata[i] == '<')
1939
             {
1940
                 SnortStrncpy(d_ptr, "&lt;", size - (d_ptr - ret_val));
1941
                 d_ptr+=4;
1942
             }
1943
             else if(xdata[i] == '&')
1944
             {
1945
                 SnortStrncpy(d_ptr, "&amp;", size - (d_ptr - ret_val));
1946
                 d_ptr += 5;
1947
             }
1948
             else if(xdata[i] == '>')
1949
             {
1950
                 SnortStrncpy(d_ptr, "&gt;", size - (d_ptr - ret_val));
1951
                 d_ptr += 4;
1952
             }
1953
             else
1954
             {
1955
                 *d_ptr++ = xdata[i];
1956
             }
1957
         }
1958
         else
1959
         {
1960
             *d_ptr++ = '.';
1961
         }        
1962
     }
1963
     
1964
     *d_ptr++ = '\0';
1965
     
1966
     return ret_val;
1967
}
1968
1969
/****************************************************************************
1970
 *
1971
 * Function: hex(u_char *xdata, int length)
1972
 *
1973
 * Purpose: This function takes takes a buffer "xdata" and its length then
1974
 *          returns a string of hex with no spaces
1975
 *
1976
 * Arguments: xdata is the buffer, length is the length of the buffer in
1977
 *            bytes
1978
 *
1979
 * Returns: char * -- You must free this char * when you are done with it.
1980
 *
1981
 ***************************************************************************/
1982
char *hex(const u_char *xdata, int length)
1983
{
1984
    int x;
1985
    char *rval = NULL;
1986
    char *buf = NULL;
1987
1988
    if (xdata == NULL)
1989
        return NULL;
1990
1991
    buf = (char *)calloc((length * 2) + 1, sizeof(char));
1992
1993
    if (buf != NULL)
1994
    {
1995
        rval = buf;
1996
1997
        for (x = 0; x < length; x++)
1998
        {
1999
            SnortSnprintf(buf, 3, "%02X", xdata[x]);
2000
            buf += 2;
2001
        } 
2002
2003
        rval[length * 2] = '\0';
2004
    }
2005
2006
    return rval;
2007
}
2008
2009
2010
2011
char *fasthex(const u_char *xdata, int length)
2012
{
2013
    char conv[] = "0123456789ABCDEF";
2014
    char *retbuf = NULL; 
2015
    const u_char *index;
2016
    const u_char *end;
2017
    char *ridx;
2018
2019
    index = xdata;
2020
    end = xdata + length;
2021
    retbuf = (char *)SnortAlloc(((length * 2) + 1) * sizeof(char));
2022
    ridx = retbuf;
2023
2024
    while(index < end)
2025
    {
2026
        *ridx++ = conv[((*index & 0xFF)>>4)];
2027
        *ridx++ = conv[((*index & 0xFF)&0x0F)];
2028
        index++;
2029
    }
2030
2031
    return retbuf;
2032
}
2033
(-)snort-2.8.3.1/src/plugin_enum.h (+1 lines)
Lines 60-65 Link Here
60
    PLUGIN_URILEN_CHECK,
60
    PLUGIN_URILEN_CHECK,
61
    PLUGIN_DYNAMIC,
61
    PLUGIN_DYNAMIC,
62
    PLUGIN_FLOWBIT,
62
    PLUGIN_FLOWBIT,
63
    PLUGIN_FWSAM, 
63
    PLUGIN_MAX  /* sentinel value */
64
    PLUGIN_MAX  /* sentinel value */
64
};
65
};
65
66
(-)snort-2.8.3.1/src/plugin_enum.h.orig (+67 lines)
Line 0 Link Here
1
/* $Id$ */
2
/****************************************************************************
3
 *
4
 * Copyright (C) 2003-2008 Sourcefire, Inc.
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License Version 2 as
8
 * published by the Free Software Foundation.  You may not use, modify or
9
 * distribute this program under any other version of the GNU General
10
 * Public License.
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
/* 
24
  Purpose: Enumerate all the various detection plugins entries for
25
           otn->ds_list[]
26
27
  No more grepping to make your own plugin!
28
*/
29
30
#ifndef _PLUGIN_ENUM_H
31
#define _PLUGIN_ENUM_H
32
33
enum {
34
    PLUGIN_CLIENTSERVER,
35
    PLUGIN_DSIZE_CHECK,
36
    PLUGIN_FRAG_BITS,
37
    PLUGIN_FRAG_OFFSET,
38
    PLUGIN_ICMP_CODE,
39
    PLUGIN_ICMP_ID_CHECK,
40
    PLUGIN_ICMP_SEQ_CHECK,
41
    PLUGIN_ICMP_TYPE,
42
    PLUGIN_IPOPTION_CHECK,
43
    PLUGIN_IP_ID_CHECK,
44
    PLUGIN_IP_PROTO_CHECK,
45
    PLUGIN_IP_SAME_CHECK,
46
    PLUGIN_IP_TOS_CHECK,
47
    PLUGIN_PATTERN_MATCH, /* AND match */
48
    PLUGIN_PATTERN_MATCH_OR, 
49
    PLUGIN_PATTERN_MATCH_URI,
50
    PLUGIN_RESPOND,
51
    PLUGIN_RPC_CHECK,
52
    PLUGIN_SESSION,
53
    PLUGIN_TCP_ACK_CHECK,
54
    PLUGIN_TCP_FLAG_CHECK,
55
    PLUGIN_TCP_SEQ_CHECK,
56
    PLUGIN_TCP_WIN_CHECK,
57
    PLUGIN_TTL_CHECK,
58
    PLUGIN_BYTE_TEST,
59
    PLUGIN_PCRE,
60
    PLUGIN_URILEN_CHECK,
61
    PLUGIN_DYNAMIC,
62
    PLUGIN_FLOWBIT,
63
    PLUGIN_MAX  /* sentinel value */
64
};
65
66
#endif /* _PLUGIN_ENUM_H */
67
(-)snort-2.8.3.1/src/twofish.c (+946 lines)
Line 0 Link Here
1
/* $Id: snortpatchb,v 1.5 2005/10/06 08:50:39 fknobbe Exp $
2
 *
3
 *
4
 * Copyright (C) 1997-2000 The Cryptix Foundation Limited.
5
 * Copyright (C) 2000 Farm9.
6
 * Copyright (C) 2001 Frank Knobbe.
7
 * All rights reserved.
8
 *
9
 * For Cryptix code:
10
 * Use, modification, copying and distribution of this software is subject
11
 * the terms and conditions of the Cryptix General Licence. You should have
12
 * received a copy of the Cryptix General Licence along with this library;
13
 * if not, you can download a copy from http://www.cryptix.org/ .
14
 *
15
 * For Farm9:
16
 * ---  jojo@farm9.com, August 2000, converted from Java to C++, added CBC mode and
17
 *      ciphertext stealing technique, added AsciiTwofish class for easy encryption
18
 *      decryption of text strings
19
 *
20
 * Frank Knobbe <frank@knobbe.us>:
21
 * ---  April 2001, converted from C++ to C, prefixed global variables
22
 *      with TwoFish, substituted some defines, changed functions to make use of
23
 *      variables supplied in a struct, modified and added routines for modular calls.
24
 *      Cleaned up the code so that defines are used instead of fixed 16's and 32's.
25
 *      Created two general purpose crypt routines for one block and multiple block
26
 *      encryption using Joh's CBC code.
27
 *		Added crypt routines that use a header (with a magic and data length).
28
 *		(Basically a major rewrite).
29
 *
30
 *      Note: Routines labeled _TwoFish are private and should not be used 
31
 *      (or with extreme caution).
32
 *
33
 */
34
35
#ifndef __TWOFISH_LIBRARY_SOURCE__
36
#define __TWOFISH_LIBRARY_SOURCE__
37
38
#include <string.h>
39
#include <stdlib.h>
40
#include <time.h>
41
#include <ctype.h>
42
#include "twofish.h"
43
44
45
bool TwoFish_srand=TRUE;				/* if TRUE, first call of TwoFishInit will seed rand(); */
46
										/* of TwoFishInit */
47
48
/* Fixed 8x8 permutation S-boxes */
49
static const unsigned char TwoFish_P[2][256] =		
50
{
51
    {  /* p0 */
52
        0xA9, 0x67, 0xB3, 0xE8,   0x04, 0xFD, 0xA3, 0x76,   0x9A, 0x92, 0x80, 0x78,
53
        0xE4, 0xDD, 0xD1, 0x38,   0x0D, 0xC6, 0x35, 0x98,   0x18, 0xF7, 0xEC, 0x6C,
54
        0x43, 0x75, 0x37, 0x26,   0xFA, 0x13, 0x94, 0x48,   0xF2, 0xD0, 0x8B, 0x30,
55
        0x84, 0x54, 0xDF, 0x23,   0x19, 0x5B, 0x3D, 0x59,   0xF3, 0xAE, 0xA2, 0x82,
56
        0x63, 0x01, 0x83, 0x2E,   0xD9, 0x51, 0x9B, 0x7C,   0xA6, 0xEB, 0xA5, 0xBE,
57
        0x16, 0x0C, 0xE3, 0x61,   0xC0, 0x8C, 0x3A, 0xF5,   0x73, 0x2C, 0x25, 0x0B,
58
        0xBB, 0x4E, 0x89, 0x6B,   0x53, 0x6A, 0xB4, 0xF1,   0xE1, 0xE6, 0xBD, 0x45,
59
        0xE2, 0xF4, 0xB6, 0x66,   0xCC, 0x95, 0x03, 0x56,   0xD4, 0x1C, 0x1E, 0xD7,
60
        0xFB, 0xC3, 0x8E, 0xB5,   0xE9, 0xCF, 0xBF, 0xBA,   0xEA, 0x77, 0x39, 0xAF,
61
        0x33, 0xC9, 0x62, 0x71,   0x81, 0x79, 0x09, 0xAD,   0x24, 0xCD, 0xF9, 0xD8,
62
        0xE5, 0xC5, 0xB9, 0x4D,   0x44, 0x08, 0x86, 0xE7,   0xA1, 0x1D, 0xAA, 0xED,
63
        0x06, 0x70, 0xB2, 0xD2,   0x41, 0x7B, 0xA0, 0x11,   0x31, 0xC2, 0x27, 0x90,
64
        0x20, 0xF6, 0x60, 0xFF,   0x96, 0x5C, 0xB1, 0xAB,   0x9E, 0x9C, 0x52, 0x1B,
65
        0x5F, 0x93, 0x0A, 0xEF,   0x91, 0x85, 0x49, 0xEE,   0x2D, 0x4F, 0x8F, 0x3B,
66
        0x47, 0x87, 0x6D, 0x46,   0xD6, 0x3E, 0x69, 0x64,   0x2A, 0xCE, 0xCB, 0x2F,
67
        0xFC, 0x97, 0x05, 0x7A,   0xAC, 0x7F, 0xD5, 0x1A,   0x4B, 0x0E, 0xA7, 0x5A,
68
        0x28, 0x14, 0x3F, 0x29,   0x88, 0x3C, 0x4C, 0x02,   0xB8, 0xDA, 0xB0, 0x17,
69
        0x55, 0x1F, 0x8A, 0x7D,   0x57, 0xC7, 0x8D, 0x74,   0xB7, 0xC4, 0x9F, 0x72,
70
        0x7E, 0x15, 0x22, 0x12,   0x58, 0x07, 0x99, 0x34,   0x6E, 0x50, 0xDE, 0x68,
71
        0x65, 0xBC, 0xDB, 0xF8,   0xC8, 0xA8, 0x2B, 0x40,   0xDC, 0xFE, 0x32, 0xA4,
72
        0xCA, 0x10, 0x21, 0xF0,   0xD3, 0x5D, 0x0F, 0x00,   0x6F, 0x9D, 0x36, 0x42,
73
        0x4A, 0x5E, 0xC1, 0xE0
74
    },
75
    {  /* p1 */
76
        0x75, 0xF3, 0xC6, 0xF4,   0xDB, 0x7B, 0xFB, 0xC8,   0x4A, 0xD3, 0xE6, 0x6B,
77
        0x45, 0x7D, 0xE8, 0x4B,   0xD6, 0x32, 0xD8, 0xFD,   0x37, 0x71, 0xF1, 0xE1,
78
        0x30, 0x0F, 0xF8, 0x1B,   0x87, 0xFA, 0x06, 0x3F,   0x5E, 0xBA, 0xAE, 0x5B,
79
        0x8A, 0x00, 0xBC, 0x9D,   0x6D, 0xC1, 0xB1, 0x0E,   0x80, 0x5D, 0xD2, 0xD5,
80
        0xA0, 0x84, 0x07, 0x14,   0xB5, 0x90, 0x2C, 0xA3,   0xB2, 0x73, 0x4C, 0x54,
81
        0x92, 0x74, 0x36, 0x51,   0x38, 0xB0, 0xBD, 0x5A,   0xFC, 0x60, 0x62, 0x96,
82
        0x6C, 0x42, 0xF7, 0x10,   0x7C, 0x28, 0x27, 0x8C,   0x13, 0x95, 0x9C, 0xC7,
83
        0x24, 0x46, 0x3B, 0x70,   0xCA, 0xE3, 0x85, 0xCB,   0x11, 0xD0, 0x93, 0xB8,
84
        0xA6, 0x83, 0x20, 0xFF,   0x9F, 0x77, 0xC3, 0xCC,   0x03, 0x6F, 0x08, 0xBF, 
85
		0x40, 0xE7, 0x2B, 0xE2,   0x79, 0x0C, 0xAA, 0x82,   0x41, 0x3A, 0xEA, 0xB9,
86
        0xE4, 0x9A, 0xA4, 0x97,   0x7E, 0xDA, 0x7A, 0x17,   0x66, 0x94, 0xA1, 0x1D,
87
        0x3D, 0xF0, 0xDE, 0xB3,   0x0B, 0x72, 0xA7, 0x1C,   0xEF, 0xD1, 0x53, 0x3E,
88
        0x8F, 0x33, 0x26, 0x5F,   0xEC, 0x76, 0x2A, 0x49,   0x81, 0x88, 0xEE, 0x21,
89
        0xC4, 0x1A, 0xEB, 0xD9,   0xC5, 0x39, 0x99, 0xCD,   0xAD, 0x31, 0x8B, 0x01,
90
        0x18, 0x23, 0xDD, 0x1F,   0x4E, 0x2D, 0xF9, 0x48,   0x4F, 0xF2, 0x65, 0x8E,
91
        0x78, 0x5C, 0x58, 0x19,   0x8D, 0xE5, 0x98, 0x57,   0x67, 0x7F, 0x05, 0x64,
92
        0xAF, 0x63, 0xB6, 0xFE,   0xF5, 0xB7, 0x3C, 0xA5,   0xCE, 0xE9, 0x68, 0x44,
93
        0xE0, 0x4D, 0x43, 0x69,   0x29, 0x2E, 0xAC, 0x15,   0x59, 0xA8, 0x0A, 0x9E,
94
        0x6E, 0x47, 0xDF, 0x34,   0x35, 0x6A, 0xCF, 0xDC,   0x22, 0xC9, 0xC0, 0x9B,
95
        0x89, 0xD4, 0xED, 0xAB,   0x12, 0xA2, 0x0D, 0x52,   0xBB, 0x02, 0x2F, 0xA9,
96
        0xD7, 0x61, 0x1E, 0xB4,   0x50, 0x04, 0xF6, 0xC2,   0x16, 0x25, 0x86, 0x56,
97
        0x55, 0x09, 0xBE, 0x91
98
    }
99
};
100
101
static bool TwoFish_MDSready=FALSE;
102
static unsigned long TwoFish_MDS[4][256]; /* TwoFish_MDS matrix */
103
104
105
#define	TwoFish_LFSR1(x) (((x)>>1)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/2:0))
106
#define	TwoFish_LFSR2(x) (((x)>>2)^(((x)&0x02)?TwoFish_MDS_GF_FDBK/2:0)^(((x)&0x01)?TwoFish_MDS_GF_FDBK/4:0))
107
108
#define	TwoFish_Mx_1(x) ((unsigned long)(x))		/* force result to dword so << will work  */
109
#define	TwoFish_Mx_X(x) ((unsigned long)((x)^TwoFish_LFSR2(x)))	/* 5B */
110
#define	TwoFish_Mx_Y(x) ((unsigned long)((x)^TwoFish_LFSR1(x)^TwoFish_LFSR2(x)))	/* EF  */
111
#define	TwoFish_RS_rem(x) { unsigned char b=(unsigned char)(x>>24); unsigned long g2=((b<<1)^((b&0x80)?TwoFish_RS_GF_FDBK:0))&0xFF; unsigned long g3=((b>>1)&0x7F)^((b&1)?TwoFish_RS_GF_FDBK>>1:0)^g2; x=(x<<8)^(g3<<24)^(g2<<16)^(g3<<8)^b; }
112
113
/*#define	TwoFish__b(x,N)	(((unsigned char *)&x)[((N)&3)^TwoFish_ADDR_XOR])*/ /* pick bytes out of a dword */
114
115
#define	TwoFish_b0(x)			TwoFish__b(x,0)		/* extract LSB of unsigned long  */
116
#define	TwoFish_b1(x)			TwoFish__b(x,1)
117
#define	TwoFish_b2(x)			TwoFish__b(x,2)
118
#define	TwoFish_b3(x)			TwoFish__b(x,3)		/* extract MSB of unsigned long  */
119
120
unsigned char TwoFish__b(unsigned long x,int n)
121
{	n&=3;
122
	while(n-->0)
123
		x>>=8;
124
	return (unsigned char)x;
125
}
126
127
128
/*	TwoFish Initialization
129
 *
130
 *	This routine generates a global data structure for use with TwoFish,
131
 *	initializes important values (such as subkeys, sBoxes), generates subkeys
132
 *	and precomputes the MDS matrix if not already done.
133
 *	
134
 *	Input:	User supplied password (will be appended by default password of 'SnortHas2FishEncryptionRoutines!')
135
 *
136
 *  Output:	Pointer to TWOFISH structure. This data structure contains key dependent data.
137
 *			This pointer is used with all other crypt functions.
138
 */
139
140
TWOFISH *TwoFishInit(char *userkey)
141
{   TWOFISH *tfdata;
142
	int i,x,m;
143
	char tkey[TwoFish_KEY_LENGTH+40];
144
145
	tfdata=malloc(sizeof(TWOFISH));			/* allocate the TwoFish structure */
146
	if(tfdata!=NULL)
147
	{	if(*userkey)
148
		{	strncpy(tkey,userkey,TwoFish_KEY_LENGTH);			/* use first 32 chars of user supplied password */
149
			tkey[TwoFish_KEY_LENGTH]=0;							/* make sure it wasn't more */
150
		}
151
		else
152
			strcpy(tkey,TwoFish_DEFAULT_PW);	/* if no key defined, use default password */
153
		for(i=0,x=0,m=strlen(tkey);i<TwoFish_KEY_LENGTH;i++)	/* copy into data structure */
154
		{	tfdata->key[i]=tkey[x++];							/* fill the whole keyspace with repeating key. */
155
			if(x==m)
156
				x=0;
157
		}
158
159
		if(!TwoFish_MDSready)
160
			_TwoFish_PrecomputeMDSmatrix();		/* "Wake Up, Neo" */
161
		_TwoFish_MakeSubKeys(tfdata);			/* generate subkeys */
162
		_TwoFish_ResetCBC(tfdata);				/* reset the CBC */
163
		tfdata->output=NULL;					/* nothing to output yet */
164
		tfdata->dontflush=FALSE;				/* reset decrypt skip block flag */
165
		if(TwoFish_srand)
166
		{	TwoFish_srand=FALSE;
167
			srand(time(NULL));
168
		}
169
	}
170
	return tfdata;							/* return the data pointer */
171
}
172
173
174
void TwoFishDestroy(TWOFISH *tfdata)
175
{	if(tfdata!=NULL)
176
		free(tfdata);
177
}
178
179
180
/* en/decryption with CBC mode */
181
unsigned long _TwoFish_CryptRawCBC(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata)
182
{	unsigned long rl;
183
184
	rl=len;											/* remember how much data to crypt. */
185
	while(len>TwoFish_BLOCK_SIZE)					/* and now we process block by block. */
186
	{	_TwoFish_BlockCrypt(in,out,TwoFish_BLOCK_SIZE,decrypt,tfdata); /* de/encrypt it. */
187
		in+=TwoFish_BLOCK_SIZE;						/* adjust pointers. */
188
		out+=TwoFish_BLOCK_SIZE;
189
		len-=TwoFish_BLOCK_SIZE;
190
	}
191
	if(len>0)										/* if we have less than a block left... */
192
		_TwoFish_BlockCrypt(in,out,len,decrypt,tfdata);	/* ...then we de/encrypt that too. */
193
	if(tfdata->qBlockDefined && !tfdata->dontflush)						/* in case len was exactly one block... */
194
		_TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata); /* ...we need to write the...  */
195
																		/* ...remaining bytes of the buffer */
196
	return rl;
197
}
198
199
/* en/decryption on one block only */
200
unsigned long _TwoFish_CryptRaw16(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata)
201
{	/* qBlockPlain already zero'ed through ResetCBC  */
202
	memcpy(tfdata->qBlockPlain,in,len);					/* toss the data into it. */
203
	_TwoFish_BlockCrypt16(tfdata->qBlockPlain,tfdata->qBlockCrypt,decrypt,tfdata); /* encrypt just that block without CBC. */
204
	memcpy(out,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE);				/* and return what we got */
205
	return TwoFish_BLOCK_SIZE;
206
}
207
208
/* en/decryption without reset of CBC and output assignment */
209
unsigned long _TwoFish_CryptRaw(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata)
210
{
211
	if(in!=NULL && out!=NULL && len>0 && tfdata!=NULL)		/* if we have valid data, then... */
212
	{	if(len>TwoFish_BLOCK_SIZE)							/* ...check if we have more than one block. */
213
			return _TwoFish_CryptRawCBC(in,out,len,decrypt,tfdata); /* if so, use the CBC routines... */
214
		else
215
			return _TwoFish_CryptRaw16(in,out,len,decrypt,tfdata); /* ...otherwise just do one block. */
216
	}
217
	return 0;
218
}
219
220
221
/*	TwoFish Raw Encryption
222
 *	
223
 *	Does not use header, but does use CBC (if more than one block has to be encrypted).
224
 *
225
 *	Input:	Pointer to the buffer of the plaintext to be encrypted.
226
 *			Pointer to the buffer receiving the ciphertext.
227
 *			The length of the plaintext buffer.
228
 *			The TwoFish structure.
229
 *
230
 *	Output:	The amount of bytes encrypted if successful, otherwise 0.
231
 */
232
233
unsigned long TwoFishEncryptRaw(char *in,
234
								char *out,
235
								unsigned long len,
236
								TWOFISH *tfdata)
237
{	_TwoFish_ResetCBC(tfdata);							/* reset CBC flag. */
238
	tfdata->output=out;							/* output straight into output buffer. */
239
	return _TwoFish_CryptRaw(in,out,len,FALSE,tfdata);	/* and go for it. */
240
}
241
242
/*	TwoFish Raw Decryption 
243
 *	
244
 *	Does not use header, but does use CBC (if more than one block has to be decrypted).
245
 *
246
 *	Input:	Pointer to the buffer of the ciphertext to be decrypted.
247
 *			Pointer to the buffer receiving the plaintext.
248
 *			The length of the ciphertext buffer (at least one cipher block).
249
 *			The TwoFish structure.
250
 *
251
 *	Output:	The amount of bytes decrypted if successful, otherwise 0.
252
 */
253
254
unsigned long TwoFishDecryptRaw(char *in,
255
								char *out,
256
								unsigned long len,
257
								TWOFISH *tfdata)
258
{	_TwoFish_ResetCBC(tfdata);							/* reset CBC flag. */
259
	tfdata->output=out;							/* output straight into output buffer. */
260
	return _TwoFish_CryptRaw(in,out,len,TRUE,tfdata);	/* and go for it. */
261
}
262
263
/*	TwoFish Free
264
 *
265
 *	Free's the allocated buffer.
266
 *
267
 *	Input:	Pointer to the TwoFish structure
268
 *
269
 *	Output:	(none)
270
 */
271
272
void TwoFishFree(TWOFISH *tfdata)
273
{	if(tfdata->output!=NULL)	/* if a valid buffer is present... */
274
	{	free(tfdata->output);	/* ...then we free it for you... */
275
		tfdata->output=NULL;	/* ...and mark as such. */
276
	}
277
}
278
279
/*	TwoFish Set Output
280
 *
281
 *	If you want to allocate the output buffer yourself,
282
 *	then you can set it with this function.
283
 *
284
 *	Input:	Pointer to your output buffer
285
 *			Pointer to the TwoFish structure
286
 *
287
 *	Output:	(none)
288
 */
289
290
void TwoFishSetOutput(char *outp,TWOFISH *tfdata)
291
{	tfdata->output=outp;				/* (do we really need a function for this?) */
292
}
293
294
/*	TwoFish Alloc
295
 *
296
 *	Allocates enough memory for the output buffer that would be required
297
 *
298
 *	Input:	Length of the plaintext.
299
 *			Boolean flag for BinHex Output.
300
 *			Pointer to the TwoFish structure.
301
 *
302
 *	Output:	Returns a pointer to the memory allocated.
303
 */
304
305
void *TwoFishAlloc(unsigned long len,bool binhex,bool decrypt,TWOFISH *tfdata)
306
{	
307
/*	TwoFishFree(tfdata);	*/			/* (don't for now) discard whatever was allocated earlier. */
308
	if(decrypt)							/* if decrypting... */
309
	{	if(binhex)						/* ...and input is binhex encoded... */
310
			len/=2;						/* ...use half as much for output. */
311
		len-=TwoFish_BLOCK_SIZE;		/* Also, subtract the size of the header. */
312
	}
313
	else
314
	{	len+=TwoFish_BLOCK_SIZE;		/* the size is just increased by the header... */
315
		if(binhex)
316
			len*=2;						/* ...and doubled if output is to be binhexed. */
317
	}
318
	tfdata->output=malloc(len+TwoFish_BLOCK_SIZE);/* grab some memory...plus some extra (it's running over somewhere, crashes without extra padding) */
319
320
	return tfdata->output;				/* ...and return to caller. */
321
}
322
323
/* bin2hex and hex2bin conversion */
324
void _TwoFish_BinHex(unsigned char *buf,unsigned long len,bool bintohex)
325
{	unsigned char *pi,*po,c;
326
327
	if(bintohex)
328
	{	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. */
329
		{	c=*pi;												 /* grab value. */
330
			c&=15;												 /* use lower 4 bits. */
331
			if(c>9)												 /* convert to ascii. */
332
				c+=('a'-10);
333
			else
334
				c+='0';
335
			*po--=c;											 /* set the lower nibble. */
336
			c=*pi;												 /* grab value again. */
337
			c>>=4;												 /* right shift 4 bits. */
338
			c&=15;												 /* make sure we only have 4 bits. */
339
			if(c>9)												 /* convert to ascii. */
340
				c+=('a'-10);
341
			else
342
				c+='0';
343
			*po=c;												 /* set the higher nibble. */
344
		}														 /* and keep going. */
345
	}
346
	else
347
	{	for(pi=buf,po=buf;len>0;pi++,po++,len-=2)				 /* let's start from the beginning of the hex block. */
348
		{	c=tolower(*pi++)-'0';								 /* grab higher nibble. */
349
			if(c>9)												 /* convert to value. */
350
				c-=('0'-9);
351
			*po=c<<4;											 /* left shit 4 bits. */
352
			c=tolower(*pi)-'0';									 /* grab lower nibble. */
353
			if(c>9)												 /* convert to value. */
354
				c-=('0'-9);
355
			*po|=c;												 /* and add to value. */
356
		}
357
	}
358
}
359
360
361
/*	TwoFish Encryption 
362
 *	
363
 *	Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
364
 *  this routine will alloc the memory. In addition, it will include a small 'header'
365
 *  containing the magic and some salt. That way the decrypt routine can check if the 
366
 *  packet got decrypted successfully, and return 0 instead of garbage.
367
 *
368
 *	Input:	Pointer to the buffer of the plaintext to be encrypted.
369
 *			Pointer to the pointer to the buffer receiving the ciphertext.
370
 *				The pointer either points to user allocated output buffer space, or to NULL, in which case
371
 *				this routine will set the pointer to the buffer allocated through the struct.
372
 *			The length of the plaintext buffer.
373
 *				Can be -1 if the input is a null terminated string, in which case we'll count for you.
374
 *			Boolean flag for BinHex Output (if used, output will be twice as large as input).
375
 *				Note: BinHex conversion overwrites (converts) input buffer!
376
 *			The TwoFish structure.
377
 *
378
 *	Output:	The amount of bytes encrypted if successful, otherwise 0.
379
 */
380
381
unsigned long TwoFishEncrypt(char *in,
382
							 char **out,
383
							 signed long len,
384
							 bool binhex,
385
							 TWOFISH *tfdata)
386
{	unsigned long ilen,olen;
387
388
389
	if(len== -1)			/* if we got -1 for len, we'll assume IN is a...  */
390
		ilen=strlen(in);	/* ...\0 terminated string and figure len out ourselves... */
391
	else
392
		ilen=len;			/* ...otherwise we trust you supply a correct length. */
393
	
394
	if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */
395
	{	if(*out==NULL)									/* if OUT points to a NULL pointer... */
396
			*out=TwoFishAlloc(ilen,binhex,FALSE,tfdata);  /* ...we'll (re-)allocate buffer space. */
397
		if(*out!=NULL)
398
		{	tfdata->output=*out;							/* set output buffer. */
399
			tfdata->header.salt=rand()*65536+rand();		/* toss in some salt. */
400
			tfdata->header.length[0]= (unsigned char)(ilen);
401
			tfdata->header.length[1]= (unsigned char)(ilen>>8);
402
			tfdata->header.length[2]= (unsigned char)(ilen>>16);
403
			tfdata->header.length[3]= (unsigned char)(ilen>>24);
404
			memcpy(tfdata->header.magic,TwoFish_MAGIC,TwoFish_MAGIC_LEN); /* set the magic. */
405
			olen=TwoFish_BLOCK_SIZE;						/* set output counter. */
406
			_TwoFish_ResetCBC(tfdata);						/* reset the CBC flag */
407
			_TwoFish_BlockCrypt((unsigned char *)&(tfdata->header),*out,olen,FALSE,tfdata); /* encrypt first block (without flush on 16 byte boundary). */
408
			olen+=_TwoFish_CryptRawCBC(in,*out+TwoFish_BLOCK_SIZE,ilen,FALSE,tfdata);	/* and encrypt the rest (we do not reset the CBC flag). */
409
			if(binhex)									/* if binhex... */
410
			{	_TwoFish_BinHex(*out,olen,TRUE);		/* ...convert output to binhex... */
411
				olen*=2;								/* ...and size twice as large. */
412
			}
413
			tfdata->output=*out;
414
			return olen;
415
		}
416
	}
417
	return 0;
418
}
419
420
/*	TwoFish Decryption 
421
 *	
422
 *	Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
423
 *  this routine will alloc the memory. In addition, it will check the small 'header'
424
 *  containing the magic. If magic does not match we return 0. Otherwise we return the 
425
 *  amount of bytes decrypted (should be the same as the length in the header).
426
 *
427
 *	Input:	Pointer to the buffer of the ciphertext to be decrypted.
428
 *			Pointer to the pointer to the buffer receiving the plaintext.
429
 *				The pointer either points to user allocated output buffer space, or to NULL, in which case
430
 *				this routine will set the pointer to the buffer allocated through the struct.
431
 *			The length of the ciphertext buffer.
432
 *				Can be -1 if the input is a null terminated binhex string, in which case we'll count for you.
433
 *			Boolean flag for BinHex Input (if used, plaintext will be half as large as input).
434
 *				Note: BinHex conversion overwrites (converts) input buffer!
435
 *			The TwoFish structure.
436
 *
437
 *	Output:	The amount of bytes decrypted if successful, otherwise 0.
438
 */
439
440
unsigned long TwoFishDecrypt(char *in,
441
							 char **out,
442
							 signed long len,
443
							 bool binhex,
444
							 TWOFISH *tfdata)
445
{	unsigned long ilen,elen,olen;
446
	const unsigned char cmagic[TwoFish_MAGIC_LEN]=TwoFish_MAGIC;
447
	unsigned char *tbuf;
448
449
450
451
	if(len== -1)			/* if we got -1 for len, we'll assume IN is...  */
452
		ilen=strlen(in);	/* ...\0 terminated binhex and figure len out ourselves... */
453
	else
454
		ilen=len;			/* ...otherwise we trust you supply a correct length. */
455
	
456
	if(in!=NULL && out!=NULL && ilen>0 && tfdata!=NULL) /* if we got usable stuff, we'll do it. */
457
	{	if(*out==NULL)									/* if OUT points to a NULL pointer... */
458
			*out=TwoFishAlloc(ilen,binhex,TRUE,tfdata); /* ...we'll (re-)allocate buffer space. */
459
		if(*out!=NULL)
460
		{	if(binhex)									/* if binhex... */
461
			{	_TwoFish_BinHex(in,ilen,FALSE);		/* ...convert input to values... */
462
				ilen/=2;								/* ...and size half as much. */
463
			}
464
			_TwoFish_ResetCBC(tfdata);						/* reset the CBC flag. */
465
  
466
			tbuf=(unsigned char *)malloc(ilen+TwoFish_BLOCK_SIZE); /* get memory for data and header. */
467
			if(tbuf==NULL)
468
				return 0;
469
			tfdata->output=tbuf;					/* set output to temp buffer. */
470
471
			olen=_TwoFish_CryptRawCBC(in,tbuf,ilen,TRUE,tfdata)-TwoFish_BLOCK_SIZE; /* decrypt the whole thing. */
472
			memcpy(&(tfdata->header),tbuf,TwoFish_BLOCK_SIZE); /* copy first block into header. */
473
			tfdata->output=*out;
474
			for(elen=0;elen<TwoFish_MAGIC_LEN;elen++)	/* compare magic. */
475
				if(tfdata->header.magic[elen]!=cmagic[elen])
476
					break;
477
			if(elen==TwoFish_MAGIC_LEN)					/* if magic matches then... */
478
			{	elen=(tfdata->header.length[0]) |
479
					 (tfdata->header.length[1])<<8 |
480
					 (tfdata->header.length[2])<<16 |
481
					 (tfdata->header.length[3])<<24;	/* .. we know how much to expect. */
482
				if(elen>olen)							/* adjust if necessary. */
483
					elen=olen;
484
				memcpy(*out,tbuf+TwoFish_BLOCK_SIZE,elen);	/* copy data into intended output. */
485
				free(tbuf);
486
				return elen;
487
			}
488
			free(tbuf);
489
		}
490
	}
491
	return 0;
492
}
493
494
void _TwoFish_PrecomputeMDSmatrix(void)	/* precompute the TwoFish_MDS matrix */
495
{   unsigned long m1[2];
496
    unsigned long mX[2];
497
    unsigned long mY[2];
498
    unsigned long i, j;
499
500
    for (i = 0; i < 256; i++) 
501
    {   j = TwoFish_P[0][i]       & 0xFF; /* compute all the matrix elements */
502
        m1[0] = j;
503
        mX[0] = TwoFish_Mx_X( j ) & 0xFF;
504
        mY[0] = TwoFish_Mx_Y( j ) & 0xFF;
505
506
        j = TwoFish_P[1][i]       & 0xFF;
507
        m1[1] = j;
508
        mX[1] = TwoFish_Mx_X( j ) & 0xFF;
509
        mY[1] = TwoFish_Mx_Y( j ) & 0xFF;
510
511
        TwoFish_MDS[0][i] = m1[TwoFish_P_00] | /* fill matrix w/ above elements */
512
                    mX[TwoFish_P_00] <<  8 |
513
                    mY[TwoFish_P_00] << 16 |
514
                    mY[TwoFish_P_00] << 24;
515
        TwoFish_MDS[1][i] = mY[TwoFish_P_10] |
516
                    mY[TwoFish_P_10] <<  8 |
517
                    mX[TwoFish_P_10] << 16 |
518
                    m1[TwoFish_P_10] << 24;
519
        TwoFish_MDS[2][i] = mX[TwoFish_P_20] |
520
                    mY[TwoFish_P_20] <<  8 |
521
                    m1[TwoFish_P_20] << 16 |
522
                    mY[TwoFish_P_20] << 24;
523
        TwoFish_MDS[3][i] = mX[TwoFish_P_30] |
524
                    m1[TwoFish_P_30] <<  8 |
525
                    mY[TwoFish_P_30] << 16 |
526
                    mX[TwoFish_P_30] << 24;
527
    }
528
	TwoFish_MDSready=TRUE;
529
}
530
531
532
void _TwoFish_MakeSubKeys(TWOFISH *tfdata)	/* Expand a user-supplied key material into a session key. */
533
{	unsigned long k64Cnt    = TwoFish_KEY_LENGTH / 8;
534
	unsigned long k32e[4]; /* even 32-bit entities */
535
	unsigned long k32o[4]; /* odd 32-bit entities */
536
	unsigned long sBoxKey[4];
537
	unsigned long offset,i,j;
538
	unsigned long A, B, q=0;
539
	unsigned long k0,k1,k2,k3;
540
    unsigned long b0,b1,b2,b3;
541
542
    /* split user key material into even and odd 32-bit entities and */
543
    /* compute S-box keys using (12, 8) Reed-Solomon code over GF(256) */
544
545
546
    for (offset=0,i=0,j=k64Cnt-1;i<4 && offset<TwoFish_KEY_LENGTH;i++,j--) 
547
    {	k32e[i] = tfdata->key[offset++];
548
		k32e[i]|= tfdata->key[offset++]<<8;
549
		k32e[i]|= tfdata->key[offset++]<<16;
550
		k32e[i]|= tfdata->key[offset++]<<24;
551
    	k32o[i] = tfdata->key[offset++];
552
		k32o[i]|= tfdata->key[offset++]<<8;
553
		k32o[i]|= tfdata->key[offset++]<<16;
554
		k32o[i]|= tfdata->key[offset++]<<24;
555
        sBoxKey[j] = _TwoFish_RS_MDS_Encode( k32e[i], k32o[i] ); /* reverse order */
556
    }
557
558
    /* compute the round decryption subkeys for PHT. these same subkeys */
559
    /* will be used in encryption but will be applied in reverse order. */
560
    i=0;
561
    while(i < TwoFish_TOTAL_SUBKEYS) 
562
    {	A = _TwoFish_F32( k64Cnt, q, k32e ); /* A uses even key entities */
563
        q += TwoFish_SK_BUMP;
564
565
        B = _TwoFish_F32( k64Cnt, q, k32o ); /* B uses odd  key entities */
566
        q += TwoFish_SK_BUMP;
567
568
        B = B << 8 | B >> 24;
569
570
        A += B;
571
        tfdata->subKeys[i++] = A;           /* combine with a PHT */
572
573
        A += B;
574
        tfdata->subKeys[i++] = A << TwoFish_SK_ROTL | A >> (32-TwoFish_SK_ROTL);
575
    }
576
577
    /* fully expand the table for speed */
578
    k0 = sBoxKey[0];
579
    k1 = sBoxKey[1];
580
    k2 = sBoxKey[2];
581
    k3 = sBoxKey[3];
582
583
    for (i = 0; i < 256; i++) 
584
    {   b0 = b1 = b2 = b3 = i;
585
        switch (k64Cnt & 3) 
586
        {	case 1: /* 64-bit keys */
587
				tfdata->sBox[      2*i  ] = TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0]) ^ TwoFish_b0(k0)];
588
				tfdata->sBox[      2*i+1] = TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1]) ^ TwoFish_b1(k0)];
589
				tfdata->sBox[0x200+2*i  ] = TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2]) ^ TwoFish_b2(k0)];
590
				tfdata->sBox[0x200+2*i+1] = TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3]) ^ TwoFish_b3(k0)];
591
				break;
592
			case 0: /* 256-bit keys (same as 4) */
593
				b0 = (TwoFish_P[TwoFish_P_04][b0]) ^ TwoFish_b0(k3);
594
				b1 = (TwoFish_P[TwoFish_P_14][b1]) ^ TwoFish_b1(k3);
595
				b2 = (TwoFish_P[TwoFish_P_24][b2]) ^ TwoFish_b2(k3);
596
				b3 = (TwoFish_P[TwoFish_P_34][b3]) ^ TwoFish_b3(k3);
597
			case 3:  /* 192-bit keys */
598
				b0 = (TwoFish_P[TwoFish_P_03][b0]) ^ TwoFish_b0(k2);
599
				b1 = (TwoFish_P[TwoFish_P_13][b1]) ^ TwoFish_b1(k2);
600
				b2 = (TwoFish_P[TwoFish_P_23][b2]) ^ TwoFish_b2(k2);
601
				b3 = (TwoFish_P[TwoFish_P_33][b3]) ^ TwoFish_b3(k2);
602
			case 2: /* 128-bit keys */
603
				tfdata->sBox[      2*i  ]= 
604
					TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0]) ^
605
					TwoFish_b0(k1)]) ^ TwoFish_b0(k0)];
606
607
				tfdata->sBox[      2*i+1]=
608
					TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1]) ^
609
					TwoFish_b1(k1)]) ^ TwoFish_b1(k0)];
610
611
				tfdata->sBox[0x200+2*i  ]=
612
					TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2]) ^
613
					TwoFish_b2(k1)]) ^ TwoFish_b2(k0)];
614
615
				tfdata->sBox[0x200+2*i+1]=
616
					TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3]) ^
617
					TwoFish_b3(k1)]) ^ TwoFish_b3(k0)];
618
		}
619
    }
620
}
621
622
623
/**
624
 * Encrypt or decrypt exactly one block of plaintext in CBC mode.  
625
 * Use "ciphertext stealing" technique described on pg. 196
626
 * of "Applied Cryptography" to encrypt the final partial
627
 * (i.e. <16 byte) block if necessary.
628
 *
629
 * jojo: the "ciphertext stealing" requires we read ahead and have
630
 * special handling for the last two blocks.  Because of this, the
631
 * output from the TwoFish algorithm is handled internally here. 
632
 * It would be better to have a higher level handle this as well as
633
 * CBC mode.  Unfortunately, I've mixed the two together, which is
634
 * pretty crappy... The Java version separates these out correctly.
635
 *
636
 * fknobbe:	I have reduced the CBC mode to work on memory buffer only.
637
 *			Higher routines should use an intermediate buffer and handle
638
 *			their output seperately (mainly so the data can be flushed
639
 *			in one chunk, not seperate 16 byte blocks...)
640
 *
641
 * @param in   The plaintext.
642
 * @param out  The ciphertext
643
 * @param size how much to encrypt
644
 * @param tfdata: Pointer to the global data structure containing session keys.
645
 * @return none
646
 */
647
void _TwoFish_BlockCrypt(unsigned char *in,unsigned char *out,unsigned long size,int decrypt,TWOFISH *tfdata) 
648
{	unsigned char PnMinusOne[TwoFish_BLOCK_SIZE];
649
	unsigned char CnMinusOne[TwoFish_BLOCK_SIZE];
650
	unsigned char CBCplusCprime[TwoFish_BLOCK_SIZE];
651
	unsigned char Pn[TwoFish_BLOCK_SIZE];
652
	unsigned char *p,*pout;
653
	unsigned long i;
654
655
    /* here is where we implement CBC mode and cipher block stealing */
656
    if(size==TwoFish_BLOCK_SIZE)
657
	{   /* if we are encrypting, CBC means we XOR the plain text block with the */
658
        /* previous cipher text block before encrypting */
659
		if(!decrypt && tfdata->qBlockDefined)
660
		{   for(p=in,i=0;i<TwoFish_BLOCK_SIZE;i++,p++)
661
				Pn[i]=*p ^ tfdata->qBlockCrypt[i];	/* FK: I'm copying the xor'ed input into Pn... */
662
		}
663
		else
664
			memcpy(Pn,in,TwoFish_BLOCK_SIZE); /* FK: same here. we work of Pn all the time. */
665
666
        /* TwoFish block level encryption or decryption */
667
		_TwoFish_BlockCrypt16(Pn,out,decrypt,tfdata);
668
669
        /* if we are decrypting, CBC means we XOR the result of the decryption */
670
        /* with the previous cipher text block to get the resulting plain text */
671
        if(decrypt && tfdata->qBlockDefined)
672
        {	for (p=out,i=0;i<TwoFish_BLOCK_SIZE;i++,p++)
673
				*p^=tfdata->qBlockPlain[i];
674
        }
675
676
        /* save the input and output blocks, since CBC needs these for XOR */
677
        /* operations */
678
        _TwoFish_qBlockPush(Pn,out,tfdata);
679
	} 
680
	else
681
	{   /* cipher block stealing, we are at Pn, */
682
        /* but since Cn-1 must now be replaced with CnC' */
683
        /* we pop it off, and recalculate Cn-1 */
684
        
685
        if(decrypt)
686
        {   /* We are on an odd block, and had to do cipher block stealing, */
687
            /* so the PnMinusOne has to be derived differently. */
688
689
            /* First we decrypt it into CBC and C' */
690
	        _TwoFish_qBlockPop(CnMinusOne,PnMinusOne,tfdata);
691
            _TwoFish_BlockCrypt16(CnMinusOne,CBCplusCprime,decrypt,tfdata);
692
693
            /* we then xor the first few bytes with the "in" bytes (Cn) */
694
            /* to recover Pn, which we put in out */
695
            for(p=in,pout=out,i=0;i<size;i++,p++,pout++) 
696
                *pout=*p ^ CBCplusCprime[i];
697
698
            /* We now recover the original CnMinusOne, which consists of */
699
            /* the first "size" bytes of "in" data, followed by the */
700
            /* "Cprime" portion of CBCplusCprime */
701
            for(p=in,i=0;i<size;i++,p++)
702
                CnMinusOne[i]=*p;
703
            for(;i<TwoFish_BLOCK_SIZE;i++)
704
                CnMinusOne[i]=CBCplusCprime[i];
705
706
            /* we now decrypt CnMinusOne to get PnMinusOne xored with Cn-2 */
707
            _TwoFish_BlockCrypt16(CnMinusOne,PnMinusOne,decrypt,tfdata);
708
709
            for(i=0;i<TwoFish_BLOCK_SIZE;i++)
710
                PnMinusOne[i]=PnMinusOne[i] ^ tfdata->prevCipher[i];
711
712
            /* So at this point, out has PnMinusOne */
713
            _TwoFish_qBlockPush(CnMinusOne,PnMinusOne,tfdata);
714
		    _TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata);
715
            _TwoFish_FlushOutput(out,size,tfdata);
716
        } 
717
		else 
718
		{	_TwoFish_qBlockPop(PnMinusOne,CnMinusOne,tfdata);
719
			memset(Pn,0,TwoFish_BLOCK_SIZE);
720
			memcpy(Pn,in,size);
721
			for(i=0;i<TwoFish_BLOCK_SIZE;i++) 
722
				Pn[i]^=CnMinusOne[i];
723
			_TwoFish_BlockCrypt16(Pn,out,decrypt,tfdata);
724
			_TwoFish_qBlockPush(Pn,out,tfdata);  /* now we officially have Cn-1 */
725
			_TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata);
726
			_TwoFish_FlushOutput(CnMinusOne,size,tfdata);  /* old Cn-1 becomes new partial Cn */
727
		}
728
		tfdata->qBlockDefined=FALSE;
729
	}
730
}
731
732
void _TwoFish_qBlockPush(unsigned char *p,unsigned char *c,TWOFISH *tfdata)
733
{	if(tfdata->qBlockDefined)
734
		_TwoFish_FlushOutput(tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE,tfdata);
735
	memcpy(tfdata->prevCipher,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE);
736
	memcpy(tfdata->qBlockPlain,p,TwoFish_BLOCK_SIZE);
737
	memcpy(tfdata->qBlockCrypt,c,TwoFish_BLOCK_SIZE);
738
	tfdata->qBlockDefined=TRUE;
739
}
740
741
void _TwoFish_qBlockPop(unsigned char *p,unsigned char *c,TWOFISH *tfdata)
742
{	memcpy(p,tfdata->qBlockPlain,TwoFish_BLOCK_SIZE );
743
	memcpy(c,tfdata->qBlockCrypt,TwoFish_BLOCK_SIZE );
744
	tfdata->qBlockDefined=FALSE;
745
}
746
747
/* Reset's the CBC flag and zero's PrevCipher (through qBlockPlain) (important) */
748
void _TwoFish_ResetCBC(TWOFISH *tfdata)
749
{	tfdata->qBlockDefined=FALSE;
750
	memset(tfdata->qBlockPlain,0,TwoFish_BLOCK_SIZE);
751
}
752
753
void _TwoFish_FlushOutput(unsigned char *b,unsigned long len,TWOFISH *tfdata) 
754
{	unsigned long i;
755
	
756
	for(i=0;i<len && !tfdata->dontflush;i++)
757
		*tfdata->output++ = *b++;
758
	tfdata->dontflush=FALSE;
759
}
760
761
void _TwoFish_BlockCrypt16(unsigned char *in,unsigned char *out,bool decrypt,TWOFISH *tfdata) 
762
{	unsigned long x0,x1,x2,x3;
763
    unsigned long k,t0,t1,R;
764
765
766
	x0=*in++;
767
	x0|=(*in++ << 8 );
768
	x0|=(*in++ << 16);
769
	x0|=(*in++ << 24);
770
    x1=*in++;
771
	x1|=(*in++ << 8 );
772
	x1|=(*in++ << 16);
773
	x1|=(*in++ << 24);
774
	x2=*in++;
775
	x2|=(*in++ << 8 );
776
	x2|=(*in++ << 16);
777
	x2|=(*in++ << 24);
778
	x3=*in++;
779
	x3|=(*in++ << 8 );
780
	x3|=(*in++ << 16);
781
	x3|=(*in++ << 24);
782
783
	if(decrypt)
784
    {	x0 ^= tfdata->subKeys[4];	/* swap input and output whitening keys when decrypting */
785
 	    x1 ^= tfdata->subKeys[5];
786
		x2 ^= tfdata->subKeys[6];
787
		x3 ^= tfdata->subKeys[7];
788
	
789
        k = 7+(TwoFish_ROUNDS*2);
790
        for (R = 0; R < TwoFish_ROUNDS; R += 2) 
791
		{   t0 = _TwoFish_Fe320( tfdata->sBox, x0);
792
            t1 = _TwoFish_Fe323( tfdata->sBox, x1);
793
            x3 ^= t0 + (t1<<1) + tfdata->subKeys[k--];
794
            x3  = x3 >> 1 | x3 << 31;
795
            x2  = x2 << 1 | x2 >> 31;
796
            x2 ^= t0 + t1 + tfdata->subKeys[k--]; 
797
798
            t0 = _TwoFish_Fe320( tfdata->sBox, x2);
799
            t1 = _TwoFish_Fe323( tfdata->sBox, x3);
800
            x1 ^= t0 + (t1<<1) + tfdata->subKeys[k--]; 
801
            x1  = x1 >> 1 | x1 << 31;
802
            x0  = x0 << 1 | x0 >> 31;
803
            x0 ^= t0 + t1 + tfdata->subKeys[k--];
804
        }
805
806
		x2 ^= tfdata->subKeys[0];
807
		x3 ^= tfdata->subKeys[1];
808
		x0 ^= tfdata->subKeys[2];
809
		x1 ^= tfdata->subKeys[3];
810
	}
811
	else 
812
    {	x0 ^= tfdata->subKeys[0];
813
	    x1 ^= tfdata->subKeys[1];
814
		x2 ^= tfdata->subKeys[2];
815
		x3 ^= tfdata->subKeys[3];
816
817
		k = 8;
818
        for (R = 0; R < TwoFish_ROUNDS; R += 2)
819
        {   t0 = _TwoFish_Fe320( tfdata->sBox, x0);
820
            t1 = _TwoFish_Fe323( tfdata->sBox, x1);
821
            x2 ^= t0 + t1 + tfdata->subKeys[k++]; 
822
            x2  = x2 >> 1 | x2 << 31;
823
            x3  = x3 << 1 | x3 >> 31;
824
            x3 ^= t0 + (t1<<1) + tfdata->subKeys[k++];
825
826
            t0 = _TwoFish_Fe320( tfdata->sBox, x2);
827
            t1 = _TwoFish_Fe323( tfdata->sBox, x3);
828
            x0 ^= t0 + t1 + tfdata->subKeys[k++];
829
            x0  = x0 >> 1 | x0 << 31;
830
            x1  = x1 << 1 | x1 >> 31;
831
            x1 ^= t0 + (t1<<1) + tfdata->subKeys[k++];
832
        }
833
834
		x2 ^= tfdata->subKeys[4];
835
		x3 ^= tfdata->subKeys[5];
836
		x0 ^= tfdata->subKeys[6];
837
		x1 ^= tfdata->subKeys[7];
838
	}
839
840
	*out++ = (unsigned char)(x2      );
841
    *out++ = (unsigned char)(x2 >>  8);  
842
    *out++ = (unsigned char)(x2 >> 16);
843
    *out++ = (unsigned char)(x2 >> 24);
844
845
    *out++ = (unsigned char)(x3      );
846
    *out++ = (unsigned char)(x3 >>  8);
847
    *out++ = (unsigned char)(x3 >> 16);
848
    *out++ = (unsigned char)(x3 >> 24);
849
850
    *out++ = (unsigned char)(x0      );
851
    *out++ = (unsigned char)(x0 >>  8);
852
    *out++ = (unsigned char)(x0 >> 16);
853
    *out++ = (unsigned char)(x0 >> 24);
854
855
    *out++ = (unsigned char)(x1      );
856
    *out++ = (unsigned char)(x1 >>  8);
857
    *out++ = (unsigned char)(x1 >> 16);
858
    *out++ = (unsigned char)(x1 >> 24);
859
}
860
861
/**
862
 * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box
863
 * 32-bit entity from two key material 32-bit entities.
864
 *
865
 * @param  k0  1st 32-bit entity.
866
 * @param  k1  2nd 32-bit entity.
867
 * @return  Remainder polynomial generated using RS code
868
 */
869
unsigned long _TwoFish_RS_MDS_Encode(unsigned long k0,unsigned long k1)
870
{	unsigned long i,r;
871
872
    for(r=k1,i=0;i<4;i++) /* shift 1 byte at a time */
873
        TwoFish_RS_rem(r);
874
    r ^= k0;
875
    for(i=0;i<4;i++)
876
        TwoFish_RS_rem(r);
877
878
    return r;
879
}
880
881
unsigned long _TwoFish_F32(unsigned long k64Cnt,unsigned long x,unsigned long *k32)
882
{   unsigned char b0,b1,b2,b3;
883
	unsigned long k0,k1,k2,k3,result = 0;
884
885
	b0=TwoFish_b0(x);
886
    b1=TwoFish_b1(x);
887
    b2=TwoFish_b2(x);
888
    b3=TwoFish_b3(x);
889
    k0=k32[0];
890
    k1=k32[1];
891
    k2=k32[2];
892
    k3=k32[3];
893
894
    switch (k64Cnt & 3) 
895
    {	case 1:	/* 64-bit keys */
896
			result =
897
				TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][b0] & 0xFF) ^ TwoFish_b0(k0)] ^
898
				TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][b1] & 0xFF) ^ TwoFish_b1(k0)] ^
899
				TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][b2] & 0xFF) ^ TwoFish_b2(k0)] ^
900
				TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][b3] & 0xFF) ^ TwoFish_b3(k0)];
901
        break;
902
		case 0:	/* 256-bit keys (same as 4) */
903
			b0 = (TwoFish_P[TwoFish_P_04][b0] & 0xFF) ^ TwoFish_b0(k3);
904
			b1 = (TwoFish_P[TwoFish_P_14][b1] & 0xFF) ^ TwoFish_b1(k3);
905
			b2 = (TwoFish_P[TwoFish_P_24][b2] & 0xFF) ^ TwoFish_b2(k3);
906
			b3 = (TwoFish_P[TwoFish_P_34][b3] & 0xFF) ^ TwoFish_b3(k3);
907
908
		case 3:	/* 192-bit keys */
909
			b0 = (TwoFish_P[TwoFish_P_03][b0] & 0xFF) ^ TwoFish_b0(k2);
910
			b1 = (TwoFish_P[TwoFish_P_13][b1] & 0xFF) ^ TwoFish_b1(k2);
911
			b2 = (TwoFish_P[TwoFish_P_23][b2] & 0xFF) ^ TwoFish_b2(k2);
912
			b3 = (TwoFish_P[TwoFish_P_33][b3] & 0xFF) ^ TwoFish_b3(k2);
913
		case 2:	/* 128-bit keys (optimize for this case) */
914
			result =
915
				  TwoFish_MDS[0][(TwoFish_P[TwoFish_P_01][(TwoFish_P[TwoFish_P_02][b0] & 0xFF) ^ TwoFish_b0(k1)] & 0xFF) ^ TwoFish_b0(k0)] ^
916
				  TwoFish_MDS[1][(TwoFish_P[TwoFish_P_11][(TwoFish_P[TwoFish_P_12][b1] & 0xFF) ^ TwoFish_b1(k1)] & 0xFF) ^ TwoFish_b1(k0)] ^
917
				  TwoFish_MDS[2][(TwoFish_P[TwoFish_P_21][(TwoFish_P[TwoFish_P_22][b2] & 0xFF) ^ TwoFish_b2(k1)] & 0xFF) ^ TwoFish_b2(k0)] ^
918
				  TwoFish_MDS[3][(TwoFish_P[TwoFish_P_31][(TwoFish_P[TwoFish_P_32][b3] & 0xFF) ^ TwoFish_b3(k1)] & 0xFF) ^ TwoFish_b3(k0)];
919
        break;
920
    }
921
    return result;
922
}
923
924
unsigned long _TwoFish_Fe320(unsigned long *lsBox,unsigned long x)
925
{   return lsBox[        TwoFish_b0(x)<<1    ]^
926
           lsBox[      ((TwoFish_b1(x)<<1)|1)]^
927
           lsBox[0x200+ (TwoFish_b2(x)<<1)   ]^
928
           lsBox[0x200+((TwoFish_b3(x)<<1)|1)];
929
}
930
931
unsigned long _TwoFish_Fe323(unsigned long *lsBox,unsigned long x) 
932
{   return lsBox[       (TwoFish_b3(x)<<1)   ]^
933
           lsBox[      ((TwoFish_b0(x)<<1)|1)]^
934
           lsBox[0x200+ (TwoFish_b1(x)<<1)   ]^
935
           lsBox[0x200+((TwoFish_b2(x)<<1)|1)];
936
}
937
938
unsigned long _TwoFish_Fe32(unsigned long *lsBox,unsigned long x,unsigned long R)
939
{   return lsBox[      2*TwoFish__b(x,R  )  ]^
940
           lsBox[      2*TwoFish__b(x,R+1)+1]^
941
           lsBox[0x200+2*TwoFish__b(x,R+2)  ]^
942
           lsBox[0x200+2*TwoFish__b(x,R+3)+1];
943
}
944
945
946
#endif
(-)snort-2.8.3.1/src/twofish.h (+276 lines)
Line 0 Link Here
1
/* $Id: snortpatchb,v 1.5 2005/10/06 08:50:39 fknobbe Exp $
2
 *
3
 *
4
 * Copyright (C) 1997-2000 The Cryptix Foundation Limited.
5
 * Copyright (C) 2000 Farm9.
6
 * Copyright (C) 2001 Frank Knobbe.
7
 * All rights reserved.
8
 *
9
 * For Cryptix code:
10
 * Use, modification, copying and distribution of this software is subject
11
 * the terms and conditions of the Cryptix General Licence. You should have
12
 * received a copy of the Cryptix General Licence along with this library;
13
 * if not, you can download a copy from http://www.cryptix.org/ .
14
 *
15
 * For Farm9:
16
 * ---  jojo@farm9.com, August 2000, converted from Java to C++, added CBC mode and
17
 *      ciphertext stealing technique, added AsciiTwofish class for easy encryption
18
 *      decryption of text strings
19
 *
20
 * Frank Knobbe <frank@knobbe.us>:
21
 * ---  April 2001, converted from C++ to C, prefixed global variables
22
 *      with TwoFish, substituted some defines, changed functions to make use of
23
 *      variables supplied in a struct, modified and added routines for modular calls.
24
 *      Cleaned up the code so that defines are used instead of fixed 16's and 32's.
25
 *      Created two general purpose crypt routines for one block and multiple block
26
 *      encryption using Joh's CBC code.
27
 *		Added crypt routines that use a header (with a magic and data length).
28
 *		(Basically a major rewrite).
29
 *
30
 *      Note: Routines labeled _TwoFish are private and should not be used 
31
 *      (or with extreme caution).
32
 *
33
 */
34
35
#ifndef __TWOFISH_LIBRARY_HEADER__
36
#define __TWOFISH_LIBRARY_HEADER__
37
38
#ifndef FALSE
39
#define FALSE	0
40
#endif
41
#ifndef TRUE
42
#define TRUE	!FALSE
43
#endif
44
#ifndef bool
45
#define bool	int
46
#endif
47
48
49
/* Constants */
50
51
#define TwoFish_DEFAULT_PW		"SnortHas2FishEncryptionRoutines!" /* default password (not more than 32 chars) */
52
#define TwoFish_MAGIC			"TwoFish"			/* to indentify a successful decryption */
53
54
enum		
55
{	TwoFish_KEY_SIZE = 256,					/* Valid values: 64, 128, 192, 256 */
56
											/* User 256, other key sizes have not been tested. */
57
											/* (But should work. I substitutes as much as */
58
											/* I could with this define.) */
59
	TwoFish_ROUNDS = 16,
60
	TwoFish_BLOCK_SIZE = 16,				/* bytes in a data-block */
61
	TwoFish_KEY_LENGTH = TwoFish_KEY_SIZE/8,	/* 32= 256-bit key */
62
	TwoFish_TOTAL_SUBKEYS = 4+4+2*TwoFish_ROUNDS,
63
	TwoFish_MAGIC_LEN = TwoFish_BLOCK_SIZE-8,
64
	TwoFish_SK_BUMP = 0x01010101,
65
	TwoFish_SK_ROTL = 9,
66
	TwoFish_P_00 = 1,
67
	TwoFish_P_01 = 0,
68
	TwoFish_P_02 = 0,
69
	TwoFish_P_03 = TwoFish_P_01 ^ 1,
70
	TwoFish_P_04 = 1,
71
	TwoFish_P_10 = 0,
72
	TwoFish_P_11 = 0,
73
	TwoFish_P_12 = 1,
74
	TwoFish_P_13 = TwoFish_P_11 ^ 1,
75
	TwoFish_P_14 = 0,
76
	TwoFish_P_20 = 1,
77
	TwoFish_P_21 = 1,
78
	TwoFish_P_22 = 0,
79
	TwoFish_P_23 = TwoFish_P_21 ^ 1,
80
	TwoFish_P_24 = 0,
81
	TwoFish_P_30 = 0,
82
	TwoFish_P_31 = 1,
83
	TwoFish_P_32 = 1,
84
	TwoFish_P_33 = TwoFish_P_31 ^ 1,
85
	TwoFish_P_34 = 1,
86
	TwoFish_GF256_FDBK =   0x169,
87
	TwoFish_GF256_FDBK_2 = 0x169 / 2,
88
	TwoFish_GF256_FDBK_4 = 0x169 / 4,
89
	TwoFish_RS_GF_FDBK = 0x14D,		/* field generator */
90
	TwoFish_MDS_GF_FDBK = 0x169		/* primitive polynomial for GF(256) */
91
};
92
93
94
/* Global data structure for callers */
95
96
typedef struct    
97
{	unsigned long sBox[4 * 256];					/* Key dependent S-box */
98
    unsigned long subKeys[TwoFish_TOTAL_SUBKEYS];	/* Subkeys  */
99
	unsigned char key[TwoFish_KEY_LENGTH];			/* Encryption Key */
100
    unsigned char *output;							/* Pointer to output buffer */
101
	unsigned char qBlockPlain[TwoFish_BLOCK_SIZE];	/* Used by CBC */
102
	unsigned char qBlockCrypt[TwoFish_BLOCK_SIZE];
103
	unsigned char prevCipher[TwoFish_BLOCK_SIZE];
104
	struct 				/* Header for crypt functions. Has to be at least one block long. */
105
	{	unsigned long salt;							/* Random salt in first block (will salt the rest through CBC) */
106
		unsigned char length[4];					/* The amount of data following the header */
107
		unsigned char magic[TwoFish_MAGIC_LEN];		/* Magic to identify successful decryption  */
108
	}	header;	
109
	bool qBlockDefined;
110
	bool dontflush;
111
}	TWOFISH;
112
113
#ifndef __TWOFISH_LIBRARY_SOURCE__
114
115
extern bool TwoFish_srand;					/* if set to TRUE (default), first call of TwoFishInit will seed rand();  */
116
											/* call of TwoFishInit */
117
#endif
118
119
120
/**** Public Functions ****/
121
122
/*	TwoFish Initialization
123
 *
124
 *	This routine generates a global data structure for use with TwoFish,
125
 *	initializes important values (such as subkeys, sBoxes), generates subkeys
126
 *	and precomputes the MDS matrix if not already done.
127
 *	
128
 *	Input:	User supplied password (will be appended by default password of 'SnortHas2FishEncryptionRoutines!')
129
 *
130
 *  Output:	Pointer to TWOFISH structure. This data structure contains key dependent data.
131
 *			This pointer is used with all other crypt functions.
132
 */
133
TWOFISH *TwoFishInit(char *userkey);
134
135
136
/*	TwoFish Destroy
137
 *
138
 *	Nothing else but a free...
139
 *	
140
 *	Input:	Pointer to the TwoFish structure.
141
 *
142
 */
143
void TwoFishDestroy(TWOFISH *tfdata);
144
145
146
/*	TwoFish Alloc
147
 *
148
 *	Allocates enough memory for the output buffer as required.
149
 *
150
 *	Input:	Length of the plaintext.
151
 *			Boolean flag for BinHex Output.
152
 *			Pointer to the TwoFish structure.
153
 *
154
 *	Output:	Returns a pointer to the memory allocated.
155
 */
156
void *TwoFishAlloc(unsigned long len,bool binhex,bool decrypt,TWOFISH *tfdata);
157
158
159
/*	TwoFish Free
160
 *
161
 *	Free's the allocated buffer.
162
 *
163
 *	Input:	Pointer to the TwoFish structure
164
 *
165
 *	Output:	(none)
166
 */
167
void TwoFishFree(TWOFISH *tfdata);
168
169
170
/*	TwoFish Set Output
171
 *
172
 *	If you want to allocate the output buffer yourself,
173
 *	then you can set it with this function.
174
 *
175
 *	Input:	Pointer to your output buffer
176
 *			Pointer to the TwoFish structure
177
 *
178
 *	Output:	(none)
179
 */
180
void TwoFishSetOutput(char *outp,TWOFISH *tfdata);
181
182
183
/*	TwoFish Raw Encryption
184
 *	
185
 *	Does not use header, but does use CBC (if more than one block has to be encrypted).
186
 *
187
 *	Input:	Pointer to the buffer of the plaintext to be encrypted.
188
 *			Pointer to the buffer receiving the ciphertext.
189
 *			The length of the plaintext buffer.
190
 *			The TwoFish structure.
191
 *
192
 *	Output:	The amount of bytes encrypted if successful, otherwise 0.
193
 */
194
unsigned long TwoFishEncryptRaw(char *in,char *out,unsigned long len,TWOFISH *tfdata);
195
196
/*	TwoFish Raw Decryption 
197
 *	
198
 *	Does not use header, but does use CBC (if more than one block has to be decrypted).
199
 *
200
 *	Input:	Pointer to the buffer of the ciphertext to be decrypted.
201
 *			Pointer to the buffer receiving the plaintext.
202
 *			The length of the ciphertext buffer (at least one cipher block).
203
 *			The TwoFish structure.
204
 *
205
 *	Output:	The amount of bytes decrypted if successful, otherwise 0.
206
 */
207
unsigned long TwoFishDecryptRaw(char *in,char *out,unsigned long len,TWOFISH *tfdata);
208
209
210
/*	TwoFish Encryption 
211
 *	
212
 *	Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
213
 *  this routine will alloc the memory. In addition, it will include a small 'header'
214
 *  containing the magic and some salt. That way the decrypt routine can check if the 
215
 *  packet got decrypted successfully, and return 0 instead of garbage.
216
 *
217
 *	Input:	Pointer to the buffer of the plaintext to be encrypted.
218
 *			Pointer to the pointer to the buffer receiving the ciphertext.
219
 *				The pointer either points to user allocated output buffer space, or to NULL, in which case
220
 *				this routine will set the pointer to the buffer allocated through the struct.
221
 *			The length of the plaintext buffer.
222
 *				Can be -1 if the input is a null terminated string, in which case we'll count for you.
223
 *			Boolean flag for BinHex Output (if used, output will be twice as large as input).
224
 *				Note: BinHex conversion overwrites (converts) input buffer!
225
 *			The TwoFish structure.
226
 *
227
 *	Output:	The amount of bytes encrypted if successful, otherwise 0.
228
 */
229
unsigned long TwoFishEncrypt(char *in,char **out,signed long len,bool binhex,TWOFISH *tfdata);
230
231
232
/*	TwoFish Decryption 
233
 *	
234
 *	Uses header and CBC. If the output area has not been intialized with TwoFishAlloc,
235
 *  this routine will alloc the memory. In addition, it will check the small 'header'
236
 *  containing the magic. If magic does not match we return 0. Otherwise we return the 
237
 *  amount of bytes decrypted (should be the same as the length in the header).
238
 *
239
 *	Input:	Pointer to the buffer of the ciphertext to be decrypted.
240
 *			Pointer to the pointer to the buffer receiving the plaintext.
241
 *				The pointer either points to user allocated output buffer space, or to NULL, in which case
242
 *				this routine will set the pointer to the buffer allocated through the struct.
243
 *			The length of the ciphertext buffer.
244
 *				Can be -1 if the input is a null terminated binhex string, in which case we'll count for you.
245
 *			Boolean flag for BinHex Input (if used, plaintext will be half as large as input).
246
 *				Note: BinHex conversion overwrites (converts) input buffer!
247
 *			The TwoFish structure.
248
 *
249
 *	Output:	The amount of bytes decrypted if successful, otherwise 0.
250
 */
251
unsigned long TwoFishDecrypt(char *in,char **out,signed long len,bool binhex,TWOFISH *tfdata);
252
253
254
/**** Private Functions ****/
255
256
unsigned char TwoFish__b(unsigned long x,int n);
257
void _TwoFish_BinHex(unsigned char *buf,unsigned long len,bool bintohex);
258
unsigned long _TwoFish_CryptRawCBC(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata);
259
unsigned long _TwoFish_CryptRaw16(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata);
260
unsigned long _TwoFish_CryptRaw(char *in,char *out,unsigned long len,bool decrypt,TWOFISH *tfdata);
261
void _TwoFish_PrecomputeMDSmatrix(void);	
262
void _TwoFish_MakeSubKeys(TWOFISH *tfdata);	
263
void _TwoFish_qBlockPush(unsigned char *p,unsigned char *c,TWOFISH *tfdata);
264
void _TwoFish_qBlockPop(unsigned char *p,unsigned char *c,TWOFISH *tfdata);
265
void _TwoFish_ResetCBC(TWOFISH *tfdata);
266
void _TwoFish_FlushOutput(unsigned char *b,unsigned long len,TWOFISH *tfdata);
267
void _TwoFish_BlockCrypt(unsigned char *in,unsigned char *out,unsigned long size,int decrypt,TWOFISH *tfdata);
268
void _TwoFish_BlockCrypt16(unsigned char *in,unsigned char *out,bool decrypt,TWOFISH *tfdata);
269
unsigned long _TwoFish_RS_MDS_Encode(unsigned long k0,unsigned long k1);
270
unsigned long _TwoFish_F32(unsigned long k64Cnt,unsigned long x,unsigned long *k32);
271
unsigned long _TwoFish_Fe320(unsigned long *lsBox,unsigned long x);
272
unsigned long _TwoFish_Fe323(unsigned long *lsBox,unsigned long x);
273
unsigned long _TwoFish_Fe32(unsigned long *lsBox,unsigned long x,unsigned long R);
274
275
276
#endif

Return to bug 245752