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