Imported Upstream version 2.3
[ossec-hids.git] / src / shared / rules_op.c
1 /* @(#) $Id: rules_op.c,v 1.6 2009/06/24 18:53:08 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_op.h"
18
19
20 /** Prototypes **/
21 int _OS_GetRulesAttributes(char **attributes, 
22                            char **values,
23                            RuleInfo *ruleinfo_pt);
24 RuleInfo *_OS_AllocateRule();
25
26
27
28
29 /* Rules_OP_ReadRules, v0.3, 2005/03/21
30  * Read the log rules.
31  * v0.3: Fixed many memory problems.
32  */ 
33 int OS_ReadXMLRules(char *rulefile, 
34                     void *(*ruleact_function)(RuleInfo *rule, void *data),
35                     void *data)
36 {
37     OS_XML xml;
38     XML_NODE node = NULL;
39
40
41     /** XML variables **/ 
42     /* These are the available options for the rule configuration */
43     
44     char *xml_group = "group";
45     char *xml_rule = "rule";
46
47     char *xml_regex = "regex";
48     char *xml_match = "match";
49     char *xml_decoded = "decoded_as";
50     char *xml_category = "category";
51     char *xml_cve = "cve";
52     char *xml_info = "info";
53     char *xml_day_time = "time";
54     char *xml_week_day = "weekday";
55     char *xml_comment = "description";
56     char *xml_ignore = "ignore";
57     char *xml_check_if_ignored = "check_if_ignored";
58     
59     char *xml_srcip = "srcip";
60     char *xml_srcport = "srcport";
61     char *xml_dstip = "dstip";
62     char *xml_dstport = "dstport";
63     char *xml_user = "user";
64     char *xml_url = "url";
65     char *xml_id = "id";
66     char *xml_data = "extra_data";
67     char *xml_hostname = "hostname";
68     char *xml_program_name = "program_name";
69     char *xml_status = "status";
70     char *xml_action = "action";
71     char *xml_compiled = "compiled_rule";
72     
73     char *xml_if_sid = "if_sid";
74     char *xml_if_group = "if_group";
75     char *xml_if_level = "if_level";
76     char *xml_fts = "if_fts";
77     
78     char *xml_if_matched_regex = "if_matched_regex";
79     char *xml_if_matched_group = "if_matched_group";
80     char *xml_if_matched_sid = "if_matched_sid";
81     
82     char *xml_same_source_ip = "same_source_ip";
83     char *xml_same_src_port = "same_src_port";
84     char *xml_same_dst_port = "same_dst_port";
85     char *xml_same_user = "same_user";
86     char *xml_same_location = "same_location";
87     char *xml_same_id = "same_id";
88
89     char *xml_different_url = "different_url";
90     
91     char *xml_notsame_source_ip = "not_same_source_ip";
92     char *xml_notsame_user = "not_same_user";
93     char *xml_notsame_agent = "not_same_agent";
94     char *xml_notsame_id = "not_same_id";
95
96     char *xml_options = "options";
97     
98     char *rulepath;
99     
100     int i;
101
102
103     /* Building the rule file name + path */
104     i = strlen(RULEPATH) + strlen(rulefile) + 2;
105     rulepath = (char *)calloc(i,sizeof(char));
106     if(!rulepath)
107     {
108         ErrorExit(MEM_ERROR,__local_name);
109     }
110     snprintf(rulepath,i,"%s/%s",RULEPATH,rulefile);
111     
112     
113     /* Reading the XML */       
114     if(OS_ReadXML(rulepath,&xml) < 0)
115     {
116         merror(XML_ERROR, __local_name, rulepath, xml.err, xml.err_line);
117         free(rulepath);
118         return(-1);     
119     }
120
121
122     /* Debug wrapper */
123     debug1("%s: DEBUG: read xml for rule '%s'.", __local_name, rulepath);
124     
125
126     /* Applying any variable found */
127     if(OS_ApplyVariables(&xml) != 0)
128     {
129         merror(XML_ERROR_VAR, __local_name, rulepath, xml.err);
130         return(-1);
131     }
132
133
134     /* Debug wrapper */
135     debug1("%s: DEBUG: XML Variables applied.", __local_name);
136     
137
138     /* Getting the root elements */
139     node = OS_GetElementsbyNode(&xml, NULL);
140     if(!node)
141     {
142         merror(CONFIG_ERROR, __local_name, rulepath);
143         OS_ClearXML(&xml);
144         return(-1);    
145     }
146
147
148     /* Zeroing the rule memory -- not used anymore */
149     free(rulepath);
150     
151
152     /* Checking if there is any invalid global option */
153     i = 0;
154     while(node[i])
155     {
156         if(node[i]->element)
157         {
158             /* Verifying group */
159             if(strcasecmp(node[i]->element,xml_group) != 0)
160             {
161                 merror(RL_INV_ROOT, __local_name, node[i]->element);
162                 OS_ClearXML(&xml);
163                 return(-1);
164             }
165             /* Checking group attribute -- only name is allowed */
166             if((!node[i]->attributes) || (!node[i]->values)||
167                (!node[i]->values[0]) || (!node[i]->attributes[0]) ||
168                (strcasecmp(node[i]->attributes[0],"name") != 0) ||
169                (node[i]->attributes[1]))
170             {
171                 merror(RL_INV_ROOT, __local_name, node[i]->element);
172                 OS_ClearXML(&xml);
173                 return(-1);
174             }
175         }
176         else
177         {
178             merror(XML_READ_ERROR, __local_name);
179             OS_ClearXML(&xml);
180             return(-1);
181         }
182         i++;
183     }
184
185
186     /* Getting the rules now */   
187     i = 0;
188     while(node[i])
189     {
190         int j = 0;
191         XML_NODE rule = NULL;
192
193
194         /* Getting all rules for a global group */        
195         rule = OS_GetElementsbyNode(&xml,node[i]);
196         if(rule == NULL)
197         {
198             i++;
199             continue;
200         }
201
202         /* Looping on the rules node */
203         while(rule[j])
204         {
205             /* Rules options */
206             int k = 0;
207             char *regex = NULL, *match = NULL, *url = NULL, 
208                  *if_matched_regex = NULL, *if_matched_group = NULL,
209                  *user = NULL, *id = NULL, *srcport = NULL,
210                  *dstport = NULL, *status = NULL, *hostname = NULL,
211                  *extra_data = NULL, *program_name = NULL;
212             
213             RuleInfo *config_ruleinfo = NULL;
214             XML_NODE rule_opt = NULL;
215            
216
217             /* Checking if the rule element is correct */
218             if((!rule[j]->element)||
219                (strcasecmp(rule[j]->element,xml_rule) != 0))
220             {
221                 merror(RL_INV_RULE, __local_name, node[i]->element);
222                 OS_ClearXML(&xml);
223                 return(-1);
224             }
225
226
227             /* Checking for the attributes of the rule */
228             if((!rule[j]->attributes) || (!rule[j]->values))
229             {
230                 merror(RL_INV_RULE, __local_name, rulefile); 
231                 OS_ClearXML(&xml);
232                 return(-1);
233             }
234
235             
236             /* Attribute block */
237             config_ruleinfo = _OS_AllocateRule();
238
239             if(_OS_GetRulesAttributes(rule[j]->attributes, rule[j]->values,
240                                       config_ruleinfo) < 0)
241             {
242                 merror(RL_INV_ATTR, __local_name, rulefile);
243                 OS_ClearXML(&xml);
244                 return(-1);
245             }
246
247             /* We must have an id or level */
248             if((config_ruleinfo->sigid == -1)||(config_ruleinfo->level == -1))
249             {
250                 merror(RL_INV_ATTR, __local_name, rulefile);
251                 OS_ClearXML(&xml);
252                 return(-1);
253             }
254
255
256             /* Here we can assign the group name to the rule.
257              * The level is correct so the rule is probably going to
258              * be fine
259              */
260             os_strdup(node[i]->values[0], config_ruleinfo->group);
261             
262
263             /* Getting rules options */    
264             rule_opt =  OS_GetElementsbyNode(&xml, rule[j]);
265             if(rule_opt == NULL)
266             {
267                 merror(RL_NO_OPT, __local_name, config_ruleinfo->sigid);
268                 OS_ClearXML(&xml);
269                 return(-1);       
270             }
271                 
272
273             /* Reading the whole rule block */    
274             while(rule_opt[k])
275             {
276                 if((!rule_opt[k]->element)||(!rule_opt[k]->content))
277                 {
278                     break;
279                 }
280                 else if(strcasecmp(rule_opt[k]->element,xml_regex)==0)
281                 {
282                     regex =
283                         os_LoadString(regex,
284                                 rule_opt[k]->content);
285                 }
286                 else if(strcasecmp(rule_opt[k]->element,xml_match)==0)
287                 {
288                     match =
289                         os_LoadString(match,
290                                 rule_opt[k]->content);
291                 }
292                 else if(strcasecmp(rule_opt[k]->element, xml_decoded) == 0)
293                 {
294                 }
295                 else if(strcasecmp(rule_opt[k]->element,xml_info) == 0)
296                 {
297                     config_ruleinfo->info=
298                         os_LoadString(config_ruleinfo->info,
299                                       rule_opt[k]->content);
300                 }
301                 else if(strcasecmp(rule_opt[k]->element,xml_day_time) == 0)
302                 {
303                     config_ruleinfo->day_time = 
304                                      OS_IsValidTime(rule_opt[k]->content);
305                     if(!config_ruleinfo->day_time)
306                     {
307                         merror(INVALID_CONFIG, __local_name,
308                                 rule_opt[k]->element,
309                                 rule_opt[k]->content);
310                         return(-1);
311                     }
312
313                     if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
314                         config_ruleinfo->alert_opts |= DO_EXTRAINFO;
315                 }
316                 else if(strcasecmp(rule_opt[k]->element,xml_week_day) == 0)
317                 {
318                     config_ruleinfo->week_day = 
319                         OS_IsValidDay(rule_opt[k]->content);
320
321                     if(!config_ruleinfo->week_day)
322                     {
323                         merror(INVALID_CONFIG, __local_name,
324                                 rule_opt[k]->element,
325                                 rule_opt[k]->content);
326                         return(-1);
327                     }
328                     if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
329                         config_ruleinfo->alert_opts |= DO_EXTRAINFO;
330                 }
331                 else if(strcasecmp(rule_opt[k]->element,xml_group) == 0)
332                 {
333                     config_ruleinfo->group =
334                         os_LoadString(config_ruleinfo->group,
335                                       rule_opt[k]->content);
336                 }
337                 else if(strcasecmp(rule_opt[k]->element,xml_cve) == 0)
338                 {
339                     config_ruleinfo->cve=
340                         os_LoadString(config_ruleinfo->cve,
341                                       rule_opt[k]->content);
342                 }
343                 else if(strcasecmp(rule_opt[k]->element,xml_comment) == 0)
344                 {
345                     char *newline;
346
347                     newline = strchr(rule_opt[k]->content, '\n');
348                     if(newline)
349                     {
350                         *newline = ' ';
351                     }
352                     config_ruleinfo->comment=
353                         os_LoadString(config_ruleinfo->comment,
354                                       rule_opt[k]->content);
355                 }
356                 else if(strcasecmp(rule_opt[k]->element,xml_srcip)==0)
357                 {
358                     int ip_s = 0;
359
360                     /* Getting size of source ip list */
361                     while(config_ruleinfo->srcip && 
362                             config_ruleinfo->srcip[ip_s])
363                     {
364                         ip_s++;
365                     }
366
367                     config_ruleinfo->srcip = 
368                                 realloc(config_ruleinfo->srcip,
369                                 (ip_s + 2) * sizeof(os_ip *));
370
371
372                     /* Allocating memory for the individual entries */
373                     os_calloc(1, sizeof(os_ip), 
374                                  config_ruleinfo->srcip[ip_s]);
375                     config_ruleinfo->srcip[ip_s +1] = NULL;
376
377
378                     /* Checking if the ip is valid */
379                     if(!OS_IsValidIP(rule_opt[k]->content, 
380                                      config_ruleinfo->srcip[ip_s]))
381                     {
382                         merror(INVALID_IP, __local_name, rule_opt[k]->content);
383                         return(-1);
384                     }
385
386                     if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
387                         config_ruleinfo->alert_opts |= DO_PACKETINFO;
388                 }
389                 else if(strcasecmp(rule_opt[k]->element,xml_dstip)==0)
390                 {
391                     int ip_s = 0;
392
393                     /* Getting size of source ip list */
394                     while(config_ruleinfo->dstip &&
395                             config_ruleinfo->dstip[ip_s])
396                     {
397                         ip_s++;
398                     }
399
400                     config_ruleinfo->dstip =
401                                 realloc(config_ruleinfo->dstip,
402                                 (ip_s + 2) * sizeof(os_ip *));
403
404
405                     /* Allocating memory for the individual entries */
406                     os_calloc(1, sizeof(os_ip),
407                             config_ruleinfo->dstip[ip_s]);
408                     config_ruleinfo->dstip[ip_s +1] = NULL;
409
410
411                     /* Checking if the ip is valid */
412                     if(!OS_IsValidIP(rule_opt[k]->content,
413                                 config_ruleinfo->dstip[ip_s]))
414                     {
415                         merror(INVALID_IP, __local_name, rule_opt[k]->content);
416                         return(-1);
417                     }
418
419                     if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
420                         config_ruleinfo->alert_opts |= DO_PACKETINFO;
421                 }
422                 else if(strcasecmp(rule_opt[k]->element,xml_user) == 0)
423                 {
424                     user = os_LoadString(user, rule_opt[k]->content);
425
426                     if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
427                         config_ruleinfo->alert_opts |= DO_EXTRAINFO;
428                 }
429                 else if(strcasecmp(rule_opt[k]->element,xml_id) == 0)
430                 {
431                     id = os_LoadString(id, rule_opt[k]->content);
432                 }
433                 else if(strcasecmp(rule_opt[k]->element,xml_srcport) == 0)
434                 {
435                     srcport = os_LoadString(srcport, rule_opt[k]->content);
436                     
437                     if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
438                         config_ruleinfo->alert_opts |= DO_PACKETINFO;
439                 }
440                 else if(strcasecmp(rule_opt[k]->element,xml_dstport) == 0)
441                 {
442                     dstport = os_LoadString(dstport, rule_opt[k]->content);
443
444                     if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
445                         config_ruleinfo->alert_opts |= DO_PACKETINFO;
446                 }
447                 else if(strcasecmp(rule_opt[k]->element,xml_status)==0)
448                 {
449                     status = os_LoadString(status, rule_opt[k]->content);
450
451                     if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
452                         config_ruleinfo->alert_opts |= DO_EXTRAINFO;
453                 }
454                 else if(strcasecmp(rule_opt[k]->element,xml_hostname) == 0)
455                 {
456                     hostname = os_LoadString(hostname, rule_opt[k]->content);
457
458                     if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
459                         config_ruleinfo->alert_opts |= DO_EXTRAINFO;
460                 }
461                 else if(strcasecmp(rule_opt[k]->element,xml_data)==0)
462                 {
463                     extra_data = os_LoadString(extra_data, rule_opt[k]->content);
464
465                     if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
466                         config_ruleinfo->alert_opts |= DO_EXTRAINFO;
467                 }
468                 else if(strcasecmp(rule_opt[k]->element,
469                             xml_program_name)==0)
470                 {
471                     program_name = os_LoadString(program_name,
472                                               rule_opt[k]->content);
473                 }
474                 else if(strcasecmp(rule_opt[k]->element,xml_action) == 0)
475                 {
476                     config_ruleinfo->action = 
477                                 os_LoadString(config_ruleinfo->action,
478                                 rule_opt[k]->content);
479                 }
480                 else if(strcasecmp(rule_opt[k]->element,xml_url) == 0)
481                 {
482                     url= os_LoadString(url, rule_opt[k]->content);
483                 }
484
485                 else if(strcasecmp(rule_opt[k]->element, xml_compiled)==0)
486                 {
487                     /* Not using this in here. */
488                 }
489
490                 /* We allow these categories so far */
491                 else if(strcasecmp(rule_opt[k]->element, xml_category)==0)
492                 {
493                     if(strcmp(rule_opt[k]->content, "firewall") == 0)
494                     {
495                         config_ruleinfo->category = FIREWALL;
496                     }
497                     else if(strcmp(rule_opt[k]->content, "ids") == 0)
498                     {
499                         config_ruleinfo->category = IDS;
500                     }
501                     else if(strcmp(rule_opt[k]->content, "syslog") == 0)
502                     {
503                         config_ruleinfo->category = SYSLOG;
504                     }
505                     else if(strcmp(rule_opt[k]->content, "web-log") == 0)
506                     {
507                         config_ruleinfo->category = WEBLOG;
508                     }
509                     else if(strcmp(rule_opt[k]->content, "squid") == 0)
510                     {
511                         config_ruleinfo->category = SQUID;
512                     }
513                     else if(strcmp(rule_opt[k]->content,"windows") == 0)
514                     {
515                         config_ruleinfo->category = WINDOWS;
516                     }
517                     else if(strcmp(rule_opt[k]->content,"ossec") == 0)
518                     {
519                         config_ruleinfo->category = OSSEC_RL;
520                     }
521                     else
522                     {
523                         merror(INVALID_CAT, __local_name, rule_opt[k]->content);
524                         return(-1);
525                     }
526                 }
527                 else if(strcasecmp(rule_opt[k]->element,xml_if_sid)==0)
528                 {
529                     config_ruleinfo->if_sid=
530                                 os_LoadString(config_ruleinfo->if_sid,
531                                 rule_opt[k]->content);
532                 }
533                 else if(strcasecmp(rule_opt[k]->element,xml_if_level)==0)
534                 {
535                     if(!OS_StrIsNum(rule_opt[k]->content))
536                     {
537                         merror(INVALID_CONFIG, __local_name, 
538                                 xml_if_level,
539                                 rule_opt[k]->content); 
540                         return(-1);
541                     }
542
543                     config_ruleinfo->if_level=
544                                 os_LoadString(config_ruleinfo->if_level,
545                                 rule_opt[k]->content);
546                 }
547                 else if(strcasecmp(rule_opt[k]->element,xml_if_group)==0)
548                 {
549                     config_ruleinfo->if_group=
550                                 os_LoadString(config_ruleinfo->if_group,
551                                 rule_opt[k]->content);
552                 }
553                 else if(strcasecmp(rule_opt[k]->element,
554                             xml_if_matched_regex) == 0)
555                 {
556                     config_ruleinfo->context = 1;
557                     if_matched_regex=
558                                 os_LoadString(if_matched_regex,
559                                 rule_opt[k]->content);
560                 }
561                 else if(strcasecmp(rule_opt[k]->element,
562                             xml_if_matched_group) == 0)
563                 {
564                     config_ruleinfo->context = 1;
565                     if_matched_group=
566                                 os_LoadString(if_matched_group,
567                                 rule_opt[k]->content);
568                 }
569                 else if(strcasecmp(rule_opt[k]->element,
570                             xml_if_matched_sid) == 0)
571                 {
572                     config_ruleinfo->context = 1;
573                     if(!OS_StrIsNum(rule_opt[k]->content))
574                     {
575                         merror(INVALID_CONFIG, __local_name,
576                                 rule_opt[k]->element,
577                                 rule_opt[k]->content);
578                         return(-1);
579                     }
580                     config_ruleinfo->if_matched_sid = 
581                         atoi(rule_opt[k]->content);
582
583                 }
584                 else if(strcasecmp(rule_opt[k]->element,
585                             xml_same_source_ip)==0)
586                 {
587                     config_ruleinfo->context_opts|= SAME_SRCIP;
588                 }
589                 else if(strcasecmp(rule_opt[k]->element,
590                             xml_same_src_port)==0)
591                 {
592                     config_ruleinfo->context_opts|= SAME_SRCPORT;
593
594                     if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
595                         config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
596                 }
597                 else if(strcasecmp(rule_opt[k]->element,
598                             xml_same_dst_port) == 0)
599                 {
600                     config_ruleinfo->context_opts|= SAME_DSTPORT;
601
602                     if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
603                         config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
604                 }
605                 else if(strcasecmp(rule_opt[k]->element,
606                             xml_notsame_source_ip)==0)
607                 {
608                     config_ruleinfo->context_opts&= NOT_SAME_SRCIP;
609                 }
610                 else if(strcmp(rule_opt[k]->element, xml_same_id) == 0)
611                 {
612                     config_ruleinfo->context_opts|= SAME_ID;
613                 }
614                 else if(strcmp(rule_opt[k]->element,
615                             xml_different_url) == 0)
616                 {
617                     config_ruleinfo->context_opts|= DIFFERENT_URL;
618
619                     if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
620                         config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
621                 }
622                 else if(strcmp(rule_opt[k]->element,xml_notsame_id) == 0)
623                 {
624                     config_ruleinfo->context_opts&= NOT_SAME_ID;
625                 }
626                 else if(strcasecmp(rule_opt[k]->element,
627                             xml_fts) == 0)
628                 {
629                     config_ruleinfo->alert_opts |= DO_FTS;
630                 }
631                 else if(strcasecmp(rule_opt[k]->element,
632                             xml_same_user)==0)
633                 {
634                     config_ruleinfo->context_opts|= SAME_USER;
635
636                     if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
637                         config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
638                 }
639                 else if(strcasecmp(rule_opt[k]->element,
640                             xml_notsame_user)==0)
641                 {
642                     config_ruleinfo->context_opts&= NOT_SAME_USER;
643                 }
644                 else if(strcasecmp(rule_opt[k]->element,
645                             xml_same_location)==0)
646                 {
647                     config_ruleinfo->context_opts|= SAME_LOCATION;
648                     if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
649                         config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
650                 }
651                 else if(strcasecmp(rule_opt[k]->element,
652                             xml_notsame_agent)==0)
653                 {
654                     config_ruleinfo->context_opts&= NOT_SAME_AGENT;
655                 }
656                 else if(strcasecmp(rule_opt[k]->element,
657                             xml_options) == 0)
658                 {
659                     if(strcmp("alert_by_email", 
660                                 rule_opt[k]->content) == 0)
661                     {
662                         if(!(config_ruleinfo->alert_opts & DO_MAILALERT))
663                         {
664                             config_ruleinfo->alert_opts|= DO_MAILALERT;
665                         }
666                     }
667                     else if(strcmp("no_email_alert",
668                                 rule_opt[k]->content) == 0)
669                     {
670                         if(config_ruleinfo->alert_opts & DO_MAILALERT)
671                         {
672                             config_ruleinfo->alert_opts&=0xfff-DO_MAILALERT;
673                         }
674                     }
675                     else if(strcmp("log_alert", 
676                                 rule_opt[k]->content) == 0)
677                     {
678                         if(!(config_ruleinfo->alert_opts & DO_LOGALERT))
679                         {
680                             config_ruleinfo->alert_opts|= DO_LOGALERT;
681                         }
682                     }
683                     else if(strcmp("no_log", rule_opt[k]->content) == 0)
684                     {
685                         if(config_ruleinfo->alert_opts & DO_LOGALERT)
686                         {
687                             config_ruleinfo->alert_opts &=0xfff-DO_LOGALERT;
688                         }
689                     }
690                     else
691                     {               
692                         merror(XML_VALUEERR, __local_name, xml_options,
693                                 rule_opt[k]->content);
694
695                         merror(INVALID_ELEMENT, __local_name,
696                                                 rule_opt[k]->element,
697                                                 rule_opt[k]->content);
698                         OS_ClearXML(&xml);
699                         return(-1);
700                     }   
701                 }
702                 else if(strcasecmp(rule_opt[k]->element,
703                             xml_ignore) == 0)
704                 {
705                     if(strstr(rule_opt[k]->content, "user") != NULL)
706                     {
707                         config_ruleinfo->ignore|=FTS_USER;
708                     }
709                     if(strstr(rule_opt[k]->content, "srcip") != NULL)
710                     {
711                         config_ruleinfo->ignore|=FTS_SRCIP;
712                     }
713                     if(strstr(rule_opt[k]->content, "dstip") != NULL)
714                     {
715                         config_ruleinfo->ignore|=FTS_DSTIP;
716                     }
717                     if(strstr(rule_opt[k]->content, "id") != NULL)
718                     {
719                         config_ruleinfo->ignore|=FTS_ID;
720                     }
721                     if(strstr(rule_opt[k]->content,"location")!= NULL)
722                     {
723                         config_ruleinfo->ignore|=FTS_LOCATION;
724                     }
725                     if(strstr(rule_opt[k]->content,"data")!= NULL)
726                     {
727                         config_ruleinfo->ignore|=FTS_DATA;
728                     }
729                     if(strstr(rule_opt[k]->content, "name") != NULL)
730                     {
731                         config_ruleinfo->ignore|=FTS_NAME;
732
733                     }
734                     if(!config_ruleinfo->ignore)
735                     {
736                         merror(INVALID_ELEMENT, __local_name,
737                                 rule_opt[k]->element,
738                                 rule_opt[k]->content);
739
740                         return(-1);
741                     }
742                 }
743                 else if(strcasecmp(rule_opt[k]->element,
744                             xml_check_if_ignored) == 0)
745                 {
746                     if(strstr(rule_opt[k]->content, "user") != NULL)
747                     {
748                         config_ruleinfo->ckignore|=FTS_USER;
749                     }
750                     if(strstr(rule_opt[k]->content, "srcip") != NULL)
751                     {
752                         config_ruleinfo->ckignore|=FTS_SRCIP;
753                     }
754                     if(strstr(rule_opt[k]->content, "dstip") != NULL)
755                     {
756                         config_ruleinfo->ckignore|=FTS_DSTIP;
757                     }
758                     if(strstr(rule_opt[k]->content, "id") != NULL)
759                     {
760                         config_ruleinfo->ckignore|=FTS_ID;
761                     }
762                     if(strstr(rule_opt[k]->content,"location")!= NULL)
763                     {
764                         config_ruleinfo->ckignore|=FTS_LOCATION;
765                     }
766                     if(strstr(rule_opt[k]->content,"data")!= NULL)
767                     {
768                         config_ruleinfo->ignore|=FTS_DATA;
769                     }
770                     if(strstr(rule_opt[k]->content, "name") != NULL)
771                     {
772                         config_ruleinfo->ckignore|=FTS_NAME;
773
774                     }
775                     if(!config_ruleinfo->ckignore)
776                     {
777                         merror(INVALID_ELEMENT, __local_name,
778                                 rule_opt[k]->element,
779                                 rule_opt[k]->content);
780
781                         return(-1);
782                     }
783                 }
784                 else
785                 {
786                     merror(XML_INVELEM, __local_name, rule_opt[k]->element);
787                     OS_ClearXML(&xml);
788                     return(-1);
789                 }
790
791                 k++;
792             }
793
794
795             /* Checking for a valid use of frequency */
796             if((config_ruleinfo->context_opts ||
797                 config_ruleinfo->frequency) &&
798                !config_ruleinfo->context)
799             {
800                 merror("%s: Invalid use of frequency/context options. "
801                         "Missing if_matched on rule '%d'.",
802                         __local_name, config_ruleinfo->sigid);
803                 OS_ClearXML(&xml);
804                 return(-1);
805             }
806
807
808             /* If if_matched_group we must have a if_sid or if_group */
809             if(if_matched_group)
810             {
811                 if(!config_ruleinfo->if_sid && !config_ruleinfo->if_group)
812                 {
813                     os_strdup(if_matched_group, config_ruleinfo->if_group);
814                 }
815             }
816                 
817
818             /* If_matched_sid, we need to get the if_sid */
819             if(config_ruleinfo->if_matched_sid &&
820                !config_ruleinfo->if_sid &&
821                !config_ruleinfo->if_group)
822             {
823                 os_calloc(16, sizeof(char), config_ruleinfo->if_sid);
824                 snprintf(config_ruleinfo->if_sid, 15, "%d",
825                         config_ruleinfo->if_matched_sid);
826             }
827
828
829             /* Checking the regexes */
830             if(regex)
831             {
832                 os_calloc(1, sizeof(OSRegex), config_ruleinfo->regex);
833                 if(!OSRegex_Compile(regex, config_ruleinfo->regex, 0))
834                 {
835                     merror(REGEX_COMPILE, __local_name, regex,
836                             config_ruleinfo->regex->error);
837                     return(-1);
838                 }
839                 free(regex);
840                 regex = NULL;
841             }
842
843
844             /* Adding in match */
845             if(match)
846             {
847                 os_calloc(1, sizeof(OSMatch), config_ruleinfo->match);
848                 if(!OSMatch_Compile(match, config_ruleinfo->match, 0))
849                 {
850                     merror(REGEX_COMPILE, __local_name, match,
851                             config_ruleinfo->match->error);
852                     return(-1);
853                 }
854                 free(match);
855                 match = NULL;
856             }
857
858
859             /* Adding in id */
860             if(id)
861             {
862                 os_calloc(1, sizeof(OSMatch), config_ruleinfo->id);
863                 if(!OSMatch_Compile(id, config_ruleinfo->id, 0))
864                 {
865                     merror(REGEX_COMPILE, __local_name, id,
866                             config_ruleinfo->id->error);
867                     return(-1);
868                 }
869                 free(id);
870                 id = NULL;
871             }
872
873
874             /* Adding srcport */
875             if(srcport)
876             {
877                 os_calloc(1, sizeof(OSMatch), config_ruleinfo->srcport);
878                 if(!OSMatch_Compile(srcport, config_ruleinfo->srcport, 0))
879                 {
880                     merror(REGEX_COMPILE, __local_name, srcport,
881                             config_ruleinfo->id->error);
882                     return(-1);
883                 }
884                 free(srcport);
885                 srcport = NULL;
886             }
887
888
889             /* Adding dstport */
890             if(dstport)
891             {
892                 os_calloc(1, sizeof(OSMatch), config_ruleinfo->dstport);
893                 if(!OSMatch_Compile(dstport, config_ruleinfo->dstport, 0))
894                 {
895                     merror(REGEX_COMPILE, __local_name, dstport,
896                             config_ruleinfo->id->error);
897                     return(-1);
898                 }
899                 free(dstport);
900                 dstport = NULL;
901             }
902
903
904             /* Adding in status */
905             if(status)
906             {
907                 os_calloc(1, sizeof(OSMatch), config_ruleinfo->status);
908                 if(!OSMatch_Compile(status, config_ruleinfo->status, 0))
909                 {
910                     merror(REGEX_COMPILE, __local_name, status,
911                             config_ruleinfo->status->error);
912                     return(-1);
913                 }
914                 free(status);
915                 status = NULL;
916             }
917
918
919             /* Adding in hostname */
920             if(hostname)
921             {
922                 os_calloc(1, sizeof(OSMatch), config_ruleinfo->hostname);
923                 if(!OSMatch_Compile(hostname, config_ruleinfo->hostname,0))
924                 {
925                     merror(REGEX_COMPILE, __local_name, hostname,
926                             config_ruleinfo->hostname->error);
927                     return(-1);
928                 }
929                 free(hostname);
930                 hostname = NULL;
931             }
932
933
934             /* Adding extra data */
935             if(extra_data)
936             {
937                 os_calloc(1, sizeof(OSMatch), config_ruleinfo->extra_data);
938                 if(!OSMatch_Compile(extra_data,
939                             config_ruleinfo->extra_data, 0))
940                 {
941                     merror(REGEX_COMPILE, __local_name, extra_data,
942                             config_ruleinfo->extra_data->error);
943                     return(-1);
944                 }
945                 free(extra_data);
946                 extra_data = NULL;
947             }
948
949
950             /* Adding in program name */
951             if(program_name)
952             {
953                 os_calloc(1,sizeof(OSMatch),config_ruleinfo->program_name);
954                 if(!OSMatch_Compile(program_name,
955                             config_ruleinfo->program_name,0))
956                 {
957                     merror(REGEX_COMPILE, __local_name, program_name,
958                             config_ruleinfo->program_name->error);
959                     return(-1);
960                 }
961                 free(program_name);
962                 program_name = NULL;
963             }
964
965
966             /* Adding in user */
967             if(user)
968             {
969                 os_calloc(1, sizeof(OSMatch), config_ruleinfo->user);
970                 if(!OSMatch_Compile(user, config_ruleinfo->user, 0))
971                 {
972                     merror(REGEX_COMPILE, __local_name, user,
973                             config_ruleinfo->user->error);
974                     return(-1);
975                 }
976                 free(user);
977                 user = NULL;
978             }
979
980
981             /* Adding in url */
982             if(url)
983             {
984                 os_calloc(1, sizeof(OSMatch), config_ruleinfo->url);
985                 if(!OSMatch_Compile(url, config_ruleinfo->url, 0))
986                 {
987                     merror(REGEX_COMPILE, __local_name, url,
988                             config_ruleinfo->url->error);
989                     return(-1);
990                 }
991                 free(url);
992                 url = NULL;
993             }
994
995
996             /* Adding matched_group */
997             if(if_matched_group)
998             {
999                 os_calloc(1,sizeof(OSMatch),config_ruleinfo->if_matched_group);
1000
1001                 if(!OSMatch_Compile(if_matched_group,
1002                             config_ruleinfo->if_matched_group,0))
1003                 {
1004                     merror(REGEX_COMPILE, __local_name, if_matched_group,
1005                             config_ruleinfo->if_matched_group->error);
1006                     return(-1);
1007                 }
1008                 free(if_matched_group);
1009                 if_matched_group = NULL;
1010             }
1011
1012
1013             /* Adding matched_regex */
1014             if(if_matched_regex)
1015             {
1016                 os_calloc(1, sizeof(OSRegex),
1017                         config_ruleinfo->if_matched_regex);
1018                 if(!OSRegex_Compile(if_matched_regex,
1019                             config_ruleinfo->if_matched_regex, 0))
1020                 {
1021                     merror(REGEX_COMPILE, __local_name, if_matched_regex,
1022                             config_ruleinfo->if_matched_regex->error);
1023                     return(-1);
1024                 }
1025                 free(if_matched_regex);
1026                 if_matched_regex = NULL;
1027             }
1028
1029
1030             /* Calling the function provided. */
1031             ruleact_function(config_ruleinfo, data);
1032
1033             
1034             j++; /* next rule */
1035
1036
1037         } /* while(rule[j]) */
1038         OS_ClearNode(rule);
1039         i++;
1040         
1041     } /* while (node[i]) */
1042
1043     /* Cleaning global node */
1044     OS_ClearNode(node);
1045     OS_ClearXML(&xml);
1046
1047
1048     /* Done over here */
1049     return(0);
1050 }
1051
1052
1053
1054 /** RuleInfo *_OS_AllocateRule()
1055  * Allocates the memory for the rule.
1056  */
1057 RuleInfo *_OS_AllocateRule()
1058 {
1059     RuleInfo *ruleinfo_pt = NULL;
1060     
1061     
1062     /* Allocation memory for structure */
1063     ruleinfo_pt = (RuleInfo *)calloc(1,sizeof(RuleInfo));
1064     if(ruleinfo_pt == NULL)
1065     {
1066         ErrorExit(MEM_ERROR,__local_name);
1067     }
1068     
1069
1070     /* Default values */
1071     ruleinfo_pt->level = -1;
1072
1073     /* Default category is syslog */
1074     ruleinfo_pt->category = SYSLOG;
1075
1076     ruleinfo_pt->ar = NULL; 
1077     
1078     ruleinfo_pt->context = 0;
1079     
1080     /* Default sigid of -1 */
1081     ruleinfo_pt->sigid = -1;
1082     ruleinfo_pt->firedtimes = 0;
1083     ruleinfo_pt->maxsize = 0;
1084     ruleinfo_pt->frequency = 0;
1085     ruleinfo_pt->ignore_time = 0;
1086     ruleinfo_pt->timeframe = 0;
1087     ruleinfo_pt->time_ignored = 0;
1088    
1089     ruleinfo_pt->context_opts = 0; 
1090     ruleinfo_pt->alert_opts = 0; 
1091     ruleinfo_pt->ignore = 0; 
1092     ruleinfo_pt->ckignore = 0; 
1093
1094     ruleinfo_pt->day_time = NULL;
1095     ruleinfo_pt->week_day = NULL;
1096
1097     ruleinfo_pt->group = NULL;
1098     ruleinfo_pt->regex = NULL;
1099     ruleinfo_pt->match = NULL;
1100     ruleinfo_pt->decoded_as = 0;
1101
1102     ruleinfo_pt->comment = NULL;
1103     ruleinfo_pt->info = NULL;
1104     ruleinfo_pt->cve = NULL;
1105     
1106     ruleinfo_pt->if_sid = NULL;
1107     ruleinfo_pt->if_group = NULL;
1108     ruleinfo_pt->if_level = NULL;
1109     
1110     ruleinfo_pt->if_matched_regex = NULL;
1111     ruleinfo_pt->if_matched_group = NULL;
1112     ruleinfo_pt->if_matched_sid = 0;
1113    
1114     ruleinfo_pt->user = NULL; 
1115     ruleinfo_pt->srcip = NULL;
1116     ruleinfo_pt->srcport = NULL;
1117     ruleinfo_pt->dstip = NULL;
1118     ruleinfo_pt->dstport = NULL;
1119     ruleinfo_pt->url = NULL;
1120     ruleinfo_pt->id = NULL;
1121     ruleinfo_pt->status = NULL;
1122     ruleinfo_pt->hostname = NULL;
1123     ruleinfo_pt->program_name = NULL;
1124     ruleinfo_pt->action = NULL;
1125     
1126     /* Zeroing last matched events */
1127     ruleinfo_pt->__frequency = 0;
1128     ruleinfo_pt->last_events = NULL;
1129
1130     /* zeroing the list of previous matches */
1131     ruleinfo_pt->sid_prev_matched = NULL;
1132     ruleinfo_pt->group_prev_matched = NULL;
1133     
1134     ruleinfo_pt->sid_search = NULL;
1135     ruleinfo_pt->group_search = NULL;
1136     
1137     ruleinfo_pt->event_search = NULL;
1138
1139     return(ruleinfo_pt);
1140 }
1141
1142
1143
1144 /** int _OS_GetRulesAttributes
1145  * Reads the rules attributes and assign them.
1146  */
1147 int _OS_GetRulesAttributes(char **attributes, char **values,
1148                            RuleInfo *ruleinfo_pt)
1149 {
1150     int k = 0;
1151     
1152     char *xml_id = "id";
1153     char *xml_level = "level";
1154     char *xml_maxsize = "maxsize";
1155     char *xml_timeframe = "timeframe";
1156     char *xml_frequency = "frequency";
1157     char *xml_accuracy = "accuracy";
1158     char *xml_noalert = "noalert";
1159     char *xml_ignore_time = "ignore";
1160     char *xml_overwrite = "overwrite";
1161     
1162    
1163     /* Getting attributes */
1164     while(attributes[k])
1165     {
1166         if(!values[k])
1167         {
1168             merror(RL_EMPTY_ATTR, __local_name, attributes[k]);
1169             return(-1);
1170         }
1171         /* Getting rule Id */
1172         else if(strcasecmp(attributes[k], xml_id) == 0)
1173         {
1174             if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 6 ))
1175             {
1176                 ruleinfo_pt->sigid = atoi(values[k]);    
1177             }
1178             else
1179             {
1180                 merror(XML_VALUEERR,__local_name, attributes[k], values[k]);
1181                 return(-1);
1182             }
1183         }
1184         /* Getting level */
1185         else if(strcasecmp(attributes[k],xml_level) == 0)
1186         {
1187             if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 3))
1188             {
1189                 ruleinfo_pt->level = atoi(values[k]);
1190             }
1191             else
1192             {
1193                 merror(XML_VALUEERR,__local_name, attributes[k], values[k]);
1194                 return(-1);
1195             }
1196         }
1197         /* Getting maxsize */
1198         else if(strcasecmp(attributes[k],xml_maxsize) == 0)
1199         {
1200             if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 4))
1201             {
1202                 ruleinfo_pt->maxsize = atoi(values[k]);
1203
1204                 /* adding EXTRAINFO options */
1205                 if(ruleinfo_pt->maxsize > 0 && 
1206                    !(ruleinfo_pt->alert_opts & DO_EXTRAINFO))
1207                 {
1208                     ruleinfo_pt->alert_opts |= DO_EXTRAINFO;
1209                 }
1210             }
1211             else
1212             {
1213                 merror(XML_VALUEERR,__local_name, attributes[k], values[k]);
1214                 return(-1);
1215             }
1216         }
1217         /* Getting timeframe */
1218         else if(strcasecmp(attributes[k],xml_timeframe) == 0)
1219         {
1220             if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 5))
1221             {
1222                 ruleinfo_pt->timeframe = atoi(values[k]);
1223             }
1224             else
1225             {
1226                 merror(XML_VALUEERR,__local_name, attributes[k], values[k]);
1227                 return(-1);
1228             }
1229         }
1230         /* Getting frequency */
1231         else if(strcasecmp(attributes[k],xml_frequency) == 0)
1232         {
1233             if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 4))
1234             {
1235                 ruleinfo_pt->frequency = atoi(values[k]);
1236             }
1237             else
1238             {
1239                 merror(XML_VALUEERR,__local_name, attributes[k], values[k]);
1240                 return(-1);
1241             }
1242         }
1243         /* Rule accuracy */
1244         else if(strcasecmp(attributes[k],xml_accuracy) == 0)
1245         {
1246             merror("%s: XXX: Use of 'accuracy' isn't supported. Ignoring.", 
1247                    __local_name);
1248         }
1249          /* Rule ignore_time */
1250         else if(strcasecmp(attributes[k],xml_ignore_time) == 0)
1251         {
1252             if(OS_StrIsNum(values[k]) && (strlen(values[k]) <= 4))
1253             {
1254                 ruleinfo_pt->ignore_time = atoi(values[k]);
1255             }
1256             else
1257             {
1258                 merror(XML_VALUEERR,__local_name, attributes[k], values[k]);
1259                 return(-1); 
1260             }
1261         }
1262         /* Rule noalert */
1263         else if(strcasecmp(attributes[k],xml_noalert) == 0)
1264         {
1265             ruleinfo_pt->alert_opts |= NO_ALERT;
1266         }
1267         else if(strcasecmp(attributes[k], xml_overwrite) == 0)
1268         {
1269             if(strcmp(values[k], "yes") == 0)
1270             {
1271                 ruleinfo_pt->alert_opts |= DO_OVERWRITE;
1272             }
1273             else if(strcmp(values[k], "no") == 0)
1274             {
1275             }
1276             else
1277             {
1278                 merror(XML_VALUEERR,__local_name, attributes[k], values[k]);
1279                 return(-1);
1280             }
1281         }
1282         else
1283         {
1284             merror(XML_INVELEM, __local_name, attributes[k]);
1285             return(-1);
1286         }
1287         k++;
1288     }
1289     return(0);
1290 }
1291
1292
1293
1294 /* print rule */
1295 void OS_PrintRuleinfo(RuleInfo *rule)
1296 {
1297     debug1("%s: __local_name: Print Rule:%d, level %d, ignore: %d, frequency:%d", 
1298             __local_name,
1299             rule->sigid, 
1300             rule->level,
1301             rule->ignore_time,
1302             rule->frequency);
1303 }
1304
1305
1306
1307 /* EOF */