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