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 */
FTS_Init()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 */
AddtoIGnore(Eventinfo * lf)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 */
IGnore(Eventinfo * lf)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 */
FTS(Eventinfo * lf)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
298