1 /* $Id: ssp_ipfw2.c,v 2.4 2008/04/26 19:53:21 fknobbe Exp $
2  *
3  *
4  * Copyright (c) 2005-2008 Robert Rolfe <rob@wehostwebpages.com>, Frank Knobbe <frank@knobbe.us>
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_ipfw2.c
30  *
31  * Purpose:
32  *
33  * This SnortSam plugin is meant for dynamic blocking on IPFW2 firewalls.
34  * SnortSam will expire the blocks itself since IPFW2 does not have
35  * automatic time-out functionality.
36  *
37  */
38 
39 
40 #if defined(FreeBSD)
41 
42 #ifndef		__SSP_IPFW2_C__
43 #define		__SSP_IPFW2_C__
44 
45 #include "snortsam.h"
46 #include "ssp_ipfw2.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 */
IPFW2Parse(char * val,char * file,unsigned long line,DATALIST * plugindatalist)59 void IPFW2Parse(char *val,char *file,unsigned long line,DATALIST *plugindatalist)
60 {	IPFW2DATA *ipfw2p=NULL;
61 	char *p2,msg[STRBUFSIZE+2],chk[STRBUFSIZE+2];
62 
63 #ifdef FWSAMDEBUG
64 	printf("Debug: [ipfw2] Plugin Parsing...\n");
65 #endif
66 
67 	if(*val)
68 	{	p2=val;
69 		while(*p2 && !myisspace(*p2)) p2++;
70 		if(*p2) *p2++ =0;
71 		ipfw2p=safemalloc(sizeof(IPFW2DATA),"IPFW2Parse","ipfw2p");
72 		plugindatalist->data=ipfw2p;
73 		safecopy(ipfw2p->interface,val);	/* save interface */
74 		ipfw2p->in_table=1;					/* Setting defaults for the tables */
75 		ipfw2p->out_table=2;
76 		if(*p2)
77 		{	while(*p2 && myisspace(*p2)) p2++;
78 			if(*p2)
79 			{	val=p2;
80 				while(*p2 && !myisspace(*p2)) p2++;
81 				if(*p2) *p2++ =0;
82 				ipfw2p->in_table=(unsigned short)atoi(val);
83 				if(*p2)
84 				{	while(*p2 && myisspace(*p2)) p2++;
85 					if(*p2)
86 					{	val=p2;
87 						while(*p2 && !myisspace(*p2)) p2++;
88 						if(*p2) *p2++ =0;
89 						ipfw2p->out_table=(unsigned short)atoi(val);
90 					}
91 				}
92 			}
93 		}
94 		/* Check if inbound table exists */
95 		snprintf(chk,sizeof(chk)-1,"/sbin/ipfw show | grep -q \"deny ip from any to table(%u) via %s\"",ipfw2p->in_table,ipfw2p->interface);
96 		if(system(chk))
97 		{	/* We just exist with an error for now. In the future, we'll set up the table automatically */
98 			snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] Inbound block table (%u) not defined!",file,line,ipfw2p->in_table);
99 			logmessage(1,msg,"ipfw2",0);
100 			free(ipfw2p);
101 			plugindatalist->data=NULL;
102 		}
103 		else	/* Check if oubound table exists */
104 		{	snprintf(chk,sizeof(chk)-1,"/sbin/ipfw show | grep -q \"deny ip from table(%u) to any via %s\"",ipfw2p->out_table,ipfw2p->interface);
105 			if(system(chk))
106 			{	snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] Outbound block table (%u) not defined!",file,line,ipfw2p->out_table);
107 				logmessage(1,msg,"ipfw2",0);
108 				free(ipfw2p);
109 				plugindatalist->data=NULL;
110 			}
111 		}
112 
113 #ifdef FWSAMDEBUG
114 		if(plugindatalist->data)
115 			printf("Debug: [ipfw2] Adding IPFW2: i/f '%s', tables %u (in) and %u (out)\n", ipfw2p->interface, ipfw2p->in_table,ipfw2p->out_table);
116 #endif
117 	}
118 	else
119 	{	snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] IPFW2 defined without parameters!",file,line);
120 		logmessage(1,msg,"ipfw2",0);
121 	}
122 }
123 
124 
125 /* This routine initiates the block.
126  */
IPFW2Block(BLOCKINFO * bd,void * data,unsigned long qp)127 void IPFW2Block(BLOCKINFO *bd,void *data,unsigned long qp)
128 {	IPFW2DATA *ipfw2p;
129 	int ret;
130 	char ipfw2cmd[STRBUFSIZE+2],msg[STRBUFSIZE+2];
131 
132 #ifdef FWSAMDEBUG
133 	pthread_t threadid=pthread_self();
134 #endif
135 
136 	if(!data) return;
137 	ipfw2p=(IPFW2DATA *)data;
138 
139 #ifdef FWSAMDEBUG
140 	printf("Debug: [ipfw2][%lx] Plugin Blocking...\n",(unsigned long)threadid);
141 #endif
142 
143 	switch(bd->mode&FWSAM_HOW)
144 	{	case FWSAM_HOW_IN:		ret=snprintf(ipfw2cmd,sizeof(ipfw2cmd)-1,
145 								"/sbin/ipfw table %u %s %s/32",
146 								ipfw2p->in_table, bd->block?"add":"delete",inettoa(bd->blockip));
147 								break;
148 		case FWSAM_HOW_OUT:		ret=snprintf(ipfw2cmd,sizeof(ipfw2cmd)-1,
149 								"/sbin/ipfw table %u %s %s/32",
150 								ipfw2p->out_table, bd->block?"add":"delete",inettoa(bd->blockip));
151 								break;
152 		case FWSAM_HOW_INOUT:;
153 		default:				ret=snprintf(ipfw2cmd,sizeof(ipfw2cmd)-1,
154 								"/sbin/ipfw table %u %s %s/32;/sbin/ipfw table %u %s %s/32",
155 								ipfw2p->in_table, bd->block?"add":"delete",inettoa(bd->blockip),
156 								ipfw2p->out_table, bd->block?"add":"delete",inettoa(bd->blockip));
157 								break;
158 	}
159 	if(ret >= sizeof(ipfw2cmd)-1)
160 	{	snprintf(msg,sizeof(msg)-1,"Error: Command %s is too long", ipfw2cmd);
161 		logmessage(1,msg,"ipfw2",0);
162 	}
163 	else
164 	{
165 #ifdef FWSAMDEBUG
166 		printf("Debug: [ipfw2][%lx] command \"%s\"\n", (unsigned long)threadid, ipfw2cmd);
167 #endif
168 		/* Run the command */
169 		if ((system(ipfw2cmd) && 0xff) )
170 		{	snprintf(msg,sizeof(msg)-1,"Error: Command \"%s\" Failed", ipfw2cmd);
171 			logmessage(1,msg,"ipfw2",0);
172 		}
173 		else
174 		{	snprintf(msg,sizeof(msg)-1,"Info: Command \"%s\" Executed Successfully", ipfw2cmd);
175 			logmessage(3,msg,"ipfw2",0);
176 		}
177 	}
178 }
179 
180 #endif /* __SSP_IPFW2_C__ */
181 #endif /* FreeBSD */
182