Imported Upstream version 2.5.1
[ossec-hids.git] / src / analysisd / rules.c
1 /* @(#) $Id$ */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All rights reserved.
5  *
6  * This program is a free software; you can redistribute it
7  * and/or modify it under the terms of the GNU General Public
8  * License (version 2) as published by the FSF - Free Software
9  * Foundation.
10  *
11  * License details at the LICENSE file included with OSSEC or 
12  * online at: http://www.ossec.net/en/licensing.html
13  */
14
15
16
17 #include "rules.h"
18 #include "config.h"
19 #include "eventinfo.h"
20 #include "compiled_rules/compiled_rules.h"
21
22
23 /* Chaging path for test rule. */
24 #ifdef TESTRULE
25   #undef RULEPATH
26   #define RULEPATH "rules/"
27 #endif
28
29
30
31 /* Internal functions */
32 int getattributes(char **attributes, 
33                   char **values,
34                   int *id, int *level, 
35                   int *maxsize, int *timeframe,
36                   int *frequency, int *accuracy, 
37                   int *noalert, int *ignore_time, int *overwrite);
38
39
40 void Rule_AddAR(RuleInfo *config_rule);
41 char *loadmemory(char *at, char *str);
42 int getDecoderfromlist(char *name);
43
44 extern int _max_freq;
45
46
47
48 /* Rules_OP_ReadRules, v0.1, 2005/07/04
49  * Will initialize the rules list
50  */
51 void Rules_OP_CreateRules()
52 {
53
54      /* Initializing the rule list */
55     OS_CreateRuleList();
56
57     return;
58 }
59
60 /* Rules_OP_ReadRules, v0.3, 2005/03/21
61  * Read the log rules.
62  * v0.3: Fixed many memory problems.
63  */ 
64 int Rules_OP_ReadRules(char * rulefile)
65 {
66     OS_XML xml;
67     XML_NODE node = NULL;
68
69     /* XML variables */ 
70     /* These are the available options for the rule configuration */
71     
72     char *xml_group = "group";
73     char *xml_rule = "rule";
74
75     char *xml_regex = "regex";
76     char *xml_match = "match";
77     char *xml_decoded = "decoded_as";
78     char *xml_category = "category";
79     char *xml_cve = "cve";
80     char *xml_info = "info";
81     char *xml_day_time = "time";
82     char *xml_week_day = "weekday";
83     char *xml_comment = "description";
84     char *xml_ignore = "ignore";
85     char *xml_check_if_ignored = "check_if_ignored";
86     
87     char *xml_srcip = "srcip";
88     char *xml_srcport = "srcport";
89     char *xml_dstip = "dstip";
90     char *xml_dstport = "dstport";
91     char *xml_user = "user";
92     char *xml_url = "url";
93     char *xml_id = "id";
94     char *xml_data = "extra_data";
95     char *xml_hostname = "hostname";
96     char *xml_program_name = "program_name";
97     char *xml_status = "status";
98     char *xml_action = "action";
99     char *xml_compiled = "compiled_rule";
100
101     char *xml_list = "list";
102     char *xml_list_lookup = "lookup";
103     char *xml_list_field = "field";
104     char *xml_list_cvalue = "check_value";
105     char *xml_match_key = "match_key";
106     char *xml_not_match_key = "not_match_key";
107     char *xml_match_key_value = "match_key_value";
108     char *xml_address_key = "address_match_key";
109     char *xml_not_address_key = "not_address_match_key";
110     char *xml_address_key_value = "address_match_key_value";         
111
112     char *xml_if_sid = "if_sid";
113     char *xml_if_group = "if_group";
114     char *xml_if_level = "if_level";
115     char *xml_fts = "if_fts";
116     
117     char *xml_if_matched_regex = "if_matched_regex";
118     char *xml_if_matched_group = "if_matched_group";
119     char *xml_if_matched_sid = "if_matched_sid";
120     
121     char *xml_same_source_ip = "same_source_ip";
122     char *xml_same_src_port = "same_src_port";
123     char *xml_same_dst_port = "same_dst_port";
124     char *xml_same_user = "same_user";
125     char *xml_same_location = "same_location";
126     char *xml_same_id = "same_id";
127     char *xml_dodiff = "check_diff";
128
129     char *xml_different_url = "different_url";
130     
131     char *xml_notsame_source_ip = "not_same_source_ip";
132     char *xml_notsame_user = "not_same_user";
133     char *xml_notsame_agent = "not_same_agent";
134     char *xml_notsame_id = "not_same_id";
135
136     char *xml_options = "options";
137     
138     char *rulepath;
139     
140     int i;
141     int default_timeframe = 360;
142
143
144     /* If no directory in the rulefile add the default */
145     if((strchr(rulefile, '/')) == NULL)
146     {
147         /* Building the rule file name + path */
148         i = strlen(RULEPATH) + strlen(rulefile) + 2;
149         rulepath = (char *)calloc(i,sizeof(char));
150         if(!rulepath)
151         {
152             ErrorExit(MEM_ERROR,ARGV0);
153         }
154         snprintf(rulepath,i,"%s/%s",RULEPATH,rulefile);
155     }
156     else
157     {
158         os_strdup(rulefile, rulepath);
159         debug1("%s is the rulefile", rulefile);
160         debug1("Not modifing the rule path");
161     }
162     
163     
164     i = 0;    
165     
166     /* Reading the XML */       
167     if(OS_ReadXML(rulepath,&xml) < 0)
168     {
169         merror(XML_ERROR, ARGV0, rulepath, xml.err, xml.err_line);
170         free(rulepath);
171         return(-1);     
172     }
173
174
175     /* Debug wrapper */
176     debug2("%s: DEBUG: read xml for rule.", ARGV0);
177     
178
179     
180     /* Applying any variable found */
181     if(OS_ApplyVariables(&xml) != 0)
182     {
183         merror(XML_ERROR_VAR, ARGV0, rulepath, xml.err);
184         return(-1);
185     }
186
187
188     /* Debug wrapper */
189     debug2("%s: DEBUG: XML Variables applied.", ARGV0);
190     
191
192     /* Getting the root elements */
193     node = OS_GetElementsbyNode(&xml,NULL);
194     if(!node)
195     {
196         merror(CONFIG_ERROR, ARGV0, rulepath);
197         OS_ClearXML(&xml);
198         return(-1);    
199     }
200
201
202     /* Zeroing the rule memory -- not used anymore */
203     free(rulepath);
204
205
206     /* Getting default time frame */
207     default_timeframe = getDefine_Int("analysisd",
208                                       "default_timeframe",
209                                       60, 3600);
210
211
212     /* Checking if there is any invalid global option */
213     while(node[i])
214     {
215         if(node[i]->element)
216         {
217             if(strcasecmp(node[i]->element,xml_group) != 0)
218             {
219                 merror("rules_op: Invalid root element \"%s\"."
220                         "Only \"group\" is allowed",node[i]->element);
221                 OS_ClearXML(&xml);
222                 return(-1);
223             }
224             if((!node[i]->attributes) || (!node[i]->values)||
225                     (!node[i]->values[0]) || (!node[i]->attributes[0]) ||
226                     (strcasecmp(node[i]->attributes[0],"name") != 0) ||
227                     (node[i]->attributes[1]))
228             {
229                 merror("rules_op: Invalid root element '%s'."
230                         "Only the group name is allowed",node[i]->element);
231                 OS_ClearXML(&xml);
232                 return(-1);
233             }
234         }
235         else
236         {
237             merror(XML_READ_ERROR, ARGV0);
238             OS_ClearXML(&xml);
239             return(-1);
240         }
241         i++;
242     }
243
244
245     /* Getting the rules now */   
246     i=0;
247     while(node[i])
248     {
249         XML_NODE rule = NULL;
250
251         int j = 0;
252
253         /* Getting all rules for a global group */        
254         rule = OS_GetElementsbyNode(&xml,node[i]);
255         if(rule == NULL)
256         {
257             merror("%s: Group '%s' without any rule.",
258                     ARGV0, node[i]->element);
259             OS_ClearXML(&xml);
260             return(-1);
261         }
262
263         while(rule[j])
264         {
265             RuleInfo *config_ruleinfo = NULL;
266            
267
268             /* Checking if the rule element is correct */
269             if((!rule[j]->element)||
270                     (strcasecmp(rule[j]->element,xml_rule) != 0))
271             {
272                 merror("%s: Invalid configuration. '%s' is not "
273                        "a valid element.", ARGV0, rule[j]->element);
274                 OS_ClearXML(&xml);
275                 return(-1);
276             }
277
278
279             /* Checking for the attributes of the rule */
280             if((!rule[j]->attributes) || (!rule[j]->values))
281             {
282                 merror("%s: Invalid rule '%d'. You must specify"
283                         " an ID and a level at least.", ARGV0, j);
284                 OS_ClearXML(&xml);
285                 return(-1);
286             }
287
288             
289             /* Attribute block */
290             {
291                 int id = -1,level = -1,maxsize = 0,timeframe = 0;
292                 int frequency = 0, accuracy = 1, noalert = 0, ignore_time = 0;
293                 int overwrite = 0;
294                 
295                 /* Getting default time frame */
296                 timeframe = default_timeframe;
297
298                 
299                 if(getattributes(rule[j]->attributes,rule[j]->values,
300                             &id,&level,&maxsize,&timeframe,
301                             &frequency,&accuracy,&noalert,
302                             &ignore_time, &overwrite) < 0)
303                 {
304                     merror("%s: Invalid attribute for rule.", ARGV0);
305                     OS_ClearXML(&xml);
306                     return(-1);
307                 }
308                 
309                 if((id == -1) || (level == -1))
310                 {
311                     merror("%s: No rule id or level specified for "
312                             "rule '%d'.",ARGV0, j);
313                     OS_ClearXML(&xml);
314                     return(-1);
315                 }
316
317                 /* Allocating memory and initializing structure */
318                 config_ruleinfo = zerorulemember(id, level, maxsize,
319                             frequency,timeframe, 
320                             noalert, ignore_time, overwrite);
321                 
322
323                 /* If rule is 0, set it to level 99 to have high priority.
324                  * set it to 0 again later 
325                  */
326                  if(config_ruleinfo->level == 0)
327                      config_ruleinfo->level = 99;
328
329                  
330                  /* Each level now is going to be multiplied by 100.
331                   * If the accuracy is set to 0 we don't multiply,
332                   * so it will be at the end of the list. We will
333                   * divide by 100 later.
334                   */
335                  if(accuracy)
336                  {
337                      config_ruleinfo->level *= 100;
338                  }
339
340                  if(config_ruleinfo->maxsize > 0)
341                  {
342                      if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
343                      {
344                          config_ruleinfo->alert_opts |= DO_EXTRAINFO;
345                      }
346                  }
347                                                  
348             } /* end attributes/memory allocation block */
349
350
351             /* Here we can assign the group name to the rule.
352              * The level is correct so the rule is probably going to
353              * be fine
354              */
355             os_strdup(node[i]->values[0], config_ruleinfo->group);
356             
357
358             /* Rule elements block */
359             {
360                 int k = 0;
361                 int info_type = 0;
362                 int count_info_detail = 0;
363                 RuleInfoDetail *last_info_detail = NULL;
364                 char *regex = NULL;
365                 char *match = NULL;
366                 char *url = NULL;
367                 char *if_matched_regex = NULL;
368                 char *if_matched_group = NULL;
369                 char *user = NULL;
370                 char *id = NULL;
371                 char *srcport = NULL;
372                 char *dstport = NULL;
373                 char *status = NULL;
374                 char *hostname = NULL;
375                 char *extra_data = NULL;
376                 char *program_name = NULL;
377                 
378                 XML_NODE rule_opt = NULL;
379                 rule_opt =  OS_GetElementsbyNode(&xml,rule[j]);
380                 if(rule_opt == NULL)
381                 {
382                     merror("%s: Rule '%d' without any option. "
383                             "It may lead to false positives and some "
384                             "other problems for the system. Exiting.",
385                             ARGV0, config_ruleinfo->sigid);
386                     OS_ClearXML(&xml);
387                     return(-1);       
388                 }
389                 
390                 while(rule_opt[k])
391                 {
392                     if((!rule_opt[k]->element)||(!rule_opt[k]->content))
393                         break;
394                     else if(strcasecmp(rule_opt[k]->element,xml_regex)==0)
395                     {
396                         regex =
397                             loadmemory(regex,
398                                     rule_opt[k]->content);
399                     }
400                     else if(strcasecmp(rule_opt[k]->element,xml_match)==0)
401                     {
402                         match =
403                             loadmemory(match,
404                                     rule_opt[k]->content);
405                     }
406                     else if(strcasecmp(rule_opt[k]->element, xml_decoded)==0)
407                     {
408                         config_ruleinfo->decoded_as = 
409                             getDecoderfromlist(rule_opt[k]->content);
410                         
411                         if(config_ruleinfo->decoded_as == 0)
412                         {
413                             merror("%s: Invalid decoder name: '%s'.",
414                                    ARGV0, rule_opt[k]->content);
415                             OS_ClearXML(&xml);
416                             return(-1); 
417                         }
418                     }
419                     else if(strcasecmp(rule_opt[k]->element,xml_cve)==0)
420                     {
421                         if(config_ruleinfo->info_details == NULL)
422                         {
423                             config_ruleinfo->info_details = zeroinfodetails(RULEINFODETAIL_CVE,
424                                     rule_opt[k]->content);
425                         }
426                         else
427                         {
428                             for (last_info_detail = config_ruleinfo->info_details;
429                                     last_info_detail->next != NULL; 
430                                     last_info_detail = last_info_detail->next)
431                             {
432                                 count_info_detail++;
433                             }
434                             /* Silently Drop info messages if their are more then MAX_RULEINFODETAIL */
435                             if (count_info_detail <= MAX_RULEINFODETAIL)
436                             {
437                                 last_info_detail->next = zeroinfodetails(RULEINFODETAIL_CVE,
438                                         rule_opt[k]->content);
439                             }
440                         }
441
442                         /* keep old methods for now */
443                         config_ruleinfo->cve=
444                             loadmemory(config_ruleinfo->cve,
445                                     rule_opt[k]->content);
446                     }
447                     else if(strcasecmp(rule_opt[k]->element,xml_info)==0)
448                     {
449
450                         info_type = get_info_attributes(rule_opt[k]->attributes,
451                                                         rule_opt[k]->values);
452                         debug1("info_type = %d", info_type);
453
454                         if(config_ruleinfo->info_details == NULL)
455                         {
456                             config_ruleinfo->info_details = zeroinfodetails(info_type, 
457                                     rule_opt[k]->content);
458                         }
459                         else
460                         {
461                             for (last_info_detail = config_ruleinfo->info_details;
462                                     last_info_detail->next != NULL; 
463                                     last_info_detail = last_info_detail->next) {
464                                 count_info_detail++;
465                             }
466                             /* Silently Drop info messages if their are more then MAX_RULEINFODETAIL */
467                             if (count_info_detail <= MAX_RULEINFODETAIL) {
468                                 last_info_detail->next = zeroinfodetails(info_type, rule_opt[k]->content);
469                             }
470                         }
471
472
473                         /* keep old methods for now */
474                         config_ruleinfo->info=
475                             loadmemory(config_ruleinfo->info,
476                                     rule_opt[k]->content);
477                     }
478                     else if(strcasecmp(rule_opt[k]->element,xml_day_time)==0)
479                     {
480                         config_ruleinfo->day_time = 
481                             OS_IsValidTime(rule_opt[k]->content);
482                         if(!config_ruleinfo->day_time)
483                         {
484                             merror(INVALID_CONFIG, ARGV0,
485                                     rule_opt[k]->element,
486                                     rule_opt[k]->content);
487                             return(-1);
488                         }
489
490                         if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
491                             config_ruleinfo->alert_opts |= DO_EXTRAINFO;
492                     }
493                     else if(strcasecmp(rule_opt[k]->element,xml_week_day)==0)
494                     {
495                         config_ruleinfo->week_day = 
496                             OS_IsValidDay(rule_opt[k]->content);
497                             
498                         if(!config_ruleinfo->week_day)
499                         {
500                             merror(INVALID_CONFIG, ARGV0,
501                                     rule_opt[k]->element,
502                                     rule_opt[k]->content);
503                             return(-1);
504                         }
505                         if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
506                             config_ruleinfo->alert_opts |= DO_EXTRAINFO;
507                     }
508                     else if(strcasecmp(rule_opt[k]->element,xml_group)==0)
509                     {
510                         config_ruleinfo->group =
511                             loadmemory(config_ruleinfo->group,
512                                     rule_opt[k]->content);
513                     }
514                     else if(strcasecmp(rule_opt[k]->element,xml_comment)==0)
515                     {
516                         char *newline;
517
518                         newline = strchr(rule_opt[k]->content, '\n');
519                         if(newline)
520                         {
521                             *newline = ' ';
522                         }
523                         
524                         config_ruleinfo->comment=
525                             loadmemory(config_ruleinfo->comment,
526                                     rule_opt[k]->content);
527                     }
528                     else if(strcasecmp(rule_opt[k]->element,xml_srcip)==0)
529                     {
530                         int ip_s = 0;
531                         
532                         /* Getting size of source ip list */
533                         while(config_ruleinfo->srcip && 
534                               config_ruleinfo->srcip[ip_s])
535                         {
536                             ip_s++;
537                         }
538                         
539                         config_ruleinfo->srcip = 
540                                     realloc(config_ruleinfo->srcip,
541                                     (ip_s + 2) * sizeof(os_ip *));
542                         
543                         
544                         /* Allocating memory for the individual entries */
545                         os_calloc(1, sizeof(os_ip), 
546                                      config_ruleinfo->srcip[ip_s]);
547                         config_ruleinfo->srcip[ip_s +1] = NULL;
548                         
549                         
550                         /* Checking if the ip is valid */
551                         if(!OS_IsValidIP(rule_opt[k]->content, 
552                                          config_ruleinfo->srcip[ip_s]))
553                         {
554                             merror(INVALID_IP, ARGV0, rule_opt[k]->content);
555                             return(-1);
556                         }
557
558                         if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
559                             config_ruleinfo->alert_opts |= DO_PACKETINFO;
560                     }
561                     else if(strcasecmp(rule_opt[k]->element,xml_dstip)==0)
562                     {
563                         int ip_s = 0;
564
565                         /* Getting size of source ip list */
566                         while(config_ruleinfo->dstip &&
567                                 config_ruleinfo->dstip[ip_s])
568                         {
569                             ip_s++;
570                         }
571
572                         config_ruleinfo->dstip =
573                                     realloc(config_ruleinfo->dstip,
574                                     (ip_s + 2) * sizeof(os_ip *));
575
576
577                         /* Allocating memory for the individual entries */
578                         os_calloc(1, sizeof(os_ip),
579                                 config_ruleinfo->dstip[ip_s]);
580                         config_ruleinfo->dstip[ip_s +1] = NULL;
581
582
583                         /* Checking if the ip is valid */
584                         if(!OS_IsValidIP(rule_opt[k]->content,
585                                     config_ruleinfo->dstip[ip_s]))
586                         {
587                             merror(INVALID_IP, ARGV0, rule_opt[k]->content);
588                             return(-1);
589                         }
590
591                         if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
592                             config_ruleinfo->alert_opts |= DO_PACKETINFO;
593                     }
594                     else if(strcasecmp(rule_opt[k]->element,xml_user)==0)
595                     {
596                         user =
597                             loadmemory(user,
598                                     rule_opt[k]->content);
599
600                         if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
601                             config_ruleinfo->alert_opts |= DO_EXTRAINFO;
602                     }
603                     else if(strcasecmp(rule_opt[k]->element,xml_id)==0)
604                     {
605                         id =
606                             loadmemory(id,
607                                     rule_opt[k]->content);
608                     }
609                     else if(strcasecmp(rule_opt[k]->element,xml_srcport)==0)
610                     {
611                         srcport =
612                             loadmemory(srcport,
613                                     rule_opt[k]->content);
614                         if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
615                             config_ruleinfo->alert_opts |= DO_PACKETINFO;
616                     }
617                     else if(strcasecmp(rule_opt[k]->element,xml_dstport)==0)
618                     {
619                         dstport =
620                             loadmemory(dstport,
621                                     rule_opt[k]->content);
622
623                         if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
624                             config_ruleinfo->alert_opts |= DO_PACKETINFO;
625                     }
626                     else if(strcasecmp(rule_opt[k]->element,xml_status)==0)
627                     {
628                         status =
629                             loadmemory(status,
630                                     rule_opt[k]->content);
631                         
632                         if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
633                             config_ruleinfo->alert_opts |= DO_EXTRAINFO;
634                     }
635                     else if(strcasecmp(rule_opt[k]->element,xml_hostname)==0)
636                     {
637                         hostname =
638                             loadmemory(hostname,
639                                     rule_opt[k]->content);
640                         
641                         if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
642                             config_ruleinfo->alert_opts |= DO_EXTRAINFO;
643                     }
644                     else if(strcasecmp(rule_opt[k]->element,xml_data)==0)
645                     {
646                         extra_data =
647                             loadmemory(extra_data,
648                                     rule_opt[k]->content);
649
650                         if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
651                             config_ruleinfo->alert_opts |= DO_EXTRAINFO;
652                     }
653                     else if(strcasecmp(rule_opt[k]->element,
654                                        xml_program_name)==0)
655                     {
656                         program_name =
657                             loadmemory(program_name,
658                                     rule_opt[k]->content);
659                     }
660                     else if(strcasecmp(rule_opt[k]->element,xml_action)==0)
661                     {
662                         config_ruleinfo->action = 
663                             loadmemory(config_ruleinfo->action,
664                                     rule_opt[k]->content);
665                     }
666                     else if(strcasecmp(rule_opt[k]->element,xml_list)==0)
667                     {
668                         debug1("-> %s == %s",rule_opt[k]->element, xml_list);
669                         if (rule_opt[k]->attributes && rule_opt[k]->values && rule_opt[k]->content)
670                         {
671                             int list_att_num=0;
672                             int rule_type=0;
673                             OSMatch *matcher=NULL;
674                             int lookup_type = LR_STRING_MATCH;
675                             while(rule_opt[k]->attributes[list_att_num])
676                             {
677                                 if(strcasecmp(rule_opt[k]->attributes[list_att_num], xml_list_lookup) == 0)
678                                 {
679                                     if(strcasecmp(rule_opt[k]->values[list_att_num],xml_match_key) == 0)
680                                         lookup_type = LR_STRING_MATCH;
681                                     else if(strcasecmp(rule_opt[k]->values[list_att_num],xml_not_match_key)==0)
682                                         lookup_type = LR_STRING_NOT_MATCH;
683                                     else if(strcasecmp(rule_opt[k]->values[list_att_num],xml_match_key_value)==0)
684                                         lookup_type = LR_STRING_MATCH_VALUE;
685                                     else if(strcasecmp(rule_opt[k]->values[list_att_num],xml_address_key)==0)
686                                         lookup_type = LR_ADDRESS_MATCH;
687                                     else if(strcasecmp(rule_opt[k]->values[list_att_num],xml_not_address_key)==0)
688                                         lookup_type = LR_ADDRESS_NOT_MATCH;
689                                     else if(strcasecmp(rule_opt[k]->values[list_att_num],xml_address_key_value)==0)
690                                         lookup_type = LR_ADDRESS_MATCH_VALUE;
691                                     else 
692                                     {
693                                         merror(INVALID_CONFIG, ARGV0, 
694                                                rule_opt[k]->element, 
695                                                rule_opt[k]->content);
696                                         merror("%s: List match lookup=\"%s\" is not valid.", 
697                                                 ARGV0,rule_opt[k]->values[list_att_num]);
698                                         return(-1);
699                                      }
700                                 }
701                                 else if(strcasecmp(rule_opt[k]->attributes[list_att_num], xml_list_field)==0)
702                                 {
703                                     if(strcasecmp(rule_opt[k]->values[list_att_num],xml_srcip)==0)
704                                         rule_type = RULE_SRCIP;
705                                     else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_srcport)==0)
706                                         rule_type = RULE_SRCPORT;
707                                     else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_dstip)==0)
708                                         rule_type = RULE_DSTIP;
709                                     else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_dstport)==0)
710                                         rule_type = RULE_DSTPORT;
711                                     else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_user)==0)
712                                         rule_type = RULE_USER;
713                                     else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_url)==0)
714                                         rule_type = RULE_URL;
715                                     else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_id)==0)
716                                         rule_type = RULE_ID;
717                                     else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_hostname)==0)
718                                         rule_type = RULE_HOSTNAME;
719                                     else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_program_name)==0)
720                                         rule_type = RULE_PROGRAM_NAME;
721                                     else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_status)==0)
722                                         rule_type = RULE_STATUS;
723                                     else if (strcasecmp(rule_opt[k]->values[list_att_num],xml_action)==0)
724                                         rule_type = RULE_ACTION;
725                                     else 
726                                     {
727                                         merror(INVALID_CONFIG, ARGV0, 
728                                                rule_opt[k]->element, 
729                                                rule_opt[k]->content);
730                                         merror("%s: List match field=\"%s\" is not valid.", 
731                                                 ARGV0,rule_opt[k]->values[list_att_num]);
732                                         return(-1);
733                                      }
734                                 }
735                                 else if(strcasecmp(rule_opt[k]->attributes[list_att_num], xml_list_cvalue)==0)
736                                 {
737                                     os_calloc(1, sizeof(OSMatch), matcher);
738                                     if(!OSMatch_Compile(rule_opt[k]->values[list_att_num], matcher, 0))
739                                     {
740                                         merror(INVALID_CONFIG, ARGV0, 
741                                                rule_opt[k]->element, 
742                                                rule_opt[k]->content);
743                                         merror(REGEX_COMPILE, 
744                                                ARGV0, 
745                                                rule_opt[k]->values[list_att_num], 
746                                                matcher->error);
747                                         return(-1);
748                                     }
749                                 }
750                                 else
751                                 {
752                                         merror("%s:List feild=\"%s\" is not valid",ARGV0,
753                                            rule_opt[k]->values[list_att_num]);
754                                     merror(INVALID_CONFIG, ARGV0, 
755                                            rule_opt[k]->element, rule_opt[k]->content);
756                                     return(-1);
757                                 }
758                                 list_att_num++;
759                             }
760                             if(rule_type == 0)
761                             {
762                                 merror("%s:List requires the field=\"\" Attrubute",ARGV0);
763                                 merror(INVALID_CONFIG, ARGV0, 
764                                        rule_opt[k]->element, rule_opt[k]->content);
765                                 return(-1);
766                             }
767
768                             /* Wow it's all ready - this seams too complex to get to this point */
769                             config_ruleinfo->lists = OS_AddListRule(config_ruleinfo->lists,
770                                            lookup_type, 
771                                            rule_type, 
772                                            rule_opt[k]->content,
773                                            matcher);
774                             if (config_ruleinfo->lists == NULL)
775                             {
776                                 merror("%s: List error: Could not load %s", ARGV0, rule_opt[k]->content);
777                                 return(-1);
778                             }
779                         }
780                         else
781                         {
782                             merror("%s:List must have a correctly formatted feild attribute",
783                                    ARGV0);
784                             merror(INVALID_CONFIG, 
785                                    ARGV0, 
786                                    rule_opt[k]->element, 
787                                    rule_opt[k]->content);
788                             return(-1);
789                         }                        
790                         /* xml_list eval is done */
791                     }
792                     else if(strcasecmp(rule_opt[k]->element,xml_url)==0)
793                     {
794                         url=
795                             loadmemory(url,
796                                     rule_opt[k]->content);
797                     }
798                     else if(strcasecmp(rule_opt[k]->element, xml_compiled)==0)
799                     {
800                         int it_id = 0;
801
802                         while(compiled_rules_name[it_id])
803                         {
804                             if(strcmp(compiled_rules_name[it_id], 
805                                       rule_opt[k]->content) == 0)
806                                 break;
807                             it_id++;
808                         }
809
810                         /* checking if the name is valid. */
811                         if(!compiled_rules_name[it_id])
812                         {
813                             merror("%s: ERROR: Compiled rule not found: '%s'", 
814                                    ARGV0, rule_opt[k]->content); 
815                             merror(INVALID_CONFIG, ARGV0, 
816                                    rule_opt[k]->element, rule_opt[k]->content);
817                             return(-1);
818
819                         }
820
821                         config_ruleinfo->compiled_rule = compiled_rules_list[it_id];
822                         if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
823                             config_ruleinfo->alert_opts |= DO_EXTRAINFO;
824                     }
825
826                     /* We allow these four categories so far */
827                     else if(strcasecmp(rule_opt[k]->element, xml_category)==0)
828                     {
829                         if(strcmp(rule_opt[k]->content, "firewall") == 0)
830                         {
831                             config_ruleinfo->category = FIREWALL;
832                         }
833                         else if(strcmp(rule_opt[k]->content, "ids") == 0)
834                         {
835                             config_ruleinfo->category = IDS;
836                         }
837                         else if(strcmp(rule_opt[k]->content, "syslog") == 0)
838                         {
839                             config_ruleinfo->category = SYSLOG;
840                         }
841                         else if(strcmp(rule_opt[k]->content, "web-log") == 0)
842                         {
843                             config_ruleinfo->category = WEBLOG;
844                         }
845                         else if(strcmp(rule_opt[k]->content, "squid") == 0)
846                         {
847                             config_ruleinfo->category = SQUID;
848                         }
849                         else if(strcmp(rule_opt[k]->content,"windows") == 0)
850                         {
851                             config_ruleinfo->category = WINDOWS;
852                         }
853                         else if(strcmp(rule_opt[k]->content,"ossec") == 0)
854                         {
855                             config_ruleinfo->category = OSSEC_RL;
856                         }
857                         else
858                         {
859                             merror(INVALID_CAT, ARGV0, rule_opt[k]->content);
860                             return(-1);
861                         }
862                     }
863                     else if(strcasecmp(rule_opt[k]->element,xml_if_sid)==0)
864                     {
865                         config_ruleinfo->if_sid=
866                             loadmemory(config_ruleinfo->if_sid,
867                                     rule_opt[k]->content);
868                     }
869                     else if(strcasecmp(rule_opt[k]->element,xml_if_level)==0)
870                     {
871                         if(!OS_StrIsNum(rule_opt[k]->content))
872                         {
873                             merror(INVALID_CONFIG, ARGV0, 
874                                     "if_level",
875                                     rule_opt[k]->content); 
876                             return(-1);
877                         }
878
879                         config_ruleinfo->if_level=
880                             loadmemory(config_ruleinfo->if_level,
881                                     rule_opt[k]->content);
882                     }
883                     else if(strcasecmp(rule_opt[k]->element,xml_if_group)==0)
884                     {
885                         config_ruleinfo->if_group=
886                             loadmemory(config_ruleinfo->if_group,
887                                     rule_opt[k]->content);
888                     }
889                     else if(strcasecmp(rule_opt[k]->element,
890                                        xml_if_matched_regex) == 0)
891                     {
892                         config_ruleinfo->context = 1;
893                         if_matched_regex=
894                             loadmemory(if_matched_regex,
895                                     rule_opt[k]->content);
896                     }
897                     else if(strcasecmp(rule_opt[k]->element,
898                                        xml_if_matched_group) == 0)
899                     {
900                         config_ruleinfo->context = 1;
901                         if_matched_group=
902                             loadmemory(if_matched_group,
903                                     rule_opt[k]->content);
904                     }
905                     else if(strcasecmp(rule_opt[k]->element,
906                                        xml_if_matched_sid) == 0)
907                     {
908                         config_ruleinfo->context = 1;
909                         if(!OS_StrIsNum(rule_opt[k]->content))
910                         {
911                             merror(INVALID_CONFIG, ARGV0,
912                                     "if_matched_sid",
913                                     rule_opt[k]->content);
914                             return(-1);
915                         }
916                         config_ruleinfo->if_matched_sid = 
917                             atoi(rule_opt[k]->content);
918
919                     }
920                     else if(strcasecmp(rule_opt[k]->element,
921                                 xml_same_source_ip)==0)
922                     {
923                         config_ruleinfo->context_opts|= SAME_SRCIP;
924                     }
925                     else if(strcasecmp(rule_opt[k]->element,
926                                 xml_same_src_port)==0)
927                     {
928                         config_ruleinfo->context_opts|= SAME_SRCPORT;
929                         
930                         if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
931                             config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
932                     }
933                     else if(strcasecmp(rule_opt[k]->element,
934                                xml_dodiff)==0)
935                     {
936                         config_ruleinfo->context++;
937                         config_ruleinfo->context_opts|= SAME_DODIFF;
938                         if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
939                             config_ruleinfo->alert_opts |= DO_EXTRAINFO;
940                     }
941                     else if(strcasecmp(rule_opt[k]->element,
942                                 xml_same_dst_port) == 0)
943                     {
944                         config_ruleinfo->context_opts|= SAME_DSTPORT;
945                         
946                         if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
947                             config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
948                     }
949                     else if(strcasecmp(rule_opt[k]->element,
950                                 xml_notsame_source_ip)==0)
951                     {
952                         config_ruleinfo->context_opts&= NOT_SAME_SRCIP;
953                     }
954                     else if(strcmp(rule_opt[k]->element, xml_same_id) == 0)
955                     {
956                         config_ruleinfo->context_opts|= SAME_ID;
957                     }
958                     else if(strcmp(rule_opt[k]->element,
959                                    xml_different_url) == 0)
960                     {
961                         config_ruleinfo->context_opts|= DIFFERENT_URL;
962                         
963                         if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
964                             config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
965                     }
966                     else if(strcmp(rule_opt[k]->element,xml_notsame_id) == 0)
967                     {
968                         config_ruleinfo->context_opts&= NOT_SAME_ID;
969                     }
970                     else if(strcasecmp(rule_opt[k]->element,
971                                 xml_fts) == 0)
972                     {
973                         config_ruleinfo->alert_opts |= DO_FTS;
974                     }
975                     else if(strcasecmp(rule_opt[k]->element,
976                                 xml_same_user)==0)
977                     {
978                         config_ruleinfo->context_opts|= SAME_USER;
979                         
980                         if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
981                             config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
982                     }
983                     else if(strcasecmp(rule_opt[k]->element,
984                                 xml_notsame_user)==0)
985                     {
986                         config_ruleinfo->context_opts&= NOT_SAME_USER;
987                     }
988                     else if(strcasecmp(rule_opt[k]->element,
989                                 xml_same_location)==0)
990                     {
991                         config_ruleinfo->context_opts|= SAME_LOCATION;
992                         if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
993                             config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
994                     }
995                     else if(strcasecmp(rule_opt[k]->element,
996                                 xml_notsame_agent)==0)
997                     {
998                         config_ruleinfo->context_opts&= NOT_SAME_AGENT;
999                     }
1000                     else if(strcasecmp(rule_opt[k]->element,
1001                                 xml_options) == 0)
1002                     {
1003                         if(strcmp("alert_by_email", 
1004                                   rule_opt[k]->content) == 0)
1005                         {
1006                             if(!(config_ruleinfo->alert_opts & DO_MAILALERT))
1007                             {
1008                                 config_ruleinfo->alert_opts|= DO_MAILALERT;
1009                             }
1010                         }
1011                         else if(strcmp("no_email_alert",
1012                                        rule_opt[k]->content) == 0)
1013                         {
1014                             if(config_ruleinfo->alert_opts & DO_MAILALERT)
1015                             {
1016                               config_ruleinfo->alert_opts&=0xfff-DO_MAILALERT;
1017                             }
1018                         }
1019                         else if(strcmp("log_alert", 
1020                                        rule_opt[k]->content) == 0)
1021                         {
1022                             if(!(config_ruleinfo->alert_opts & DO_LOGALERT))
1023                             {
1024                                 config_ruleinfo->alert_opts|= DO_LOGALERT;
1025                             }
1026                         }
1027                         else if(strcmp("no_log", rule_opt[k]->content) == 0)
1028                         {
1029                             if(config_ruleinfo->alert_opts & DO_LOGALERT)
1030                             {
1031                               config_ruleinfo->alert_opts &=0xfff-DO_LOGALERT;
1032                             }
1033                         }
1034                         else if(strcmp("no_ar", rule_opt[k]->content) == 0)
1035                         {
1036                             if(!(config_ruleinfo->alert_opts & NO_AR))
1037                             {
1038                                 config_ruleinfo->alert_opts|= NO_AR;
1039                             }
1040                         }
1041                         else
1042                         {               
1043                             merror(XML_VALUEERR, ARGV0, xml_options,
1044                                                         rule_opt[k]->content);
1045
1046                             merror("%s: Invalid option '%s' for "
1047                                    "rule '%d'.",ARGV0, rule_opt[k]->element,
1048                                    config_ruleinfo->sigid);
1049                             OS_ClearXML(&xml);
1050                             return(-1);
1051                         }   
1052                     }
1053                     else if(strcasecmp(rule_opt[k]->element,
1054                                 xml_ignore) == 0)
1055                     {
1056                         if(strstr(rule_opt[k]->content, "user") != NULL)
1057                         {
1058                             config_ruleinfo->ignore|=FTS_DSTUSER;
1059                         }
1060                         if(strstr(rule_opt[k]->content, "srcip") != NULL)
1061                         {
1062                             config_ruleinfo->ignore|=FTS_SRCIP;
1063                         }
1064                         if(strstr(rule_opt[k]->content, "dstip") != NULL)
1065                         {
1066                             config_ruleinfo->ignore|=FTS_DSTIP;
1067                         }
1068                         if(strstr(rule_opt[k]->content, "id") != NULL)
1069                         {
1070                             config_ruleinfo->ignore|=FTS_ID;
1071                         }
1072                         if(strstr(rule_opt[k]->content,"location")!= NULL)
1073                         {
1074                             config_ruleinfo->ignore|=FTS_LOCATION;
1075                         }
1076                         if(strstr(rule_opt[k]->content,"data")!= NULL)
1077                         {
1078                             config_ruleinfo->ignore|=FTS_DATA;
1079                         }
1080                         if(strstr(rule_opt[k]->content, "name") != NULL)
1081                         {
1082                             config_ruleinfo->ignore|=FTS_NAME;
1083
1084                         }
1085                         if(!config_ruleinfo->ignore)
1086                         {
1087                             merror("%s: Wrong ignore option: '%s'", 
1088                                                     ARGV0,
1089                                                     rule_opt[k]->content);
1090                             return(-1);
1091                         }
1092                     }
1093                     else if(strcasecmp(rule_opt[k]->element,
1094                                 xml_check_if_ignored) == 0)
1095                     {
1096                         if(strstr(rule_opt[k]->content, "user") != NULL)
1097                         {
1098                             config_ruleinfo->ckignore|=FTS_DSTUSER;
1099                         }
1100                         if(strstr(rule_opt[k]->content, "srcip") != NULL)
1101                         {
1102                             config_ruleinfo->ckignore|=FTS_SRCIP;
1103                         }
1104                         if(strstr(rule_opt[k]->content, "dstip") != NULL)
1105                         {
1106                             config_ruleinfo->ckignore|=FTS_DSTIP;
1107                         }
1108                         if(strstr(rule_opt[k]->content, "id") != NULL)
1109                         {
1110                             config_ruleinfo->ckignore|=FTS_ID;
1111                         }
1112                         if(strstr(rule_opt[k]->content,"location")!= NULL)
1113                         {
1114                             config_ruleinfo->ckignore|=FTS_LOCATION;
1115                         }
1116                         if(strstr(rule_opt[k]->content,"data")!= NULL)
1117                         {
1118                             config_ruleinfo->ignore|=FTS_DATA;
1119                         }
1120                         if(strstr(rule_opt[k]->content, "name") != NULL)
1121                         {
1122                             config_ruleinfo->ckignore|=FTS_NAME;
1123
1124                         }
1125                         if(!config_ruleinfo->ckignore)
1126                         {
1127                             merror("%s: Wrong check_if_ignored option: '%s'", 
1128                                                     ARGV0,
1129                                                     rule_opt[k]->content);
1130                             return(-1);
1131                         }
1132                     }
1133                     else
1134                     {
1135                         merror("%s: Invalid option '%s' for "
1136                                 "rule '%d'.",ARGV0, rule_opt[k]->element,
1137                                 config_ruleinfo->sigid);
1138                         OS_ClearXML(&xml);
1139                         return(-1);
1140                     }
1141                     k++;
1142                 }
1143
1144
1145                 /* Checking for a valid use of frequency */
1146                 if((config_ruleinfo->context_opts || 
1147                    config_ruleinfo->frequency) &&
1148                    !config_ruleinfo->context)
1149                 {
1150                     merror("%s: Invalid use of frequency/context options. "
1151                            "Missing if_matched on rule '%d'.",
1152                            ARGV0, config_ruleinfo->sigid);
1153                     OS_ClearXML(&xml);
1154                     return(-1);
1155                 }
1156                 
1157
1158                 /* If if_matched_group we must have a if_sid or if_group */
1159                 if(if_matched_group)
1160                 {
1161                     if(!config_ruleinfo->if_sid && !config_ruleinfo->if_group)
1162                     {
1163                         os_strdup(if_matched_group, 
1164                                   config_ruleinfo->if_group);        
1165                     }
1166                 }
1167
1168                 /* If_matched_sid, we need to get the if_sid */
1169                 if(config_ruleinfo->if_matched_sid && 
1170                    !config_ruleinfo->if_sid &&
1171                    !config_ruleinfo->if_group)
1172                 {
1173                     os_calloc(16, sizeof(char), config_ruleinfo->if_sid);
1174                     snprintf(config_ruleinfo->if_sid, 15, "%d", 
1175                              config_ruleinfo->if_matched_sid);
1176                 }
1177                 
1178                 /* Checking the regexes */
1179                 if(regex)
1180                 {
1181                     os_calloc(1, sizeof(OSRegex), config_ruleinfo->regex);
1182                     if(!OSRegex_Compile(regex, config_ruleinfo->regex, 0))
1183                     {
1184                         merror(REGEX_COMPILE, ARGV0, regex, 
1185                                 config_ruleinfo->regex->error);
1186                         return(-1);
1187                     }
1188                     free(regex);
1189                     regex = NULL;
1190                 }
1191                 
1192                 /* Adding in match */
1193                 if(match)
1194                 {
1195                     os_calloc(1, sizeof(OSMatch), config_ruleinfo->match);
1196                     if(!OSMatch_Compile(match, config_ruleinfo->match, 0))
1197                     {
1198                         merror(REGEX_COMPILE, ARGV0, match,
1199                                 config_ruleinfo->match->error);
1200                         return(-1);
1201                     }
1202                     free(match);
1203                     match = NULL;
1204                 }
1205                 
1206                 /* Adding in id */
1207                 if(id)
1208                 {
1209                     os_calloc(1, sizeof(OSMatch), config_ruleinfo->id);
1210                     if(!OSMatch_Compile(id, config_ruleinfo->id, 0))
1211                     {
1212                         merror(REGEX_COMPILE, ARGV0, id, 
1213                                               config_ruleinfo->id->error);
1214                         return(-1);
1215                     }
1216                     free(id);
1217                     id = NULL;
1218                 }
1219
1220                 /* Adding srcport */
1221                 if(srcport)
1222                 {
1223                     os_calloc(1, sizeof(OSMatch), config_ruleinfo->srcport);
1224                     if(!OSMatch_Compile(srcport, config_ruleinfo->srcport, 0))
1225                     {
1226                         merror(REGEX_COMPILE, ARGV0, srcport, 
1227                                               config_ruleinfo->id->error);
1228                         return(-1);
1229                     }
1230                     free(srcport);
1231                     srcport = NULL;
1232                 }
1233
1234                 /* Adding dstport */
1235                 if(dstport)
1236                 {
1237                     os_calloc(1, sizeof(OSMatch), config_ruleinfo->dstport);
1238                     if(!OSMatch_Compile(dstport, config_ruleinfo->dstport, 0))
1239                     {
1240                         merror(REGEX_COMPILE, ARGV0, dstport, 
1241                                               config_ruleinfo->id->error);
1242                         return(-1);
1243                     }
1244                     free(dstport);
1245                     dstport = NULL;
1246                 }
1247
1248                 /* Adding in status */
1249                 if(status)
1250                 {
1251                     os_calloc(1, sizeof(OSMatch), config_ruleinfo->status);
1252                     if(!OSMatch_Compile(status, config_ruleinfo->status, 0))
1253                     {
1254                         merror(REGEX_COMPILE, ARGV0, status,
1255                                               config_ruleinfo->status->error);
1256                         return(-1);
1257                     }
1258                     free(status);
1259                     status = NULL;
1260                 }
1261
1262                 /* Adding in hostname */
1263                 if(hostname)
1264                 {
1265                     os_calloc(1, sizeof(OSMatch), config_ruleinfo->hostname);
1266                     if(!OSMatch_Compile(hostname, config_ruleinfo->hostname,0))
1267                     {
1268                         merror(REGEX_COMPILE, ARGV0, hostname,
1269                                 config_ruleinfo->hostname->error);
1270                         return(-1);
1271                     }
1272                     free(hostname);
1273                     hostname = NULL;
1274                 }
1275
1276                 /* Adding extra data */
1277                 if(extra_data)
1278                 {
1279                     os_calloc(1, sizeof(OSMatch), config_ruleinfo->extra_data);
1280                     if(!OSMatch_Compile(extra_data, 
1281                                         config_ruleinfo->extra_data, 0))
1282                     {
1283                         merror(REGEX_COMPILE, ARGV0, extra_data,
1284                                 config_ruleinfo->extra_data->error);
1285                         return(-1);
1286                     }
1287                     free(extra_data);
1288                     extra_data = NULL;
1289                 }
1290
1291                 /* Adding in program name */
1292                 if(program_name)
1293                 {
1294                     os_calloc(1,sizeof(OSMatch),config_ruleinfo->program_name);
1295                     if(!OSMatch_Compile(program_name,
1296                                         config_ruleinfo->program_name,0))
1297                     {
1298                         merror(REGEX_COMPILE, ARGV0, program_name,
1299                                 config_ruleinfo->program_name->error);
1300                         return(-1);
1301                     }
1302                     free(program_name);
1303                     program_name = NULL;
1304                 }
1305                 
1306                 /* Adding in user */
1307                 if(user)
1308                 {
1309                     os_calloc(1, sizeof(OSMatch), config_ruleinfo->user);
1310                     if(!OSMatch_Compile(user, config_ruleinfo->user, 0))
1311                     {
1312                         merror(REGEX_COMPILE, ARGV0, user,
1313                                               config_ruleinfo->user->error);
1314                         return(-1);
1315                     }
1316                     free(user);
1317                     user = NULL;
1318                 }
1319                 
1320                 /* Adding in url */
1321                 if(url)
1322                 {
1323                     os_calloc(1, sizeof(OSMatch), config_ruleinfo->url);
1324                     if(!OSMatch_Compile(url, config_ruleinfo->url, 0))
1325                     {
1326                         merror(REGEX_COMPILE, ARGV0, url, 
1327                                 config_ruleinfo->url->error);
1328                         return(-1);
1329                     }
1330                     free(url);
1331                     url = NULL;
1332                 }
1333                 
1334                 /* Adding matched_group */
1335                 if(if_matched_group)
1336                 {
1337                     os_calloc(1, sizeof(OSMatch), 
1338                                  config_ruleinfo->if_matched_group);
1339                     
1340                     if(!OSMatch_Compile(if_matched_group, 
1341                                         config_ruleinfo->if_matched_group,
1342                                         0))
1343                     {
1344                         merror(REGEX_COMPILE, ARGV0, if_matched_group,
1345                                 config_ruleinfo->if_matched_group->error);
1346                         return(-1);
1347                     }
1348                     free(if_matched_group);
1349                     if_matched_group = NULL;
1350                 }
1351                 
1352                 /* Adding matched_regex */
1353                 if(if_matched_regex)
1354                 {
1355                     os_calloc(1, sizeof(OSRegex), 
1356                             config_ruleinfo->if_matched_regex);
1357                     if(!OSRegex_Compile(if_matched_regex, 
1358                                 config_ruleinfo->if_matched_regex, 0))
1359                     {
1360                         merror(REGEX_COMPILE, ARGV0, if_matched_regex, 
1361                                 config_ruleinfo->if_matched_regex->error);
1362                         return(-1);
1363                     }
1364                     free(if_matched_regex);
1365                     if_matched_regex = NULL;
1366                 }
1367             } /* enf of elements block */
1368
1369
1370             /* Assigning an active response to the rule */
1371             Rule_AddAR(config_ruleinfo);
1372
1373             j++; /* next rule */
1374
1375
1376             /* Creating the last_events if necessary */
1377             if(config_ruleinfo->context)
1378             {
1379                 int ii = 0;
1380                 os_calloc(MAX_LAST_EVENTS + 1, sizeof(char *), 
1381                           config_ruleinfo->last_events);
1382                 
1383                 /* Zeroing each entry */
1384                 for(;ii<=MAX_LAST_EVENTS;ii++)
1385                 {
1386                     config_ruleinfo->last_events[ii] = NULL;
1387                 }
1388             }
1389
1390             
1391             /* Adding the rule to the rules list.
1392              * Only the template rules are supposed
1393              * to be at the top level. All others
1394              * will be a "child" of someone.
1395              */
1396             if(config_ruleinfo->sigid < 10)
1397             {    
1398                 OS_AddRule(config_ruleinfo);
1399             }
1400             else if(config_ruleinfo->alert_opts & DO_OVERWRITE)
1401             {
1402                 if(!OS_AddRuleInfo(NULL, config_ruleinfo, 
1403                                    config_ruleinfo->sigid))
1404                 {
1405                     merror("%s: Overwrite rule '%d' not found.",
1406                             ARGV0, config_ruleinfo->sigid);
1407                     OS_ClearXML(&xml);
1408                     return(-1);
1409                 }
1410             }
1411             else
1412             {
1413                 OS_AddChild(config_ruleinfo);
1414             }
1415
1416             /* Cleaning what we do not need */
1417             if(config_ruleinfo->if_group)
1418             {
1419                 free(config_ruleinfo->if_group);
1420                 config_ruleinfo->if_group = NULL;
1421             }
1422
1423             /* Setting the event_search pointer */
1424             if(config_ruleinfo->if_matched_sid)
1425             {
1426                 config_ruleinfo->event_search = 
1427                                  (void *)Search_LastSids;
1428             
1429                 /* Marking rules that match this id */
1430                 OS_MarkID(NULL, config_ruleinfo);                     
1431             }
1432             
1433             /* Marking the rules that match if_matched_group */
1434             else if(config_ruleinfo->if_matched_group)
1435             {
1436                 /* Creating list */
1437                 config_ruleinfo->group_search = OSList_Create();
1438                 if(!config_ruleinfo->group_search)
1439                 {
1440                     ErrorExit(MEM_ERROR, ARGV0);
1441                 }
1442
1443                 /* Marking rules that match this group */
1444                 OS_MarkGroup(NULL, config_ruleinfo);
1445
1446                 /* Setting function pointer */
1447                 config_ruleinfo->event_search = 
1448                                  (void *)Search_LastGroups;
1449             }
1450             else if(config_ruleinfo->context)
1451             {
1452                 if((config_ruleinfo->context == 1) && 
1453                    (config_ruleinfo->context_opts & SAME_DODIFF))
1454                 {
1455                     config_ruleinfo->context = 0;
1456                 }
1457                 else
1458                 {
1459                     config_ruleinfo->event_search = 
1460                                  (void *)Search_LastEvents;
1461                 }
1462             }
1463
1464         } /* while(rule[j]) */
1465         OS_ClearNode(rule);
1466         i++;
1467         
1468     } /* while (node[i]) */
1469
1470     /* Cleaning global node */
1471     OS_ClearNode(node);
1472     OS_ClearXML(&xml);
1473
1474     #ifdef DEBUG
1475     {
1476         RuleNode *dbg_node = OS_GetFirstRule();
1477         while(dbg_node)
1478         {
1479             if(dbg_node->child)
1480             {
1481                 RuleNode *child_node = dbg_node->child;
1482
1483                 printf("** Child Node for %d **\n",dbg_node->ruleinfo->sigid);
1484                 while(child_node)
1485                 {
1486                     child_node = child_node->next;
1487                 }
1488             }
1489             dbg_node = dbg_node->next;
1490         }
1491     }
1492     #endif
1493
1494     /* Done over here */
1495     return(0);
1496 }
1497
1498
1499 /* loadmemory: v0.1
1500  * Allocate memory at "*at" and copy *str to it.
1501  * If *at already exist, realloc the memory and cat str
1502  * on it.
1503  * It will return the new string
1504  */
1505 char *loadmemory(char *at, char *str)
1506 {
1507     if(at == NULL)
1508     {
1509         int strsize = 0;
1510         if((strsize = strlen(str)) < OS_SIZE_2048)
1511         {
1512             at = calloc(strsize+1,sizeof(char));
1513             if(at == NULL)
1514             {
1515                 merror(MEM_ERROR,ARGV0);
1516                 return(NULL);
1517             }
1518             strncpy(at,str,strsize);
1519             return(at);
1520         }
1521         else
1522         {
1523             merror(SIZE_ERROR,ARGV0,str);
1524             return(NULL);
1525         }
1526     }
1527     else /*at is not null. Need to reallocat its memory and copy str to it*/
1528     {
1529         int strsize = strlen(str);
1530         int atsize = strlen(at);
1531         int finalsize = atsize+strsize+1;
1532         
1533         if((atsize > OS_SIZE_2048) || (strsize > OS_SIZE_2048))
1534         {
1535             merror(SIZE_ERROR,ARGV0,str);
1536             return(NULL);
1537         }
1538         
1539         at = realloc(at, (finalsize)*sizeof(char));
1540         
1541         if(at == NULL)
1542         {
1543             merror(MEM_ERROR,ARGV0);
1544             return(NULL);
1545         }
1546         
1547         strncat(at,str,strsize);
1548         
1549         at[finalsize-1]='\0';
1550         
1551         return(at);
1552     }
1553     return(NULL);
1554 }
1555
1556
1557 RuleInfoDetail *zeroinfodetails(int type, char *data)
1558 {
1559     RuleInfoDetail *info_details_pt = NULL;
1560
1561     info_details_pt = (RuleInfoDetail *)calloc(1,sizeof(RuleInfoDetail));
1562
1563     if (info_details_pt == NULL)
1564     {
1565         ErrorExit(MEM_ERROR,ARGV0);
1566     }
1567     /* type */
1568     info_details_pt->type = type;
1569
1570     /* data */
1571     os_strdup(data, info_details_pt->data);
1572
1573     info_details_pt->next = NULL;
1574     
1575
1576     return(info_details_pt);
1577 }
1578
1579
1580 RuleInfo *zerorulemember(int id, int level, 
1581                          int maxsize, int frequency,
1582                          int timeframe, int noalert, 
1583                          int ignore_time, int overwrite)
1584 {
1585     RuleInfo *ruleinfo_pt = NULL;
1586     
1587     /* Allocation memory for structure */
1588     ruleinfo_pt = (RuleInfo *)calloc(1,sizeof(RuleInfo));
1589
1590     if(ruleinfo_pt == NULL)
1591     {
1592         ErrorExit(MEM_ERROR,ARGV0);
1593     }
1594     
1595     /* Default values */
1596     ruleinfo_pt->level = level;
1597
1598     /* Default category is syslog */
1599     ruleinfo_pt->category = SYSLOG;
1600
1601     ruleinfo_pt->ar = NULL; 
1602     
1603     ruleinfo_pt->context = 0;
1604     
1605     ruleinfo_pt->sigid = id;
1606     ruleinfo_pt->firedtimes = 0;
1607     ruleinfo_pt->maxsize = maxsize;
1608     ruleinfo_pt->frequency = frequency;
1609     if(ruleinfo_pt->frequency > _max_freq)
1610     {
1611         _max_freq = ruleinfo_pt->frequency;
1612     }
1613     ruleinfo_pt->ignore_time = ignore_time;
1614     ruleinfo_pt->timeframe = timeframe;
1615     ruleinfo_pt->time_ignored = 0;
1616    
1617     ruleinfo_pt->context_opts = 0; 
1618     ruleinfo_pt->alert_opts = 0; 
1619     ruleinfo_pt->ignore = 0; 
1620     ruleinfo_pt->ckignore = 0; 
1621
1622     if(noalert)
1623     {
1624         ruleinfo_pt->alert_opts |= NO_ALERT;
1625     }
1626     if(Config.mailbylevel <= level)
1627         ruleinfo_pt->alert_opts |= DO_MAILALERT;
1628     if(Config.logbylevel <= level)    
1629         ruleinfo_pt->alert_opts |= DO_LOGALERT;
1630
1631     /* Overwriting a rule */
1632     if(overwrite)
1633     {
1634         ruleinfo_pt->alert_opts |= DO_OVERWRITE;
1635     }
1636
1637     ruleinfo_pt->day_time = NULL;
1638     ruleinfo_pt->week_day = NULL;
1639
1640     ruleinfo_pt->group = NULL;
1641     ruleinfo_pt->regex = NULL;
1642     ruleinfo_pt->match = NULL;
1643     ruleinfo_pt->decoded_as = 0;
1644
1645     ruleinfo_pt->comment = NULL;
1646     ruleinfo_pt->info = NULL;
1647     ruleinfo_pt->cve = NULL;
1648     ruleinfo_pt->info_details = NULL;
1649     
1650     ruleinfo_pt->if_sid = NULL;
1651     ruleinfo_pt->if_group = NULL;
1652     ruleinfo_pt->if_level = NULL;
1653     
1654     ruleinfo_pt->if_matched_regex = NULL;
1655     ruleinfo_pt->if_matched_group = NULL;
1656     ruleinfo_pt->if_matched_sid = 0;
1657    
1658     ruleinfo_pt->user = NULL; 
1659     ruleinfo_pt->srcip = NULL;
1660     ruleinfo_pt->srcport = NULL;
1661     ruleinfo_pt->dstip = NULL;
1662     ruleinfo_pt->dstport = NULL;
1663     ruleinfo_pt->url = NULL;
1664     ruleinfo_pt->id = NULL;
1665     ruleinfo_pt->status = NULL;
1666     ruleinfo_pt->hostname = NULL;
1667     ruleinfo_pt->program_name = NULL;
1668     ruleinfo_pt->action = NULL;
1669     
1670     /* Zeroing last matched events */
1671     ruleinfo_pt->__frequency = 0;
1672     ruleinfo_pt->last_events = NULL;
1673
1674     /* zeroing the list of previous matches */
1675     ruleinfo_pt->sid_prev_matched = NULL;
1676     ruleinfo_pt->group_prev_matched = NULL;
1677     
1678     ruleinfo_pt->sid_search = NULL;
1679     ruleinfo_pt->group_search = NULL;
1680     
1681     ruleinfo_pt->event_search = NULL;
1682     ruleinfo_pt->compiled_rule = NULL;
1683     ruleinfo_pt->lists = NULL;
1684
1685     return(ruleinfo_pt);
1686 }
1687
1688 int get_info_attributes(char **attributes, char **values)
1689 {
1690     char *xml_type = "type";
1691     int k=0;
1692     if(!attributes)
1693         return(RULEINFODETAIL_TEXT);
1694
1695     while(attributes[k])
1696     {
1697         if (!values[k])
1698         {
1699             merror("rules_op: Entry info type \"%s\" does not have a value", 
1700                     attributes[k]);
1701             return (-1);
1702         }
1703         else if(strcasecmp(attributes[k],xml_type) == 0)
1704         {
1705             if(strcmp(values[k], "text") == 0)
1706             {
1707                 return(RULEINFODETAIL_TEXT);
1708             } 
1709             else if(strcmp(values[k], "link") == 0)
1710             {
1711                 return(RULEINFODETAIL_LINK);
1712             }
1713             else if(strcmp(values[k], "cve") == 0)
1714             {
1715                 return(RULEINFODETAIL_CVE);
1716             }
1717             else if(strcmp(values[k], "osvdb") == 0)
1718             {
1719                 return(RULEINFODETAIL_OSVDB);
1720             }
1721         }
1722     }
1723     return(RULEINFODETAIL_TEXT);
1724 }
1725
1726 /* Get the attributes */
1727 int getattributes(char **attributes, char **values,
1728                   int *id, int *level, 
1729                   int *maxsize, int *timeframe,
1730                   int *frequency, int *accuracy, 
1731                   int *noalert, int *ignore_time, int *overwrite)
1732 {
1733     int k=0;
1734     
1735     char *xml_id = "id";
1736     char *xml_level = "level";
1737     char *xml_maxsize = "maxsize";
1738     char *xml_timeframe = "timeframe";
1739     char *xml_frequency = "frequency";
1740     char *xml_accuracy = "accuracy";
1741     char *xml_noalert = "noalert";
1742     char *xml_ignore_time = "ignore";
1743     char *xml_overwrite = "overwrite";
1744     
1745    
1746     /* Getting attributes */
1747     while(attributes[k])
1748     {
1749         if(!values[k])
1750         {
1751             merror("rules_op: Attribute \"%s\" without value."
1752                     ,attributes[k]);
1753             return(-1);
1754         }
1755         /* Getting rule Id */
1756         else if(strcasecmp(attributes[k],xml_id) == 0)
1757         {
1758             if(OS_StrIsNum(values[k]))
1759             {
1760                 sscanf(values[k],"%6d",id);
1761             }
1762             else
1763             {
1764                 merror("rules_op: Invalid rule id: %s. "
1765                         "Must be integer" ,
1766                         values[k]);
1767                 return(-1);
1768             }
1769         }
1770         /* Getting level */
1771         else if(strcasecmp(attributes[k],xml_level) == 0)
1772         {
1773             if(OS_StrIsNum(values[k]))
1774             {
1775                 sscanf(values[k],"%4d",level);
1776             }
1777             else
1778             {
1779                 merror("rules_op: Invalid level: %s. "
1780                         "Must be integer" ,
1781                         values[k]);
1782                 return(-1);
1783             }
1784         }
1785         /* Getting maxsize */
1786         else if(strcasecmp(attributes[k],xml_maxsize) == 0)
1787         {
1788             if(OS_StrIsNum(values[k]))
1789             {
1790                 sscanf(values[k],"%4d",maxsize);
1791             }
1792             else
1793             {
1794                 merror("rules_op: Invalid maxsize: %s. "
1795                         "Must be integer" ,
1796                         values[k]);
1797                 return(-1);
1798             }
1799         }
1800         /* Getting timeframe */
1801         else if(strcasecmp(attributes[k],xml_timeframe) == 0)
1802         {
1803             if(OS_StrIsNum(values[k]))
1804             {
1805                 sscanf(values[k],"%5d",timeframe);
1806             }
1807             else
1808             {
1809                 merror("rules_op: Invalid timeframe: %s. "
1810                         "Must be integer" ,
1811                         values[k]);
1812                 return(-1);
1813             }
1814         }
1815         /* Getting frequency */
1816         else if(strcasecmp(attributes[k],xml_frequency) == 0)
1817         {
1818             if(OS_StrIsNum(values[k]))
1819             {
1820                 sscanf(values[k],"%4d",frequency);
1821             }
1822             else
1823             {
1824                 merror("rules_op: Invalid frequency: %s. "
1825                         "Must be integer" ,
1826                         values[k]);
1827                 return(-1);
1828             }
1829         }
1830         /* Rule accuracy */
1831         else if(strcasecmp(attributes[k],xml_accuracy) == 0)
1832         {
1833             if(OS_StrIsNum(values[k]))
1834             {
1835                 sscanf(values[k],"%4d",accuracy);
1836             }
1837             else
1838             {
1839                 merror("rules_op: Invalid accuracy: %s. "
1840                        "Must be integer" ,
1841                        values[k]);
1842                 return(-1); 
1843             }
1844         }
1845          /* Rule ignore_time */
1846         else if(strcasecmp(attributes[k],xml_ignore_time) == 0)
1847         {
1848             if(OS_StrIsNum(values[k]))
1849             {
1850                 sscanf(values[k],"%6d",ignore_time);
1851             }
1852             else
1853             {
1854                 merror("rules_op: Invalid ignore_time: %s. "
1855                        "Must be integer" ,
1856                        values[k]);
1857                 return(-1); 
1858             }
1859         }
1860         /* Rule noalert */
1861         else if(strcasecmp(attributes[k],xml_noalert) == 0)
1862         {
1863             *noalert = 1;
1864         }
1865         else if(strcasecmp(attributes[k], xml_overwrite) == 0)
1866         {
1867             if(strcmp(values[k], "yes") == 0)
1868             {
1869                 *overwrite = 1;
1870             }
1871             else if(strcmp(values[k], "no") == 0)
1872             {
1873                 *overwrite = 0;
1874             }
1875             else
1876             {
1877                 merror("rules_op: Invalid overwrite: %s. "
1878                        "Can only by 'yes' or 'no'.", values[k]);
1879                 return(-1);
1880             }
1881         }
1882         else
1883         {
1884             merror("rules_op: Invalid attribute \"%s\". "
1885                     "Only id, level, maxsize, accuracy, noalert and timeframe "
1886                     "are allowed.", attributes[k]);
1887             return(-1);
1888         }
1889         k++;
1890     }
1891     return(0);
1892 }
1893
1894
1895 /* Bind active responses to the rule.
1896  * No return.
1897  */
1898 void Rule_AddAR(RuleInfo *rule_config)
1899 {
1900     int rule_ar_size = 0;
1901     int mark_to_ar = 0;
1902     int rule_real_level = 0;
1903     
1904     OSListNode *my_ars_node;
1905     
1906     
1907     /* Setting the correctly levels 
1908      * We play internally with the rules, to set
1909      * the priorities... Rules with 0 of accuracy,
1910      * receive a low level and go down in the list
1911      */
1912     if(rule_config->level == 9900)
1913         rule_real_level = 0;
1914     
1915     else if(rule_config->level >= 100)
1916         rule_real_level = rule_config->level/100;
1917     
1918     
1919     /* No AR for ignored rules */
1920     if(rule_real_level == 0)
1921     {
1922         return;
1923     }
1924
1925     /* No AR when options no_ar is set */
1926     if(rule_config->alert_opts & NO_AR)
1927     {
1928         return;
1929     }
1930
1931     if(!active_responses)
1932     {
1933         return;
1934     }
1935     
1936     /* Looping on all AR */
1937     my_ars_node = OSList_GetFirstNode(active_responses);
1938     while(my_ars_node)
1939     {
1940         active_response *my_ar;
1941
1942
1943         my_ar = (active_response *)my_ars_node->data;
1944         mark_to_ar = 0;
1945
1946         /* Checking if the level for the ar is higher */
1947         if(my_ar->level)
1948         {
1949             if(rule_real_level >= my_ar->level)
1950             {
1951                 mark_to_ar = 1;
1952             }
1953         }
1954        
1955         /* Checking if group matches */
1956         if(my_ar->rules_group)
1957         {
1958            if(OS_Regex(my_ar->rules_group, rule_config->group))
1959            {
1960                mark_to_ar = 1;
1961            }
1962         }
1963         
1964         /* Checking if rule id matches */
1965         if(my_ar->rules_id)
1966         {
1967             int r_id = 0;
1968             char *str_pt = my_ar->rules_id;
1969
1970             while(*str_pt != '\0')
1971             {
1972                 /* We allow spaces in between */
1973                 if(*str_pt == ' ')
1974                 {
1975                     str_pt++;
1976                     continue;
1977                 }
1978
1979                 /* If is digit, we get the value
1980                  * and search for the next digit
1981                  * available
1982                  */
1983                 else if(isdigit((int)*str_pt))
1984                 {
1985                     r_id = atoi(str_pt);
1986                     
1987                     /* mark to ar if id matches */
1988                     if(r_id == rule_config->sigid)
1989                     {
1990                         mark_to_ar = 1;
1991                     }
1992                     
1993                     str_pt = strchr(str_pt, ',');
1994                     if(str_pt)
1995                     {
1996                         str_pt++;
1997                     }
1998                     else
1999                     {
2000                         break;
2001                     }
2002                 }
2003
2004                 /* Checking for duplicate commas */
2005                 else if(*str_pt == ',')
2006                 {
2007                     str_pt++;
2008                     continue;
2009                 }
2010
2011                 else
2012                 {
2013                     break;
2014                 }
2015             }
2016         } /* eof of rules_id */
2017  
2018         
2019         /* Bind AR to the rule */ 
2020         if(mark_to_ar == 1)
2021         {
2022             rule_ar_size++;
2023
2024             rule_config->ar = realloc(rule_config->ar,
2025                                       (rule_ar_size + 1)
2026                                       *sizeof(active_response *));
2027             
2028             /* Always set the last node to NULL */
2029             rule_config->ar[rule_ar_size - 1] = my_ar;
2030             rule_config->ar[rule_ar_size] = NULL;  
2031         }
2032         
2033         my_ars_node = OSList_GetNextNode(active_responses);
2034     }
2035
2036     return;
2037 }
2038
2039
2040 /* print rule */
2041 void printRuleinfo(RuleInfo *rule, int node)
2042 {
2043     debug1("%d : rule:%d, level %d, timeout: %d", 
2044             node,
2045             rule->sigid, 
2046             rule->level,
2047             rule->ignore_time);
2048 }
2049
2050
2051
2052 /* Add Rule to hash. */
2053 int AddHash_Rule(RuleNode *node)
2054 {
2055     while(node)
2056     {
2057         char _id_key[15];
2058         char *id_key;
2059
2060         snprintf(_id_key, 14, "%d", node->ruleinfo->sigid);
2061         os_strdup(_id_key, id_key);
2062         
2063         
2064         /* Adding key to hash. */
2065         OSHash_Add(Config.g_rules_hash, id_key, node->ruleinfo);
2066         if(node->child)
2067         {
2068             AddHash_Rule(node->child);
2069         }
2070
2071         node = node->next;
2072     }
2073
2074     return(0);
2075 }
2076
2077
2078
2079 /* _set levels */
2080 int _setlevels(RuleNode *node, int nnode)
2081 {
2082     int l_size = 0;
2083     while(node)
2084     {
2085         if(node->ruleinfo->level == 9900)
2086             node->ruleinfo->level = 0;
2087
2088         if(node->ruleinfo->level >= 100)
2089             node->ruleinfo->level/=100;
2090
2091         l_size++;
2092         
2093         /* Rule information */
2094         printRuleinfo(node->ruleinfo, nnode);
2095         
2096         if(node->child)
2097         {
2098             int chl_size = 0;
2099             chl_size = _setlevels(node->child, nnode+1);
2100
2101             l_size += chl_size;
2102         }
2103
2104         node = node->next;
2105     }
2106
2107     return(l_size);
2108 }
2109
2110
2111 /* EOF */