new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / alerts / log.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 2) as published by the FSF - Free Software
7  * Foundation
8  */
9
10 #include "shared.h"
11 #include "log.h"
12 #include "alerts.h"
13 #include "getloglocation.h"
14 #include "rules.h"
15 #include "eventinfo.h"
16 #include "config.h"
17
18
19 /* Drop/allow patterns */
20 static OSMatch FWDROPpm;
21 static OSMatch FWALLOWpm;
22
23 /* Allow custom alert output tokens */
24 typedef enum e_custom_alert_tokens_id {
25     CUSTOM_ALERT_TOKEN_TIMESTAMP = 0,
26     CUSTOM_ALERT_TOKEN_FTELL,
27     CUSTOM_ALERT_TOKEN_RULE_ALERT_OPTIONS,
28     CUSTOM_ALERT_TOKEN_HOSTNAME,
29     CUSTOM_ALERT_TOKEN_LOCATION,
30     CUSTOM_ALERT_TOKEN_RULE_ID,
31     CUSTOM_ALERT_TOKEN_RULE_LEVEL,
32     CUSTOM_ALERT_TOKEN_RULE_COMMENT,
33     CUSTOM_ALERT_TOKEN_SRC_IP,
34     CUSTOM_ALERT_TOKEN_DST_USER,
35     CUSTOM_ALERT_TOKEN_FULL_LOG,
36     CUSTOM_ALERT_TOKEN_RULE_GROUP,
37     CUSTOM_ALERT_TOKEN_LAST
38 } CustomAlertTokenID;
39
40 static const char CustomAlertTokenName[CUSTOM_ALERT_TOKEN_LAST][15] = {
41     { "$TIMESTAMP" },
42     { "$FTELL" },
43     { "$RULEALERT" },
44     { "$HOSTNAME" },
45     { "$LOCATION" },
46     { "$RULEID" },
47     { "$RULELEVEL" },
48     { "$RULECOMMENT" },
49     { "$SRCIP" },
50     { "$DSTUSER" },
51     { "$FULLLOG" },
52     { "$RULEGROUP" },
53 };
54
55 /* Store the events in a file
56  * The string must be null terminated and contain
57  * any necessary new lines, tabs, etc.
58  */
59 void OS_Store(const Eventinfo *lf)
60 {
61     if (strcmp(lf->location, "ossec-keepalive") == 0) {
62         return;
63     }
64     if (strstr(lf->location, "->ossec-keepalive") != NULL) {
65         return;
66     }
67
68     fprintf(_eflog,
69             "%d %s %02d %s %s%s%s %s\n",
70             lf->year,
71             lf->mon,
72             lf->day,
73             lf->hour,
74             lf->hostname != lf->location ? lf->hostname : "",
75             lf->hostname != lf->location ? "->" : "",
76             lf->location,
77             lf->full_log);
78
79     fflush(_eflog);
80     return;
81 }
82
83 void OS_LogOutput(Eventinfo *lf)
84 {
85 #ifdef LIBGEOIP_ENABLED
86     if (Config.geoipdb_file) {
87         if (lf->srcip && !lf->srcgeoip) {
88             lf->srcgeoip = GetGeoInfobyIP(lf->srcip);
89         }
90         if (lf->dstip && !lf->dstgeoip) {
91             lf->dstgeoip = GetGeoInfobyIP(lf->dstip);
92         }
93     }
94 #endif
95
96     printf(
97         "** Alert %ld.%ld:%s - %s\n"
98         "%d %s %02d %s %s%s%s\nRule: %d (level %d) -> '%s'"
99         "%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n%.1256s\n",
100         (long int)lf->time,
101         __crt_ftell,
102         lf->generated_rule->alert_opts & DO_MAILALERT ? " mail " : "",
103         lf->generated_rule->group,
104         lf->year,
105         lf->mon,
106         lf->day,
107         lf->hour,
108         lf->hostname != lf->location ? lf->hostname : "",
109         lf->hostname != lf->location ? "->" : "",
110         lf->location,
111         lf->generated_rule->sigid,
112         lf->generated_rule->level,
113         lf->generated_rule->comment,
114
115         lf->srcip == NULL ? "" : "\nSrc IP: ",
116         lf->srcip == NULL ? "" : lf->srcip,
117
118 #ifdef LIBGEOIP_ENABLED
119         lf->srcgeoip == NULL ? "" : "\nSrc Location: ",
120         lf->srcgeoip == NULL ? "" : lf->srcgeoip,
121 #else
122         "",
123         "",
124 #endif
125
126
127
128         lf->srcport == NULL ? "" : "\nSrc Port: ",
129         lf->srcport == NULL ? "" : lf->srcport,
130
131         lf->dstip == NULL ? "" : "\nDst IP: ",
132         lf->dstip == NULL ? "" : lf->dstip,
133
134 #ifdef LIBGEOIP_ENABLED
135         lf->dstgeoip == NULL ? "" : "\nDst Location: ",
136         lf->dstgeoip == NULL ? "" : lf->dstgeoip,
137 #else
138         "",
139         "",
140 #endif
141
142
143
144         lf->dstport == NULL ? "" : "\nDst Port: ",
145         lf->dstport == NULL ? "" : lf->dstport,
146
147         lf->dstuser == NULL ? "" : "\nUser: ",
148         lf->dstuser == NULL ? "" : lf->dstuser,
149
150         lf->full_log);
151
152     /* Print the last events if present */
153     if (lf->generated_rule->last_events) {
154         char **lasts = lf->generated_rule->last_events;
155         while (*lasts) {
156             printf("%.1256s\n", *lasts);
157             lasts++;
158         }
159         lf->generated_rule->last_events[0] = NULL;
160     }
161
162     printf("\n");
163
164     fflush(stdout);
165     return;
166 }
167
168 void OS_Log(Eventinfo *lf)
169 {
170 #ifdef LIBGEOIP_ENABLED
171     if (Config.geoipdb_file) {
172         if (lf->srcip && !lf->srcgeoip) {
173             lf->srcgeoip = GetGeoInfobyIP(lf->srcip);
174         }
175         if (lf->dstip && !lf->dstgeoip) {
176             lf->dstgeoip = GetGeoInfobyIP(lf->dstip);
177         }
178     }
179 #endif
180
181     /* Writing to the alert log file */
182     fprintf(_aflog,
183             "** Alert %ld.%ld:%s - %s\n"
184             "%d %s %02d %s %s%s%s\nRule: %d (level %d) -> '%s'"
185             "%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n%.1256s\n",
186             (long int)lf->time,
187             __crt_ftell,
188             lf->generated_rule->alert_opts & DO_MAILALERT ? " mail " : "",
189             lf->generated_rule->group,
190             lf->year,
191             lf->mon,
192             lf->day,
193             lf->hour,
194             lf->hostname != lf->location ? lf->hostname : "",
195             lf->hostname != lf->location ? "->" : "",
196             lf->location,
197             lf->generated_rule->sigid,
198             lf->generated_rule->level,
199             lf->generated_rule->comment,
200
201             lf->srcip == NULL ? "" : "\nSrc IP: ",
202             lf->srcip == NULL ? "" : lf->srcip,
203
204 #ifdef LIBGEOIP_ENABLED
205             lf->srcgeoip == NULL ? "" : "\nSrc Location: ",
206             lf->srcgeoip == NULL ? "" : lf->srcgeoip,
207 #else
208             "",
209             "",
210 #endif
211
212
213             lf->srcport == NULL ? "" : "\nSrc Port: ",
214             lf->srcport == NULL ? "" : lf->srcport,
215
216             lf->dstip == NULL ? "" : "\nDst IP: ",
217             lf->dstip == NULL ? "" : lf->dstip,
218
219 #ifdef LIBGEOIP_ENABLED
220             lf->dstgeoip == NULL ? "" : "\nDst Location: ",
221             lf->dstgeoip == NULL ? "" : lf->dstgeoip,
222 #else
223             "",
224             "",
225 #endif
226
227
228
229             lf->dstport == NULL ? "" : "\nDst Port: ",
230             lf->dstport == NULL ? "" : lf->dstport,
231
232             lf->dstuser == NULL ? "" : "\nUser: ",
233             lf->dstuser == NULL ? "" : lf->dstuser,
234
235             lf->full_log);
236
237     /* Print the last events if present */
238     if (lf->generated_rule->last_events) {
239         char **lasts = lf->generated_rule->last_events;
240         while (*lasts) {
241             fprintf(_aflog, "%.1256s\n", *lasts);
242             lasts++;
243         }
244         lf->generated_rule->last_events[0] = NULL;
245     }
246
247     fprintf(_aflog, "\n");
248     fflush(_aflog);
249
250     return;
251 }
252
253 void OS_CustomLog(const Eventinfo *lf, const char *format)
254 {
255     char *log;
256     char *tmp_log;
257     char tmp_buffer[1024];
258
259     /* Replace all the tokens */
260     os_strdup(format, log);
261
262     snprintf(tmp_buffer, 1024, "%ld", (long int)lf->time);
263     tmp_log = searchAndReplace(log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_TIMESTAMP], tmp_buffer);
264     if (log) {
265         os_free(log);
266         log = NULL;
267     }
268     snprintf(tmp_buffer, 1024, "%ld", __crt_ftell);
269     log = searchAndReplace(tmp_log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_FTELL], tmp_buffer);
270     if (tmp_log) {
271         os_free(tmp_log);
272         tmp_log = NULL;
273     }
274
275     snprintf(tmp_buffer, 1024, "%s", (lf->generated_rule->alert_opts & DO_MAILALERT) ? "mail " : "");
276     tmp_log = searchAndReplace(log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_RULE_ALERT_OPTIONS], tmp_buffer);
277     if (log) {
278         os_free(log);
279         log = NULL;
280     }
281
282     snprintf(tmp_buffer, 1024, "%s", lf->hostname ? lf->hostname : "None");
283     log = searchAndReplace(tmp_log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_HOSTNAME], tmp_buffer);
284     if (tmp_log) {
285         os_free(tmp_log);
286         tmp_log = NULL;
287     }
288
289     snprintf(tmp_buffer, 1024, "%s", lf->location ? lf->location : "None");
290     tmp_log = searchAndReplace(log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_LOCATION], tmp_buffer);
291     if (log) {
292         os_free(log);
293         log = NULL;
294     }
295
296     snprintf(tmp_buffer, 1024, "%d", lf->generated_rule->sigid);
297     log = searchAndReplace(tmp_log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_RULE_ID], tmp_buffer);
298     if (tmp_log) {
299         os_free(tmp_log);
300         tmp_log = NULL;
301     }
302
303     snprintf(tmp_buffer, 1024, "%d", lf->generated_rule->level);
304     tmp_log = searchAndReplace(log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_RULE_LEVEL], tmp_buffer);
305     if (log) {
306         os_free(log);
307         log = NULL;
308     }
309
310     snprintf(tmp_buffer, 1024, "%s", lf->srcip ? lf->srcip : "None");
311     log = searchAndReplace(tmp_log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_SRC_IP], tmp_buffer);
312     if (tmp_log) {
313         os_free(tmp_log);
314         tmp_log = NULL;
315     }
316
317     snprintf(tmp_buffer, 1024, "%s", lf->dstuser ? lf->dstuser : "None");
318
319     tmp_log = searchAndReplace(log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_DST_USER], tmp_buffer);
320     if (log) {
321         os_free(log);
322         log = NULL;
323     }
324     char *escaped_log;
325     escaped_log = escape_newlines(lf->full_log);
326
327     log = searchAndReplace(tmp_log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_FULL_LOG], escaped_log );
328     if (tmp_log) {
329         os_free(tmp_log);
330         tmp_log = NULL;
331     }
332
333     if (escaped_log) {
334         os_free(escaped_log);
335         escaped_log = NULL;
336     }
337
338     snprintf(tmp_buffer, 1024, "%s", lf->generated_rule->comment ? lf->generated_rule->comment : "");
339     tmp_log = searchAndReplace(log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_RULE_COMMENT], tmp_buffer);
340     if (log) {
341         os_free(log);
342         log = NULL;
343     }
344
345     snprintf(tmp_buffer, 1024, "%s", lf->generated_rule->group ? lf->generated_rule->group : "");
346     log = searchAndReplace(tmp_log, CustomAlertTokenName[CUSTOM_ALERT_TOKEN_RULE_GROUP], tmp_buffer);
347     if (tmp_log) {
348         os_free(tmp_log);
349         tmp_log = NULL;
350     }
351
352     fprintf(_aflog, "%s", log);
353     fprintf(_aflog, "\n");
354     fflush(_aflog);
355
356     if (log) {
357         os_free(log);
358         log = NULL;
359     }
360
361     return;
362 }
363
364 void OS_InitFwLog()
365 {
366     /* Initialize fw log regexes */
367     if (!OSMatch_Compile(FWDROP, &FWDROPpm, 0)) {
368         ErrorExit(REGEX_COMPILE, ARGV0, FWDROP,
369                   FWDROPpm.error);
370     }
371
372     if (!OSMatch_Compile(FWALLOW, &FWALLOWpm, 0)) {
373         ErrorExit(REGEX_COMPILE, ARGV0, FWALLOW,
374                   FWALLOWpm.error);
375     }
376 }
377
378 int FW_Log(Eventinfo *lf)
379 {
380     /* If we don't have the srcip or the
381      * action, there is no point in going
382      * forward over here
383      */
384     if (!lf->action || !lf->srcip || !lf->dstip || !lf->srcport ||
385             !lf->dstport || !lf->protocol) {
386         return (0);
387     }
388
389     /* Set the actions */
390     switch (*lf->action) {
391         /* discard, drop, deny, */
392         case 'd':
393         case 'D':
394         /* reject, */
395         case 'r':
396         case 'R':
397         /* block */
398         case 'b':
399         case 'B':
400             os_free(lf->action);
401             os_strdup("DROP", lf->action);
402             break;
403         /* Closed */
404         case 'c':
405         case 'C':
406         /* Teardown */
407         case 't':
408         case 'T':
409             os_free(lf->action);
410             os_strdup("CLOSED", lf->action);
411             break;
412         /* allow, accept, */
413         case 'a':
414         case 'A':
415         /* pass/permitted */
416         case 'p':
417         case 'P':
418         /* open */
419         case 'o':
420         case 'O':
421             os_free(lf->action);
422             os_strdup("ALLOW", lf->action);
423             break;
424         default:
425             if (OSMatch_Execute(lf->action, strlen(lf->action), &FWDROPpm)) {
426                 os_free(lf->action);
427                 os_strdup("DROP", lf->action);
428             }
429             if (OSMatch_Execute(lf->action, strlen(lf->action), &FWALLOWpm)) {
430                 os_free(lf->action);
431                 os_strdup("ALLOW", lf->action);
432             } else {
433                 os_free(lf->action);
434                 os_strdup("UNKNOWN", lf->action);
435             }
436             break;
437     }
438
439     /* Log to file */
440     fprintf(_fflog,
441             "%d %s %02d %s %s%s%s %s %s %s:%s->%s:%s\n",
442             lf->year,
443             lf->mon,
444             lf->day,
445             lf->hour,
446             lf->hostname != lf->location ? lf->hostname : "",
447             lf->hostname != lf->location ? "->" : "",
448             lf->location,
449             lf->action,
450             lf->protocol,
451             lf->srcip,
452             lf->srcport,
453             lf->dstip,
454             lf->dstport);
455
456     fflush(_fflog);
457
458     return (1);
459 }
460