1 /* Copyright (C) 2009 Trend Micro Inc.
2 * All right reserved.
3 *
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
7 * Foundation
8 */
9
10 #include "shared.h"
11 #include "rules.h"
12
13 /* Rulenode local */
14 static RuleNode *rulenode;
15
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);
20
21
22 /* Create the RuleList */
OS_CreateRuleList()23 void OS_CreateRuleList()
24 {
25 rulenode = NULL;
26 return;
27 }
28
29 /* Get first node from rule */
OS_GetFirstRule()30 RuleNode *OS_GetFirstRule()
31 {
32 RuleNode *rulenode_pt = rulenode;
33 return (rulenode_pt);
34 }
35
36 /* Search all rules, including children */
_AddtoRule(int sid,int level,int none,const char * group,RuleNode * r_node,RuleInfo * read_rule)37 static int _AddtoRule(int sid, int level, int none, const char *group,
38 RuleNode *r_node, RuleInfo *read_rule)
39 {
40 int r_code = 0;
41
42 /* If we don't have the first node, start from
43 * the beginning of the list
44 */
45 if (!r_node) {
46 r_node = OS_GetFirstRule();
47 }
48
49 while (r_node) {
50 /* Check if the sigid matches */
51 if (sid) {
52 if (r_node->ruleinfo->sigid == sid) {
53 /* Assign the category of this rule to the child
54 * as they must match
55 */
56 read_rule->category = r_node->ruleinfo->category;
57
58 /* If no context for rule, check if the parent has context
59 * and use that
60 */
61 if (!read_rule->last_events && r_node->ruleinfo->last_events) {
62 read_rule->last_events = r_node->ruleinfo->last_events;
63 }
64
65 r_node->child =
66 _OS_AddRule(r_node->child, read_rule);
67 return (1);
68 }
69 }
70
71 /* Check if the group matches */
72 else if (group) {
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
76 * and use that
77 */
78 if (!read_rule->last_events && r_node->ruleinfo->last_events) {
79 read_rule->last_events = r_node->ruleinfo->last_events;
80 }
81
82 /* Loop over all rules until we find it */
83 r_node->child =
84 _OS_AddRule(r_node->child, read_rule);
85 r_code = 1;
86 }
87 }
88
89 /* Check if the level matches */
90 else if (level) {
91 if ((r_node->ruleinfo->level >= level) &&
92 (r_node->ruleinfo->sigid != read_rule->sigid)) {
93 r_node->child =
94 _OS_AddRule(r_node->child, read_rule);
95 r_code = 1;
96 }
97 }
98
99 /* If we are not searching for the sid/group, the category must
100 * be the same
101 */
102 else if (read_rule->category != r_node->ruleinfo->category) {
103 r_node = r_node->next;
104 continue;
105 }
106
107 /* If none of them are set, add for the category */
108 else {
109 /* Set the parent category to it */
110 read_rule->category = r_node->ruleinfo->category;
111 r_node->child =
112 _OS_AddRule(r_node->child, read_rule);
113 return (1);
114 }
115
116 /* Check if the child has a rule */
117 if (r_node->child) {
118 if (_AddtoRule(sid, level, none, group, r_node->child, read_rule)) {
119 r_code = 1;
120 }
121 }
122
123 r_node = r_node->next;
124 }
125
126 return (r_code);
127 }
128
129 /* Add a child */
OS_AddChild(RuleInfo * read_rule)130 int OS_AddChild(RuleInfo *read_rule)
131 {
132 if (!read_rule) {
133 merror("rules_list: Passing a NULL rule. Inconsistent state");
134 return (1);
135 }
136
137 /* Adding for if_sid */
138 if (read_rule->if_sid) {
139 int val = 0;
140 const char *sid;
141
142 sid = read_rule->if_sid;
143
144 /* Loop to read all the rules (comma or space separated) */
145 do {
146 int rule_id = 0;
147 if ((*sid == ',') || (*sid == ' ')) {
148 val = 0;
149 continue;
150 } else if ((isdigit((int)*sid)) || (*sid == '\0')) {
151 if (val == 0) {
152 rule_id = atoi(sid);
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);
156 }
157 val = 1;
158 }
159 } else {
160 ErrorExit("rules_list: Signature ID must be an integer. "
161 "Exiting...");
162 }
163 } while (*sid++ != '\0');
164 }
165
166 /* Adding for if_level */
167 else if (read_rule->if_level) {
168 int ilevel = 0;
169
170 ilevel = atoi(read_rule->if_level);
171 if (ilevel == 0) {
172 merror("%s: Invalid level (atoi)", ARGV0);
173 return (1);
174 }
175
176 ilevel *= 100;
177
178 if (!_AddtoRule(0, ilevel, 0, NULL, NULL, read_rule)) {
179 ErrorExit("rules_list: Level ID '%d' not "
180 "found. Invalid 'if_level'.", ilevel);
181 }
182 }
183
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);
189 }
190 }
191
192 /* Just add based on the category */
193 else {
194 if (!_AddtoRule(0, 0, 0, NULL, NULL, read_rule)) {
195 ErrorExit("rules_list: Category '%d' not "
196 "found. Invalid 'category'.", read_rule->category);
197 }
198 }
199
200 /* done over here */
201 return (0);
202 }
203
204 /* Add a rule in the chain */
_OS_AddRule(RuleNode * _rulenode,RuleInfo * read_rule)205 static RuleNode *_OS_AddRule(RuleNode *_rulenode, RuleInfo *read_rule)
206 {
207 RuleNode *tmp_rulenode = _rulenode;
208
209 if (tmp_rulenode != NULL) {
210 int middle_insertion = 0;
211 RuleNode *prev_rulenode = NULL;
212 RuleNode *new_rulenode = NULL;
213
214 while (tmp_rulenode != NULL) {
215 if (read_rule->level > tmp_rulenode->ruleinfo->level) {
216 middle_insertion = 1;
217 break;
218 }
219 prev_rulenode = tmp_rulenode;
220 tmp_rulenode = tmp_rulenode->next;
221 }
222
223 new_rulenode = (RuleNode *)calloc(1, sizeof(RuleNode));
224
225 if (!new_rulenode) {
226 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
227 }
228
229 if (middle_insertion == 1) {
230 if (prev_rulenode == NULL) {
231 _rulenode = new_rulenode;
232 } else {
233 prev_rulenode->next = new_rulenode;
234 }
235
236 new_rulenode->next = tmp_rulenode;
237 new_rulenode->ruleinfo = read_rule;
238 new_rulenode->child = NULL;
239 } else {
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;
244 }
245 } else {
246 _rulenode = (RuleNode *)calloc(1, sizeof(RuleNode));
247 if (_rulenode == NULL) {
248 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
249 }
250
251 _rulenode->ruleinfo = read_rule;
252 _rulenode->next = NULL;
253 _rulenode->child = NULL;
254 }
255
256 return (_rulenode);
257 }
258
259 /* External AddRule */
OS_AddRule(RuleInfo * read_rule)260 int OS_AddRule(RuleInfo *read_rule)
261 {
262 rulenode = _OS_AddRule(rulenode, read_rule);
263
264 return (0);
265 }
266
267 /* Update rule info for overwritten ones */
OS_AddRuleInfo(RuleNode * r_node,RuleInfo * newrule,int sid)268 int OS_AddRuleInfo(RuleNode *r_node, RuleInfo *newrule, int sid)
269 {
270 /* If no r_node is given, get first node */
271 if (r_node == NULL) {
272 r_node = OS_GetFirstRule();
273 }
274
275 if (sid == 0) {
276 return (0);
277 }
278
279 while (r_node) {
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;
287
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;
319 }
320
321 return (1);
322 }
323
324
325 /* Check if the child has a rule */
326 if (r_node->child) {
327 if (OS_AddRuleInfo(r_node->child, newrule, sid)) {
328 return (1);
329 }
330 }
331
332 r_node = r_node->next;
333 }
334
335 return (0);
336 }
337
338 /* Mark rules that match specific id (for if_matched_sid) */
OS_MarkID(RuleNode * r_node,RuleInfo * orig_rule)339 int OS_MarkID(RuleNode *r_node, RuleInfo *orig_rule)
340 {
341 /* If no r_node is given, get first node */
342 if (r_node == NULL) {
343 r_node = OS_GetFirstRule();
344 }
345
346 while (r_node) {
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));
353 }
354 }
355
356 /* Assign the parent pointer to it */
357 orig_rule->sid_search = r_node->ruleinfo->sid_prev_matched;
358 }
359
360 /* Check if the child has a rule */
361 if (r_node->child) {
362 OS_MarkID(r_node->child, orig_rule);
363 }
364
365 r_node = r_node->next;
366 }
367
368 return (0);
369 }
370
371 /* Mark rules that match specific group (for if_matched_group) */
OS_MarkGroup(RuleNode * r_node,RuleInfo * orig_rule)372 int OS_MarkGroup(RuleNode *r_node, RuleInfo *orig_rule)
373 {
374 /* If no r_node is given, get first node */
375 if (r_node == NULL) {
376 r_node = OS_GetFirstRule();
377 }
378
379 while (r_node) {
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]) {
386 rule_g++;
387 }
388 }
389
390 os_realloc(r_node->ruleinfo->group_prev_matched,
391 (rule_g + 2)*sizeof(OSList *),
392 r_node->ruleinfo->group_prev_matched);
393
394 r_node->ruleinfo->group_prev_matched[rule_g] = NULL;
395 r_node->ruleinfo->group_prev_matched[rule_g + 1] = NULL;
396
397 /* Set the size */
398 r_node->ruleinfo->group_prev_matched_sz = rule_g + 1;
399
400 r_node->ruleinfo->group_prev_matched[rule_g] =
401 orig_rule->group_search;
402 }
403
404 /* Check if the child has a rule */
405 if (r_node->child) {
406 OS_MarkGroup(r_node->child, orig_rule);
407 }
408
409 r_node = r_node->next;
410 }
411
412 return (0);
413 }
414
415