📄 rules.c
字号:
/* $Id: rules.c,v 1.38 2001/01/26 19:03:07 roesch Exp $ *//*** Copyright (C) 1998,1999,2000,2001 Martin Roesch <roesch@clark.net>**** 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.*/#include "rules.h"ListHead Alert; /* Alert Block Header */ListHead Log; /* Log Block Header */ListHead Pass; /* Pass Block Header */ListHead Activation; /* Activation Block Header */ListHead Dynamic; /* Dynamic Block Header */RuleTreeNode *rtn_tmp; /* temp data holder */OptTreeNode *otn_tmp; /* OptTreeNode temp ptr */ListHead *head_tmp = NULL; /* ListHead temp ptr */RuleListNode *RuleLists;struct VarEntry *VarHead = NULL;char *file_name; /* current rules file being processed */int file_line; /* current line being processed in the rules * file */int list_file_line; /* current line being processed in the list * file */int rule_count; /* number of rules generated */int head_count; /* number of header blocks (chain heads?) */int opt_count; /* number of chains */int do_detect;int dynamic_rules_present;int active_dynamic_nodes;extern KeywordXlateList *KeywordList; /* detection/response plugin keywords */extern PreprocessKeywordList *PreprocessKeywords; /* preprocessor plugin * keywords */extern PreprocessFuncNode *PreprocessList; /* Preprocessor function list */extern OutputKeywordList *OutputKeywords; /* Output plugin keyword list */extern OutputFuncNode *AlertList; /* Alert function list */extern OutputFuncNode *LogList; /* log function list *//* Local Function Declarations */OutputFuncNode *AppendOutputFuncList(void (*) (Packet *, char *, void *), void *, OutputFuncNode *);#ifdef BENCHMARKint check_count; /* number of tests for a given rule to * determine a match */int cmpcount; /* compare counter */#endif/**************************************************************************** * * Function: ParseRulesFile(char *, int) * * Purpose: Read the rules file a line at a time and send each rule to * the rule parser * * Arguments: file => rules file filename * inclevel => nr of stacked "include"s * * Returns: void function * ***************************************************************************/FILE *rule_file;void ParseRulesFile(char *file, int inclevel){ FILE *thefp; /* file pointer for the rules file */ char buf[STD_BUF]; /* file read buffer */ char *index; /* buffer indexing pointer */ char *stored_file_name = file_name; int stored_file_line = file_line;#ifdef DEBUG printf("Opening rules file: %s\n", file);#endif if(inclevel == 0) { if(!pv.quiet_flag) { printf("\n+++++++++++++++++++++++++++++++++++++++++++++++++++\n"); printf("Initializing rule chains...\n"); } file_name = strdup(file); } /* open the rules file */ if((thefp = fopen(file, "r")) == NULL) { FatalError("ERROR: Unable to open rules file: %s\n", file); } /* clear the line buffer */ bzero((char *) buf, STD_BUF); stored_file_line = file_line; stored_file_name = file_name; file_name = strdup(file); file_line = 0; rule_file = thefp; /* loop thru each file line and send it to the rule parser */ while((fgets(buf, STD_BUF, thefp)) != NULL) { /* * inc the line counter so the error messages know which line to * bitch about */ file_line++; index = buf;#ifdef DEBUG2 printf("Got line %s (%d): %s", file_name, file_line, buf);#endif /* advance through any whitespace at the beginning of the line */ while(*index == ' ' || *index == '\t') index++; /* if it's not a comment or a <CR>, send it to the parser */ if((*index != '#') && (*index != 0x0a) && (*index != ';') && (index != NULL)) { ParseRule(index, inclevel); } bzero((char *) buf, STD_BUF); } if(file_name) free(file_name); file_name = stored_file_name; file_line = stored_file_line; if(inclevel == 0 && !pv.quiet_flag) { printf("%d Snort rules read...\n", rule_count); printf("%d Option Chains linked into %d Chain Headers\n", opt_count, head_count); printf("%d Dynamic rules\n", dynamic_rules_present); printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n\n"); } rule_file = NULL; fclose(thefp); /* plug all the dynamic rules together */ if(dynamic_rules_present) { LinkDynamicRules(); } if(inclevel == 0) {#ifdef DEBUG DumpRuleChains();#endif IntegrityCheckRules(); } return;}int CheckRule(char *str){ int len; int got_paren = 0; int got_semi = 0; char *index; len = strlen(str); index = str + len - 1; /* go to the end of the string */ while((isspace((int)*index))) { if(index > str) index--; else return 0; } /* the last non-whitspace character should be a ')' */ if(*index == ')') { got_paren = 1; index--; } while((isspace((int)*index))) { if(index > str) index--; else return 0; } /* the next to last char should be a semicolon */ if(*index == ';') { got_semi = 1; } if(got_semi && got_paren) { return 1; } else { /* check for a '(' to make sure that rule options are being used... */ for(index = str; index < str+len; index++) { if(*index == '(') { return 0; } } return 1; } return 0;}void DumpRuleChains(){ RuleListNode *rule; rule = RuleLists; while(rule != NULL) { DumpChain(rule->RuleList->TcpList, rule->name, "TCP Chains"); DumpChain(rule->RuleList->UdpList, rule->name, "UDP Chains"); DumpChain(rule->RuleList->IcmpList, rule->name, "ICMP Chains"); rule = rule->next; }}void IntegrityCheckRules(){ RuleListNode *rule; rule = RuleLists;#ifdef DEBUG if(!pv.quiet_flag) { printf("Performing Rule List Integrity Tests...\n"); printf("---------------------------------------\n"); }#endif while(rule != NULL) { IntegrityCheck(rule->RuleList->TcpList, rule->name, "TCP Chains"); IntegrityCheck(rule->RuleList->UdpList, rule->name, "UDP Chains"); IntegrityCheck(rule->RuleList->IcmpList, rule->name, "ICMP Chains"); rule = rule->next; }#ifdef DEBUG if(!pv.quiet_flag) { printf("---------------------------------------\n\n"); }#endif}/**************************************************************************** * * Function: ParseRule(char *, int) * * Purpose: Process an individual rule and add it to the rule list * * Arguments: rule => rule string * inclevel => nr of stacked "include"s * * Returns: void function * ***************************************************************************/void ParseRule(char *prule, int inclevel){ char **toks; /* dbl ptr for mSplit call, holds rule tokens */ int num_toks; /* holds number of tokens found by mSplit */ int rule_type; /* rule type enumeration variable */ char rule[PARSERULE_SIZE]; int protocol; RuleTreeNode proto_node; int i;#ifdef PARSERULE_BIFURCATE int bid = 0;#endif#ifdef PARSERULE_REVERSED char *tmp_tok_host, *tmp_tok_port; /* 2 tmps for clarity */#endif /* chop off the <CR/LF> from the string */ strip(prule); /* expand all variables */ bzero((void *)rule, sizeof(rule)); strncpy(rule, ExpandVars(prule), PARSERULE_SIZE-1); /* break out the tokens from the rule string */ toks = mSplit(rule, " ", 10, &num_toks, 0);#ifdef PARSERULE_REVERSED if(num_toks > 5 && (strncmp("<-", toks[4], 2) == 0)) {#ifdef DEBUG printf("Reversing rule %s %s %s %s %s %s %s ( into )\n", toks[0],toks[1],toks[2],toks[3],toks[4],toks[5],toks[6]);#endif /* DEBUG */ /* Switch the src and dst port/ips and change the direction */ tmp_tok_host = toks[2]; tmp_tok_port = toks[3]; toks[2] = toks[5]; toks[3] = toks[6]; toks[5] = tmp_tok_host; toks[6] = tmp_tok_port; /* the == 0 makes sure this has room to copy */ strncpy (toks[4], "->", 2); #ifdef DEBUG printf("Reversed rule: %s %s %s %s %s %s %s\n", toks[0],toks[1],toks[2],toks[3],toks[4],toks[5],toks[6]);#endif /* DEBUG */ }#endif /* PARSERULE_REVERSED */#ifdef PARSERULE_BIFURCATE if(num_toks > 5 && (bid = !strncmp("<>", toks[4], 2))) {#ifdef DEBUG printf("Generating bid rules for: %s %s %s %s %s %s %s\n", toks[0],toks[1],toks[2],toks[3],toks[4],toks[5],toks[6]);#endif strncpy (toks[4], "->", 2); } bidog:#endif /* clean house */ bzero((char *) &proto_node, sizeof(RuleTreeNode));#ifdef DEBUG printf("[*] Rule start\n");#endif /* figure out what we're looking at */ rule_type = RuleType(toks[0]);#ifdef DEBUG printf("Rule type: ");#endif /* handle non-rule entries */ switch(rule_type) { case RULE_PASS:#ifdef DEBUG printf("Pass\n");#endif break; case RULE_LOG:#ifdef DEBUG printf("Log\n");#endif break; case RULE_ALERT:#ifdef DEBUG printf("Alert\n");#endif break; case RULE_INCLUDE:#ifdef DEBUG printf("Include\n");#endif ParseRulesFile(toks[1], inclevel + 1); return; case RULE_VAR:#ifdef DEBUG printf("Variable\n");#endif VarDefine(toks[1], toks[2]); return; case RULE_PREPROCESS:#ifdef DEBUG printf("Preprocessor\n");#endif ParsePreprocessor(rule); return; case RULE_OUTPUT:#ifdef DEBUG printf("Output Plugin\n");#endif ParseOutputPlugin(rule); return; case RULE_ACTIVATE:#ifdef DEBUG printf("Activation rule\n");#endif break; case RULE_DYNAMIC:#ifdef DEBUG printf("Dynamic rule\n");#endif break; case RULE_CONFIG:#ifdef DEBUG printf("Rule file config\n");#endif ParseConfig(rule); return; case RULE_DECLARE:#ifdef DEBUG printf("Rule type declaration\n");#endif ParseRuleTypeDeclaration(rule); return; case RULE_UNKNOWN:#ifdef DEBUG printf("Unknown rule type, might be declared\n");#endif ParseDeclaredRuleType(rule); return; default: printf("Invalid input: %s\n", prule); return; } if(!CheckRule(prule)) { ErrorMessage("[!] ERROR: Unterminated rule in file %s, line %d\n", file_name, file_line); ErrorMessage(" (Snort rules must be contained on a single line, make sure\n"); FatalError(" there are no carriage returns before the end of this line)\n"); return; } proto_node.type = rule_type; /* 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 "!<ip number>" we need to set a flag so that we can * properly deal with it when we are processing packets */ /* we found a negated address */ /* if( *toks[2] == '!' ) { proto_node.flags |= EXCEPT_SRC_IP; ProcessIP(&toks[2][1], &proto_node, SRC); } else {*/ ProcessIP(toks[2], &proto_node, SRC); /*}*/ /* check to make sure that the user entered port numbers */ /* sometimes they forget/don't know that ICMP rules need them */ if(!strncasecmp(toks[3], "->", 2) || !strncasecmp(toks[3], "<>", 2)) { FatalError("ERROR %s:%d => Port value missing in rule!\n", file_name, file_line);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -