1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
14 static RuleNode *rulenode;
16 /* _OS_Addrule: Internal AddRule */
17 static RuleNode *_OS_AddRule(RuleNode *_rulenode, RuleInfo *read_rule);
18 static int _AddtoRule(int sid, int level, int none, const char *group,
19 RuleNode *r_node, RuleInfo *read_rule);
22 /* Create the RuleList */
23 void OS_CreateRuleList()
29 /* Get first node from rule */
30 RuleNode *OS_GetFirstRule()
32 RuleNode *rulenode_pt = rulenode;
36 /* Search all rules, including children */
37 static int _AddtoRule(int sid, int level, int none, const char *group,
38 RuleNode *r_node, RuleInfo *read_rule)
42 /* If we don't have the first node, start from
43 * the beginning of the list
46 r_node = OS_GetFirstRule();
50 /* Check if the sigid matches */
52 if (r_node->ruleinfo->sigid == sid) {
53 /* Assign the category of this rule to the child
56 read_rule->category = r_node->ruleinfo->category;
58 /* If no context for rule, check if the parent has context
61 if (!read_rule->last_events && r_node->ruleinfo->last_events) {
62 read_rule->last_events = r_node->ruleinfo->last_events;
66 _OS_AddRule(r_node->child, read_rule);
71 /* Check if the group matches */
73 if (OS_WordMatch(group, r_node->ruleinfo->group) &&
74 (r_node->ruleinfo->sigid != read_rule->sigid)) {
75 /* If no context for rule, check if the parent has context
78 if (!read_rule->last_events && r_node->ruleinfo->last_events) {
79 read_rule->last_events = r_node->ruleinfo->last_events;
82 /* Loop over all rules until we find it */
84 _OS_AddRule(r_node->child, read_rule);
89 /* Check if the level matches */
91 if ((r_node->ruleinfo->level >= level) &&
92 (r_node->ruleinfo->sigid != read_rule->sigid)) {
94 _OS_AddRule(r_node->child, read_rule);
99 /* If we are not searching for the sid/group, the category must
102 else if (read_rule->category != r_node->ruleinfo->category) {
103 r_node = r_node->next;
107 /* If none of them are set, add for the category */
109 /* Set the parent category to it */
110 read_rule->category = r_node->ruleinfo->category;
112 _OS_AddRule(r_node->child, read_rule);
116 /* Check if the child has a rule */
118 if (_AddtoRule(sid, level, none, group, r_node->child, read_rule)) {
123 r_node = r_node->next;
130 int OS_AddChild(RuleInfo *read_rule)
133 merror("rules_list: Passing a NULL rule. Inconsistent state");
137 /* Adding for if_sid */
138 if (read_rule->if_sid) {
142 sid = read_rule->if_sid;
144 /* Loop to read all the rules (comma or space separated) */
147 if ((*sid == ',') || (*sid == ' ')) {
150 } else if ((isdigit((int)*sid)) || (*sid == '\0')) {
153 if (!_AddtoRule(rule_id, 0, 0, NULL, NULL, read_rule)) {
154 ErrorExit("rules_list: Signature ID '%d' not "
155 "found. Invalid 'if_sid'.", rule_id);
160 ErrorExit("rules_list: Signature ID must be an integer. "
163 } while (*sid++ != '\0');
166 /* Adding for if_level */
167 else if (read_rule->if_level) {
170 ilevel = atoi(read_rule->if_level);
172 merror("%s: Invalid level (atoi)", ARGV0);
178 if (!_AddtoRule(0, ilevel, 0, NULL, NULL, read_rule)) {
179 ErrorExit("rules_list: Level ID '%d' not "
180 "found. Invalid 'if_level'.", ilevel);
184 /* Adding for if_group */
185 else if (read_rule->if_group) {
186 if (!_AddtoRule(0, 0, 0, read_rule->if_group, NULL, read_rule)) {
187 ErrorExit("rules_list: Group '%s' not "
188 "found. Invalid 'if_group'.", read_rule->if_group);
192 /* Just add based on the category */
194 if (!_AddtoRule(0, 0, 0, NULL, NULL, read_rule)) {
195 ErrorExit("rules_list: Category '%d' not "
196 "found. Invalid 'category'.", read_rule->category);
204 /* Add a rule in the chain */
205 static RuleNode *_OS_AddRule(RuleNode *_rulenode, RuleInfo *read_rule)
207 RuleNode *tmp_rulenode = _rulenode;
209 if (tmp_rulenode != NULL) {
210 int middle_insertion = 0;
211 RuleNode *prev_rulenode = NULL;
212 RuleNode *new_rulenode = NULL;
214 while (tmp_rulenode != NULL) {
215 if (read_rule->level > tmp_rulenode->ruleinfo->level) {
216 middle_insertion = 1;
219 prev_rulenode = tmp_rulenode;
220 tmp_rulenode = tmp_rulenode->next;
223 new_rulenode = (RuleNode *)calloc(1, sizeof(RuleNode));
226 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
229 if (middle_insertion == 1) {
230 if (prev_rulenode == NULL) {
231 _rulenode = new_rulenode;
233 prev_rulenode->next = new_rulenode;
236 new_rulenode->next = tmp_rulenode;
237 new_rulenode->ruleinfo = read_rule;
238 new_rulenode->child = NULL;
240 prev_rulenode->next = new_rulenode;
241 prev_rulenode->next->ruleinfo = read_rule;
242 prev_rulenode->next->next = NULL;
243 prev_rulenode->next->child = NULL;
246 _rulenode = (RuleNode *)calloc(1, sizeof(RuleNode));
247 if (_rulenode == NULL) {
248 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
251 _rulenode->ruleinfo = read_rule;
252 _rulenode->next = NULL;
253 _rulenode->child = NULL;
259 /* External AddRule */
260 int OS_AddRule(RuleInfo *read_rule)
262 rulenode = _OS_AddRule(rulenode, read_rule);
267 /* Update rule info for overwritten ones */
268 int OS_AddRuleInfo(RuleNode *r_node, RuleInfo *newrule, int sid)
270 /* If no r_node is given, get first node */
271 if (r_node == NULL) {
272 r_node = OS_GetFirstRule();
280 /* Check if the sigid matches */
281 if (r_node->ruleinfo->sigid == sid) {
282 r_node->ruleinfo->level = newrule->level;
283 r_node->ruleinfo->maxsize = newrule->maxsize;
284 r_node->ruleinfo->frequency = newrule->frequency;
285 r_node->ruleinfo->timeframe = newrule->timeframe;
286 r_node->ruleinfo->ignore_time = newrule->ignore_time;
288 r_node->ruleinfo->group = newrule->group;
289 r_node->ruleinfo->match = newrule->match;
290 r_node->ruleinfo->regex = newrule->regex;
291 r_node->ruleinfo->day_time = newrule->day_time;
292 r_node->ruleinfo->week_day = newrule->week_day;
293 r_node->ruleinfo->srcip = newrule->srcip;
294 r_node->ruleinfo->dstip = newrule->dstip;
295 r_node->ruleinfo->srcport = newrule->srcport;
296 r_node->ruleinfo->dstport = newrule->dstport;
297 r_node->ruleinfo->user = newrule->user;
298 r_node->ruleinfo->url = newrule->url;
299 r_node->ruleinfo->id = newrule->id;
300 r_node->ruleinfo->status = newrule->status;
301 r_node->ruleinfo->hostname = newrule->hostname;
302 r_node->ruleinfo->program_name = newrule->program_name;
303 r_node->ruleinfo->extra_data = newrule->extra_data;
304 r_node->ruleinfo->action = newrule->action;
305 r_node->ruleinfo->comment = newrule->comment;
306 r_node->ruleinfo->info = newrule->info;
307 r_node->ruleinfo->cve = newrule->cve;
308 r_node->ruleinfo->if_matched_regex = newrule->if_matched_regex;
309 r_node->ruleinfo->if_matched_group = newrule->if_matched_group;
310 r_node->ruleinfo->if_matched_sid = newrule->if_matched_sid;
311 r_node->ruleinfo->alert_opts = newrule->alert_opts;
312 r_node->ruleinfo->context_opts = newrule->context_opts;
313 r_node->ruleinfo->context = newrule->context;
314 r_node->ruleinfo->decoded_as = newrule->decoded_as;
315 r_node->ruleinfo->ar = newrule->ar;
316 r_node->ruleinfo->compiled_rule = newrule->compiled_rule;
317 if ((newrule->context_opts & SAME_DODIFF) && r_node->ruleinfo->last_events == NULL) {
318 r_node->ruleinfo->last_events = newrule->last_events;
325 /* Check if the child has a rule */
327 if (OS_AddRuleInfo(r_node->child, newrule, sid)) {
332 r_node = r_node->next;
338 /* Mark rules that match specific id (for if_matched_sid) */
339 int OS_MarkID(RuleNode *r_node, RuleInfo *orig_rule)
341 /* If no r_node is given, get first node */
342 if (r_node == NULL) {
343 r_node = OS_GetFirstRule();
347 if (r_node->ruleinfo->sigid == orig_rule->if_matched_sid) {
348 /* If child does not have a list, create one */
349 if (!r_node->ruleinfo->sid_prev_matched) {
350 r_node->ruleinfo->sid_prev_matched = OSList_Create();
351 if (!r_node->ruleinfo->sid_prev_matched) {
352 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
356 /* Assign the parent pointer to it */
357 orig_rule->sid_search = r_node->ruleinfo->sid_prev_matched;
360 /* Check if the child has a rule */
362 OS_MarkID(r_node->child, orig_rule);
365 r_node = r_node->next;
371 /* Mark rules that match specific group (for if_matched_group) */
372 int OS_MarkGroup(RuleNode *r_node, RuleInfo *orig_rule)
374 /* If no r_node is given, get first node */
375 if (r_node == NULL) {
376 r_node = OS_GetFirstRule();
380 if (OSMatch_Execute(r_node->ruleinfo->group,
381 strlen(r_node->ruleinfo->group),
382 orig_rule->if_matched_group)) {
383 unsigned int rule_g = 0;
384 if (r_node->ruleinfo->group_prev_matched) {
385 while (r_node->ruleinfo->group_prev_matched[rule_g]) {
390 os_realloc(r_node->ruleinfo->group_prev_matched,
391 (rule_g + 2)*sizeof(OSList *),
392 r_node->ruleinfo->group_prev_matched);
394 r_node->ruleinfo->group_prev_matched[rule_g] = NULL;
395 r_node->ruleinfo->group_prev_matched[rule_g + 1] = NULL;
398 r_node->ruleinfo->group_prev_matched_sz = rule_g + 1;
400 r_node->ruleinfo->group_prev_matched[rule_g] =
401 orig_rule->group_search;
404 /* Check if the child has a rule */
406 OS_MarkGroup(r_node->child, orig_rule);
409 r_node = r_node->next;