new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / lists_list.c
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 3) as published by the FSF - Free Software
7  * Foundation
8  */
9
10 #include "shared.h"
11 #include "rules.h"
12 #include "cdb/cdb.h"
13 #include <fcntl.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17
18 /* Local variables */
19 static ListNode *global_listnode;
20 static ListRule *global_listrule;
21
22
23 /* Create the ListRule */
24 void OS_CreateListsList()
25 {
26     global_listnode = NULL;
27     global_listrule = NULL;
28
29     return;
30 }
31
32 /* Get first listnode  */
33 ListNode *OS_GetFirstList()
34 {
35     ListNode *listnode_pt = global_listnode;
36
37     return (listnode_pt);
38 }
39
40 void OS_ListLoadRules()
41 {
42     ListRule *lrule = global_listrule;
43     while (lrule != NULL) {
44         if (!lrule->loaded) {
45             lrule->db = OS_FindList(lrule->filename);
46             lrule->loaded = 1;
47         }
48         lrule = lrule->next;
49     }
50 }
51
52 /* External AddList */
53 int OS_AddList(ListNode *new_listnode)
54 {
55     if (global_listnode == NULL) {
56         /* First list */
57         global_listnode = new_listnode;
58     } else {
59         /* Add new list to the end */
60         ListNode *last_list_node = global_listnode;
61
62         while (last_list_node->next != NULL) {
63             last_list_node = last_list_node->next;
64         }
65         last_list_node->next = new_listnode;
66
67     }
68     return 0;
69 }
70
71 ListNode *OS_FindList(const char *listname)
72 {
73     ListNode *last_list_node = OS_GetFirstList();
74     if (last_list_node != NULL) {
75         do {
76             if (strcmp(last_list_node->txt_filename, listname) == 0 ||
77                     strcmp(last_list_node->cdb_filename, listname) == 0) {
78                 /* Found first match returning */
79                 return (last_list_node);
80             }
81             last_list_node = last_list_node->next;
82         } while (last_list_node != NULL);
83     }
84     return (NULL);
85 }
86
87 ListRule *OS_AddListRule(ListRule *first_rule_list,
88                          int lookup_type,
89                          int field,
90                          char *listname,
91                          OSMatch *matcher)
92 {
93     ListRule *new_rulelist_pt = NULL;
94     new_rulelist_pt = (ListRule *)calloc(1, sizeof(ListRule));
95     if (!new_rulelist_pt) {
96         return (NULL);
97     }
98
99     new_rulelist_pt->field = field;
100     new_rulelist_pt->next = NULL;
101     new_rulelist_pt->matcher = matcher;
102     new_rulelist_pt->lookup_type = lookup_type;
103     new_rulelist_pt->filename = listname;
104     if ((new_rulelist_pt->db = OS_FindList(listname)) == NULL) {
105         new_rulelist_pt->loaded = 0;
106     } else {
107         new_rulelist_pt->loaded = 1;
108     }
109     if (first_rule_list == NULL) {
110         debug1("Adding First rulelist item: filename: %s field: %d lookup_type: %d",
111                new_rulelist_pt->filename,
112                new_rulelist_pt->field,
113                new_rulelist_pt->lookup_type);
114         first_rule_list = new_rulelist_pt;
115     } else {
116         while (first_rule_list->next) {
117             first_rule_list = first_rule_list->next;
118         }
119         debug1("Adding rulelist item: filename: %s field: %d lookup_type: %d",
120                new_rulelist_pt->filename,
121                new_rulelist_pt->field,
122                new_rulelist_pt->lookup_type);
123         first_rule_list->next = new_rulelist_pt;
124     }
125     return first_rule_list;
126 }
127
128 static int _OS_CDBOpen(ListNode *lnode)
129 {
130     int fd;
131     if (lnode->loaded != 1) {
132         if ((fd = open(lnode->cdb_filename, O_RDONLY)) == -1) {
133             merror(OPEN_ERROR, ARGV0, lnode->cdb_filename, errno, strerror (errno));
134             return -1;
135         }
136         cdb_init(&lnode->cdb, fd);
137         lnode->loaded = 1;
138     }
139     return 0;
140 }
141
142 static int OS_DBSearchKeyValue(ListRule *lrule, char *key)
143 {
144     int result = -1;
145     char *val;
146     unsigned vlen, vpos;
147     if (lrule->db != NULL) {
148         if (_OS_CDBOpen(lrule->db) == -1) {
149             return 0;
150         }
151         if (cdb_find(&lrule->db->cdb, key, strlen(key)) > 0 ) {
152             vpos = cdb_datapos(&lrule->db->cdb);
153             vlen = cdb_datalen(&lrule->db->cdb);
154             val = (char *) calloc(vlen + 1, sizeof(char));
155             if(val == NULL) {
156                 merror("%s: malloc failed: %s", ARGV0, strerror(errno));
157                 return(0);
158             }
159             cdb_read(&lrule->db->cdb, val, vlen, vpos);
160             result = OSMatch_Execute(val, vlen, lrule->matcher);
161             free(val);
162             return result;
163         } else {
164             return 0;
165         }
166     }
167     return 0;
168 }
169
170 static int OS_DBSeachKey(ListRule *lrule, char *key)
171 {
172     if (lrule->db != NULL) {
173         if (_OS_CDBOpen(lrule->db) == -1) {
174             return -1;
175         }
176         if ( cdb_find(&lrule->db->cdb, key, strlen(key)) > 0 ) {
177             return 1;
178         }
179     }
180     return 0;
181 }
182
183 static int OS_DBSeachKeyAddress(ListRule *lrule, char *key)
184 {
185     if (lrule->db != NULL) {
186         if (_OS_CDBOpen(lrule->db) == -1) {
187             return -1;
188         }
189
190         if ( cdb_find(&lrule->db->cdb, key, strlen(key)) > 0 ) {
191             return 1;
192         } else {
193             char *tmpkey;
194             os_strdup(key, tmpkey);
195             while (strlen(tmpkey) > 0) {
196                 if (tmpkey[strlen(tmpkey) - 1] == '.') {
197                     if ( cdb_find(&lrule->db->cdb, tmpkey, strlen(tmpkey)) > 0 ) {
198                         free(tmpkey);
199                         return 1;
200                     }
201                 }
202                 tmpkey[strlen(tmpkey) - 1] = '\0';
203             }
204             free(tmpkey);
205         }
206     }
207     return 0;
208 }
209
210 static int OS_DBSearchKeyAddressValue(ListRule *lrule, char *key)
211 {
212     int result = -1;
213     char *val;
214     unsigned vlen, vpos;
215     if (lrule->db != NULL) {
216         if (_OS_CDBOpen(lrule->db) == -1) {
217             return 0;
218         }
219
220         /* First lookup for a single IP address */
221         if (cdb_find(&lrule->db->cdb, key, strlen(key)) > 0 ) {
222             vpos = cdb_datapos(&lrule->db->cdb);
223             vlen = cdb_datalen(&lrule->db->cdb);
224             val = (char *) malloc(vlen);
225             if(val == NULL) {
226                 merror("%s: malloc failed", ARGV0);
227                 return(0);
228             }
229             cdb_read(&lrule->db->cdb, val, vlen, vpos);
230             result = OSMatch_Execute(val, vlen, lrule->matcher);
231             free(val);
232             return result;
233         } else {
234             /* IP address not found, look for matching subnets */
235             char *tmpkey;
236             os_strdup(key, tmpkey);
237             while (strlen(tmpkey) > 0) {
238                 if (tmpkey[strlen(tmpkey) - 1] == '.') {
239                     if ( cdb_find(&lrule->db->cdb, tmpkey, strlen(tmpkey)) > 0 ) {
240                         vpos = cdb_datapos(&lrule->db->cdb);
241                         vlen = cdb_datalen(&lrule->db->cdb);
242                         val = (char *) malloc(vlen);
243                         cdb_read(&lrule->db->cdb, val, vlen, vpos);
244                         result = OSMatch_Execute(val, vlen, lrule->matcher);
245                         free(val);
246                         free(tmpkey);
247                         return result;
248                     }
249                 }
250                 tmpkey[strlen(tmpkey) - 1] = '\0';
251             }
252             free(tmpkey);
253             return 0;
254         }
255     }
256     return 0;
257 }
258
259 int OS_DBSearch(ListRule *lrule, char *key)
260 {
261     //XXX - god damn hack!!! Jeremy Rossi
262     if (lrule->loaded == 0) {
263         lrule->db = OS_FindList(lrule->filename);
264         lrule->loaded = 1;
265     }
266     switch (lrule->lookup_type) {
267         case LR_STRING_MATCH:
268             //debug1("LR_STRING_MATCH");
269             if (OS_DBSeachKey(lrule, key) == 1) {
270                 return 1;
271             }
272             return 0;
273         case LR_STRING_NOT_MATCH:
274             //debug1("LR_STRING_NOT_MATCH");
275             if (OS_DBSeachKey(lrule, key) == 1) {
276                 return 0;
277             }
278             return 1;
279         case LR_STRING_MATCH_VALUE:
280             //debug1("LR_STRING_MATCH_VALUE");
281             if (OS_DBSearchKeyValue(lrule, key) == 1) {
282                 return 1;
283             }
284             return 0;
285         case LR_ADDRESS_MATCH:
286             //debug1("LR_ADDRESS_MATCH");
287             return OS_DBSeachKeyAddress(lrule, key);
288         case LR_ADDRESS_NOT_MATCH:
289             //debug1("LR_ADDRESS_NOT_MATCH");
290             if (OS_DBSeachKeyAddress(lrule, key) == 0) {
291                 return 1;
292             }
293             return 0;
294         case LR_ADDRESS_MATCH_VALUE:
295             //debug1("LR_ADDRESS_MATCH_VALUE");
296             if (OS_DBSearchKeyAddressValue(lrule, key) == 0) {
297                 return 1;
298             }
299             return 0;
300         default:
301             debug1("lists_list.c::OS_DBSearch should never hit default");
302             return 0;
303     }
304 }