1 /*
2 *
3 * Copyright (c) 2009 Wouter de Jong <maddog2k@maddog2k.net>
4 * Copyright (c) 2005-2008 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 * Acknowledgements:
29 *
30 * Heavily based on ssp_cisco_nullroute of Frank Knobbe <frank@knobbe.us>
31 *
32 *
33 * ssp_cisco_nullroute2.c
34 *
35 * Purpose:
36 *
37 * This SnortSam plugin telnet's into one or more Cisco routers and issues
38 * a route command to effectively "null-route" the intruding IP address.
39 * SnortSam will remove the added routes when the blocks expire.
40 * This plugin is an improved version, that add's the option to add
41 * a tag to a route, and to use 'auto-enable' mode.
42 *
43 *
44 */
45
46
47 #ifndef __SSP_CISCO_NULLROUTE2_C__
48 #define __SSP_CISCO_NULLROUTE2_C__
49
50
51 #include "snortsam.h"
52 #include "ssp_cisco_nullroute2.h"
53
54
55 #include <sys/types.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include <time.h>
59
60 #ifdef WIN32
61 #include <winsock.h>
62
63 #ifndef strsep
64 /* Okay, I'm lazy today. Below a copy of strsep which doesn't exist on Windows,
65 * at least my old compiler. Remove/disable this section as necessary.
66 */
67 /* ---8<------8<------8<------8<------8<------8<------8<------8<------8<--- */
68 /*-
69 * Copyright (c) 1990, 1993
70 * The Regents of the University of California. All rights reserved.
71 *
72 * Redistribution and use in source and binary forms, with or without
73 * modification, are permitted provided that the following conditions
74 * are met:
75 * 1. Redistributions of source code must retain the above copyright
76 * notice, this list of conditions and the following disclaimer.
77 * 2. Redistributions in binary form must reproduce the above copyright
78 * notice, this list of conditions and the following disclaimer in the
79 * documentation and/or other materials provided with the distribution.
80 * 4. Neither the name of the University nor the names of its contributors
81 * may be used to endorse or promote products derived from this software
82 * without specific prior written permission.
83 *
84 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
85 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
86 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
87 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
88 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
89 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
90 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
91 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
92 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
93 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94 * SUCH DAMAGE.
95 */
96 /*
97 * Get next token from string *stringp, where tokens are possibly-empty
98 * strings separated by characters from delim.
99 *
100 * Writes NULs into the string at *stringp to end tokens.
101 * delim need not remain constant from call to call.
102 * On return, *stringp points past the last NUL written (if there might
103 * be further tokens), or is NULL (if there are definitely no more tokens).
104 *
105 * If *stringp is NULL, strsep returns NULL.
106 */
107
108 char *strsep(char **, const char *);
109
strsep(stringp,delim)110 char *strsep(stringp, delim)
111 char **stringp;
112 const char *delim;
113 {
114 char *s;
115 const char *spanp;
116 int c, sc;
117 char *tok;
118
119 if ((s = *stringp) == NULL)
120 return (NULL);
121 for (tok = s;;) {
122 c = *s++;
123 spanp = delim;
124 do {
125 if ((sc = *spanp++) == c) {
126 if (c == 0)
127 s = NULL;
128 else
129 s[-1] = 0;
130 *stringp = s;
131 return (tok);
132 }
133 } while (sc != 0);
134 }
135 /* NOTREACHED */
136 }
137
138 /* --->8------>8------>8------>8------>8------>8------>8------>8------>8--- */
139 #endif /* strsep */
140
141 #else
142 #include <netinet/in.h>
143 #include <arpa/inet.h>
144 #endif /* WIN32 */
145
146
147
148
149 /* This routine parses the cisconullroute2 statements in the config file.
150 * It builds a list of routers)
151 */
CiscoNullRoute2Parse(char * val,char * file,unsigned long line,DATALIST * plugindatalist)152 void CiscoNullRoute2Parse(char *val,char *file,unsigned long line,DATALIST *plugindatalist)
153 {
154 CISCONULLROUTE2DATA *ciscop;
155 char *p2,msg[STRBUFSIZE+2],*p3,*p4,*p5;
156 struct in_addr routerip;
157
158 #ifdef FWSAMDEBUG
159 printf("Debug: [cisconullroute2] Plugin Parsing...\n");
160 #endif
161
162 if(*val)
163 {
164 p2=val;
165 ciscop=safemalloc(sizeof(CISCONULLROUTE2DATA),"cisconullroute2parse","ciscop"); /* create new router */
166 plugindatalist->data=ciscop;
167 ciscop->routersocket=0;
168 ciscop->loggedin=FALSE;
169 ciscop->username[0]=ciscop->telnetpw[0]=ciscop->enablepw[0]=ciscop->routetag[0]=ciscop->userlogin=0;
170 ciscop->autoenable=FALSE;
171
172 while ((p3 = strsep(&p2, " ")) != NULL)
173 {
174 if (!p3)
175 continue;
176
177 p4 = strsep(&p3, "=");
178 if(p4 != NULL)
179 {
180 p5 = strsep(&p3, "=");
181
182 if(p5 == NULL)
183 {
184 snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] Skipping unknown option '%s'",file,line,p4);
185 logmessage(1,msg,"cisconullroute2",0);
186 continue;
187 }
188
189 if (!strcmp(p4, "r"))
190 {
191 routerip.s_addr=getip(p5);
192 if(routerip.s_addr)
193 ciscop->ip.s_addr=routerip.s_addr; /* save router ip */
194 continue;
195 }
196 if(!strcmp(p4, "u"))
197 {
198 safecopy(ciscop->username,p5); /* save username */
199 continue;
200 }
201 if(!strcmp(p4, "p"))
202 {
203 safecopy(ciscop->telnetpw,p5); /* save telnet password */
204 continue;
205 }
206 if(!strcmp(p4, "e"))
207 {
208 safecopy(ciscop->enablepw,p5); /* save enable password */
209 continue;
210 }
211 if(!strcmp(p4, "t"))
212 {
213 safecopy(ciscop->routetag,p5); /* save route tag */
214 continue;
215 }
216 if(!strcmp(p4, "a"))
217 {
218 if(!strcasecmp(p5, "y"))
219 ciscop->autoenable=TRUE; /* set autoenable */
220 continue;
221 }
222
223 snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] Skipping unknown option '%s' (%s)",file,line,p4,p5);
224 logmessage(1,msg,"cisconullroute2",0);
225 }
226 }
227
228 if(!ciscop->ip.s_addr)
229 {
230 snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] No router specified, CiscoNullRoute2 Plugin disabled",file,line);
231 logmessage(1,msg,"cisconullroute2",0);
232 free(ciscop);
233 plugindatalist->data=NULL;
234 return;
235 }
236
237 if(ciscop->username[0])
238 ciscop->userlogin=TRUE;
239
240 if(!ciscop->telnetpw[0])
241 {
242 snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] No password specified, CiscoNullRoute2 Plugin disabled",file,line);
243 logmessage(1,msg,"cisconullroute2",0);
244 free(ciscop);
245 plugindatalist->data=NULL;
246 return;
247 }
248
249 if(ciscop->routetag[0] && !((strtoul(ciscop->routetag,NULL,10))>=(unsigned long)RTAGVAL_MIN && (strtoul(ciscop->routetag,NULL,10))<=(unsigned long)RTAGVAL_MAX))
250 {
251 snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] Invalid CiscoNullRoute2 route tag value '%s' (min: %lu, max: %lu), CiscoNullRoute2 Plugin disabled",
252 file,line,ciscop->routetag,(unsigned long)RTAGVAL_MIN,(unsigned long)RTAGVAL_MAX);
253 logmessage(1,msg,"cisconullroute2",0);
254 free(ciscop);
255 plugindatalist->data=NULL;
256 return;
257 }
258
259 if(!ciscop->enablepw[0])
260 safecopy(ciscop->enablepw,ciscop->telnetpw); /* If no enable password specified, make it the same as telnet password */
261
262 #ifdef FWSAMDEBUG
263 printf("Debug: [cisconullroute2] Adding Cisco Router: IP \"%s\", USER \"%s\", PW \"%s\", EN \"%s\", TAG \"%s\", AUTO-ENABLE \"%s\"\n",
264 inettoa(ciscop->ip.s_addr),ciscop->userlogin?ciscop->username:"(none)",ciscop->telnetpw,ciscop->enablepw,ciscop->routetag[0]?ciscop->routetag:"(none)",ciscop->autoenable?"y":"n");
265 #endif
266 }
267 else
268 {
269 snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] Empty CiscoNullRoute2 parameter.",file,line);
270 logmessage(1,msg,"cisconullroute2",0);
271 }
272 }
273
274
275 /* This routine initiates the block. It walks the list of routers
276 * telnet's in, and issues the route command.
277 */
CiscoNullRoute2Block(BLOCKINFO * bd,void * data,unsigned long qp)278 void CiscoNullRoute2Block(BLOCKINFO *bd,void *data,unsigned long qp)
279 {
280 CISCONULLROUTE2DATA *ciscop;
281 struct sockaddr_in thissocketaddr,routersocketaddr;
282 unsigned long flag;
283 char cnrmsg[STRBUFSIZE+1],cnrat[STRBUFSIZE+1];
284 #ifdef FWSAMDEBUG
285 #ifdef WIN32
286 unsigned long threadid=GetCurrentThreadId();
287 #else
288 pthread_t threadid=pthread_self();
289 #endif
290 #endif
291
292 if(!data)
293 return;
294 ciscop=(CISCONULLROUTE2DATA *)data;
295
296 #ifdef FWSAMDEBUG
297 printf("Debug: [cisconullroute2][%lx] Plugin Blocking...\n",(unsigned long)threadid);
298 #endif
299
300 snprintf(cnrat,sizeof(cnrat)-1,"router at %s",inettoa(ciscop->ip.s_addr));
301
302 if(!ciscop->routersocket)
303 {
304 routersocketaddr.sin_port=htons(23); /* telnet */
305 routersocketaddr.sin_addr.s_addr=ciscop->ip.s_addr;
306 routersocketaddr.sin_family=AF_INET;
307
308 thissocketaddr.sin_port=htons(0); /* get a dynamic port */
309 thissocketaddr.sin_addr.s_addr=0;
310 thissocketaddr.sin_family=AF_INET;
311
312 /* create socket */
313 ciscop->routersocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
314 if(ciscop->routersocket==INVALID_SOCKET)
315 {
316 snprintf(cnrmsg,sizeof(cnrmsg)-1,"Error: [cisconullroute2] Couldn't create socket!");
317 logmessage(1,cnrmsg,"cisconullroute2",ciscop->ip.s_addr);
318 ciscop->routersocket=0;
319 return;
320 }
321 /* bind it */
322 if(bind(ciscop->routersocket,(struct sockaddr *)&(thissocketaddr),sizeof(struct sockaddr)))
323 {
324 snprintf(cnrmsg,sizeof(cnrmsg)-1,"Error: [cisconullroute2] Couldn't bind socket!");
325 logmessage(1,cnrmsg,"ciscocnullroute",ciscop->ip.s_addr);
326 ciscop->routersocket=0;
327 return;
328 }
329 /* and connect to router */
330 if(connect(ciscop->routersocket,(struct sockaddr *)&routersocketaddr,sizeof(struct sockaddr)))
331 {
332 snprintf(cnrmsg,sizeof(cnrmsg)-1,"Error: [cisconullroute2] Could not connect to %s! Will try later.",cnrat);
333 logmessage(1,cnrmsg,"cisconullroute2",ciscop->ip.s_addr);
334 closesocket(ciscop->routersocket);
335 ciscop->routersocket=0;
336 }
337 }
338 if(ciscop->routersocket)
339 {
340 do
341 {
342 #ifdef FWSAMDEBUG
343 printf("Debug: [cisconullroute2][%lx] Connected to %s.\n",(unsigned long)threadid,cnrat);
344 #endif
345 flag=-1;
346 ioctlsocket(ciscop->routersocket,FIONBIO,&flag); /* set non blocking */
347 flag=FALSE;
348
349 if(!ciscop->loggedin)
350 {
351 if(ciscop->userlogin)
352 {
353 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,"","username","waiting for user logon prompt from ",cnrat))
354 {
355 flag=TRUE;
356 continue;
357 }
358 snprintf(cnrmsg,sizeof(cnrmsg)-1,"%s\r",ciscop->username); /* Send username */
359
360 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,cnrmsg,"pass","at password prompt from ",cnrat))
361 {
362 flag=TRUE;
363 continue;
364 }
365 }
366 else
367 {
368 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,"","pass","waiting for logon prompt from ",cnrat))
369 {
370 flag=TRUE;
371 continue;
372 }
373 }
374
375 snprintf(cnrmsg,sizeof(cnrmsg)-1,"%s\r",ciscop->telnetpw); /* Send telnet password */
376
377 if(ciscop->autoenable)
378 {
379 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,cnrmsg,"#","at enable prompt of ",cnrat))
380 {
381 flag=TRUE;
382 continue;
383 }
384 }
385 else
386 {
387 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,cnrmsg,">","at logon prompt of ",cnrat))
388 {
389 flag=TRUE;
390 continue;
391 }
392
393 /* Send enable */
394 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,"enable\r","pass","at enable command of ",cnrat))
395 {
396 flag=TRUE;
397 continue;
398 }
399
400 /* Send enable password */
401 snprintf(cnrmsg,sizeof(cnrmsg)-1,"%s\r",ciscop->enablepw);
402 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,cnrmsg,"#","at enable prompt of ",cnrat))
403 {
404 flag=TRUE;
405 continue;
406 }
407 }
408
409 /* Send config */
410 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,"config t\r","#","at config command of ",cnrat))
411 {
412 flag=TRUE;
413 continue;
414 }
415 ciscop->loggedin=TRUE;
416 }
417
418 /* send route command */
419 snprintf(cnrmsg,sizeof(cnrmsg)-1,"%sip route %s 255.255.255.255 null 0%s%s\r",
420 bd->block?"":"no ",inettoa(bd->blockip),ciscop->routetag[0]?" tag ":"",ciscop->routetag[0]?ciscop->routetag:"");
421 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,cnrmsg,"#","at route command of ",cnrat))
422 {
423 flag=TRUE;
424 continue;
425 }
426
427 if(!moreinqueue(qp))
428 {
429 /* End input */
430 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,"\032","#","at CTRL-Z of ",cnrat))
431 {
432 flag=TRUE;
433 continue;
434 }
435
436 /* Save config */
437 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,"write mem\r","#","at write mem command of ",cnrat))
438 {
439 flag=TRUE;
440 continue;
441 }
442
443 /* and we're outta here... */
444 sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute2",ciscop->ip,"quit\r","","at quit command of ",cnrat);
445 flag=TRUE;
446 }
447 }while(FALSE);
448
449 if(flag)
450 {
451 closesocket(ciscop->routersocket);
452 ciscop->routersocket=0;
453 ciscop->loggedin=FALSE;
454 }
455 }
456 }
457
458 #endif /* __SSP_CISCO_NULLROUTE2_C__ */
459
460
461
462
463
464
465