X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?p=ossec-hids.git;a=blobdiff_plain;f=src%2Fanalysisd%2Frules.c;h=d018cefa13f1a5250309cc0b97d2e1a7b1011198;hp=8c97197cdfc419ba216493b7b8968a15ed899f4f;hb=6ef2f786c6c8ead94841b5f93baf9f43421f08c8;hpb=914feba5d54f979cd5d7e69c349c3d01f630042a diff --git a/src/analysisd/rules.c b/src/analysisd/rules.c index 8c97197..d018cef 100755 --- a/src/analysisd/rules.c +++ b/src/analysisd/rules.c @@ -1,14 +1,15 @@ -/* @(#) $Id: rules.c,v 1.79 2009/11/04 18:45:37 dcid Exp $ */ +/* @(#) $Id: ./src/analysisd/rules.c, 2011/09/08 dcid Exp $ + */ /* Copyright (C) 2009 Trend Micro Inc. * All rights reserved. * * This program is a free software; you can redistribute it * and/or modify it under the terms of the GNU General Public - * License (version 3) as published by the FSF - Free Software + * License (version 2) as published by the FSF - Free Software * Foundation. * - * License details at the LICENSE file included with OSSEC or + * License details at the LICENSE file included with OSSEC or * online at: http://www.ossec.net/en/licensing.html */ @@ -29,11 +30,11 @@ /* Internal functions */ -int getattributes(char **attributes, +int getattributes(char **attributes, char **values, - int *id, int *level, + int *id, int *level, int *maxsize, int *timeframe, - int *frequency, int *accuracy, + int *frequency, int *accuracy, int *noalert, int *ignore_time, int *overwrite); @@ -57,20 +58,18 @@ void Rules_OP_CreateRules() return; } - - /* Rules_OP_ReadRules, v0.3, 2005/03/21 * Read the log rules. * v0.3: Fixed many memory problems. - */ + */ int Rules_OP_ReadRules(char * rulefile) { OS_XML xml; XML_NODE node = NULL; - /* XML variables */ + /* XML variables */ /* These are the available options for the rule configuration */ - + char *xml_group = "group"; char *xml_rule = "rule"; @@ -85,7 +84,7 @@ int Rules_OP_ReadRules(char * rulefile) char *xml_comment = "description"; char *xml_ignore = "ignore"; char *xml_check_if_ignored = "check_if_ignored"; - + char *xml_srcip = "srcip"; char *xml_srcport = "srcport"; char *xml_dstip = "dstip"; @@ -99,51 +98,73 @@ int Rules_OP_ReadRules(char * rulefile) char *xml_status = "status"; char *xml_action = "action"; char *xml_compiled = "compiled_rule"; - + + char *xml_list = "list"; + char *xml_list_lookup = "lookup"; + char *xml_list_field = "field"; + char *xml_list_cvalue = "check_value"; + char *xml_match_key = "match_key"; + char *xml_not_match_key = "not_match_key"; + char *xml_match_key_value = "match_key_value"; + char *xml_address_key = "address_match_key"; + char *xml_not_address_key = "not_address_match_key"; + char *xml_address_key_value = "address_match_key_value"; + char *xml_if_sid = "if_sid"; char *xml_if_group = "if_group"; char *xml_if_level = "if_level"; char *xml_fts = "if_fts"; - + char *xml_if_matched_regex = "if_matched_regex"; char *xml_if_matched_group = "if_matched_group"; char *xml_if_matched_sid = "if_matched_sid"; - + char *xml_same_source_ip = "same_source_ip"; char *xml_same_src_port = "same_src_port"; char *xml_same_dst_port = "same_dst_port"; char *xml_same_user = "same_user"; char *xml_same_location = "same_location"; char *xml_same_id = "same_id"; + char *xml_dodiff = "check_diff"; char *xml_different_url = "different_url"; - + char *xml_notsame_source_ip = "not_same_source_ip"; char *xml_notsame_user = "not_same_user"; char *xml_notsame_agent = "not_same_agent"; char *xml_notsame_id = "not_same_id"; char *xml_options = "options"; - + char *rulepath; - + int i; int default_timeframe = 360; - /* Building the rule file name + path */ - i = strlen(RULEPATH) + strlen(rulefile) + 2; - rulepath = (char *)calloc(i,sizeof(char)); - if(!rulepath) + /* If no directory in the rulefile add the default */ + if((strchr(rulefile, '/')) == NULL) { - ErrorExit(MEM_ERROR,ARGV0); + /* Building the rule file name + path */ + i = strlen(RULEPATH) + strlen(rulefile) + 2; + rulepath = (char *)calloc(i,sizeof(char)); + if(!rulepath) + { + ErrorExit(MEM_ERROR,ARGV0); + } + snprintf(rulepath,i,"%s/%s",RULEPATH,rulefile); + } + else + { + os_strdup(rulefile, rulepath); + debug1("%s is the rulefile", rulefile); + debug1("Not modifing the rule path"); } - - snprintf(rulepath,i,"%s/%s",RULEPATH,rulefile); - - i = 0; - - /* Reading the XML */ + + + i = 0; + + /* Reading the XML */ if(OS_ReadXML(rulepath,&xml) < 0) { merror(XML_ERROR, ARGV0, rulepath, xml.err, xml.err_line); @@ -154,9 +175,9 @@ int Rules_OP_ReadRules(char * rulefile) /* Debug wrapper */ debug2("%s: DEBUG: read xml for rule.", ARGV0); - - + + /* Applying any variable found */ if(OS_ApplyVariables(&xml) != 0) { @@ -167,7 +188,7 @@ int Rules_OP_ReadRules(char * rulefile) /* Debug wrapper */ debug2("%s: DEBUG: XML Variables applied.", ARGV0); - + /* Getting the root elements */ node = OS_GetElementsbyNode(&xml,NULL); @@ -175,7 +196,7 @@ int Rules_OP_ReadRules(char * rulefile) { merror(CONFIG_ERROR, ARGV0, rulepath); OS_ClearXML(&xml); - return(-1); + return(-1); } @@ -222,7 +243,7 @@ int Rules_OP_ReadRules(char * rulefile) } - /* Getting the rules now */ + /* Getting the rules now */ i=0; while(node[i]) { @@ -230,7 +251,7 @@ int Rules_OP_ReadRules(char * rulefile) int j = 0; - /* Getting all rules for a global group */ + /* Getting all rules for a global group */ rule = OS_GetElementsbyNode(&xml,node[i]); if(rule == NULL) { @@ -243,7 +264,7 @@ int Rules_OP_ReadRules(char * rulefile) while(rule[j]) { RuleInfo *config_ruleinfo = NULL; - + /* Checking if the rule element is correct */ if((!rule[j]->element)|| @@ -265,17 +286,17 @@ int Rules_OP_ReadRules(char * rulefile) return(-1); } - + /* Attribute block */ { int id = -1,level = -1,maxsize = 0,timeframe = 0; int frequency = 0, accuracy = 1, noalert = 0, ignore_time = 0; int overwrite = 0; - + /* Getting default time frame */ timeframe = default_timeframe; - + if(getattributes(rule[j]->attributes,rule[j]->values, &id,&level,&maxsize,&timeframe, &frequency,&accuracy,&noalert, @@ -285,7 +306,7 @@ int Rules_OP_ReadRules(char * rulefile) OS_ClearXML(&xml); return(-1); } - + if((id == -1) || (level == -1)) { merror("%s: No rule id or level specified for " @@ -296,17 +317,17 @@ int Rules_OP_ReadRules(char * rulefile) /* Allocating memory and initializing structure */ config_ruleinfo = zerorulemember(id, level, maxsize, - frequency,timeframe, + frequency,timeframe, noalert, ignore_time, overwrite); - + /* If rule is 0, set it to level 99 to have high priority. - * set it to 0 again later + * set it to 0 again later */ if(config_ruleinfo->level == 0) config_ruleinfo->level = 99; - + /* Each level now is going to be multiplied by 100. * If the accuracy is set to 0 we don't multiply, * so it will be at the end of the list. We will @@ -324,7 +345,7 @@ int Rules_OP_ReadRules(char * rulefile) config_ruleinfo->alert_opts |= DO_EXTRAINFO; } } - + } /* end attributes/memory allocation block */ @@ -333,11 +354,14 @@ int Rules_OP_ReadRules(char * rulefile) * be fine */ os_strdup(node[i]->values[0], config_ruleinfo->group); - + /* Rule elements block */ { int k = 0; + int info_type = 0; + int count_info_detail = 0; + RuleInfoDetail *last_info_detail = NULL; char *regex = NULL; char *match = NULL; char *url = NULL; @@ -351,7 +375,7 @@ int Rules_OP_ReadRules(char * rulefile) char *hostname = NULL; char *extra_data = NULL; char *program_name = NULL; - + XML_NODE rule_opt = NULL; rule_opt = OS_GetElementsbyNode(&xml,rule[j]); if(rule_opt == NULL) @@ -361,9 +385,9 @@ int Rules_OP_ReadRules(char * rulefile) "other problems for the system. Exiting.", ARGV0, config_ruleinfo->sigid); OS_ClearXML(&xml); - return(-1); + return(-1); } - + while(rule_opt[k]) { if((!rule_opt[k]->element)||(!rule_opt[k]->content)) @@ -382,26 +406,79 @@ int Rules_OP_ReadRules(char * rulefile) } else if(strcasecmp(rule_opt[k]->element, xml_decoded)==0) { - config_ruleinfo->decoded_as = + config_ruleinfo->decoded_as = getDecoderfromlist(rule_opt[k]->content); - + if(config_ruleinfo->decoded_as == 0) { merror("%s: Invalid decoder name: '%s'.", ARGV0, rule_opt[k]->content); OS_ClearXML(&xml); - return(-1); + return(-1); } } + else if(strcasecmp(rule_opt[k]->element,xml_cve)==0) + { + if(config_ruleinfo->info_details == NULL) + { + config_ruleinfo->info_details = zeroinfodetails(RULEINFODETAIL_CVE, + rule_opt[k]->content); + } + else + { + for (last_info_detail = config_ruleinfo->info_details; + last_info_detail->next != NULL; + last_info_detail = last_info_detail->next) + { + count_info_detail++; + } + /* Silently Drop info messages if their are more then MAX_RULEINFODETAIL */ + if (count_info_detail <= MAX_RULEINFODETAIL) + { + last_info_detail->next = zeroinfodetails(RULEINFODETAIL_CVE, + rule_opt[k]->content); + } + } + + /* keep old methods for now */ + config_ruleinfo->cve= + loadmemory(config_ruleinfo->cve, + rule_opt[k]->content); + } else if(strcasecmp(rule_opt[k]->element,xml_info)==0) { + + info_type = get_info_attributes(rule_opt[k]->attributes, + rule_opt[k]->values); + debug1("info_type = %d", info_type); + + if(config_ruleinfo->info_details == NULL) + { + config_ruleinfo->info_details = zeroinfodetails(info_type, + rule_opt[k]->content); + } + else + { + for (last_info_detail = config_ruleinfo->info_details; + last_info_detail->next != NULL; + last_info_detail = last_info_detail->next) { + count_info_detail++; + } + /* Silently Drop info messages if their are more then MAX_RULEINFODETAIL */ + if (count_info_detail <= MAX_RULEINFODETAIL) { + last_info_detail->next = zeroinfodetails(info_type, rule_opt[k]->content); + } + } + + + /* keep old methods for now */ config_ruleinfo->info= loadmemory(config_ruleinfo->info, rule_opt[k]->content); } else if(strcasecmp(rule_opt[k]->element,xml_day_time)==0) { - config_ruleinfo->day_time = + config_ruleinfo->day_time = OS_IsValidTime(rule_opt[k]->content); if(!config_ruleinfo->day_time) { @@ -416,9 +493,9 @@ int Rules_OP_ReadRules(char * rulefile) } else if(strcasecmp(rule_opt[k]->element,xml_week_day)==0) { - config_ruleinfo->week_day = + config_ruleinfo->week_day = OS_IsValidDay(rule_opt[k]->content); - + if(!config_ruleinfo->week_day) { merror(INVALID_CONFIG, ARGV0, @@ -435,12 +512,6 @@ int Rules_OP_ReadRules(char * rulefile) loadmemory(config_ruleinfo->group, rule_opt[k]->content); } - else if(strcasecmp(rule_opt[k]->element,xml_cve)==0) - { - config_ruleinfo->cve= - loadmemory(config_ruleinfo->cve, - rule_opt[k]->content); - } else if(strcasecmp(rule_opt[k]->element,xml_comment)==0) { char *newline; @@ -450,7 +521,7 @@ int Rules_OP_ReadRules(char * rulefile) { *newline = ' '; } - + config_ruleinfo->comment= loadmemory(config_ruleinfo->comment, rule_opt[k]->content); @@ -458,27 +529,27 @@ int Rules_OP_ReadRules(char * rulefile) else if(strcasecmp(rule_opt[k]->element,xml_srcip)==0) { int ip_s = 0; - + /* Getting size of source ip list */ - while(config_ruleinfo->srcip && + while(config_ruleinfo->srcip && config_ruleinfo->srcip[ip_s]) { ip_s++; } - - config_ruleinfo->srcip = + + config_ruleinfo->srcip = realloc(config_ruleinfo->srcip, (ip_s + 2) * sizeof(os_ip *)); - - + + /* Allocating memory for the individual entries */ - os_calloc(1, sizeof(os_ip), + os_calloc(1, sizeof(os_ip), config_ruleinfo->srcip[ip_s]); config_ruleinfo->srcip[ip_s +1] = NULL; - - + + /* Checking if the ip is valid */ - if(!OS_IsValidIP(rule_opt[k]->content, + if(!OS_IsValidIP(rule_opt[k]->content, config_ruleinfo->srcip[ip_s])) { merror(INVALID_IP, ARGV0, rule_opt[k]->content); @@ -558,7 +629,7 @@ int Rules_OP_ReadRules(char * rulefile) status = loadmemory(status, rule_opt[k]->content); - + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) config_ruleinfo->alert_opts |= DO_EXTRAINFO; } @@ -567,7 +638,7 @@ int Rules_OP_ReadRules(char * rulefile) hostname = loadmemory(hostname, rule_opt[k]->content); - + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) config_ruleinfo->alert_opts |= DO_EXTRAINFO; } @@ -589,10 +660,136 @@ int Rules_OP_ReadRules(char * rulefile) } else if(strcasecmp(rule_opt[k]->element,xml_action)==0) { - config_ruleinfo->action = + config_ruleinfo->action = loadmemory(config_ruleinfo->action, rule_opt[k]->content); } + else if(strcasecmp(rule_opt[k]->element,xml_list)==0) + { + debug1("-> %s == %s",rule_opt[k]->element, xml_list); + if (rule_opt[k]->attributes && rule_opt[k]->values && rule_opt[k]->content) + { + int list_att_num=0; + int rule_type=0; + OSMatch *matcher=NULL; + int lookup_type = LR_STRING_MATCH; + while(rule_opt[k]->attributes[list_att_num]) + { + if(strcasecmp(rule_opt[k]->attributes[list_att_num], xml_list_lookup) == 0) + { + if(strcasecmp(rule_opt[k]->values[list_att_num],xml_match_key) == 0) + lookup_type = LR_STRING_MATCH; + else if(strcasecmp(rule_opt[k]->values[list_att_num],xml_not_match_key)==0) + lookup_type = LR_STRING_NOT_MATCH; + else if(strcasecmp(rule_opt[k]->values[list_att_num],xml_match_key_value)==0) + lookup_type = LR_STRING_MATCH_VALUE; + else if(strcasecmp(rule_opt[k]->values[list_att_num],xml_address_key)==0) + lookup_type = LR_ADDRESS_MATCH; + else if(strcasecmp(rule_opt[k]->values[list_att_num],xml_not_address_key)==0) + lookup_type = LR_ADDRESS_NOT_MATCH; + else if(strcasecmp(rule_opt[k]->values[list_att_num],xml_address_key_value)==0) + lookup_type = LR_ADDRESS_MATCH_VALUE; + else + { + merror(INVALID_CONFIG, ARGV0, + rule_opt[k]->element, + rule_opt[k]->content); + merror("%s: List match lookup=\"%s\" is not valid.", + ARGV0,rule_opt[k]->values[list_att_num]); + return(-1); + } + } + else if(strcasecmp(rule_opt[k]->attributes[list_att_num], xml_list_field)==0) + { + if(strcasecmp(rule_opt[k]->values[list_att_num],xml_srcip)==0) + rule_type = RULE_SRCIP; + else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_srcport)==0) + rule_type = RULE_SRCPORT; + else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_dstip)==0) + rule_type = RULE_DSTIP; + else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_dstport)==0) + rule_type = RULE_DSTPORT; + else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_user)==0) + rule_type = RULE_USER; + else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_url)==0) + rule_type = RULE_URL; + else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_id)==0) + rule_type = RULE_ID; + else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_hostname)==0) + rule_type = RULE_HOSTNAME; + else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_program_name)==0) + rule_type = RULE_PROGRAM_NAME; + else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_status)==0) + rule_type = RULE_STATUS; + else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_action)==0) + rule_type = RULE_ACTION; + else + { + merror(INVALID_CONFIG, ARGV0, + rule_opt[k]->element, + rule_opt[k]->content); + merror("%s: List match field=\"%s\" is not valid.", + ARGV0,rule_opt[k]->values[list_att_num]); + return(-1); + } + } + else if(strcasecmp(rule_opt[k]->attributes[list_att_num], xml_list_cvalue)==0) + { + os_calloc(1, sizeof(OSMatch), matcher); + if(!OSMatch_Compile(rule_opt[k]->values[list_att_num], matcher, 0)) + { + merror(INVALID_CONFIG, ARGV0, + rule_opt[k]->element, + rule_opt[k]->content); + merror(REGEX_COMPILE, + ARGV0, + rule_opt[k]->values[list_att_num], + matcher->error); + return(-1); + } + } + else + { + merror("%s:List feild=\"%s\" is not valid",ARGV0, + rule_opt[k]->values[list_att_num]); + merror(INVALID_CONFIG, ARGV0, + rule_opt[k]->element, rule_opt[k]->content); + return(-1); + } + list_att_num++; + } + if(rule_type == 0) + { + merror("%s:List requires the field=\"\" Attrubute",ARGV0); + merror(INVALID_CONFIG, ARGV0, + rule_opt[k]->element, rule_opt[k]->content); + return(-1); + } + + /* Wow it's all ready - this seams too complex to get to this point */ + config_ruleinfo->lists = OS_AddListRule(config_ruleinfo->lists, + lookup_type, + rule_type, + rule_opt[k]->content, + matcher); + if (config_ruleinfo->lists == NULL) + { + merror("%s: List error: Could not load %s", ARGV0, rule_opt[k]->content); + return(-1); + } + } + else + { + merror("%s:List must have a correctly formatted feild attribute", + ARGV0); + merror(INVALID_CONFIG, + ARGV0, + rule_opt[k]->element, + rule_opt[k]->content); + return(-1); + } + /* xml_list eval is done */ + } else if(strcasecmp(rule_opt[k]->element,xml_url)==0) { url= @@ -605,7 +802,7 @@ int Rules_OP_ReadRules(char * rulefile) while(compiled_rules_name[it_id]) { - if(strcmp(compiled_rules_name[it_id], + if(strcmp(compiled_rules_name[it_id], rule_opt[k]->content) == 0) break; it_id++; @@ -614,9 +811,9 @@ int Rules_OP_ReadRules(char * rulefile) /* checking if the name is valid. */ if(!compiled_rules_name[it_id]) { - merror("%s: ERROR: Compiled rule not found: '%s'", - ARGV0, rule_opt[k]->content); - merror(INVALID_CONFIG, ARGV0, + merror("%s: ERROR: Compiled rule not found: '%s'", + ARGV0, rule_opt[k]->content); + merror(INVALID_CONFIG, ARGV0, rule_opt[k]->element, rule_opt[k]->content); return(-1); @@ -674,9 +871,9 @@ int Rules_OP_ReadRules(char * rulefile) { if(!OS_StrIsNum(rule_opt[k]->content)) { - merror(INVALID_CONFIG, ARGV0, + merror(INVALID_CONFIG, ARGV0, "if_level", - rule_opt[k]->content); + rule_opt[k]->content); return(-1); } @@ -717,7 +914,7 @@ int Rules_OP_ReadRules(char * rulefile) rule_opt[k]->content); return(-1); } - config_ruleinfo->if_matched_sid = + config_ruleinfo->if_matched_sid = atoi(rule_opt[k]->content); } @@ -730,15 +927,23 @@ int Rules_OP_ReadRules(char * rulefile) xml_same_src_port)==0) { config_ruleinfo->context_opts|= SAME_SRCPORT; - + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) config_ruleinfo->alert_opts |= SAME_EXTRAINFO; } else if(strcasecmp(rule_opt[k]->element, + xml_dodiff)==0) + { + config_ruleinfo->context = 1; + config_ruleinfo->context_opts|= SAME_DODIFF; + if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) + config_ruleinfo->alert_opts |= DO_EXTRAINFO; + } + else if(strcasecmp(rule_opt[k]->element, xml_same_dst_port) == 0) { config_ruleinfo->context_opts|= SAME_DSTPORT; - + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) config_ruleinfo->alert_opts |= SAME_EXTRAINFO; } @@ -755,7 +960,7 @@ int Rules_OP_ReadRules(char * rulefile) xml_different_url) == 0) { config_ruleinfo->context_opts|= DIFFERENT_URL; - + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) config_ruleinfo->alert_opts |= SAME_EXTRAINFO; } @@ -772,7 +977,7 @@ int Rules_OP_ReadRules(char * rulefile) xml_same_user)==0) { config_ruleinfo->context_opts|= SAME_USER; - + if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) config_ruleinfo->alert_opts |= SAME_EXTRAINFO; } @@ -796,7 +1001,7 @@ int Rules_OP_ReadRules(char * rulefile) else if(strcasecmp(rule_opt[k]->element, xml_options) == 0) { - if(strcmp("alert_by_email", + if(strcmp("alert_by_email", rule_opt[k]->content) == 0) { if(!(config_ruleinfo->alert_opts & DO_MAILALERT)) @@ -812,7 +1017,7 @@ int Rules_OP_ReadRules(char * rulefile) config_ruleinfo->alert_opts&=0xfff-DO_MAILALERT; } } - else if(strcmp("log_alert", + else if(strcmp("log_alert", rule_opt[k]->content) == 0) { if(!(config_ruleinfo->alert_opts & DO_LOGALERT)) @@ -827,8 +1032,15 @@ int Rules_OP_ReadRules(char * rulefile) config_ruleinfo->alert_opts &=0xfff-DO_LOGALERT; } } + else if(strcmp("no_ar", rule_opt[k]->content) == 0) + { + if(!(config_ruleinfo->alert_opts & NO_AR)) + { + config_ruleinfo->alert_opts|= NO_AR; + } + } else - { + { merror(XML_VALUEERR, ARGV0, xml_options, rule_opt[k]->content); @@ -837,7 +1049,7 @@ int Rules_OP_ReadRules(char * rulefile) config_ruleinfo->sigid); OS_ClearXML(&xml); return(-1); - } + } } else if(strcasecmp(rule_opt[k]->element, xml_ignore) == 0) @@ -873,7 +1085,7 @@ int Rules_OP_ReadRules(char * rulefile) } if(!config_ruleinfo->ignore) { - merror("%s: Wrong ignore option: '%s'", + merror("%s: Wrong ignore option: '%s'", ARGV0, rule_opt[k]->content); return(-1); @@ -913,7 +1125,7 @@ int Rules_OP_ReadRules(char * rulefile) } if(!config_ruleinfo->ckignore) { - merror("%s: Wrong check_if_ignored option: '%s'", + merror("%s: Wrong check_if_ignored option: '%s'", ARGV0, rule_opt[k]->content); return(-1); @@ -932,7 +1144,7 @@ int Rules_OP_ReadRules(char * rulefile) /* Checking for a valid use of frequency */ - if((config_ruleinfo->context_opts || + if((config_ruleinfo->context_opts || config_ruleinfo->frequency) && !config_ruleinfo->context) { @@ -942,42 +1154,42 @@ int Rules_OP_ReadRules(char * rulefile) OS_ClearXML(&xml); return(-1); } - + /* If if_matched_group we must have a if_sid or if_group */ if(if_matched_group) { if(!config_ruleinfo->if_sid && !config_ruleinfo->if_group) { - os_strdup(if_matched_group, - config_ruleinfo->if_group); + os_strdup(if_matched_group, + config_ruleinfo->if_group); } } /* If_matched_sid, we need to get the if_sid */ - if(config_ruleinfo->if_matched_sid && + if(config_ruleinfo->if_matched_sid && !config_ruleinfo->if_sid && !config_ruleinfo->if_group) { os_calloc(16, sizeof(char), config_ruleinfo->if_sid); - snprintf(config_ruleinfo->if_sid, 15, "%d", + snprintf(config_ruleinfo->if_sid, 15, "%d", config_ruleinfo->if_matched_sid); } - + /* Checking the regexes */ if(regex) { os_calloc(1, sizeof(OSRegex), config_ruleinfo->regex); if(!OSRegex_Compile(regex, config_ruleinfo->regex, 0)) { - merror(REGEX_COMPILE, ARGV0, regex, + merror(REGEX_COMPILE, ARGV0, regex, config_ruleinfo->regex->error); return(-1); } free(regex); regex = NULL; } - + /* Adding in match */ if(match) { @@ -991,14 +1203,14 @@ int Rules_OP_ReadRules(char * rulefile) free(match); match = NULL; } - + /* Adding in id */ if(id) { os_calloc(1, sizeof(OSMatch), config_ruleinfo->id); if(!OSMatch_Compile(id, config_ruleinfo->id, 0)) { - merror(REGEX_COMPILE, ARGV0, id, + merror(REGEX_COMPILE, ARGV0, id, config_ruleinfo->id->error); return(-1); } @@ -1012,7 +1224,7 @@ int Rules_OP_ReadRules(char * rulefile) os_calloc(1, sizeof(OSMatch), config_ruleinfo->srcport); if(!OSMatch_Compile(srcport, config_ruleinfo->srcport, 0)) { - merror(REGEX_COMPILE, ARGV0, srcport, + merror(REGEX_COMPILE, ARGV0, srcport, config_ruleinfo->id->error); return(-1); } @@ -1026,7 +1238,7 @@ int Rules_OP_ReadRules(char * rulefile) os_calloc(1, sizeof(OSMatch), config_ruleinfo->dstport); if(!OSMatch_Compile(dstport, config_ruleinfo->dstport, 0)) { - merror(REGEX_COMPILE, ARGV0, dstport, + merror(REGEX_COMPILE, ARGV0, dstport, config_ruleinfo->id->error); return(-1); } @@ -1066,7 +1278,7 @@ int Rules_OP_ReadRules(char * rulefile) if(extra_data) { os_calloc(1, sizeof(OSMatch), config_ruleinfo->extra_data); - if(!OSMatch_Compile(extra_data, + if(!OSMatch_Compile(extra_data, config_ruleinfo->extra_data, 0)) { merror(REGEX_COMPILE, ARGV0, extra_data, @@ -1091,7 +1303,7 @@ int Rules_OP_ReadRules(char * rulefile) free(program_name); program_name = NULL; } - + /* Adding in user */ if(user) { @@ -1105,28 +1317,28 @@ int Rules_OP_ReadRules(char * rulefile) free(user); user = NULL; } - + /* Adding in url */ if(url) { os_calloc(1, sizeof(OSMatch), config_ruleinfo->url); if(!OSMatch_Compile(url, config_ruleinfo->url, 0)) { - merror(REGEX_COMPILE, ARGV0, url, + merror(REGEX_COMPILE, ARGV0, url, config_ruleinfo->url->error); return(-1); } free(url); url = NULL; } - + /* Adding matched_group */ if(if_matched_group) { - os_calloc(1, sizeof(OSMatch), + os_calloc(1, sizeof(OSMatch), config_ruleinfo->if_matched_group); - - if(!OSMatch_Compile(if_matched_group, + + if(!OSMatch_Compile(if_matched_group, config_ruleinfo->if_matched_group, 0)) { @@ -1137,16 +1349,16 @@ int Rules_OP_ReadRules(char * rulefile) free(if_matched_group); if_matched_group = NULL; } - + /* Adding matched_regex */ if(if_matched_regex) { - os_calloc(1, sizeof(OSRegex), + os_calloc(1, sizeof(OSRegex), config_ruleinfo->if_matched_regex); - if(!OSRegex_Compile(if_matched_regex, + if(!OSRegex_Compile(if_matched_regex, config_ruleinfo->if_matched_regex, 0)) { - merror(REGEX_COMPILE, ARGV0, if_matched_regex, + merror(REGEX_COMPILE, ARGV0, if_matched_regex, config_ruleinfo->if_matched_regex->error); return(-1); } @@ -1166,9 +1378,9 @@ int Rules_OP_ReadRules(char * rulefile) if(config_ruleinfo->context) { int ii = 0; - os_calloc(MAX_LAST_EVENTS + 1, sizeof(char *), + os_calloc(MAX_LAST_EVENTS + 1, sizeof(char *), config_ruleinfo->last_events); - + /* Zeroing each entry */ for(;ii<=MAX_LAST_EVENTS;ii++) { @@ -1176,19 +1388,19 @@ int Rules_OP_ReadRules(char * rulefile) } } - + /* Adding the rule to the rules list. * Only the template rules are supposed * to be at the top level. All others * will be a "child" of someone. */ if(config_ruleinfo->sigid < 10) - { + { OS_AddRule(config_ruleinfo); } else if(config_ruleinfo->alert_opts & DO_OVERWRITE) { - if(!OS_AddRuleInfo(NULL, config_ruleinfo, + if(!OS_AddRuleInfo(NULL, config_ruleinfo, config_ruleinfo->sigid)) { merror("%s: Overwrite rule '%d' not found.", @@ -1212,13 +1424,13 @@ int Rules_OP_ReadRules(char * rulefile) /* Setting the event_search pointer */ if(config_ruleinfo->if_matched_sid) { - config_ruleinfo->event_search = + config_ruleinfo->event_search = (void *)Search_LastSids; - + /* Marking rules that match this id */ - OS_MarkID(NULL, config_ruleinfo); + OS_MarkID(NULL, config_ruleinfo); } - + /* Marking the rules that match if_matched_group */ else if(config_ruleinfo->if_matched_group) { @@ -1233,19 +1445,27 @@ int Rules_OP_ReadRules(char * rulefile) OS_MarkGroup(NULL, config_ruleinfo); /* Setting function pointer */ - config_ruleinfo->event_search = + config_ruleinfo->event_search = (void *)Search_LastGroups; } else if(config_ruleinfo->context) { - config_ruleinfo->event_search = + if((config_ruleinfo->context == 1) && + (config_ruleinfo->context_opts & SAME_DODIFF)) + { + config_ruleinfo->context = 0; + } + else + { + config_ruleinfo->event_search = (void *)Search_LastEvents; + } } } /* while(rule[j]) */ OS_ClearNode(rule); i++; - + } /* while (node[i]) */ /* Cleaning global node */ @@ -1310,38 +1530,61 @@ char *loadmemory(char *at, char *str) int strsize = strlen(str); int atsize = strlen(at); int finalsize = atsize+strsize+1; - + if((atsize > OS_SIZE_2048) || (strsize > OS_SIZE_2048)) { merror(SIZE_ERROR,ARGV0,str); return(NULL); } - + at = realloc(at, (finalsize)*sizeof(char)); - + if(at == NULL) { merror(MEM_ERROR,ARGV0); return(NULL); } - + strncat(at,str,strsize); - + at[finalsize-1]='\0'; - + return(at); } return(NULL); } -RuleInfo *zerorulemember(int id, int level, +RuleInfoDetail *zeroinfodetails(int type, char *data) +{ + RuleInfoDetail *info_details_pt = NULL; + + info_details_pt = (RuleInfoDetail *)calloc(1,sizeof(RuleInfoDetail)); + + if (info_details_pt == NULL) + { + ErrorExit(MEM_ERROR,ARGV0); + } + /* type */ + info_details_pt->type = type; + + /* data */ + os_strdup(data, info_details_pt->data); + + info_details_pt->next = NULL; + + + return(info_details_pt); +} + + +RuleInfo *zerorulemember(int id, int level, int maxsize, int frequency, - int timeframe, int noalert, + int timeframe, int noalert, int ignore_time, int overwrite) { RuleInfo *ruleinfo_pt = NULL; - + /* Allocation memory for structure */ ruleinfo_pt = (RuleInfo *)calloc(1,sizeof(RuleInfo)); @@ -1349,17 +1592,17 @@ RuleInfo *zerorulemember(int id, int level, { ErrorExit(MEM_ERROR,ARGV0); } - + /* Default values */ ruleinfo_pt->level = level; /* Default category is syslog */ ruleinfo_pt->category = SYSLOG; - ruleinfo_pt->ar = NULL; - + ruleinfo_pt->ar = NULL; + ruleinfo_pt->context = 0; - + ruleinfo_pt->sigid = id; ruleinfo_pt->firedtimes = 0; ruleinfo_pt->maxsize = maxsize; @@ -1371,11 +1614,11 @@ RuleInfo *zerorulemember(int id, int level, ruleinfo_pt->ignore_time = ignore_time; ruleinfo_pt->timeframe = timeframe; ruleinfo_pt->time_ignored = 0; - - ruleinfo_pt->context_opts = 0; - ruleinfo_pt->alert_opts = 0; - ruleinfo_pt->ignore = 0; - ruleinfo_pt->ckignore = 0; + + ruleinfo_pt->context_opts = 0; + ruleinfo_pt->alert_opts = 0; + ruleinfo_pt->ignore = 0; + ruleinfo_pt->ckignore = 0; if(noalert) { @@ -1383,7 +1626,7 @@ RuleInfo *zerorulemember(int id, int level, } if(Config.mailbylevel <= level) ruleinfo_pt->alert_opts |= DO_MAILALERT; - if(Config.logbylevel <= level) + if(Config.logbylevel <= level) ruleinfo_pt->alert_opts |= DO_LOGALERT; /* Overwriting a rule */ @@ -1403,16 +1646,17 @@ RuleInfo *zerorulemember(int id, int level, ruleinfo_pt->comment = NULL; ruleinfo_pt->info = NULL; ruleinfo_pt->cve = NULL; - + ruleinfo_pt->info_details = NULL; + ruleinfo_pt->if_sid = NULL; ruleinfo_pt->if_group = NULL; ruleinfo_pt->if_level = NULL; - + ruleinfo_pt->if_matched_regex = NULL; ruleinfo_pt->if_matched_group = NULL; ruleinfo_pt->if_matched_sid = 0; - - ruleinfo_pt->user = NULL; + + ruleinfo_pt->user = NULL; ruleinfo_pt->srcip = NULL; ruleinfo_pt->srcport = NULL; ruleinfo_pt->dstip = NULL; @@ -1423,7 +1667,7 @@ RuleInfo *zerorulemember(int id, int level, ruleinfo_pt->hostname = NULL; ruleinfo_pt->program_name = NULL; ruleinfo_pt->action = NULL; - + /* Zeroing last matched events */ ruleinfo_pt->__frequency = 0; ruleinfo_pt->last_events = NULL; @@ -1431,26 +1675,64 @@ RuleInfo *zerorulemember(int id, int level, /* zeroing the list of previous matches */ ruleinfo_pt->sid_prev_matched = NULL; ruleinfo_pt->group_prev_matched = NULL; - + ruleinfo_pt->sid_search = NULL; ruleinfo_pt->group_search = NULL; - + ruleinfo_pt->event_search = NULL; ruleinfo_pt->compiled_rule = NULL; + ruleinfo_pt->lists = NULL; return(ruleinfo_pt); } +int get_info_attributes(char **attributes, char **values) +{ + char *xml_type = "type"; + int k=0; + if(!attributes) + return(RULEINFODETAIL_TEXT); + + while(attributes[k]) + { + if (!values[k]) + { + merror("rules_op: Entry info type \"%s\" does not have a value", + attributes[k]); + return (-1); + } + else if(strcasecmp(attributes[k],xml_type) == 0) + { + if(strcmp(values[k], "text") == 0) + { + return(RULEINFODETAIL_TEXT); + } + else if(strcmp(values[k], "link") == 0) + { + return(RULEINFODETAIL_LINK); + } + else if(strcmp(values[k], "cve") == 0) + { + return(RULEINFODETAIL_CVE); + } + else if(strcmp(values[k], "osvdb") == 0) + { + return(RULEINFODETAIL_OSVDB); + } + } + } + return(RULEINFODETAIL_TEXT); +} /* Get the attributes */ int getattributes(char **attributes, char **values, - int *id, int *level, + int *id, int *level, int *maxsize, int *timeframe, - int *frequency, int *accuracy, + int *frequency, int *accuracy, int *noalert, int *ignore_time, int *overwrite) { int k=0; - + char *xml_id = "id"; char *xml_level = "level"; char *xml_maxsize = "maxsize"; @@ -1460,8 +1742,8 @@ int getattributes(char **attributes, char **values, char *xml_noalert = "noalert"; char *xml_ignore_time = "ignore"; char *xml_overwrite = "overwrite"; - - + + /* Getting attributes */ while(attributes[k]) { @@ -1558,7 +1840,7 @@ int getattributes(char **attributes, char **values, merror("rules_op: Invalid accuracy: %s. " "Must be integer" , values[k]); - return(-1); + return(-1); } } /* Rule ignore_time */ @@ -1573,7 +1855,7 @@ int getattributes(char **attributes, char **values, merror("rules_op: Invalid ignore_time: %s. " "Must be integer" , values[k]); - return(-1); + return(-1); } } /* Rule noalert */ @@ -1619,33 +1901,39 @@ void Rule_AddAR(RuleInfo *rule_config) int rule_ar_size = 0; int mark_to_ar = 0; int rule_real_level = 0; - + OSListNode *my_ars_node; - - - /* Setting the correctly levels + + + /* Setting the correctly levels * We play internally with the rules, to set * the priorities... Rules with 0 of accuracy, * receive a low level and go down in the list */ if(rule_config->level == 9900) rule_real_level = 0; - + else if(rule_config->level >= 100) rule_real_level = rule_config->level/100; - - + + /* No AR for ignored rules */ if(rule_real_level == 0) { return; } + /* No AR when options no_ar is set */ + if(rule_config->alert_opts & NO_AR) + { + return; + } + if(!active_responses) { return; } - + /* Looping on all AR */ my_ars_node = OSList_GetFirstNode(active_responses); while(my_ars_node) @@ -1664,7 +1952,7 @@ void Rule_AddAR(RuleInfo *rule_config) mark_to_ar = 1; } } - + /* Checking if group matches */ if(my_ar->rules_group) { @@ -1673,7 +1961,7 @@ void Rule_AddAR(RuleInfo *rule_config) mark_to_ar = 1; } } - + /* Checking if rule id matches */ if(my_ar->rules_id) { @@ -1696,13 +1984,13 @@ void Rule_AddAR(RuleInfo *rule_config) else if(isdigit((int)*str_pt)) { r_id = atoi(str_pt); - + /* mark to ar if id matches */ if(r_id == rule_config->sigid) { mark_to_ar = 1; } - + str_pt = strchr(str_pt, ','); if(str_pt) { @@ -1727,9 +2015,9 @@ void Rule_AddAR(RuleInfo *rule_config) } } } /* eof of rules_id */ - - - /* Bind AR to the rule */ + + + /* Bind AR to the rule */ if(mark_to_ar == 1) { rule_ar_size++; @@ -1737,12 +2025,12 @@ void Rule_AddAR(RuleInfo *rule_config) rule_config->ar = realloc(rule_config->ar, (rule_ar_size + 1) *sizeof(active_response *)); - + /* Always set the last node to NULL */ rule_config->ar[rule_ar_size - 1] = my_ar; - rule_config->ar[rule_ar_size] = NULL; + rule_config->ar[rule_ar_size] = NULL; } - + my_ars_node = OSList_GetNextNode(active_responses); } @@ -1753,9 +2041,9 @@ void Rule_AddAR(RuleInfo *rule_config) /* print rule */ void printRuleinfo(RuleInfo *rule, int node) { - debug1("%d : rule:%d, level %d, timeout: %d", + debug1("%d : rule:%d, level %d, timeout: %d", node, - rule->sigid, + rule->sigid, rule->level, rule->ignore_time); } @@ -1772,8 +2060,8 @@ int AddHash_Rule(RuleNode *node) snprintf(_id_key, 14, "%d", node->ruleinfo->sigid); os_strdup(_id_key, id_key); - - + + /* Adding key to hash. */ OSHash_Add(Config.g_rules_hash, id_key, node->ruleinfo); if(node->child) @@ -1802,10 +2090,10 @@ int _setlevels(RuleNode *node, int nnode) node->ruleinfo->level/=100; l_size++; - + /* Rule information */ printRuleinfo(node->ruleinfo, nnode); - + if(node->child) { int chl_size = 0;