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