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