new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / fts.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 /* First time seen functions */
11
12 #include "fts.h"
13 #include "eventinfo.h"
14
15 /* Local variables */
16 static unsigned int fts_minsize_for_str = 0;
17
18 static OSList *fts_list = NULL;
19 static OSHash *fts_store = NULL;
20
21 static FILE *fp_list = NULL;
22 static FILE *fp_ignore = NULL;
23
24
25 /* Start the FTS module */
26 int FTS_Init()
27 {
28     int fts_list_size;
29     char _line[OS_FLSIZE + 1];
30
31     _line[OS_FLSIZE] = '\0';
32
33     fts_list = OSList_Create();
34     if (!fts_list) {
35         merror(LIST_ERROR, ARGV0);
36         return (0);
37     }
38
39     /* Create store data */
40     fts_store = OSHash_Create();
41     if (!fts_store) {
42         merror(LIST_ERROR, ARGV0);
43         return (0);
44     }
45     if (!OSHash_setSize(fts_store, 2048)) {
46         merror(LIST_ERROR, ARGV0);
47         return (0);
48     }
49
50     /* Get default list size */
51     fts_list_size = getDefine_Int("analysisd",
52                                   "fts_list_size",
53                                   12, 512);
54
55     /* Get minimum string size */
56     fts_minsize_for_str = (unsigned int) getDefine_Int("analysisd",
57                           "fts_min_size_for_str",
58                           6, 128);
59
60     if (!OSList_SetMaxSize(fts_list, fts_list_size)) {
61         merror(LIST_SIZE_ERROR, ARGV0);
62         return (0);
63     }
64
65     /* Create fts list */
66     fp_list = fopen(FTS_QUEUE, "r+");
67     if (!fp_list) {
68         /* Create the file if we cant open it */
69         fp_list = fopen(FTS_QUEUE, "w+");
70         if (fp_list) {
71             fclose(fp_list);
72         }
73
74         if (chmod(FTS_QUEUE, 0640) == -1) {
75             merror(CHMOD_ERROR, ARGV0, FTS_QUEUE, errno, strerror(errno));
76             return 0;
77         }
78
79         uid_t uid = Privsep_GetUser(USER);
80         gid_t gid = Privsep_GetGroup(GROUPGLOBAL);
81         if (uid != (uid_t) - 1 && gid != (gid_t) - 1) {
82             if (chown(FTS_QUEUE, uid, gid) == -1) {
83                 merror(CHOWN_ERROR, ARGV0, FTS_QUEUE, errno, strerror(errno));
84                 return (0);
85             }
86         }
87
88         fp_list = fopen(FTS_QUEUE, "r+");
89         if (!fp_list) {
90             merror(FOPEN_ERROR, ARGV0, FTS_QUEUE, errno, strerror(errno));
91             return (0);
92         }
93     }
94
95     /* Add content from the files to memory */
96     fseek(fp_list, 0, SEEK_SET);
97     while (fgets(_line, OS_FLSIZE , fp_list) != NULL) {
98         char *tmp_s;
99
100         /* Remove newlines */
101         tmp_s = strchr(_line, '\n');
102         if (tmp_s) {
103             *tmp_s = '\0';
104         }
105
106         os_strdup(_line, tmp_s);
107         if (OSHash_Add(fts_store, tmp_s, tmp_s) <= 0) {
108             free(tmp_s);
109             merror(LIST_ADD_ERROR, ARGV0);
110         }
111     }
112
113     /* Create ignore list */
114     fp_ignore = fopen(IG_QUEUE, "r+");
115     if (!fp_ignore) {
116         /* Create the file if we cannot open it */
117         fp_ignore = fopen(IG_QUEUE, "w+");
118         if (fp_ignore) {
119             fclose(fp_ignore);
120         }
121
122         if (chmod(IG_QUEUE, 0640) == -1) {
123             merror(CHMOD_ERROR, ARGV0, IG_QUEUE, errno, strerror(errno));
124             return (0);
125         }
126
127         uid_t uid = Privsep_GetUser(USER);
128         gid_t gid = Privsep_GetGroup(GROUPGLOBAL);
129         if (uid != (uid_t) - 1 && gid != (gid_t) - 1) {
130             if (chown(IG_QUEUE, uid, gid) == -1) {
131                 merror(CHOWN_ERROR, ARGV0, IG_QUEUE, errno, strerror(errno));
132                 return (0);
133             }
134         }
135
136         fp_ignore = fopen(IG_QUEUE, "r+");
137         if (!fp_ignore) {
138             merror(FOPEN_ERROR, ARGV0, IG_QUEUE, errno, strerror(errno));
139             return (0);
140         }
141     }
142
143     debug1("%s: DEBUG: FTSInit completed.", ARGV0);
144
145     return (1);
146 }
147
148 /* Add a pattern to be ignored */
149 void AddtoIGnore(Eventinfo *lf)
150 {
151     fseek(fp_ignore, 0, SEEK_END);
152
153 #ifdef TESTRULE
154     return;
155 #endif
156
157     /* Assign the values to the FTS */
158     fprintf(fp_ignore, "%s %s %s %s %s %s %s %s\n",
159             (lf->decoder_info->name && (lf->generated_rule->ignore & FTS_NAME)) ?
160             lf->decoder_info->name : "",
161             (lf->id && (lf->generated_rule->ignore & FTS_ID)) ? lf->id : "",
162             (lf->dstuser && (lf->generated_rule->ignore & FTS_DSTUSER)) ?
163             lf->dstuser : "",
164             (lf->srcip && (lf->generated_rule->ignore & FTS_SRCIP)) ?
165             lf->srcip : "",
166             (lf->dstip && (lf->generated_rule->ignore & FTS_DSTIP)) ?
167             lf->dstip : "",
168             (lf->data && (lf->generated_rule->ignore & FTS_DATA)) ?
169             lf->data : "",
170             (lf->systemname && (lf->generated_rule->ignore & FTS_SYSTEMNAME)) ?
171             lf->systemname : "",
172             (lf->generated_rule->ignore & FTS_LOCATION) ? lf->location : "");
173
174     fflush(fp_ignore);
175
176     return;
177 }
178
179 /* Check if the event is to be ignored.
180  * Only after an event is matched (generated_rule must be set).
181  */
182 int IGnore(Eventinfo *lf)
183 {
184     char _line[OS_FLSIZE + 1];
185     char _fline[OS_FLSIZE + 1];
186
187     _line[OS_FLSIZE] = '\0';
188
189     /* Assign the values to the FTS */
190     snprintf(_line, OS_FLSIZE, "%s %s %s %s %s %s %s %s\n",
191              (lf->decoder_info->name && (lf->generated_rule->ckignore & FTS_NAME)) ?
192              lf->decoder_info->name : "",
193              (lf->id && (lf->generated_rule->ckignore & FTS_ID)) ? lf->id : "",
194              (lf->dstuser && (lf->generated_rule->ckignore & FTS_DSTUSER)) ?
195              lf->dstuser : "",
196              (lf->srcip && (lf->generated_rule->ckignore & FTS_SRCIP)) ?
197              lf->srcip : "",
198              (lf->dstip && (lf->generated_rule->ckignore & FTS_DSTIP)) ?
199              lf->dstip : "",
200              (lf->data && (lf->generated_rule->ignore & FTS_DATA)) ?
201              lf->data : "",
202              (lf->systemname && (lf->generated_rule->ignore & FTS_SYSTEMNAME)) ?
203              lf->systemname : "",
204              (lf->generated_rule->ckignore & FTS_LOCATION) ? lf->location : "");
205
206     _fline[OS_FLSIZE] = '\0';
207
208     /** Check if the ignore is present **/
209     /* Point to the beginning of the file */
210     fseek(fp_ignore, 0, SEEK_SET);
211     while (fgets(_fline, OS_FLSIZE , fp_ignore) != NULL) {
212         if (strcmp(_fline, _line) != 0) {
213             continue;
214         }
215
216         /* If we match, we can return 1 */
217         return (1);
218     }
219
220     return (0);
221 }
222
223 /*  Check if the word "msg" is present on the "queue".
224  *  If it is not, write it there.
225  */
226 int FTS(Eventinfo *lf)
227 {
228     int number_of_matches = 0;
229     char _line[OS_FLSIZE + 1];
230     char *line_for_list = NULL;
231     OSListNode *fts_node;
232
233     _line[OS_FLSIZE] = '\0';
234
235     /* Assign the values to the FTS */
236     snprintf(_line, OS_FLSIZE, "%s %s %s %s %s %s %s %s %s",
237              lf->decoder_info->name,
238              (lf->id && (lf->decoder_info->fts & FTS_ID)) ? lf->id : "",
239              (lf->dstuser && (lf->decoder_info->fts & FTS_DSTUSER)) ? lf->dstuser : "",
240              (lf->srcuser && (lf->decoder_info->fts & FTS_SRCUSER)) ? lf->srcuser : "",
241              (lf->srcip && (lf->decoder_info->fts & FTS_SRCIP)) ? lf->srcip : "",
242              (lf->dstip && (lf->decoder_info->fts & FTS_DSTIP)) ? lf->dstip : "",
243              (lf->data && (lf->decoder_info->fts & FTS_DATA)) ? lf->data : "",
244              (lf->systemname && (lf->decoder_info->fts & FTS_SYSTEMNAME)) ? lf->systemname : "",
245              (lf->decoder_info->fts & FTS_LOCATION) ? lf->location : "");
246
247     /** Check if FTS is already present **/
248     if (OSHash_Get(fts_store, _line)) {
249         return (0);
250     }
251
252     /* Check if from the last FTS events, we had at least 3 "similars" before.
253      * If yes, we just ignore it.
254      */
255     if (lf->decoder_info->type == IDS) {
256         fts_node = OSList_GetLastNode(fts_list);
257         while (fts_node) {
258             if (OS_StrHowClosedMatch((char *)fts_node->data, _line) >
259                     fts_minsize_for_str) {
260                 number_of_matches++;
261
262                 /* We go and add this new entry to the list */
263                 if (number_of_matches > 2) {
264                     _line[fts_minsize_for_str] = '\0';
265                     break;
266                 }
267             }
268
269             fts_node = OSList_GetPrevNode(fts_list);
270         }
271
272         os_strdup(_line, line_for_list);
273         OSList_AddData(fts_list, line_for_list);
274     }
275
276     /* Store new entry */
277     if (line_for_list == NULL) {
278         os_strdup(_line, line_for_list);
279     }
280
281     if (OSHash_Add(fts_store, line_for_list, line_for_list) <= 1) {
282         return (0);
283     }
284
285
286 #ifdef TESTRULE
287     return (1);
288 #endif
289
290     /* Save to fts fp */
291     fseek(fp_list, 0, SEEK_END);
292     fprintf(fp_list, "%s\n", _line);
293     fflush(fp_list);
294
295     return (1);
296 }
297