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