1 /* $Id: ssp_iptables.c,v 2.9 2008/12/17 22:16:23 fknobbe Exp $
2  *
3  *
4  * Copyright (c) 2003-2008 Fabizio Tivano <fabrizio@sad.it>
5  * Copyright (c) 2008 Modifications by Luis Marichal <luismarichal@gmail.com>
6  * All rights reserved.
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_iptables.c
30  *
31  * Purpose:
32  *
33  * This SnortSam plugin is meant for dynamic (un)blocking on iptables firewall,
34  * SnortSam will expire the blocks itself with  automatic time-out functionality.
35  *
36  *
37  *
38  *
39  *
40  *
41  *
42  */
43 
44 
45 #ifdef	Linux
46 
47 #ifndef		__SSP_IPT_C__
48 #define		__SSP_IPT_C__
49 
50 #include "snortsam.h"
51 #include "ssp_iptables.h"
52 
53 #include <sys/types.h>
54 #include <stdio.h>
55 #include <string.h>
56 #include <time.h>
57 #include <netinet/in.h>
58 #include <arpa/inet.h>
59 
60 
61 /* Set this if you want IP tables to save the tables after every (un)block. */
62 
63 /* #define SAVETABLES */
64 
65 
66 
67 /* This routine parses the ipf statements in the config file.
68 */
IPTParse(char * val,char * file,unsigned long line,DATALIST * plugindatalist)69 void IPTParse(char *val,char *file,unsigned long line,DATALIST *plugindatalist)
70 {	IPTDATA *iptp=NULL;
71 	char *p2, msg[STRBUFSIZE+2];
72 
73 #ifdef FWSAMDEBUG
74 	printf("Debug: [iptables] Plugin Parsing...\n");
75 #endif
76 
77 	if(*val)
78 	{	p2=val;
79 		while(*p2 && !myisspace(*p2)) p2++;
80 		if(*p2) *p2++ =0;
81 		iptp=safemalloc(sizeof(IPTDATA),"IPTParse","iptp");
82 		plugindatalist->data=iptp;
83 		safecopy(iptp->iface,val);	/* save interface */
84 
85 		if(*p2)	/* if we have a loglevel defined */
86 		{	while(*p2 && myisspace(*p2)) p2++;
87 			safecopy(iptp->loglv,p2); 		/* loglevel defined */
88 		} else {
89 			safecopy(iptp->loglv,IPTLOGLEVEL); 	/* use default loglevel */
90 		}
91 
92 #ifdef FWSAMDEBUG
93 		printf("Debug: [iptables] Adding IPTABLES: interface \"%s\", loglevel \"%s\"\n", iptp->iface, iptp->loglv);
94 #endif
95 
96 	}
97 	else
98 	{	snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] IPTABLES defined without parameters!",file,line);
99 		logmessage(1,msg,"iptables",0);
100 	}
101 }
102 
103 
104 /* This routine initiates the block.
105  */
IPTBlock(BLOCKINFO * bd,void * data,unsigned long qp)106 void IPTBlock(BLOCKINFO *bd,void *data,unsigned long qp)
107 {   IPTDATA *iptp;
108 	char iptcmd[255], iptcmd2[255], msg[STRBUFSIZE+2];
109 	/*Nuevo*/
110 	char iptcmd1[255],iptcmd4[255];
111 #ifdef SAVETABLES
112 	const char savecmd[]="/sbin/iptables-save -c > /etc/sysconfig/iptables";
113 #endif
114 
115 #ifdef FWSAMDEBUG
116 	pthread_t threadid=pthread_self();
117 #endif
118 
119 	if(!data) return;
120 		iptp=(IPTDATA *)data;
121 
122 #ifdef FWSAMDEBUG
123 	printf("Debug: [iptables][%lx] Plugin Blocking...\n",threadid);
124 #endif
125 
126 	if(bd->block)
127 	{ snprintf(msg,sizeof(msg)-1,"Info: Blocking ip %s", inettoa(bd->blockip));
128 	  logmessage(3,msg,"iptables",0);
129 
130 	  switch(bd->mode&FWSAM_HOW)
131 		{	case FWSAM_HOW_IN:
132 	  /* Assemble command */
133 	  if (snprintf(iptcmd,sizeof(iptcmd)-1,
134 		"/sbin/iptables -I FORWARD -i %s  -s %s -j DROP",
135  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd)) {
136                 snprintf(msg,sizeof(msg)-1,"Error: Command %s is too long", iptcmd);
137                 logmessage(1,msg,"iptables",0);
138 		return;
139           }
140 	  if (snprintf(iptcmd2,sizeof(iptcmd2)-1,
141 		"/sbin/iptables -I INPUT -i %s  -s %s -j DROP",
142  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd2)) {
143                 snprintf(msg,sizeof(msg)-1,"Error: Command2 %s is too long", iptcmd2);
144                 logmessage(1,msg,"iptables",0);
145 		return;
146           }
147 		  break;
148 		  case FWSAM_HOW_OUT:
149 	  /* Assemble command */
150 	  if (snprintf(iptcmd,sizeof(iptcmd)-1,
151 		"/sbin/iptables -I FORWARD -i %s  -d %s -j DROP",
152  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd)) {
153                 snprintf(msg,sizeof(msg)-1,"Error: Command %s is too long", iptcmd);
154                 logmessage(1,msg,"iptables",0);
155 		return;
156           }
157 	  if (snprintf(iptcmd2,sizeof(iptcmd2)-1,
158 		"/sbin/iptables -I INPUT -i %s  -d %s -j DROP",
159  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd2)) {
160                 snprintf(msg,sizeof(msg)-1,"Error: Command2 %s is too long", iptcmd2);
161                 logmessage(1,msg,"iptables",0);
162 		return;
163           }
164 		  break;
165 		  case FWSAM_HOW_INOUT:
166 	  /* Assemble command - block src*/
167 		if ((snprintf(iptcmd,sizeof(iptcmd)-1,
168 		"/sbin/iptables -I FORWARD -i %s  -s %s -j DROP",
169  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd)) || (snprintf(iptcmd1,sizeof(iptcmd1)-1,
170 		"/sbin/iptables -I FORWARD -i %s  -d %s -j DROP",
171  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd1))) {
172                 snprintf(msg,sizeof(msg)-1,"Error: Command %s is too long", iptcmd);
173                 logmessage(1,msg,"iptables",0);
174 		return;
175           }
176 		if ((snprintf(iptcmd2,sizeof(iptcmd2)-1,
177 		"/sbin/iptables -I INPUT -i %s  -s %s -j DROP",
178  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd2)) || (snprintf(iptcmd4,sizeof(iptcmd4)-1,
179 		"/sbin/iptables -I INPUT -i %s  -d %s -j DROP",
180  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd4))) {
181                 snprintf(msg,sizeof(msg)-1,"Error: Command2 %s is too long", iptcmd2);
182                 logmessage(1,msg,"iptables",0);
183 		return;
184           }
185 		  break;
186 		  case FWSAM_HOW_THIS:
187 	  /* Assemble command */
188 	  if (snprintf(iptcmd,sizeof(iptcmd)-1,
189 		"/sbin/iptables -I FORWARD -i %s  -s %s  -d %s  -p %d  --dport %d -j DROP",
190  		iptp->iface, inettoa(bd->blockip), inettoa(bd->peerip), bd->proto, bd->port) >= sizeof(iptcmd)) {
191                 snprintf(msg,sizeof(msg)-1,"Error: Command %s is too long", iptcmd);
192                 logmessage(1,msg,"iptables",0);
193 		return;
194           }
195 	  if (snprintf(iptcmd2,sizeof(iptcmd2)-1,
196 		"/sbin/iptables -I INPUT -i %s  -s %s  -d %s  -p %d  --dport %d -j DROP",
197  		iptp->iface, inettoa(bd->blockip), inettoa(bd->peerip), bd->proto, bd->port) >= sizeof(iptcmd2)) {
198                 snprintf(msg,sizeof(msg)-1,"Error: Command2 %s is too long", iptcmd2);
199                 logmessage(1,msg,"iptables",0);
200 		return;
201           }
202 		  break;
203 		  }
204 	}
205 	else
206 	{
207 	  snprintf(msg,sizeof(msg)-1,"Info: UnBlocking ip %s", inettoa(bd->blockip));
208 	  logmessage(1,msg,"iptables",0);
209 switch(bd->mode&FWSAM_HOW)
210 	{	case FWSAM_HOW_IN:
211           /* Assemble command */
212           if (snprintf(iptcmd,sizeof(iptcmd)-1,
213 		"/sbin/iptables -D FORWARD -i %s  -s %s -j DROP",
214 	  	iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd)) {
215                 snprintf(msg,sizeof(msg)-1,"Error: Command %s is too long", iptcmd);
216                 logmessage(1,msg,"iptables",0);
217 		return;
218         }
219 	    if (snprintf(iptcmd2,sizeof(iptcmd2)-1,
220 		"/sbin/iptables -D INPUT -i %s  -s %s -j DROP",
221 	  	iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd2)) {
222                 snprintf(msg,sizeof(msg)-1,"Error: Command2 %s is too long", iptcmd2);
223                 logmessage(1,msg,"iptables",0);
224 		return;
225 	    }
226 		break;
227 		case FWSAM_HOW_OUT:
228 		 /* Assemble command */
229           if (snprintf(iptcmd,sizeof(iptcmd)-1,
230 		"/sbin/iptables -D FORWARD -i %s  -d %s -j DROP",
231 	  	iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd)) {
232                 snprintf(msg,sizeof(msg)-1,"Error: Command %s is too long", iptcmd);
233                 logmessage(1,msg,"iptables",0);
234 		return;
235         }
236 	    if (snprintf(iptcmd2,sizeof(iptcmd2)-1,
237 		"/sbin/iptables -D INPUT -i %s  -d %s -j DROP",
238 	  	iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd2)) {
239                 snprintf(msg,sizeof(msg)-1,"Error: Command2 %s is too long", iptcmd2);
240                 logmessage(1,msg,"iptables",0);
241 		return;
242 	    }
243 		break;
244 		case FWSAM_HOW_INOUT:
245 	  /* Assemble command - block src*/
246 		if ((snprintf(iptcmd,sizeof(iptcmd)-1,
247 		"/sbin/iptables -D FORWARD -i %s  -s %s -j DROP",
248  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd)) || (snprintf(iptcmd1,sizeof(iptcmd1)-1,
249 		"/sbin/iptables -D FORWARD -i %s  -d %s -j DROP",
250  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd1))) {
251                 snprintf(msg,sizeof(msg)-1,"Error: Command %s is too long", iptcmd);
252                 logmessage(1,msg,"iptables",0);
253 		return;
254           }
255 		if ((snprintf(iptcmd2,sizeof(iptcmd2)-1,
256 		"/sbin/iptables -D INPUT -i %s  -s %s -j DROP",
257  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd2)) || (snprintf(iptcmd4,sizeof(iptcmd4)-1,
258 		"/sbin/iptables -D INPUT -i %s  -d %s -j DROP",
259  		iptp->iface, inettoa(bd->blockip)) >= sizeof(iptcmd4))) {
260                 snprintf(msg,sizeof(msg)-1,"Error: Command2 %s is too long", iptcmd2);
261                 logmessage(1,msg,"iptables",0);
262 		return;
263           }
264 		  break;
265 		  case FWSAM_HOW_THIS:
266 	  /* Assemble command */
267 	  if (snprintf(iptcmd,sizeof(iptcmd)-1,
268 		"/sbin/iptables -D FORWARD -i %s  -s %s  -d %s  -p %d  --dport %d -j DROP",
269  		iptp->iface, inettoa(bd->blockip), inettoa(bd->peerip), bd->proto, bd->port) >= sizeof(iptcmd)) {
270                 snprintf(msg,sizeof(msg)-1,"Error: Command %s is too long", iptcmd);
271                 logmessage(1,msg,"iptables",0);
272 		return;
273           }
274 	  if (snprintf(iptcmd2,sizeof(iptcmd2)-1,
275 		"/sbin/iptables -D INPUT -i %s  -s %s  -d %s  -p %d  --dport %d -j DROP",
276  		iptp->iface, inettoa(bd->blockip), inettoa(bd->peerip), bd->proto, bd->port) >= sizeof(iptcmd)) {
277                 snprintf(msg,sizeof(msg)-1,"Error: Command2 %s is too long", iptcmd2);
278                 logmessage(1,msg,"iptables",0);
279 		return;
280           }
281 		  break;
282 		}
283 	}
284 #ifdef FWSAMDEBUG
285         printf("Debug: [iptables][%lx] command  %s\n", threadid, iptcmd);
286         printf("Debug: [iptables][%lx] command2 %s\n", threadid, iptcmd2);
287 #endif
288 	/* Run the command */
289         if (system(iptcmd) != 0) {
290 		snprintf(msg,sizeof(msg)-1,"Error: Command %s Failed", iptcmd);
291 		logmessage(3,msg,"iptables",0);
292 	} else {
293                 snprintf(msg,sizeof(msg)-1,"Info: Command %s Executed Successfully", iptcmd);
294                 logmessage(3,msg,"iptables",0);
295 	}
296         if (system(iptcmd2) != 0) {
297 		snprintf(msg,sizeof(msg)-1,"Error: Command2 %s Failed", iptcmd2);
298 		logmessage(1,msg,"iptables",0);
299 	} else {
300                 snprintf(msg,sizeof(msg)-1,"Info: Command2 %s Executed Successfully", iptcmd2);
301                 logmessage(3,msg,"iptables",0);
302 	}
303 
304 /*inventiva-recorte*/
305 	if((bd->mode&FWSAM_HOW)==FWSAM_HOW_INOUT)
306 	{
307 		if (system(iptcmd1) != 0) {
308 			snprintf(msg,sizeof(msg)-1,"Error: Command %s Failed", iptcmd1);
309 			logmessage(3,msg,"iptables",0);
310 		} else {
311 					snprintf(msg,sizeof(msg)-1,"Info: Command %s Executed Successfully", iptcmd1);
312 					logmessage(3,msg,"iptables",0);
313 		}
314 			if (system(iptcmd4) != 0) {
315 			snprintf(msg,sizeof(msg)-1,"Error: Command2 %s Failed", iptcmd4);
316 			logmessage(1,msg,"iptables",0);
317 		} else {
318 				snprintf(msg,sizeof(msg)-1,"Info: Command2 %s Executed Successfully", iptcmd4);
319                 logmessage(3,msg,"iptables",0);
320 		}
321 	}
322 
323 
324 #ifdef SAVETABLES
325 /* Save command */
326         if (system(savecmd) != 0) {
327             snprintf(msg,sizeof(msg)-1,"Error: Save command %s Failed",savecmd);
328          logmessage(1,msg,"iptables",0);
329  } else {
330                 snprintf(msg,sizeof(msg)-1,"Info: Save command %s Executed Successfully", savecmd);
331                 logmessage(3,msg,"iptables",0);
332  }
333 #endif
334 
335 	return;
336 }
337 
338 #endif /* __SSP_IPT_C__ */
339 #endif /* Linux */
340 
341 
342