1 /* $Id: ssp_ipf.c,v 2.16 2008/04/26 19:53:21 fknobbe Exp $
2  *
3  *
4  * Copyright (c) 2002-2008 Frank Knobbe <frank@knobbe.us>, Erik Sneep <erik@webflex.nl>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  *
29  * ssp_ipf.c
30  *
31  * Purpose:
32  *
33  * This SnortSam plugin is meant for dynamic (un)blocking on IPFilter firewall,
34  * SnortSam will expire the blocks itself since IPFilter does not have
35  * automatic time-out functionality.
36  *
37  */
38 
39 
40 #if !defined(WIN32) && !defined(Linux)
41 
42 #ifndef		__SSP_IPF_C__
43 #define		__SSP_IPF_C__
44 
45 #include "snortsam.h"
46 #include "ssp_ipf.h"
47 
48 
49 #include <sys/types.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include <time.h>
53 #include <netinet/in.h>
54 #include <arpa/inet.h>
55 
56 
57 /* This routine parses the ipf statements in the config file.
58 */
IPFParse(char * val,char * file,unsigned long line,DATALIST * plugindatalist)59 void IPFParse(char *val,char *file,unsigned long line,DATALIST *plugindatalist)
60 {	IPFDATA *ipfp=NULL;
61 	char *p2, msg[STRBUFSIZE+2];
62 
63 #ifdef FWSAMDEBUG
64 	printf("Debug: [ipf] Plugin Parsing...\n");
65 #endif
66 
67 	if(*val)
68 	{	p2=val;
69 		while(*p2 && !myisspace(*p2)) p2++;
70 		if(*p2) *p2++ =0;
71 		ipfp=safemalloc(sizeof(IPFDATA),"IPFParse","ipfp");
72 		plugindatalist->data=ipfp;
73 		safecopy(ipfp->iface,val);	/* save interface */
74 
75 		if(*p2)	/* if we have a loglevel defined */
76 		{	while(*p2 && myisspace(*p2)) p2++;
77 			safecopy(ipfp->loglv,p2); 		/* loglevel defined */
78 		} else {
79 			safecopy(ipfp->loglv,IPFLOGLEVEL); 	/* use default loglevel */
80 		}
81 
82 #ifdef FWSAMDEBUG
83 		printf("Debug: [ipf] Adding IPF: interface \"%s\", loglevel \"%s\"\n", ipfp->iface, ipfp->loglv);
84 #endif
85 
86 	}
87 	else
88 	{	snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] IPF defined without parameters!",file,line);
89 		logmessage(1,msg,"ipf",0);
90 	}
91 }
92 
93 
94 /* This routine initiates the block.
95  */
IPFBlock(BLOCKINFO * bd,void * data,unsigned long qp)96 void IPFBlock(BLOCKINFO *bd,void *data,unsigned long qp)
97 {   IPFDATA *ipfp;
98 	int ret;
99 	char ipfcmd[STRBUFSIZE+2], msg[STRBUFSIZE+2], interf[STRBUFSIZE+2]="";
100 #ifdef FWSAMDEBUG
101 	pthread_t threadid=pthread_self();
102 #endif
103 
104 	if(!data) return;
105 	ipfp=(IPFDATA *)data;
106 
107 #ifdef FWSAMDEBUG
108 	printf("Debug: [ipf][%lx] Plugin Blocking...\n",(unsigned long)threadid);
109 #endif
110 
111 	if(bd->block)
112 	{ 	snprintf(msg,sizeof(msg)-1,"Info: Blocking IP %s", inettoa(bd->blockip));
113 	  	logmessage(3,msg,"ipf",0);
114 	}
115 	else
116 	{	snprintf(msg,sizeof(msg)-1,"Info: Unblocking IP %s", inettoa(bd->blockip));
117 	  	logmessage(3,msg,"ipf",0);
118 	}
119 	if(stricmp(ipfp->iface,"any"))
120 		snprintf(interf,sizeof(interf)-1,"on %s",ipfp->iface);
121 
122 
123 	/* Assemble command */
124 	switch(bd->mode&FWSAM_HOW)
125 	{	case FWSAM_HOW_IN:		if(bd->mode&FWSAM_WHO == FWSAM_WHO_SRC)
126 	  							{	ret=snprintf(ipfcmd,sizeof(ipfcmd)-1,
127 									"echo \"@1 block in log level %s quick %s from %s/32 to any\"|/sbin/ipf -%sf -",
128 									ipfp->loglv, interf, inettoa(bd->blockip), bd->block?"":"r");
129 								}
130 								else
131 	  							{	ret=snprintf(ipfcmd,sizeof(ipfcmd)-1,
132 									"echo \"@1 block in log level %s quick %s from any to %s/32\"|/sbin/ipf -%sf -",
133 									ipfp->loglv, interf, inettoa(bd->blockip), bd->block?"":"r");
134 								}
135 
136 								break;
137 	  	case FWSAM_HOW_OUT:		if(bd->mode&FWSAM_WHO == FWSAM_WHO_SRC)
138 	  							{	ret=snprintf(ipfcmd,sizeof(ipfcmd)-1,
139 									"echo \"@1 block out log level %s quick %s from any to %s/32\"|/sbin/ipf -%sf -",
140 									ipfp->loglv, interf, inettoa(bd->blockip), bd->block?"":"r");
141 								}
142 								else
143 	  							{	ret=snprintf(ipfcmd,sizeof(ipfcmd)-1,
144 									"echo \"@1 block out log level %s quick %s from %s/32 to any\"|/sbin/ipf -%sf -",
145 									ipfp->loglv, interf, inettoa(bd->blockip), bd->block?"":"r");
146 								}
147 
148 								break;
149 	  	case FWSAM_HOW_THIS:	if(bd->proto==6 || bd->proto==17)
150 								{	if(bd->mode&FWSAM_WHO == FWSAM_WHO_SRC)
151 									{	ret=snprintf(ipfcmd,sizeof(ipfcmd)-1,
152 										"echo \"@1 block in log level %s quick %s proto %s from %s/32 to %s/32 port = %i\"|/sbin/ipf -%sf -",
153 										ipfp->loglv, interf, bd->proto==6?"tcp":"udp", inettoa(bd->blockip),inettoa(bd->peerip), bd->port, bd->block?"":"r");
154 									}
155 									else
156 									{	ret=snprintf(ipfcmd,sizeof(ipfcmd)-1,
157 										"echo \"@1 block in log level %s quick %s proto %s from %s/32 to %s/32 port = %i\"|/sbin/ipf -%sf -",
158 										ipfp->loglv, interf, bd->proto==6?"tcp":"udp", inettoa(bd->blockip),inettoa(bd->peerip), bd->port, bd->block?"":"r");
159 									}
160 								}
161 								else
162 								{	if(bd->mode&FWSAM_WHO == FWSAM_WHO_SRC)
163 									{	ret=snprintf(ipfcmd,sizeof(ipfcmd)-1,
164 										"echo \"@1 block in log level %s quick %s proto %i from %s/32 to %s/32\"|/sbin/ipf -%sf -",
165 										ipfp->loglv, interf, bd->proto, inettoa(bd->blockip), inettoa(bd->peerip), bd->block?"":"r");
166 									}
167 									else
168 									{	ret=snprintf(ipfcmd,sizeof(ipfcmd)-1,
169 										"echo \"@1 block in log level %s quick %s proto %i from %s/32 to %s/32\"|/sbin/ipf -%sf -",
170 										ipfp->loglv, interf, bd->proto, inettoa(bd->blockip), inettoa(bd->peerip), bd->block?"":"r");
171 									}
172 								}
173 								break;
174 	  	case FWSAM_HOW_INOUT:
175 		default:				ret=snprintf(ipfcmd,sizeof(ipfcmd)-1,
176 								"echo \"@1 block in log level %s quick %s from %s/32 to any\"|/sbin/ipf -%sf -;echo \"@1 block out log level %s quick %s from any to %s/32\"|/sbin/ipf -%sf -;",
177 								ipfp->loglv, interf, inettoa(bd->blockip),bd->block?"":"r",ipfp->loglv, interf, inettoa(bd->blockip),bd->block?"":"r");
178 								break;
179 	}
180 	if(ret >= sizeof(ipfcmd))
181 	{	snprintf(msg,sizeof(msg)-1,"Error: Command %s is too long", ipfcmd);
182 		logmessage(1,msg,"ipf",0);
183 		return;
184 	}
185 #ifdef FWSAMDEBUG
186 	printf("Debug: [ipf][%lx] Command: %s\n", (unsigned long)threadid, ipfcmd);
187 #endif
188 	/* Run the command */
189 	if (system(ipfcmd) != 0)
190 	{	snprintf(msg,sizeof(msg)-1,"Error: Command %s Failed", ipfcmd);
191 		logmessage(1,msg,"ipf",0);
192 	}
193 	else
194 	{	snprintf(msg,sizeof(msg)-1,"Info: Command %s Executed Successfully", ipfcmd);
195 		logmessage(3,msg,"ipf",0);
196 	}
197 	return;
198 }
199 
200 #endif /* __SSP_IPF_C__ */
201 #endif /* WIN32 */
202 
203 
204