1 /* $Id: ssp_cisco_nullroute.c,v 2.5 2009/10/16 22:19:36 fknobbe Exp $
2 *
3 *
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 * Brent Erickson and Sergio Salazar for the idea and sample commands.
31 *
32 *
33 * ssp_cisco_nullroute.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 *
41 *
42 */
43
44
45 #ifndef __SSP_CISCO_NULLROUTE_C__
46 #define __SSP_CISCO_NULLROUTE_C__
47
48
49 #include "snortsam.h"
50 #include "ssp_cisco_nullroute.h"
51
52
53 #include <sys/types.h>
54 #include <stdio.h>
55 #include <string.h>
56 #include <time.h>
57 #ifdef WIN32
58 #include <winsock.h>
59 #else
60 #include <netinet/in.h>
61 #include <arpa/inet.h>
62 #endif
63
64
65
66
67 /* This routine parses the cisconullroute statements in the config file.
68 * It builds a list of routers)
69 */
CiscoNullRouteParse(char * val,char * file,unsigned long line,DATALIST * plugindatalist)70 void CiscoNullRouteParse(char *val,char *file,unsigned long line,DATALIST *plugindatalist)
71 { CISCONULLROUTEDATA *ciscop;
72 char *p2,msg[STRBUFSIZE+2],*p3;
73 struct in_addr routerip;
74
75 #ifdef FWSAMDEBUG
76 printf("Debug: [cisconullroute] Plugin Parsing...\n");
77 #endif
78
79 if(*val)
80 { p2=val;
81 while(*p2 && !myisspace(*p2))
82 p2++;
83 if(*p2)
84 *p2++ =0;
85 routerip.s_addr=getip(val);
86 if(routerip.s_addr) /* If we have a valid IP address */
87 { ciscop=safemalloc(sizeof(CISCONULLROUTEDATA),"cisconullrouteparse","ciscop"); /* create new router */
88 plugindatalist->data=ciscop;
89 ciscop->ip.s_addr=routerip.s_addr;
90 ciscop->routersocket=0;
91 ciscop->loggedin=FALSE;
92 ciscop->username[0]=ciscop->enablepw[0]=ciscop->userlogin=0;
93 ciscop->telnetpw=ciscop->username;
94
95 if(*p2)
96 { val=p2;
97 while(*val && myisspace(*val)) /* now parse the remaining text */
98 val++;
99 if(val)
100 { p2=val;
101 while(*p2 && !myisspace(*p2))
102 p2++;
103 if(*p2)
104 *p2++ =0;
105 safecopy(ciscop->username,val); /* save telnet password */
106
107 p3=strchr(ciscop->username,'/'); /* Check if a username is given */
108 if(p3)
109 { *p3++ =0;
110 ciscop->telnetpw=p3;
111 ciscop->userlogin=TRUE;
112 }
113
114 if(*p2) /* if we have a second password */
115 { while(*p2 && myisspace(*p2))
116 p2++;
117 safecopy(ciscop->enablepw,p2);/* it would be the enable password */
118 }
119 else
120 safecopy(ciscop->enablepw,ciscop->telnetpw); /* if only one password was found, use it for both */
121 }
122 }
123 if(!ciscop->telnetpw[0])
124 { snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] Cisco Router defined without passwords!",file,line);
125 logmessage(1,msg,"cisconullroute",0);
126 free(ciscop);
127 plugindatalist->data=NULL;
128 }
129 #ifdef FWSAMDEBUG
130 else
131 printf("Debug: [cisconullroute] Adding Cisco Router: IP \"%s\", PW \"%s\", EN \"%s\"\n",inettoa(ciscop->ip.s_addr),ciscop->telnetpw,ciscop->enablepw);
132 #endif
133 }
134 else
135 { snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] Invalid CiscoNullRoute parameter '%s' ignored.",file,line,val);
136 logmessage(1,msg,"cisconullroute",0);
137 }
138 }
139 else
140 { snprintf(msg,sizeof(msg)-1,"Error: [%s: %lu] Empty CiscoNullRoute parameter.",file,line);
141 logmessage(1,msg,"cisconullroute",0);
142 }
143 }
144
145
146 /* This routine initiates the block. It walks the list of routers
147 * telnet's in, and issues the route command.
148 */
CiscoNullRouteBlock(BLOCKINFO * bd,void * data,unsigned long qp)149 void CiscoNullRouteBlock(BLOCKINFO *bd,void *data,unsigned long qp)
150 { CISCONULLROUTEDATA *ciscop;
151 struct sockaddr_in thissocketaddr,routersocketaddr;
152 unsigned long flag;
153 char cnrmsg[STRBUFSIZE+1],cnrat[STRBUFSIZE+1];
154 #ifdef FWSAMDEBUG
155 #ifdef WIN32
156 unsigned long threadid=GetCurrentThreadId();
157 #else
158 pthread_t threadid=pthread_self();
159 #endif
160 #endif
161
162 if(!data)
163 return;
164 ciscop=(CISCONULLROUTEDATA *)data;
165
166 #ifdef FWSAMDEBUG
167 printf("Debug: [cisconullroute][%lx] Plugin Blocking...\n",(unsigned long)threadid);
168 #endif
169
170 snprintf(cnrat,sizeof(cnrat)-1,"router at %s",inettoa(ciscop->ip.s_addr));
171
172 if(!ciscop->routersocket)
173 { routersocketaddr.sin_port=htons(23); /* telnet */
174 routersocketaddr.sin_addr.s_addr=ciscop->ip.s_addr;
175 routersocketaddr.sin_family=AF_INET;
176
177 thissocketaddr.sin_port=htons(0); /* get a dynamic port */
178 thissocketaddr.sin_addr.s_addr=0;
179 thissocketaddr.sin_family=AF_INET;
180
181 /* create socket */
182 ciscop->routersocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
183 if(ciscop->routersocket==INVALID_SOCKET)
184 { snprintf(cnrmsg,sizeof(cnrmsg)-1,"Error: [cisconullroute] Couldn't create socket!");
185 logmessage(1,cnrmsg,"cisconullroute",ciscop->ip.s_addr);
186 ciscop->routersocket=0;
187 return;
188 }
189 /* bind it */
190 if(bind(ciscop->routersocket,(struct sockaddr *)&(thissocketaddr),sizeof(struct sockaddr)))
191 { snprintf(cnrmsg,sizeof(cnrmsg)-1,"Error: [cisconullroute] Couldn't bind socket!");
192 logmessage(1,cnrmsg,"ciscocnullroute",ciscop->ip.s_addr);
193 ciscop->routersocket=0;
194 return;
195 }
196 /* and connect to router */
197 if(connect(ciscop->routersocket,(struct sockaddr *)&routersocketaddr,sizeof(struct sockaddr)))
198 { snprintf(cnrmsg,sizeof(cnrmsg)-1,"Error: [cisconullroute] Could not connect to %s! Will try later.",cnrat);
199 logmessage(1,cnrmsg,"cisconullroute",ciscop->ip.s_addr);
200 closesocket(ciscop->routersocket);
201 ciscop->routersocket=0;
202 }
203 }
204 if(ciscop->routersocket)
205 { do
206 {
207 #ifdef FWSAMDEBUG
208 printf("Debug: [cisconullroute][%lx] Connected to %s.\n",(unsigned long)threadid,cnrat);
209 #endif
210 flag=-1;
211 ioctlsocket(ciscop->routersocket,FIONBIO,&flag); /* set non blocking */
212 flag=FALSE;
213
214 if(!ciscop->loggedin)
215 { if(ciscop->userlogin)
216 { if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute",ciscop->ip,"","username","waiting for user logon prompt from ",cnrat))
217 { flag=TRUE;
218 continue;
219 }
220 snprintf(cnrmsg,sizeof(cnrmsg)-1,"%s\r",ciscop->username); /* Send username password */
221
222 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute",ciscop->ip,cnrmsg,"pass","at password prompt from ",cnrat))
223 { flag=TRUE;
224 continue;
225 }
226 snprintf(cnrmsg,sizeof(cnrmsg)-1,"%s\r",ciscop->telnetpw); /* Send telnet password */
227 }
228 else
229 { if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute",ciscop->ip,"","pass","waiting for logon prompt from ",cnrat))
230 { flag=TRUE;
231 continue;
232 }
233 snprintf(cnrmsg,sizeof(cnrmsg)-1,"%s\r",ciscop->telnetpw); /* Send telnet password */
234 }
235
236 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute",ciscop->ip,cnrmsg,">","at logon prompt of ",cnrat))
237 { flag=TRUE;
238 continue;
239 }
240
241 /* Send enable */
242 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute",ciscop->ip,"enable\r","pass","at enable command of ",cnrat))
243 { flag=TRUE;
244 continue;
245 }
246
247 /* Send enable password */
248 snprintf(cnrmsg,sizeof(cnrmsg)-1,"%s\r",ciscop->enablepw);
249 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute",ciscop->ip,cnrmsg,"#","at enable prompt of ",cnrat))
250 { flag=TRUE;
251 continue;
252 }
253
254 /* Send config */
255 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute",ciscop->ip,"config t\r","#","at config command of ",cnrat))
256 { flag=TRUE;
257 continue;
258 }
259 ciscop->loggedin=TRUE;
260 }
261
262 /* send route command */
263 snprintf(cnrmsg,sizeof(cnrmsg)-1,"%sip route %s 255.255.255.255 null 0\r",bd->block?"":"no ",inettoa(bd->blockip));
264 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute",ciscop->ip,cnrmsg,"#","at route command of ",cnrat))
265 { flag=TRUE;
266 continue;
267 }
268
269 if(!moreinqueue(qp))
270 { /* End input */
271 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute",ciscop->ip,"\032","#","at CTRL-Z of ",cnrat))
272 { flag=TRUE;
273 continue;
274 }
275
276 /* Save config */
277 if(!sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute",ciscop->ip,"write mem\r","#","at write mem command of ",cnrat))
278 { flag=TRUE;
279 continue;
280 }
281
282 /* and we're outta here... */
283 sendreceive(ciscop->routersocket,CNRNETWAIT,"cisconullroute",ciscop->ip,"quit\r","","at quit command of ",cnrat);
284 flag=TRUE;
285 }
286 }while(FALSE);
287
288 if(flag)
289 { closesocket(ciscop->routersocket);
290 ciscop->routersocket=0;
291 ciscop->loggedin=FALSE;
292 }
293 }
294 }
295
296 #endif /* __SSP_CISCO_NULLROUTE_C__ */
297
298
299
300
301
302
303