1 /* $Id: ssp_ipchains.c,v 2.8 2008/04/26 19:53:21 fknobbe Exp $
2 *
3 * Copyright (c) 2002-2008 Hector Paterno <apaterno@dsnsecurity.com>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * ssp_ipchains.c
29 *
30 * Purpose:
31 *
32 * This SnortSam plugin is meant for dynamic (un)blocking on ipchains (Linux) firewall,
33 * SnortSam will expire the blocks itself since ipchains does not have
34 * automatic time-out functionality.
35 *
36 * Todo:
37 *
38 * This is a basic plugin, I'v a lot of ideas to implement on ipchains.
39 *
40 */
41
42
43 #ifdef Linux
44
45 #ifndef __SSP_IPCHAINS_C__
46 #define __SSP_IPCHAINS_C__
47
48
49 #include <stdio.h>
50 #include <string.h>
51 #include <sys/types.h>
52 #include <sys/socket.h>
53 #include <net/if.h>
54 #include <errno.h>
55 #include "snortsam.h"
56 #include "ssp_ipchains.h"
57
58
59 static int sockfd = -1;
60
61
ipfwc_init()62 static int ipfwc_init()
63 {
64 return ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) != -1);
65 }
66
do_setsockopt(int cmd,const void * data,int length)67 static int do_setsockopt(int cmd, const void *data, int length)
68 {
69 return setsockopt(sockfd, IPPROTO_IP, cmd, (char *)data, length) != -1;
70 }
71
72 /*
73 * This routine parses the ipchains statements in the config file.
74 */
75 void
IPCHParse(char * val,char * file,unsigned long line,DATALIST * plugindatalist)76 IPCHParse(char *val, char *file, unsigned long line, DATALIST * plugindatalist)
77 {
78 IPCHDATA *ipchp = NULL;
79 char *p2, msg[STRBUFSIZE + 2];
80
81 #ifdef FWSAMDEBUG
82 printf("Debug: [ipchains] Plugin Parsing...\n");
83 #endif
84
85 if (*val)
86 {
87 p2 = val;
88 while (*p2 && !myisspace(*p2))
89 p2++;
90 if (*p2)
91 *p2++ = 0;
92 ipchp = safemalloc(sizeof(IPCHDATA), "IPCHParse", "ipchp");
93 plugindatalist->data = ipchp;
94 ipchp->logopt = 0;
95 safecopy(ipchp->iface, val); /* save interface */
96
97 if (*p2) /* if we have a log option defined */
98 { while (*p2 && myisspace(*p2)) p2++;
99 if (strcmp(p2, "log") == 0)
100 { ipchp->logopt = 1;
101 }
102 }
103
104 #ifdef FWSAMDEBUG
105 printf("Debug: [ipchains] Adding IPCH: interface \"%s\", log \"%d\"\n", ipchp->iface, ipchp->logopt);
106 #endif
107
108 } else
109 { snprintf(msg, sizeof(msg) - 1, "Error: [%s: %lu] ipchains defined without parameters!", file, line);
110 logmessage(1, msg, "ipchains", 0);
111 }
112
113 }
114
115
116 /*
117 * This routine initiates the block.
118 */
IPCHBlock(BLOCKINFO * bd,void * data,unsigned long qp)119 void IPCHBlock(BLOCKINFO *bd, void *data,unsigned long qp)
120 {
121
122 IPCHDATA * ipchp;
123 struct ip_fwchange newfw;
124 char msg[STRBUFSIZE + 2];
125 int who;
126 #ifdef FWSAMDEBUG
127 pthread_t threadid = pthread_self();
128 #endif
129
130 if (!data)
131 return;
132 ipchp=(IPCHDATA *)data;
133
134 #ifdef FWSAMDEBUG
135 printf("Debug: [ipchains][%lx] Plugin Blocking...\n", threadid);
136 #endif
137
138
139 bzero(&newfw, sizeof(struct ip_fwchange));
140
141 if(ipfwc_init()==-1)
142 {
143 snprintf(msg, sizeof(msg) - 1, "Error: Can't open RAW socket, %s", strerror(errno));
144 logmessage(1, msg, "ipchains", 0);
145 return;
146 }
147
148 newfw.fwc_rule.ipfw.fw_smsk.s_addr = 0xffffffff;
149 memcpy(newfw.fwc_rule.label, IP_FW_LABEL_BLOCK, sizeof(newfw.fwc_rule.label));
150 memcpy(newfw.fwc_rule.ipfw.fw_vianame, ipchp->iface, IFNAMSIZ-1);
151 newfw.fwc_rule.ipfw.fw_tosand = 255;
152 newfw.fwc_rule.ipfw.fw_spts[0] = 0; /* Default all */
153 newfw.fwc_rule.ipfw.fw_spts[1] = 65535;
154 newfw.fwc_rule.ipfw.fw_dpts[0] = 0;
155 newfw.fwc_rule.ipfw.fw_dpts[1] = 65535;
156
157 if(ipchp->logopt)
158 newfw.fwc_rule.ipfw.fw_flg = 0x0001;
159
160 /* Future Improvments via config file
161 newfw.fwc_rule.ipfw.fw_mark =
162 newfw.fwc_rule.ipfw.fw_flg =
163 newfw.fwc_rule.ipfw.fw_invflg =
164 newfw.fwc_rule.ipfw.fw_redirpt =
165 newfw.fwc_rule.ipfw.fw_outputsize =
166 newfw.fwc_rule.ipfw.fw_tosxor = */
167
168 if (bd->block) { // Will block
169 snprintf(msg, sizeof(msg) - 1, "Info: Blocking ip %s", inettoa(bd->blockip));
170 logmessage(1, msg, "ipchains", 0);
171
172 switch (bd->mode & FWSAM_HOW) {
173 case FWSAM_HOW_THIS:
174 memcpy(newfw.fwc_label, IP_FW_LABEL_INPUT, sizeof(newfw.fwc_label));
175 newfw.fwc_rule.ipfw.fw_src.s_addr = (u_int32_t) bd->blockip;
176 newfw.fwc_rule.ipfw.fw_dst.s_addr = (u_int32_t) bd->peerip;
177 newfw.fwc_rule.ipfw.fw_dmsk.s_addr = 0xffffffff;
178 newfw.fwc_rule.ipfw.fw_proto = bd->proto;
179
180 if(bd->port)
181 {
182 newfw.fwc_rule.ipfw.fw_dpts[0] = bd->port;
183 newfw.fwc_rule.ipfw.fw_dpts[1] = bd->port;
184 }
185
186 break;
187
188 default: ; /* IN Rule */
189 case FWSAM_HOW_IN: /* Incoming FROM host ( src ) */
190 memcpy(newfw.fwc_label, IP_FW_LABEL_INPUT, sizeof(newfw.fwc_label));
191 newfw.fwc_rule.ipfw.fw_src.s_addr = (u_int32_t) bd->blockip;
192
193 break;
194
195 case FWSAM_HOW_OUT: /* Outgoing TO host ( dst ) */
196 memcpy(newfw.fwc_label, IP_FW_LABEL_OUTPUT, sizeof(newfw.fwc_label));
197 newfw.fwc_rule.ipfw.fw_dst.s_addr = (u_int32_t) bd->blockip;
198 newfw.fwc_rule.ipfw.fw_smsk.s_addr = 0x0;
199 newfw.fwc_rule.ipfw.fw_dmsk.s_addr = 0xffffffff;
200
201 break;
202
203 case FWSAM_HOW_INOUT: /* Need 2 rules 1 for IN, 1 for OUT */
204
205 /* Incoming FROM */
206 memcpy(newfw.fwc_label, IP_FW_LABEL_INPUT, sizeof(newfw.fwc_label));
207 newfw.fwc_rule.ipfw.fw_src.s_addr = (u_int32_t) bd->blockip;
208
209 if(do_setsockopt(IP_FW_APPEND, &newfw, sizeof(newfw))==-1)
210 {
211 snprintf(msg, sizeof(msg) - 1, "Error: Can't Block ip %s, %s", inettoa(bd->blockip), strerror(errno));
212 logmessage(1, msg, "ipchains", 0);
213 return;
214 }
215
216 /* Outgoing TO */
217 memcpy(newfw.fwc_label, IP_FW_LABEL_OUTPUT, sizeof(newfw.fwc_label));
218 newfw.fwc_rule.ipfw.fw_dst.s_addr = (u_int32_t) bd->blockip;
219 newfw.fwc_rule.ipfw.fw_dmsk.s_addr = 0xffffffff;
220 newfw.fwc_rule.ipfw.fw_smsk.s_addr = 0x0;
221
222 break;
223
224 }
225
226 if(do_setsockopt(IP_FW_APPEND, &newfw, sizeof(newfw))==-1)
227 {
228 snprintf(msg, sizeof(msg) - 1, "Error: Can't Block ip %s, %s", inettoa(bd->blockip), strerror(errno));
229 logmessage(1, msg, "ipchains", 0);
230 return;
231 }
232
233
234 }else{ /* Will unblock */
235 snprintf(msg, sizeof(msg) - 1, "Info: UnBlocking ip %s", inettoa(bd->blockip));
236 logmessage(1, msg, "ipchains", 0);
237
238 switch (bd->mode & FWSAM_HOW) {
239 case FWSAM_HOW_THIS:
240 memcpy(newfw.fwc_label, IP_FW_LABEL_INPUT, sizeof(newfw.fwc_label));
241 newfw.fwc_rule.ipfw.fw_src.s_addr = (u_int32_t) bd->blockip;
242 newfw.fwc_rule.ipfw.fw_dst.s_addr = (u_int32_t) bd->peerip;
243 newfw.fwc_rule.ipfw.fw_dmsk.s_addr = 0xffffffff;
244
245 if(bd->port)
246 {
247 newfw.fwc_rule.ipfw.fw_dpts[0] = bd->port;
248 newfw.fwc_rule.ipfw.fw_dpts[1] = bd->port;
249 }
250
251 break;
252
253 default: ; /* IN Rule */
254 case FWSAM_HOW_IN: /* Incoming FROM host ( src ) */
255 memcpy(newfw.fwc_label, IP_FW_LABEL_INPUT, sizeof(newfw.fwc_label));
256 newfw.fwc_rule.ipfw.fw_src.s_addr = (u_int32_t) bd->blockip;
257
258 break;
259
260 case FWSAM_HOW_OUT: /* Outgoing TO host ( dst ) */
261 memcpy(newfw.fwc_label, IP_FW_LABEL_OUTPUT, sizeof(newfw.fwc_label));
262 newfw.fwc_rule.ipfw.fw_dst.s_addr = (u_int32_t) bd->blockip;
263 newfw.fwc_rule.ipfw.fw_smsk.s_addr = 0x0;
264 newfw.fwc_rule.ipfw.fw_dmsk.s_addr = 0xffffffff;
265
266 break;
267
268 case FWSAM_HOW_INOUT: /* Need 2 rules 1 for IN, 1 for OUT */
269
270 /* Incoming FROM */
271 memcpy(newfw.fwc_label, IP_FW_LABEL_INPUT, sizeof(newfw.fwc_label));
272 newfw.fwc_rule.ipfw.fw_src.s_addr = (u_int32_t) bd->blockip;
273
274 if(do_setsockopt(IP_FW_DELETE, &newfw, sizeof(newfw))==-1)
275 {
276 snprintf(msg, sizeof(msg) - 1, "Error: Can't UnBlock ip %s, %s", inettoa(bd->blockip), strerror(errno));
277 logmessage(1, msg, "ipchains", 0);
278 return;
279 }
280
281 /* Outgoing TO */
282 memcpy(newfw.fwc_label, IP_FW_LABEL_OUTPUT, sizeof(newfw.fwc_label));
283 newfw.fwc_rule.ipfw.fw_dst.s_addr = (u_int32_t) bd->blockip;
284 newfw.fwc_rule.ipfw.fw_dmsk.s_addr = 0xffffffff;
285 newfw.fwc_rule.ipfw.fw_smsk.s_addr = 0x0;
286
287 break;
288
289 }
290
291
292 if(do_setsockopt(IP_FW_DELETE, &newfw, sizeof(newfw))==-1)
293 {
294 snprintf(msg, sizeof(msg) - 1, "Error: Can't UnBlock ip %s, %s", inettoa(bd->blockip), strerror(errno));
295 logmessage(1, msg, "ipchains", 0);
296 return;
297 }
298
299
300 }
301
302 close(sockfd);
303
304 return;
305 }
306
307 #endif /* __SSP_IPCHAINS_C__ */
308 #endif /* LINUX */
309