1 /* $Id: ssp_ciscoacl.c,v 2.12 2008/04/26 19:53:21 fknobbe Exp $
2  *
3  *
4  * Copyright (c) 2002-2008 Ali BASEL <alib@sabanciuniv.edu>
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_ciscoacl.c
30  *
31  * Purpose:
32  *
33  * This SnortSam plugin ciscoacl telnet's into one or more Cisco CISCOACL routers,
34  * and issues the blocking ACL statements. SnortSam will also expire the blocks
35  * itself since the routers do not have automatic time-out functionality.
36  *
37  * Comments:
38  *
39  *
40  */
41 
42 
43 #ifndef		__SSP_CISCOACL_C__
44 #define		__SSP_CISCOACL_C__
45 
46 
47 #include "snortsam.h"
48 #include "ssp_ciscoacl.h"
49 
50 
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <time.h>
56 #ifdef WIN32
57 #include <winsock.h>
58 #else
59 #include <netinet/in.h>
60 #include <arpa/inet.h>
61 #endif
62 
63 
64 /* This routine parses the ciscoacl statements in the config file.
65  * It builds a list of ciscoacls)
66 */
67 void
CISCOACLParse(char * val,char * file,unsigned long line,DATALIST * datalistp)68 CISCOACLParse(char *val, char *file, unsigned long line, DATALIST * datalistp)
69 {
70     CISCOACLDATA *ciscoaclp;
71     char msg[STRBUFSIZE + 1], *p2;
72     struct in_addr ciscoaclip;
73 
74     char buf[CISCOACLFILELEN + 1], *pp;
75     int i, j, change;
76 
77     logmessage(3, "Plugin Parsing...", "ciscoacl", 0);
78 
79     if(*val) {
80 	p2 = val;
81 	while(*p2 && !myisspace(*p2))
82 	    p2++; /* go to first space */
83 	if(*p2)
84 	    *p2++ = 0;
85 
86 	ciscoaclip.s_addr = getip(val);
87 	if(ciscoaclip.s_addr) {	/* If we have a valid IP address */
88 	    ciscoaclp = safemalloc(sizeof(CISCOACLDATA), "CISCOACLParse", "ciscoaclp");	/* create new ciscoacl */
89 	    datalistp->data = ciscoaclp;
90 	    ciscoaclp->ip.s_addr = ciscoaclip.s_addr;
91 	   /* ciscoaclp->username[0] = (char) NULL;
92 	    ciscoaclp->telnetpw[0] = (char) NULL;
93 	    ciscoaclp->enablepw[0] = (char) NULL;
94 	    ciscoaclp->aclfile[0] = (char) NULL;
95 	    ciscoaclp->ftpfile[0] = (char) NULL;
96 	    */
97 	    if(*p2) {
98 		val = p2;
99 		while(*val && myisspace(*val))	/* jump spaces */
100 		    val++;
101 		if(*val) {
102 		    p2 = val;
103 		    while(*p2 && !myisspace(*p2)) /* go to first following space */
104 			p2++;
105 		    if(*p2)
106 			*p2++ = 0;
107 		    safecopy(buf, val); /* username/password or only telnet password */
108 
109 		    pp = buf;
110 		    i=j=0;
111 		    change = 0;
112 		    do {
113 			if(myisspace(*pp))
114 			    continue;
115 			if(*pp == '/') {
116 			    change = 1;
117 			    continue;
118 			}
119 			if(!change)
120 			    ciscoaclp->username[i++] = *pp;
121 			else
122 			    ciscoaclp->telnetpw[j++] = *pp;
123 		    }
124 		    while(*(++pp) && !myisspace(*pp));
125 		    ciscoaclp->username[i] = (char) 0;
126 		    ciscoaclp->telnetpw[j] = (char) 0;
127 
128 		    if(*p2) {
129 			val = p2;
130 			while(*val && myisspace(*val))	/* jump spaces */
131 			    val++;
132 			if(*val) {
133 			    p2 = val;
134 			    while(*p2 && !myisspace(*p2))
135 				p2++;
136 			    if(*p2)
137 				*p2++ = 0;
138 			    safecopy(ciscoaclp->enablepw, val);	/* save enable password */
139 			}
140 			if(*p2) {
141 			    while(*p2 && myisspace(*p2))
142 				p2++;	/* jump spaces */
143 
144 			    safecopy(buf, p2);	/* this would be the aclfile name... */
145 
146 			    pp = buf;
147 			    i=j=0;
148 			    change = 0;
149 			    do {
150 				if(myisspace(*pp))
151 				    continue;
152 				if(*pp == '|') {
153 				    change = 1;
154 				    continue;
155 				}
156 				if(!change)
157 				    ciscoaclp->aclfile[i++] = *pp;
158 				else
159 				    ciscoaclp->ftpfile[j++] = *pp;
160 			    }
161 			    while(*(++pp) && !myisspace(*pp));
162 			    ciscoaclp->aclfile[i] = (char) 0;
163 			    ciscoaclp->ftpfile[j] = (char) 0;
164 			    snprintf(msg, sizeof(msg) - 1,
165 				     "Adding CISCOACL: IP \"%s\", UName \"%s\", PW \"%s\", EN \"%s\", ACL \"%s\", FTPFILE \"%s\"",
166 				     inettoa(ciscoaclp->ip.s_addr),
167 				     ciscoaclp->username,
168 				     ciscoaclp->telnetpw,
169 				     ciscoaclp->enablepw,
170 				     ciscoaclp->aclfile,
171 				     ciscoaclp->ftpfile
172 				);
173 			    logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr );
174 			    return;
175 			} else {
176 			    snprintf(msg, sizeof(msg) - 1,
177 				     "Error: [%s: %lu] CISCOACL defined without aclfile name !",
178 				     file, line);
179 			    logmessage(1, msg, "ciscoacl", 0);
180 			    getout(3);
181 			}
182 		    } else {
183 			snprintf(msg, sizeof(msg) - 1,
184 				 "Error: [%s: %lu] CISCOACL defined without enable passwords!",
185 				 file, line);
186 			logmessage(1, msg, "ciscoacl", 0);
187 			getout(3);
188 		    }
189 		} else {
190 		    snprintf(msg, sizeof(msg) - 1,
191 			     "Error: [%s: %lu] CISCOACL defined without passwords and ACL-file-name !",
192 			     file, line);
193 		    logmessage(1, msg, "ciscoacl", 0);
194 		    getout(3);
195 		}
196 	    } else {
197 		snprintf(msg, sizeof(msg) - 1,
198 			 "Error: [%s: %lu] CISCOACL defined without passwords and ACL-file-name !",
199 			 file, line);
200 		logmessage(1, msg, "ciscoacl", 0);
201 		getout(3);
202 	    }
203 
204 	    snprintf(msg, sizeof(msg) - 1,
205 		     "Adding CISCOACL: IP \"%s\", UN \"%s\", PW \"%s\", EN \"%s\", ACL \"%s\", FTPFILE \"%s\"",
206 		     inettoa(ciscoaclp->ip.s_addr), ciscoaclp->username,
207 		     ciscoaclp->telnetpw, ciscoaclp->enablepw,
208 		     ciscoaclp->aclfile, ciscoaclp->ftpfile);
209 	    logmessage(3, msg, "ciscoacl", ciscoaclp->ip.s_addr);
210 	} else {
211 	    snprintf(msg, sizeof(msg) - 1,
212 		     "Error: [%s: %lu] Invalid CISCOACL parameter '%s' ignored.",
213 		     file, line, val);
214 	    logmessage(1, msg, "ciscoacl", 0);
215 	    getout(3);
216 	}
217     } else {
218 	snprintf(msg, sizeof(msg) - 1,
219 		 "Error: [%s: %lu] Empty CISCOACL parameter.", file, line);
220 	logmessage(1, msg, "ciscoacl", 0);
221 	getout(3);
222     }
223 }
224 
225 /* This routine initiates the block. It walks the list of CISCOACL's
226  * telnet's in, and issues the blocking ACL statement.
227  */
CISCOACLBlock(BLOCKINFO * bd,void * data,unsigned long qp)228 void CISCOACLBlock(BLOCKINFO * bd, void *data,unsigned long qp)
229 {
230     CISCOACLDATA *ciscoaclp;
231     struct sockaddr_in thissocketaddr, ciscoaclsocketaddr;
232     SOCKET ciscoaclsocket = 0;
233     signed long len;
234     char msg[STRBUFSIZE + 2];
235     struct in_addr blockthis;
236 
237     FILE *readfile, *writefile, *writefile_upload, *readftpfile;
238     char ace[STRBUFSIZE + 1], buf[STRBUFSIZE + 1];
239     char filename_temp[FILEBUFSIZE + 1];
240     const char *ciscoaclbegin = "snortsam-ciscoacl-begin";
241     const char *ciscoaclend = "snortsam-ciscoacl-end";
242     int uzbegin = strlen(ciscoaclbegin), uzend = strlen(ciscoaclend);
243     int error, search, present, i, blank, ftp = 0, expect = 0, result = 0;
244 
245     /* Holds the expect script's file name, if it's defined in the snortsam config file */
246     /* this plugin arranges the ACL file, and then will call this expect script to upload the ACL file */
247     char expect_file[STRBUFSIZE + 1];
248 
249     /* Copy of the actual ACL file, "snortsam-ciscoacl-begin" and "snortsam-ciscoacl-end" lines are removed */
250     /* These two lines are removed in order to avoid errors when uploading this ACL file into the router */
251     char aclfile_upload[STRBUFSIZE + 1];
252     /* This file will be removed after beeing uploaded into the router */
253 
254 
255     if(!data)
256 	return;			/* if we don't have ciscoacls, we exit */
257     ciscoaclp = (CISCOACLDATA *) data;
258 
259     snprintf(msg, sizeof(msg) - 1, "Plugin Blocking... block=%d", bd->block);
260     logmessage(2, msg, "ciscoacl", 0);
261 
262     blockthis.s_addr = bd->blockip;
263     snprintf(msg, sizeof(msg) - 1, "deny ip host %s any",
264 	     inettoa(blockthis.s_addr));
265     present = CISCOACLCheck(msg, ciscoaclp->aclfile);	/* check the ACL file if the blocking rule is already applied ? */
266     if(present && bd->block) {
267 	logmessage(3, "already blocked, no thing to do.", "ciscoacl",
268 		   ciscoaclp->ip.s_addr);
269 	return;
270 	/* no need to reapply to this router, continue with the other */
271     }
272     if(!present && !bd->block) {
273 	logmessage(3, "This is not blocked, no thing to do.", "ciscoacl",
274 		   ciscoaclp->ip.s_addr);
275 	return;
276 	/* it doesn't exist, so nothing to do */
277     }
278 
279     if(strlen(ciscoaclp->ftpfile)) {
280 	ftp = 1;
281 	if(strstr(ciscoaclp->ftpfile, "expect:")) {
282 	    /* Remove the "expect:" string from the file name */
283 	    safecopy(expect_file, &ciscoaclp->ftpfile[strlen("expect:")] );
284 	    ftp = 2;
285 	    expect = 1;		/* There is an expect script to call */
286 	    snprintf(msg, sizeof(msg) - 1, "Expect script name:%s",
287 		     expect_file);
288 	    logmessage(1, msg, "ciscoacl", 0);
289 	    readftpfile = fopen(expect_file, "r");
290 	    if(!readftpfile) {
291 		snprintf(msg, sizeof(msg) - 1,
292 			 "Error: file: %s doesn't exist!", expect_file);
293 		logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
294 		return;
295 	    }
296 	    fclose(readftpfile);
297 	} else {
298 	    readftpfile = fopen(ciscoaclp->ftpfile, "r");
299 	    if(!readftpfile) {
300 		snprintf(msg, sizeof(msg) - 1,
301 			 "Error: file: %s doesn't exist!", ciscoaclp->ftpfile);
302 		logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
303 		return;
304 	    }
305 	    fclose(readftpfile);
306 	}
307     } else
308 	ftp = 0;
309     /* If there is an expect script to be called, there is no need to connect to the router...
310        Otherwise make the telnet connection as usual */
311     if(!expect) {
312 	ciscoaclsocketaddr.sin_port = htons(23);	/* telnet */
313 	ciscoaclsocketaddr.sin_addr.s_addr = ciscoaclp->ip.s_addr;
314 	ciscoaclsocketaddr.sin_family = AF_INET;
315 
316 	thissocketaddr.sin_port = htons(0);	/* get a dynamic port  */
317 	thissocketaddr.sin_addr.s_addr = 0;
318 	thissocketaddr.sin_family = AF_INET;
319 
320 	/* create socket */
321 	ciscoaclsocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
322 	if(ciscoaclsocket == INVALID_SOCKET) {
323 	    snprintf(msg, sizeof(msg) - 1,
324 		     "Error: [ciscoacl] Couldn't create socket!");
325 	    logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
326 	    return;
327 	}
328 	/* bind it */
329 	if(bind
330 	   (ciscoaclsocket, (struct sockaddr *) &(thissocketaddr),
331 	    sizeof(struct sockaddr))) {
332 	    snprintf(msg, sizeof(msg) - 1,
333 		     "Error: [ciscoacl] Couldn't bind socket!");
334 	    logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
335 	    return;
336 	}
337 	/* and connect to ciscoacl */
338 	if(connect
339 	   (ciscoaclsocket, (struct sockaddr *) &ciscoaclsocketaddr,
340 	    sizeof(struct sockaddr))) {
341 	    snprintf(msg, sizeof(msg) - 1,
342 		     "Error: [ciscoacl] Could not connect to CISCOACL at %s! Will try later.",
343 		     inettoa(ciscoaclp->ip.s_addr));
344 	    logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
345 	    return;
346 	}
347 
348 	snprintf(msg, sizeof(msg) - 1, "Connected to CISCOACL at %s.",
349 		 inettoa(ciscoaclp->ip.s_addr));
350 	logmessage(2, msg, "ciscoacl", ciscoaclp->ip.s_addr);
351 
352 	len = 1;
353 
354 	ioctlsocket(ciscoaclsocket, FIONBIO, &len);	/* set non blocking  */
355 
356 	if(ciscoaclp->telnetpw[0]) {	/* there are username and password, so apply tacacs+ authentication */
357 	    if(CISCOACLsendreceive(ciscoaclsocket, "", "Username: ")) {
358 		closesocket(ciscoaclsocket);
359 		return;
360 	    }
361 
362 	    if(CISCOACLsendreceive
363 	       (ciscoaclsocket, ciscoaclp->username, "Password: ")) {
364 		closesocket(ciscoaclsocket);
365 		return;
366 	    }
367 
368 	    if(CISCOACLsendreceive(ciscoaclsocket, ciscoaclp->telnetpw, ">")) {
369 		closesocket(ciscoaclsocket);
370 		return;
371 	    }
372 	} else {		/* do simple authentication with password */
373 	    if(CISCOACLsendreceive(ciscoaclsocket, "", "Password: ")) {
374 		closesocket(ciscoaclsocket);
375 		return;
376 	    }
377 
378 	    if(CISCOACLsendreceive(ciscoaclsocket, ciscoaclp->username, ">")) {
379 		closesocket(ciscoaclsocket);
380 		return;
381 	    }
382 	}
383 
384 	if(CISCOACLsendreceive(ciscoaclsocket, "enable", "Password: ")) {
385 	    closesocket(ciscoaclsocket);
386 	    return;
387 	}
388 	if(CISCOACLsendreceive(ciscoaclsocket, ciscoaclp->enablepw, "#")) {
389 	    closesocket(ciscoaclsocket);
390 	    return;
391 	}
392 	/* A Telnet connection has been established */
393 	/* If expect was 0 */
394     }
395 
396     blockthis.s_addr = bd->blockip;
397     snprintf(msg, sizeof(msg) - 1, "deny ip host %s any",
398 	     inettoa(blockthis.s_addr));
399     /* don't search the whole file; search only between snortsam-acl-begin and snortsam-acl-end */
400     error = 0;
401     present = 0;
402     search = 0;
403 
404     /* Expect script and tftp will use the file "ciscoaclp->aclfile"_upload */
405     snprintf(aclfile_upload, sizeof(aclfile_upload) - 1, "%s_upload",
406 	     ciscoaclp->aclfile);
407 
408     readfile = fopen(ciscoaclp->aclfile, "r");
409     if(!readfile) {
410 	snprintf(msg, sizeof(msg) - 1, "Error: file: %s doesn't exist!",
411 		 ciscoaclp->aclfile);
412 	logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
413 	if(!expect)
414 	    closesocket(ciscoaclsocket);
415 	return;
416     }
417     snprintf(filename_temp, sizeof(filename_temp) - 1, "%s-%x%x",
418 	     ciscoaclp->aclfile, rand() * 65536 + rand(),
419 	     rand() * 65536 + rand());
420 
421 
422     writefile_upload = fopen(aclfile_upload, "w");
423     if(!writefile_upload) {
424 	snprintf(msg, sizeof(msg) - 1, "Error: can not create file: %s !",
425 		 aclfile_upload);
426 	logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
427 	fclose(readfile);
428 	if(!expect)
429 	    closesocket(ciscoaclsocket);
430 	return;
431     }
432 
433     writefile = fopen(filename_temp, "w");
434     if(!writefile_upload) {
435 	snprintf(msg, sizeof(msg) - 1, "Error: can not create file: %s !",
436 		 ciscoaclp->aclfile);
437 	logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
438 	fclose(readfile);
439 	fclose(writefile_upload);
440 	if(!expect)
441 	    closesocket(ciscoaclsocket);
442 	return;
443     }
444 
445 
446     while(!feof(readfile)) {
447 	fgets(ace, sizeof(ace) - 1, readfile);
448 	ace[sizeof(ace) - 1] = 0;
449 	if(strlen(ace) < 4)
450 	    continue;		/* skip blank lines */
451 
452 	/* if the file is created in Linux with the vi editor, lines end with 0x0A newline
453 	   but if in windows, lines end with 0x0D 0x0A; so, check 0x0D */
454 	if(ace[strlen(ace) - 2] == (char) 0x0d)
455 	    ace[strlen(ace) - 2] = (char) 0;	/*  in windows */
456 	else
457 	    ace[strlen(ace) - 1] = (char) 0;	/* in Linux with vi */
458 
459 	blank = 0;		/* skip initial blank characters */
460 	for(i = 0; i < strlen(ace); i++) {
461 	    if(myisspace(ace[i]))
462 		blank++;
463 	    else
464 		break;
465 	}
466 	safecopy(buf, &ace[blank]);
467 	safecopy(ace, buf);
468 
469 
470 	if(!strncmp("snortsam-ciscoacl-begin", ace, uzbegin)) {
471 	    search = 1;
472 	    fprintf(writefile, "%s\r\n", ace);
473 	    ace[0] = (char) 0;
474 	    continue;
475 	}
476 
477 	if(!strncmp("snortsam-ciscoacl-end", ace, uzend)) {
478 	    search = 0;
479 
480 	    if(!present && bd->block) {	/* if this ACE doesn't already exist add it. */
481 		fprintf(writefile, "%s\r\n", msg);
482 		fprintf(writefile_upload, "%s\r\n", msg);
483 		if(!ftp)
484 		    CISCOACLsendreceive(ciscoaclsocket, msg, "#");
485 	    }
486 
487 	    fprintf(writefile, "%s\r\n", ace);
488 	    ace[0] = (char) 0;
489 	    present = 0;
490 	    continue;
491 	}
492 
493 	if(search)		/* search this ACE if it already exists ? */
494 	    if(!strcmp(msg, ace))
495 		present = 1;
496 
497 	if(!bd->block && present) {
498 	    ace[0] = (char) 0;
499 	    present = 0;
500 	    continue;		/* once we found a match, make present=0 in order to no skip others */
501 	}
502 
503 	fprintf(writefile, "%s\r\n", ace);
504 	fprintf(writefile_upload, "%s\r\n", ace);
505 
506 	if(!ftp) {
507 	    logmessage(2, "sending command to the router...", "ciscoacl",
508 		       ciscoaclp->ip.s_addr);
509 
510 	    if(CISCOACLsendreceive(ciscoaclsocket, ace, "#")) {
511 		error = 1;
512 		break;
513 	    }
514 	}
515 
516 	ace[0] = (char) 0;
517     }
518 
519 
520     if(error) {
521 	snprintf(msg, sizeof(msg) - 1,
522 		 "Error: [ciscoacl] Did not receive a response from CISCOACL at %s (wait for # prompt), and skipping to the next router, check acl_temp file!!!",
523 		 inettoa(ciscoaclp->ip.s_addr));
524 	logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
525 	fclose(readfile);
526 	fclose(writefile);
527 	fclose(writefile_upload);
528 	if(!expect)
529 	    closesocket(ciscoaclsocket);
530 	return;
531     }
532 
533     fclose(readfile);
534     fclose(writefile);
535     fclose(writefile_upload);
536     unlink(ciscoaclp->aclfile);
537     rename(filename_temp, ciscoaclp->aclfile);
538 
539 #ifndef WIN32
540     /* Changes permissions of the aclfile to make it readable by the tftp daemon */
541     chmod(ciscoaclp->aclfile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
542 #endif
543     if(expect) {
544 	snprintf(msg, sizeof(msg) - 1, "%s>>/var/log/snortsam_expect.log",
545 		 expect_file);
546 	result = system(msg);
547 	logmessage(1, "expect script has been executed", "ciscoacl",
548 		   ciscoaclp->ip.s_addr);
549 	snprintf(msg, sizeof(msg) - 1, "Expect return code:%d", result);
550 	logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
551 	unlink(aclfile_upload);	/* Remove the temporary upload file */
552 
553     } else if(ftp) {
554 	readftpfile = fopen(ciscoaclp->ftpfile, "r");
555 
556 	while(!feof(readftpfile)) {
557 	    fgets(ace, sizeof(ace) - 1, readftpfile);
558 	    ace[sizeof(ace) - 1] = 0;
559 	    if(strlen(ace) < 4)
560 		continue;	/* skip blank lines */
561 
562 	    /* if the file is created in Linux with the vi editor, lines end with 0x0A newline
563 	       but if in windows, lines end with 0x0D 0x0A; so, check 0x0D */
564 	    if(ace[strlen(ace) - 2] == (char) 0x0d)
565 		ace[strlen(ace) - 2] = (char) 0;	/*  in windows */
566 	    else
567 		ace[strlen(ace) - 1] = (char) 0;	/* in Linux with vi */
568 
569 	    blank = 0;		/* skip initial blank characters */
570 	    for(i = 0; i < strlen(ace); i++) {
571 		if(myisspace(ace[i]))
572 		    blank++;
573 		else
574 		    break;
575 	    }
576 	    safecopy(buf, &ace[blank]);
577 	    safecopy(ace, buf);
578 
579 
580 	    logmessage(2, "sending command to the router...", "ciscoacl",
581 		       ciscoaclp->ip.s_addr);
582 
583 	    if(CISCOACLsendreceive(ciscoaclsocket, ace, "]? ")) {
584 		error = 1;
585 		break;
586 	    }
587 
588 	    ace[0] = (char) 0;
589 	}
590 
591 	fclose(readftpfile);
592 
593 	if(!error)		// if there is no error send the last two answers
594 	{
595 	    if(CISCOACLsendreceive(ciscoaclsocket, ciscoaclp->aclfile, "]? "))
596 		error = 1;
597 	    else if(CISCOACLsendreceive(ciscoaclsocket, "running-config", "#"))
598 		error = 1;
599 	}
600 	if(error) {
601 	    snprintf(msg, sizeof(msg) - 1,
602 		     "Error: [ciscoacl] Did not receive a response from CISCOACL at %s, and skipping to the next router, check %s file!!!",
603 		     inettoa(ciscoaclp->ip.s_addr), ciscoaclp->ftpfile);
604 	    logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
605 	    fclose(readftpfile), closesocket(ciscoaclsocket);
606 	    return;
607 	}
608     }
609 
610     if(!expect)
611 	closesocket(ciscoaclsocket);	/* If there is an expect script, a telnet connection
612 					   hasn't been established, so there is not any open socket to close */
613 
614     snprintf(msg, sizeof(msg) - 1,
615 	     "Uploading has finished and disconnected from the router:%s",
616 	     inettoa(ciscoaclp->ip.s_addr));
617     logmessage(1, msg, "ciscoacl", ciscoaclp->ip.s_addr);
618     logmessage(3, "Return from ciscoacl Blocking function", "ciscoacl", 0);
619 }
620 
621 
622 
623 /*
624  *
625  */
CISCOACLCheck(char * message,char * filename)626 int CISCOACLCheck(char *message, char *filename)
627 {
628     char msg[STRBUFSIZE + 1];
629 
630     FILE *readfile;
631     char ace[STRBUFSIZE + 1], buf[STRBUFSIZE + 1];
632     const char *ciscoaclbegin = "snortsam-ciscoacl-begin";
633     const char *ciscoaclend = "snortsam-ciscoacl-end";
634     int uzbegin = strlen(ciscoaclbegin), uzend =
635 	strlen(ciscoaclend), search = 1, present = 0, i, blank;
636 
637     readfile = fopen(filename, "r");
638     if(!readfile) {
639 	puts("hata: dosya yok !");
640 	return 0;
641     }
642 
643     snprintf(msg, sizeof(msg) - 1, "ACL existence check:%s", message);
644     logmessage(1, msg, "ciscoacl", 0);
645 
646     while(!feof(readfile)) {
647 	fgets(ace, sizeof(ace) - 1, readfile);
648 	ace[sizeof(ace) - 1] = 0;
649 	if(strlen(ace) < 4)
650 	    continue;		/* skip blank lines */
651 
652 	/* if the file is created in Linux with the vi editor, lines end with 0x0A newline
653 	   but if in windows, lines end with 0x0D 0x0A; so, check 0x0D */
654 	if(ace[strlen(ace) - 2] == (char) 0x0d)
655 	    ace[strlen(ace) - 2] = (char) 0;	/*  in windows */
656 	else
657 	    ace[strlen(ace) - 1] = (char) 0;	/* in Linux with vi */
658 
659 	blank = 0;		/* skip inital blank characters */
660 	for(i = 0; i < strlen(ace); i++) {
661 	    if(myisspace(ace[i]))
662 		blank++;
663 	    else
664 		break;
665 	}
666 	safecopy(buf, &ace[blank]);
667 	safecopy(ace, buf);
668 
669 	if(!strncmp("snortsam-ciscoacl-begin", ace, uzbegin)) {
670 	    search = 1;
671 	    ace[0] = (char) 0;
672 	    continue;
673 	}
674 
675 	if(!strncmp("snortsam-ciscoacl-end", ace, uzend)) {
676 	    break;
677 	}
678 
679 	if(search)		/*  search this ACE if it already exists ? */
680 	    if(!strcmp(message, ace)) {
681 		present = 1;
682 		break;
683 	    }
684 	ace[0] = (char) 0;
685     }
686 
687     fclose(readfile);
688     if(present)
689 	logmessage(1, "Present", "ciscoacl", 0);
690     else
691 	logmessage(1, "Not Present", "ciscoacl", 0);
692     return present;
693 }
694 
695 
696 
CISCOACLsendreceive(SOCKET ciscoaclsocket,char * message,char * receive)697 int CISCOACLsendreceive(SOCKET ciscoaclsocket, char *message, char *receive)
698 {
699     signed long len;
700     char msg[STRBUFSIZE + 1], buf[STRBUFSIZE + 1];
701 
702     if(*message) {
703 	snprintf(msg, sizeof(msg) - 1, "%s\r", message);	/* send  */
704 	len = strlen(msg);
705 
706 	snprintf(buf, sizeof(buf) - 1, "Sending:%s", msg);
707 	logmessage(3, buf, "ciscoacl", 0);
708 
709 	if(send(ciscoaclsocket, msg, len, 0) != len) {	/* weird...could not send */
710 	    snprintf(msg, sizeof(msg) - 1,
711 		     "Error: [ciscoacl] Could not send to CISCOACL at %s !",
712 		     message);
713 	    logmessage(1, msg, "ciscoacl", 0);
714 	    return 1;
715 	}
716     }
717 
718     if(*receive) {
719 	snprintf(buf, sizeof(buf) - 1, "Receiving: --%s--", receive);
720 	logmessage(3, buf, "ciscoacl", 0);
721 
722 	if(!waitfor(ciscoaclsocket, receive, CISCOACLNETWAIT)) {	/* wait for prompt */
723 	    snprintf(msg, sizeof(msg) - 1,
724 		     "Error: [ciscoacl] Did not receive a response from CISCOACL at %s !",
725 		     receive);
726 	    logmessage(1, msg, "ciscoacl", 0);
727 	    return 1;
728 	}
729     }
730 
731     return 0;
732 }
733 
734 #endif				/* __SSP_CISCOACL_C__ */
735