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