www.pudn.com > ids_snort.zip > parser.c
/* ** Copyright (C) 1998,1999,2000,2001 Martin Roesch** Copyright (C) 2000,2001 Andrew R. Baker ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* $Id: parser.c,v 1.6 2001/01/02 08:06:00 roesch Exp $ */ #include "parser.h" extern char *file_name; extern char *file_line; extern RuleListNode *RuleLists; extern int rule_count; extern FILE *rule_file; extern ListHead *head_tmp; /**************************************************************************** * * Function: ProcessAlertFileOption(char *) * * Purpose: define the alert file * * Arguments: filespec => the file specification * * Returns: void function * ***************************************************************************/ void ProcessAlertFileOption(char *filespec) { pv.alert_filename = ProcessFileOption(filespec); #if DEBUG printf("alertfile set to: %s\n", pv.alert_filename); #endif return; } char *ProcessFileOption(char *filespec) { char *filename; char buffer[STD_BUF]; /* look for ".." in the string and complain and exit if it is found */ if(strstr(filespec, "..") != NULL) { FatalError("ERROR: file definition contains \"..\". Do not do that!\n"); } if(filespec[0] == '/') { /* absolute filespecs are saved as is */ filename = strdup(filespec); } else { /* relative filespec is considered relative to the log directory */ /* or /var/log if the log directory has not been set */ if(pv.log_flag) { strncpy(buffer, pv.log_dir, STD_BUF - 1); } else { strncpy(buffer, "/var/log", STD_BUF - 1); } strncat(buffer, "/", STD_BUF - strlen(buffer) - 1); strncat(buffer, filespec, STD_BUF - strlen(buffer) - 1); filename = strdup(buffer); } printf("ProcessFileOption: %s\n", filename); return filename; } void ParseConfig(char *rule) { char **toks; char **config_decl; char *args = NULL; char *config; int num_toks; toks = mSplit(rule, ":", 2, &num_toks, 0); if(num_toks >= 1) { args = toks[1]; } config_decl = mSplit(toks[0], " ", 2, &num_toks, '\\'); if(num_toks != 2) { FatalError("Error parsing config: %s\n", rule); } config = config_decl[1]; #ifdef DEBUG printf("Config: %s\n", config); printf("Args: %s\n", args); #endif if(!strcasecmp(config, "order")) { if(!pv.rules_order_flag) { OrderRuleLists(args); return; } #ifdef DEBUG else printf("Commandline option overiding rule file config\n"); #endif } if(!strcasecmp(config, "alertfile")) { toks = mSplit(args, " ", 1, &num_toks, 0); ProcessAlertFileOption(toks[0]); return; } FatalError("Error: Unknown config: %s\n", config); return; } /* verify that we are not reusing some other keyword */ int checkKeyword(char *keyword) { RuleListNode *node = RuleLists; if(RuleType(keyword) != RULE_UNKNOWN) { return 1; } /* check the declared ruletypes now */ while(node != NULL) { if(!strcmp(node->name, keyword)) { return 1; } node = node->next; } return 0; } void ParseRuleTypeDeclaration(char *rule) { char *input; char *keyword; char **toks; int num_toks; int type; int rval = 1; int i; ListHead *listhead = NULL; toks = mSplit(rule, " ", 10, &num_toks, 0); keyword = strdup(toks[1]); /* Verify keyword is unique */ if(checkKeyword(keyword)) { FatalError("ERROR line %s (%d): Duplicate keyword: %s\n", file_name, file_line, keyword); } #ifdef DEBUG printf("Declaring new rule type: %s\n", keyword); #endif if(num_toks > 2) { if(strcasecmp("{", toks[2]) != 0) { FatalError("ERROR line %s (%d): Syntax error: %s\n", file_name, file_line, rule); } } else { input = ReadLine(rule_file); for(i=0;i name, toks[0])) break; node = node->next; } /* if we did not find a match, then there is no such ruletype */ if(node == NULL) { FatalError("ERROR line %s (%d) => Unknown rule type: %s\n", file_name, file_line, toks[0]); } printf("[**] Rule start\n"); printf("Rule id: %s\n", toks[0]); printf("Rule type: "); switch(node->mode) { case RULE_PASS: printf("Pass\n"); break; case RULE_LOG: printf("Log\n"); break; case RULE_ALERT: printf("Alert\n"); break; default: printf("Unknown\n"); } /* the rest of this function is almost identical to code in ParseRule */ bzero((char *) &proto_node, sizeof(RuleTreeNode)); proto_node.type = node->mode; /* set the rule protocol */ protocol = WhichProto(toks[1]); /* Process the IP address and CIDR netmask */ /* changed version 1.2.1 */ /* * "any" IP's are now set to addr 0, netmask 0, and the normal rules are * applied instead of checking the flag */ /* * if we see a "! " we need to set a flag so that we can * properly deal with it when we are processing packets */ /* if( *toks[2] == '!' ) { proto_node.flags |= EXCEPT_SRC_IP; ParseIP(&toks[2][1], (u_long *) & proto_node.sip, (u_long *) & proto_node.smask); } else { ParseIP(toks[2], (u_long *) & proto_node.sip, (u_long *) & proto_node.smask); }*/ ProcessIP(toks[2], &proto_node, SRC); /* do the same for the port */ if(ParsePort(toks[3], (u_short *) & proto_node.hsp, (u_short *) & proto_node.lsp, toks[1], (int *) &proto_node.not_sp_flag)) { proto_node.flags |= ANY_SRC_PORT; } if(proto_node.not_sp_flag) proto_node.flags |= EXCEPT_SRC_PORT; /* New in version 1.3: support for bidirectional rules */ /* * this checks the rule "direction" token and sets the bidirectional flag * if the token = '<>' */ if(!strncmp("<>", toks[4], 2)) { #ifdef DEBUG printf("Bidirectional rule!\n"); #endif proto_node.flags |= BIDIRECTIONAL; } /* changed version 1.2.1 */ /* * "any" IP's are now set to addr 0, netmask 0, and the normal rules are * applied instead of checking the flag */ /* * if we see a "! " we need to set a flag so that we can * properly deal with it when we are processing packets */ /* if( *toks[5] == '!' ) { #ifdef DEBUG printf("setting exception flag for dest IP\n"); #endif proto_node.flags |= EXCEPT_DST_IP; ParseIP(&toks[5][1], (u_long *) & proto_node.dip, (u_long *) & proto_node.dmask); } else ParseIP(toks[5], (u_long *) & proto_node.dip, (u_long *) & proto_node.dmask); */ ProcessIP(toks[5], &proto_node, DST); if(ParsePort(toks[6], (u_short *) & proto_node.hdp, (u_short *) & proto_node.ldp, toks[1], (int *) &proto_node.not_dp_flag)) { proto_node.flags |= ANY_DST_PORT; } if(proto_node.not_dp_flag) proto_node.flags |= EXCEPT_DST_PORT; #ifdef DEBUG printf("proto_node.flags = 0x%X\n", proto_node.flags); #endif if(&proto_node == NULL) printf("NULL proto_node\n"); ProcessHeadNode(&proto_node, node->RuleList, protocol); rule_count++; ParseRuleOptions(rule, node->mode, protocol); for(i=0;i , we return it */ if((*index != '#') && (*index != 0x0a) && (*index != ';') && (index != NULL)) { /* advance through any whitespace at the beginning of ther line */ while(isspace((int) *index)) index++; /* return a copy of the line */ return strdup(buf); } } return NULL; }