new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / os_dbd / rules.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All rights 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 "dbd.h"
11 #include "config/config.h"
12 #include "rules_op.h"
13
14 /* Prototypes */
15 static int __Groups_SelectGroup(const char *group, const DBConfig *db_config) __attribute((nonnull));
16 static int __Groups_InsertGroup(const char *group, const DBConfig *db_config) __attribute((nonnull));
17 static int __Groups_SelectGroupMapping(int cat_id, int rule_id, const DBConfig *db_config) __attribute((nonnull));
18 static int __Groups_InsertGroupMapping(int cat_id, int rule_id, const DBConfig *db_config) __attribute((nonnull));
19 static void _Groups_ReadInsertDB(RuleInfo *rule, const DBConfig *db_config) __attribute((nonnull));
20 static void *_Rules_ReadInsertDB(RuleInfo *rule, void *db_config) __attribute((nonnull));
21
22
23 /* Select group (categories) from the db
24  * Returns 0 if not found
25  */
26 static int __Groups_SelectGroup(const char *group, const DBConfig *db_config)
27 {
28     int result = 0;
29     char sql_query[OS_SIZE_1024];
30
31     memset(sql_query, '\0', OS_SIZE_1024);
32
33     /* Generate SQL */
34     snprintf(sql_query, OS_SIZE_1024 - 1,
35              "SELECT cat_id FROM "
36              "category WHERE cat_name = '%s'",
37              group);
38
39     result = osdb_query_select(db_config->conn, sql_query);
40
41     return (result);
42 }
43
44 /* Insert group (categories) in to the db */
45 static int __Groups_InsertGroup(const char *group, const DBConfig *db_config)
46 {
47     char sql_query[OS_SIZE_1024];
48
49     memset(sql_query, '\0', OS_SIZE_1024);
50
51     /* Generate SQL */
52     snprintf(sql_query, OS_SIZE_1024 - 1,
53              "INSERT INTO "
54              "category(cat_name) "
55              "VALUES ('%s')",
56              group);
57
58     if (!osdb_query_insert(db_config->conn, sql_query)) {
59         merror(DB_GENERROR, ARGV0);
60     }
61
62     return (0);
63 }
64
65 static int __Groups_SelectGroupMapping(int cat_id, int rule_id, const DBConfig *db_config)
66 {
67     int result = 0;
68     char sql_query[OS_SIZE_1024];
69
70     memset(sql_query, '\0', OS_SIZE_1024);
71
72     /* Generate SQL */
73     snprintf(sql_query, OS_SIZE_1024 - 1,
74              "SELECT id FROM signature_category_mapping "
75              "WHERE cat_id = '%u' AND rule_id = '%u'",
76              cat_id, rule_id);
77
78     result = osdb_query_select(db_config->conn, sql_query);
79
80     return (result);
81 }
82
83 static int __Groups_InsertGroupMapping(int cat_id, int rule_id, const DBConfig *db_config)
84 {
85     char sql_query[OS_SIZE_1024];
86
87     memset(sql_query, '\0', OS_SIZE_1024);
88
89     /* Generate SQL */
90     snprintf(sql_query, OS_SIZE_1024 - 1,
91              "INSERT INTO "
92              "signature_category_mapping(cat_id, rule_id) "
93              "VALUES ('%u', '%u')",
94              cat_id, rule_id);
95
96     if (!osdb_query_insert(db_config->conn, sql_query)) {
97         merror(DB_GENERROR, ARGV0);
98     }
99
100     return (0);
101 }
102
103 static void _Groups_ReadInsertDB(RuleInfo *rule, const DBConfig *db_config)
104 {
105     /* We must insert each group separately */
106     int cat_id;
107     char *tmp_group;
108     char *tmp_str;
109
110     debug1("%s: DEBUG: entering _Groups_ReadInsertDB", ARGV0);
111
112     /* If group is null, just return */
113     if (rule->group == NULL) {
114         return;
115     }
116
117     tmp_str = strchr(rule->group, ',');
118     tmp_group = rule->group;
119
120     /* Groups are separated by comma */
121     while (tmp_group) {
122         if (tmp_str) {
123             *tmp_str = '\0';
124             tmp_str++;
125         }
126
127         /* Remove whitespace */
128         while (*tmp_group == ' ') {
129             tmp_group++;
130         }
131
132         /* Check for empty group */
133         if (*tmp_group == '\0') {
134             tmp_group = tmp_str;
135             if (tmp_group) {
136                 tmp_str = strchr(tmp_group, ',');
137             }
138             continue;
139         }
140
141         cat_id = __Groups_SelectGroup(tmp_group, db_config);
142
143         /* Check if we have this group in the db already. If not, add it. */
144         if (cat_id == 0) {
145             __Groups_InsertGroup(tmp_group, db_config);
146             cat_id = __Groups_SelectGroup(tmp_group, db_config);
147         }
148
149         /* If cat_id is valid (not zero), insert the mapping between
150          * the category and the rule
151          */
152         if (cat_id != 0) {
153             /* First check if the mapping is not already there */
154             if (!__Groups_SelectGroupMapping(cat_id, rule->sigid, db_config)) {
155                 /* If not, we add it */
156                 __Groups_InsertGroupMapping(cat_id, rule->sigid, db_config);
157             }
158         }
159
160         /* Get next category */
161         tmp_group = tmp_str;
162         if (tmp_group) {
163             tmp_str = strchr(tmp_group, ',');
164         }
165     }
166
167     return;
168 }
169
170 /* Insert rules in to the db */
171 static void *_Rules_ReadInsertDB(RuleInfo *rule, void *db_config)
172 {
173     char sql_query[OS_SIZE_1024];
174     memset(sql_query, '\0', OS_SIZE_1024);
175
176     /* Escape strings */
177     osdb_escapestr(rule->group);
178     osdb_escapestr(rule->comment);
179
180     /* Check level limit */
181     if (rule->level > 20) {
182         rule->level = 20;
183     }
184     if (rule->level < 0) {
185         rule->level = 0;
186     }
187
188     debug1("%s: DEBUG: entering _Rules_ReadInsertDB()", ARGV0);
189
190     /* Check rule limit */
191     if (rule->sigid < 0 || rule->sigid > 9999999) {
192         merror("%s: Invalid rule id: %u", ARGV0, rule->sigid);
193         return (NULL);
194     }
195
196     /* Insert group into the signature mapping */
197     _Groups_ReadInsertDB(rule, (DBConfig *) db_config);
198
199     debug2("%s: DEBUG: Inserting: %d", ARGV0, rule->sigid);
200
201     /* Generate SQL */
202     snprintf(sql_query, OS_SIZE_1024 - 1,
203              "REPLACE INTO "
204              "signature(rule_id, level, description) "
205              "VALUES ('%u','%u','%s')",
206              rule->sigid, rule->level,
207              rule->comment != NULL ? rule->comment : "NULL");
208
209     /* XXX We don't actually insert!?
210     if(!osdb_query_insert(dbc->conn, sql_query))
211     {
212         merror(DB_GENERROR, ARGV0);
213     }
214     */
215
216     return (NULL);
217 }
218
219 int OS_InsertRulesDB(DBConfig *db_config)
220 {
221     char **rulesfiles;
222
223     rulesfiles = db_config->includes;
224     while (rulesfiles && *rulesfiles) {
225         debug1("%s: Reading rules file: '%s'", ARGV0, *rulesfiles);
226
227         if (OS_ReadXMLRules(*rulesfiles, _Rules_ReadInsertDB, db_config) < 0) {
228             merror(RULES_ERROR, ARGV0, *rulesfiles);
229             return (-1);
230         }
231
232         free(*rulesfiles);
233         rulesfiles++;
234     }
235
236     free(db_config->includes);
237     db_config->includes = NULL;
238
239
240     return (0);
241 }
242