new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / analysisd.c
1 /* Copyright (C) 2010-2012 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 /* ossec-analysisd
11  * Responsible for correlation and log decoding
12  */
13
14 #ifndef ARGV0
15 #define ARGV0 "ossec-analysisd"
16 #endif
17
18 #include "shared.h"
19 #include "alerts/alerts.h"
20 #include "alerts/getloglocation.h"
21 #include "os_execd/execd.h"
22 #include "os_regex/os_regex.h"
23 #include "os_net/os_net.h"
24 #include "active-response.h"
25 #include "config.h"
26 #include "rules.h"
27 #include "stats.h"
28 #include "eventinfo.h"
29 #include "accumulator.h"
30 #include "analysisd.h"
31 #include "fts.h"
32 #include "cleanevent.h"
33 #include "dodiff.h"
34 #include "output/jsonout.h"
35
36 #ifdef PRELUDE_OUTPUT_ENABLED
37 #include "output/prelude.h"
38 #endif
39
40 #ifdef ZEROMQ_OUTPUT_ENABLED
41 #include "output/zeromq.h"
42 #endif
43
44 #ifdef SQLITE_ENABLED
45 #include "syscheck-sqlite.h"
46 #endif
47
48 /** Prototypes **/
49 void OS_ReadMSG(int m_queue);
50 RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node);
51 static void LoopRule(RuleNode *curr_node, FILE *flog);
52
53 /* For decoders */
54 void DecodeEvent(Eventinfo *lf);
55 int DecodeSyscheck(Eventinfo *lf);
56 int DecodeRootcheck(Eventinfo *lf);
57 int DecodeHostinfo(Eventinfo *lf);
58
59 /* For stats */
60 static void DumpLogstats(void);
61
62 /** Global definitions **/
63 int today;
64 int thishour;
65 int prev_year;
66 char prev_month[4];
67 int __crt_hour;
68 int __crt_wday;
69 time_t c_time;
70 char __shost[512];
71 OSDecoderInfo *NULL_Decoder;
72
73 /* execd queue */
74 static int execdq = 0;
75
76 /* Active response queue */
77 static int arq = 0;
78
79 static int hourly_alerts;
80 static int hourly_events;
81 static int hourly_syscheck;
82 static int hourly_firewall;
83
84
85 /* Print help statement */
86 __attribute__((noreturn))
87 static void help_analysisd(void)
88 {
89     print_header();
90     print_out("  %s: -[Vhdtf] [-u user] [-g group] [-c config] [-D dir]", ARGV0);
91     print_out("    -V          Version and license message");
92     print_out("    -h          This help message");
93     print_out("    -d          Execute in debug mode. This parameter");
94     print_out("                can be specified multiple times");
95     print_out("                to increase the debug level.");
96     print_out("    -t          Test configuration");
97     print_out("    -f          Run in foreground");
98     print_out("    -u <user>   User to run as (default: %s)", USER);
99     print_out("    -g <group>  Group to run as (default: %s)", GROUPGLOBAL);
100     print_out("    -c <config> Configuration file to use (default: %s)", DEFAULTCPATH);
101     print_out("    -D <dir>    Directory to chroot into (default: %s)", DEFAULTDIR);
102     print_out(" ");
103     exit(1);
104 }
105
106 #ifndef TESTRULE
107 int main(int argc, char **argv)
108 #else
109 __attribute__((noreturn))
110 int main_analysisd(int argc, char **argv)
111 #endif
112 {
113     int c = 0, m_queue = 0, test_config = 0, run_foreground = 0;
114     int debug_level = 0;
115     const char *dir = DEFAULTDIR;
116     const char *user = USER;
117     const char *group = GROUPGLOBAL;
118     uid_t uid;
119     gid_t gid;
120
121     const char *cfg = DEFAULTCPATH;
122
123     /* Set the name */
124     OS_SetName(ARGV0);
125
126     thishour = 0;
127     today = 0;
128     prev_year = 0;
129     memset(prev_month, '\0', 4);
130     hourly_alerts = 0;
131     hourly_events = 0;
132     hourly_syscheck = 0;
133     hourly_firewall = 0;
134
135 #ifdef LIBGEOIP_ENABLED
136     geoipdb = NULL;
137 #endif
138
139
140     while ((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1) {
141         switch (c) {
142             case 'V':
143                 print_version();
144                 break;
145             case 'h':
146                 help_analysisd();
147                 break;
148             case 'd':
149                 nowDebug();
150                 debug_level = 1;
151                 break;
152             case 'f':
153                 run_foreground = 1;
154                 break;
155             case 'u':
156                 if (!optarg) {
157                     ErrorExit("%s: -u needs an argument", ARGV0);
158                 }
159                 user = optarg;
160                 break;
161             case 'g':
162                 if (!optarg) {
163                     ErrorExit("%s: -g needs an argument", ARGV0);
164                 }
165                 group = optarg;
166                 break;
167             case 'D':
168                 if (!optarg) {
169                     ErrorExit("%s: -D needs an argument", ARGV0);
170                 }
171                 dir = optarg;
172                 break;
173             case 'c':
174                 if (!optarg) {
175                     ErrorExit("%s: -c needs an argument", ARGV0);
176                 }
177                 cfg = optarg;
178                 break;
179             case 't':
180                 test_config = 1;
181                 break;
182             default:
183                 help_analysisd();
184                 break;
185         }
186
187     }
188
189     /* Check current debug_level
190      * Command line setting takes precedence
191      */
192     if (debug_level == 0) {
193         /* Get debug level */
194         debug_level = getDefine_Int("analysisd", "debug", 0, 2);
195         while (debug_level != 0) {
196             nowDebug();
197             debug_level--;
198         }
199     }
200
201     /* Start daemon */
202     debug1(STARTED_MSG, ARGV0);
203     DEBUG_MSG("%s: DEBUG: Starting on debug mode - %d ", ARGV0, (int)time(0));
204
205     /* Check if the user/group given are valid */
206     uid = Privsep_GetUser(user);
207     gid = Privsep_GetGroup(group);
208     if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
209         ErrorExit(USER_ERROR, ARGV0, user, group);
210     }
211
212     /* Found user */
213     debug1(FOUND_USER, ARGV0);
214
215     /* Initialize Active response */
216     AR_Init();
217     if (AR_ReadConfig(cfg) < 0) {
218         ErrorExit(CONFIG_ERROR, ARGV0, cfg);
219     }
220     debug1(ASINIT, ARGV0);
221
222     /* Read configuration file */
223     if (GlobalConf(cfg) < 0) {
224         ErrorExit(CONFIG_ERROR, ARGV0, cfg);
225     }
226
227     debug1(READ_CONFIG, ARGV0);
228
229
230 #ifdef LIBGEOIP_ENABLED
231      Config.geoip_jsonout = getDefine_Int("analysisd", "geoip_jsonout", 0, 1);
232
233     /* Opening GeoIP DB */
234     if(Config.geoipdb_file) {
235         geoipdb = GeoIP_open(Config.geoipdb_file, GEOIP_INDEX_CACHE);
236         if (geoipdb == NULL)
237         {
238             merror("%s: ERROR: Unable to open GeoIP database from: %s (disabling GeoIP).", ARGV0, Config.geoipdb_file);
239         }
240     }
241 #endif
242
243
244
245     /* Fix Config.ar */
246     Config.ar = ar_flag;
247     if (Config.ar == -1) {
248         Config.ar = 0;
249     }
250
251     /* Get server's hostname */
252     memset(__shost, '\0', 512);
253     if (gethostname(__shost, 512 - 1) != 0) {
254         strncpy(__shost, OSSEC_SERVER, 512 - 1);
255     } else {
256         char *_ltmp;
257
258         /* Remove domain part if available */
259         _ltmp = strchr(__shost, '.');
260         if (_ltmp) {
261             *_ltmp = '\0';
262         }
263     }
264
265     /* Continuing in Daemon mode */
266     if (!test_config && !run_foreground) {
267         nowDaemon();
268         goDaemon();
269     }
270
271 #ifdef PRELUDE_OUTPUT_ENABLED
272     /* Start prelude */
273     if (Config.prelude) {
274         prelude_start(Config.prelude_profile, argc, argv);
275     }
276 #endif
277
278 #ifdef ZEROMQ_OUTPUT_ENABLED
279     /* Start zeromq */
280     if (Config.zeromq_output) {
281 #if CZMQ_VERSION_MAJOR == 2 
282         zeromq_output_start(Config.zeromq_output_uri);
283 #elif CZMQ_VERSION_MAJOR >= 3
284         zeromq_output_start(Config.zeromq_output_uri, Config.zeromq_output_client_cert, Config.zeromq_output_server_cert);
285 #endif
286     }
287 #endif
288
289     /* Set the group */
290     if (Privsep_SetGroup(gid) < 0) {
291         ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
292     }
293
294     /* Chroot */
295     if (Privsep_Chroot(dir) < 0) {
296         ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
297     }
298     nowChroot();
299
300     Config.decoder_order_size = (size_t)getDefine_Int("analysisd", "decoder_order_size", 8, MAX_DECODER_ORDER_SIZE);
301
302
303     /*
304      * Anonymous Section: Load rules, decoders, and lists
305      *
306      * As lists require two-pass loading of rules that makes use of lists, lookups
307      * are created with blank database structs, and need to be filled in after
308      * completion of all rules and lists.
309      */
310     {
311         {
312             /* Initialize the decoders list */
313             OS_CreateOSDecoderList();
314
315             if (!Config.decoders) {
316                 /* Legacy loading */
317                 /* Read decoders */
318                 if (!ReadDecodeXML(XML_DECODER)) {
319                     ErrorExit(CONFIG_ERROR, ARGV0,  XML_DECODER);
320                 }
321
322                 /* Read local ones */
323                 c = ReadDecodeXML(XML_LDECODER);
324                 if (!c) {
325                     if ((c != -2)) {
326                         ErrorExit(CONFIG_ERROR, ARGV0,  XML_LDECODER);
327                     }
328                 } else {
329                     if (!test_config) {
330                         verbose("%s: INFO: Reading local decoder file.", ARGV0);
331                     }
332                 }
333             } else {
334                 /* New loaded based on file speified in ossec.conf */
335                 char **decodersfiles;
336                 decodersfiles = Config.decoders;
337                 while ( decodersfiles && *decodersfiles) {
338                     if (!test_config) {
339                         verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
340                     }
341                     if (!ReadDecodeXML(*decodersfiles)) {
342                         ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles);
343                     }
344
345                     free(*decodersfiles);
346                     decodersfiles++;
347                 }
348             }
349
350             /* Load decoders */
351             SetDecodeXML();
352         }
353         {
354             /* Load Lists */
355             /* Initialize the lists of list struct */
356             Lists_OP_CreateLists();
357             /* Load each list into list struct */
358             {
359                 char **listfiles;
360                 listfiles = Config.lists;
361                 while (listfiles && *listfiles) {
362                     if (!test_config) {
363                         verbose("%s: INFO: Reading loading the lists file: '%s'", ARGV0, *listfiles);
364                     }
365                     if (Lists_OP_LoadList(*listfiles) < 0) {
366                         ErrorExit(LISTS_ERROR, ARGV0, *listfiles);
367                     }
368                     free(*listfiles);
369                     listfiles++;
370                 }
371                 free(Config.lists);
372                 Config.lists = NULL;
373             }
374         }
375
376         {
377             /* Load Rules */
378             /* Create the rules list */
379             Rules_OP_CreateRules();
380
381             /* Read the rules */
382             {
383                 char **rulesfiles;
384                 rulesfiles = Config.includes;
385                 while (rulesfiles && *rulesfiles) {
386                     if (!test_config) {
387                         verbose("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles);
388                     }
389                     if (Rules_OP_ReadRules(*rulesfiles) < 0) {
390                         ErrorExit(RULES_ERROR, ARGV0, *rulesfiles);
391                     }
392
393                     free(*rulesfiles);
394                     rulesfiles++;
395                 }
396
397                 free(Config.includes);
398                 Config.includes = NULL;
399             }
400
401             /* Find all rules that require list lookups and attache the the
402              * correct list struct to the rule. This keeps rules from having to
403              * search thought the list of lists for the correct file during
404              * rule evaluation.
405              */
406             OS_ListLoadRules();
407         }
408     }
409
410     /* Fix the levels/accuracy */
411     {
412         int total_rules;
413         RuleNode *tmp_node = OS_GetFirstRule();
414
415         total_rules = _setlevels(tmp_node, 0);
416         if (!test_config) {
417             verbose("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules);
418         }
419     }
420
421     /* Create a rules hash (for reading alerts from other servers) */
422     {
423         RuleNode *tmp_node = OS_GetFirstRule();
424         Config.g_rules_hash = OSHash_Create();
425         if (!Config.g_rules_hash) {
426             ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
427         }
428         AddHash_Rule(tmp_node);
429     }
430
431     /* Ignored files on syscheck */
432     {
433         char **files;
434         files = Config.syscheck_ignore;
435         while (files && *files) {
436             if (!test_config) {
437                 verbose("%s: INFO: Ignoring file: '%s'", ARGV0, *files);
438             }
439             files++;
440         }
441     }
442
443     /* Check if log_fw is enabled */
444     Config.logfw = (u_int8_t) getDefine_Int("analysisd",
445                                  "log_fw",
446                                  0, 1);
447
448     /* Success on the configuration test */
449     if (test_config) {
450         exit(0);
451     }
452
453     /* Verbose message */
454     debug1(CHROOT_MSG, ARGV0, dir);
455     debug1(PRIVSEP_MSG, ARGV0, user);
456
457     /* Signal manipulation */
458     StartSIG(ARGV0);
459
460     /* Set the user */
461     if (Privsep_SetUser(uid) < 0) {
462         ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
463     }
464
465     /* Create the PID file */
466     if (CreatePID(ARGV0, getpid()) < 0) {
467         ErrorExit(PID_ERROR, ARGV0);
468     }
469
470     /* Set the queue */
471     if ((m_queue = StartMQ(DEFAULTQUEUE, READ)) < 0) {
472         ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno));
473     }
474
475     /* allowlist */
476     if (Config.allow_list == NULL) {
477         if (Config.ar) {
478             verbose("%s: INFO: No IP in the allow list for active response.", ARGV0);
479         }
480     } else {
481         if (Config.ar) {
482             os_ip **wl;
483             int wlc = 0;
484             wl = Config.allow_list;
485             while (*wl) {
486                 verbose("%s: INFO: Allow listing IP: '%s'", ARGV0, (*wl)->ip);
487                 wl++;
488                 wlc++;
489             }
490             verbose("%s: INFO: %d IPs in the allow list for active response.",
491                     ARGV0, wlc);
492         }
493     }
494
495     /* Hostname allowlist */
496     if (Config.hostname_allow_list == NULL) {
497         if (Config.ar)
498             verbose("%s: INFO: No Hostname in the allow list for active response.",
499                     ARGV0);
500     } else {
501         if (Config.ar) {
502             int wlc = 0;
503             char **wl;
504
505             wl = Config.hostname_allow_list;
506             while (*wl) {
507                 verbose("%s: INFO: Allow listing Hostname: '%s'", ARGV0, *wl);
508                 wlc++;
509                 wl++;
510             }
511             verbose("%s: INFO: %d Hostname(s) in the allow list for active response.",
512                     ARGV0, wlc);
513         }
514     }
515
516     /* Startup message */
517     verbose(STARTUP_MSG, ARGV0, (int)getpid());
518
519     /* Going to main loop */
520     OS_ReadMSG(m_queue);
521
522     exit(0);
523 }
524
525 /* Main function. Receives the messages(events) and analyze them all */
526 #ifndef TESTRULE
527 __attribute__((noreturn))
528 void OS_ReadMSG(int m_queue)
529 #else
530 __attribute__((noreturn))
531 void OS_ReadMSG_analysisd(int m_queue)
532 #endif
533 {
534     int i;
535     char msg[OS_MAXSTR + 1];
536     Eventinfo *lf;
537
538     RuleInfo *stats_rule = NULL;
539
540     /* Null to global currently pointers */
541     currently_rule = NULL;
542
543     /* Initialize the logs */
544     OS_InitLog();
545
546     /* Initialize the integrity database */
547     SyscheckInit();
548
549     /* Initialize Rootcheck */
550     RootcheckInit();
551
552     /* Initialize host info */
553     HostinfoInit();
554
555     /* Create the event list */
556     OS_CreateEventList(Config.memorysize);
557
558     /* Initiate the FTS list */
559     if (!FTS_Init()) {
560         ErrorExit(FTS_LIST_ERROR, ARGV0);
561     }
562
563     /* Initialize the Accumulator */
564     if (!Accumulate_Init()) {
565         merror("accumulator: ERROR: Initialization failed");
566         exit(1);
567     }
568
569     /* Start the active response queues */
570     if (Config.ar) {
571         /* Waiting the ARQ to settle */
572         sleep(3);
573
574 #ifndef LOCAL
575         if (Config.ar & REMOTE_AR) {
576             if ((arq = StartMQ(ARQUEUE, WRITE)) < 0) {
577                 merror(ARQ_ERROR, ARGV0);
578
579                 /* If LOCAL_AR is set, keep it there */
580                 if (Config.ar & LOCAL_AR) {
581                     Config.ar = 0;
582                     Config.ar |= LOCAL_AR;
583                 } else {
584                     Config.ar = 0;
585                 }
586             } else {
587                 verbose(CONN_TO, ARGV0, ARQUEUE, "active-response");
588             }
589         }
590 #else
591         /* Only for LOCAL_ONLY installs */
592         if (Config.ar & REMOTE_AR) {
593             if (Config.ar & LOCAL_AR) {
594                 Config.ar = 0;
595                 Config.ar |= LOCAL_AR;
596             } else {
597                 Config.ar = 0;
598             }
599         }
600 #endif
601
602         if (Config.ar & LOCAL_AR) {
603             if ((execdq = StartMQ(EXECQUEUE, WRITE)) < 0) {
604                 merror(ARQ_ERROR, ARGV0);
605
606                 /* If REMOTE_AR is set, keep it there */
607                 if (Config.ar & REMOTE_AR) {
608                     Config.ar = 0;
609                     Config.ar |= REMOTE_AR;
610                 } else {
611                     Config.ar = 0;
612                 }
613             } else {
614                 verbose(CONN_TO, ARGV0, EXECQUEUE, "exec");
615             }
616         }
617     }
618     debug1("%s: DEBUG: Active response Init completed.", ARGV0);
619
620     /* Get current time before starting */
621     c_time = time(NULL);
622
623     /* Start the hourly/weekly stats */
624     if (Start_Hour() < 0) {
625         Config.stats = 0;
626     } else {
627         /* Initialize stats rules */
628         stats_rule = zerorulemember(
629                          STATS_MODULE,
630                          Config.stats,
631                          0, 0, 0, 0, 0, 0);
632
633         if (!stats_rule) {
634             ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
635         }
636         stats_rule->group = "stats,";
637         stats_rule->comment = "Excessive number of events (above normal).";
638     }
639
640     /* Do some cleanup */
641     memset(msg, '\0', OS_MAXSTR + 1);
642
643     /* Initialize the logs */
644     {
645         lf = (Eventinfo *)calloc(1, sizeof(Eventinfo));
646         if (!lf) {
647             ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
648         }
649         os_calloc(Config.decoder_order_size, sizeof(char*), lf->fields);
650         lf->year = prev_year;
651         strncpy(lf->mon, prev_month, 3);
652         lf->day = today;
653
654         if (OS_GetLogLocation(lf) < 0) {
655             ErrorExit("%s: Error allocating log files", ARGV0);
656         }
657
658         Free_Eventinfo(lf);
659     }
660
661 #ifdef SQLITE_ENABLED
662     /* Open the sqlite db */
663     extern sqlite3 *conn;
664     int s_error = 0;
665     if (Config.md5_allowlist) {
666         debug2("Opening md5_allowlist: %s", Config.md5_allowlist);
667         if((s_error = sqlite3_open(Config.md5_allowlist, &conn))) {
668             merror(INVALID_IGNORE_MD5DB, ARGV0, Config.md5_allowlist);
669         }
670
671     }
672 #endif
673
674     debug1("%s: DEBUG: Startup completed. Waiting for new messages..", ARGV0);
675
676     if (Config.custom_alert_output) {
677         debug1("%s: INFO: Custom output found.!", ARGV0);
678     }
679
680     /* Daemon loop */
681     while (1) {
682         lf = (Eventinfo *)calloc(1, sizeof(Eventinfo));
683         os_calloc(Config.decoder_order_size, sizeof(char*), lf->fields);
684
685         /* This shouldn't happen */
686         if (lf == NULL) {
687             ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
688         }
689
690         DEBUG_MSG("%s: DEBUG: Waiting for msgs - %d ", ARGV0, (int)time(0));
691
692         /* Receive message from queue */
693         if ((i = OS_RecvUnix(m_queue, OS_MAXSTR, msg))) {
694             RuleNode *rulenode_pt;
695
696             /* Get the time we received the event */
697             c_time = time(NULL);
698
699             /* Default values for the log info */
700             Zero_Eventinfo(lf);
701
702             /* Check for a valid message */
703             if (i < 4) {
704                 merror(IMSG_ERROR, ARGV0, msg);
705                 Free_Eventinfo(lf);
706                 continue;
707             }
708
709             /* Message before extracting header */
710             DEBUG_MSG("%s: DEBUG: Received msg: %s ", ARGV0, msg);
711
712             /* Clean the msg appropriately */
713             if (OS_CleanMSG(msg, lf) < 0) {
714                 merror(IMSG_ERROR, ARGV0, msg);
715                 Free_Eventinfo(lf);
716                 continue;
717             }
718
719             /* Msg cleaned */
720             DEBUG_MSG("%s: DEBUG: Msg cleanup: %s ", ARGV0, lf->log);
721
722             /* Current rule must be null in here */
723             currently_rule = NULL;
724
725             /** Check the date/hour changes **/
726
727             /* Update the hour */
728             if (thishour != __crt_hour) {
729                 /* Search all the rules and print the number
730                  * of alerts that each one fired
731                  */
732                 DumpLogstats();
733                 thishour = __crt_hour;
734
735                 /* Check if the date has changed */
736                 if (today != lf->day) {
737                     if (Config.stats) {
738                         /* Update the hourly stats (done daily) */
739                         Update_Hour();
740                     }
741
742                     if (OS_GetLogLocation(lf) < 0) {
743                         ErrorExit("%s: Error allocating log files", ARGV0);
744                     }
745
746                     today = lf->day;
747                     strncpy(prev_month, lf->mon, 3);
748                     prev_year = lf->year;
749                 }
750             }
751
752
753             /* Increment number of events received */
754             hourly_events++;
755
756             /***  Run decoders ***/
757
758             /* Integrity check from syscheck */
759             if (msg[0] == SYSCHECK_MQ) {
760                 hourly_syscheck++;
761
762                 if (!DecodeSyscheck(lf)) {
763                     /* We don't process syscheck events further */
764                     goto CLMEM;
765                 }
766
767                 /* Get log size */
768                 lf->size = strlen(lf->log);
769             }
770
771             /* Rootcheck decoding */
772             else if (msg[0] == ROOTCHECK_MQ) {
773                 if (!DecodeRootcheck(lf)) {
774                     /* We don't process rootcheck events further */
775                     goto CLMEM;
776                 }
777                 lf->size = strlen(lf->log);
778             }
779
780             /* Host information special decoder */
781             else if (msg[0] == HOSTINFO_MQ) {
782                 if (!DecodeHostinfo(lf)) {
783                     /* We don't process hostinfo events further */
784                     goto CLMEM;
785                 }
786                 lf->size = strlen(lf->log);
787             }
788
789             /* Run the general Decoders */
790             else {
791                 /* Get log size */
792                 lf->size = strlen(lf->log);
793
794                 DecodeEvent(lf);
795             }
796
797             /* Run accumulator */
798             if ( lf->decoder_info->accumulate == 1 ) {
799                 lf = Accumulate(lf);
800             }
801
802             /* Firewall event */
803             if (lf->decoder_info->type == FIREWALL) {
804                 /* If we could not get any information from
805                  * the log, just ignore it
806                  */
807                 hourly_firewall++;
808                 if (Config.logfw) {
809                     if (!FW_Log(lf)) {
810                         goto CLMEM;
811                     }
812                 }
813             }
814
815             /* We only check if the last message is
816              * duplicated on syslog
817              */
818             else if (lf->decoder_info->type == SYSLOG) {
819                 /* Check if the message is duplicated */
820                 if (LastMsg_Stats(lf->full_log) == 1) {
821                     goto CLMEM;
822                 } else {
823                     LastMsg_Change(lf->full_log);
824                 }
825             }
826
827             /* Stats checking */
828             if (Config.stats) {
829                 if (Check_Hour() == 1) {
830                     RuleInfo *saved_rule = lf->generated_rule;
831                     char *saved_log;
832
833                     /* Save previous log */
834                     saved_log = lf->full_log;
835
836                     lf->generated_rule = stats_rule;
837                     lf->full_log = __stats_comment;
838
839                     /* Alert for statistical analysis */
840                     if (stats_rule->alert_opts & DO_LOGALERT) {
841                         __crt_ftell = ftell(_aflog);
842                         if (Config.custom_alert_output) {
843                             OS_CustomLog(lf, Config.custom_alert_output_format);
844                         } else {
845                             OS_Log(lf);
846                         }
847                         /* Log to json file */
848                         if (Config.jsonout_output) {
849                             jsonout_output_event(lf);
850                         }
851
852                     }
853
854                     /* Set lf to the old values */
855                     lf->generated_rule = saved_rule;
856                     lf->full_log = saved_log;
857                 }
858             }
859
860             /* Check the rules */
861             DEBUG_MSG("%s: DEBUG: Checking the rules - %d ",
862                       ARGV0, lf->decoder_info->type);
863
864             /* Loop over all the rules */
865             rulenode_pt = OS_GetFirstRule();
866             if (!rulenode_pt) {
867                 ErrorExit("%s: Rules in an inconsistent state. Exiting.",
868                           ARGV0);
869             }
870
871             do {
872                 if (lf->decoder_info->type == OSSEC_ALERT) {
873                     if (!lf->generated_rule) {
874                         goto CLMEM;
875                     }
876
877                     /* Process the alert */
878                     currently_rule = lf->generated_rule;
879                 }
880
881                 /* Categories must match */
882                 else if (rulenode_pt->ruleinfo->category !=
883                          lf->decoder_info->type) {
884                     continue;
885                 }
886
887                 /* Check each rule */
888                 else if ((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt))
889                          == NULL) {
890                     continue;
891                 }
892
893                 /* Ignore level 0 */
894                 if (currently_rule->level == 0) {
895                     break;
896                 }
897
898                 /* Check ignore time */
899                 if (currently_rule->ignore_time) {
900                     if (currently_rule->time_ignored == 0) {
901                         currently_rule->time_ignored = lf->time;
902                     }
903                     /* If the current time - the time the rule was ignored
904                      * is less than the time it should be ignored,
905                      * leave (do not alert again)
906                      */
907                     else if ((lf->time - currently_rule->time_ignored)
908                              < currently_rule->ignore_time) {
909                         break;
910                     } else {
911                         currently_rule->time_ignored = lf->time;
912                     }
913                 }
914
915                 /* Pointer to the rule that generated it */
916                 lf->generated_rule = currently_rule;
917
918                 /* Check if we should ignore it */
919                 if (currently_rule->ckignore && IGnore(lf)) {
920                     /* Ignore rule */
921                     lf->generated_rule = NULL;
922                     break;
923                 }
924
925                 /* Check if we need to add to ignore list */
926                 if (currently_rule->ignore) {
927                     AddtoIGnore(lf);
928                 }
929
930                 /* Log the alert if configured to */
931                 if (currently_rule->alert_opts & DO_LOGALERT) {
932                     __crt_ftell = ftell(_aflog);
933
934                     if (Config.custom_alert_output) {
935                         OS_CustomLog(lf, Config.custom_alert_output_format);
936                     } else {
937                         OS_Log(lf);
938                     }
939                     /* Log to json file */
940                     if (Config.jsonout_output) {
941                         jsonout_output_event(lf);
942                     }
943                 }
944
945 #ifdef PRELUDE_OUTPUT_ENABLED
946                 /* Log to prelude */
947                 if (Config.prelude) {
948                     if (Config.prelude_log_level <= currently_rule->level) {
949                         OS_PreludeLog(lf);
950                     }
951                 }
952 #endif
953
954 #ifdef ZEROMQ_OUTPUT_ENABLED
955                 /* Log to zeromq */
956                 if (Config.zeromq_output) {
957                     zeromq_output_event(lf);
958                 }
959 #endif
960
961
962                 /* Execute an active response */
963                 if (currently_rule->ar) {
964                     int do_ar;
965                     active_response **rule_ar;
966
967                     rule_ar = currently_rule->ar;
968
969                     while (*rule_ar) {
970                         do_ar = 1;
971                         if ((*rule_ar)->ar_cmd->expect & USERNAME) {
972                             if (!lf->dstuser ||
973                                     !OS_PRegex(lf->dstuser, "^[a-zA-Z._0-9@?-]*$")) {
974                                 if (lf->dstuser) {
975                                     merror(CRAFTED_USER, ARGV0, lf->dstuser);
976                                 }
977                                 do_ar = 0;
978                             }
979                         }
980                         if ((*rule_ar)->ar_cmd->expect & SRCIP) {
981                             if (!lf->srcip ||
982                                     !OS_PRegex(lf->srcip, "^[a-zA-Z.:_0-9-]*$")) {
983                                 if (lf->srcip) {
984                                     merror(CRAFTED_IP, ARGV0, lf->srcip);
985                                 }
986                                 do_ar = 0;
987                             }
988                         }
989                         if ((*rule_ar)->ar_cmd->expect & FILENAME) {
990                             if (!lf->filename) {
991                                 do_ar = 0;
992                             }
993                         }
994
995                         if (do_ar && execdq > 0) {
996                             OS_Exec(execdq, arq, lf, *rule_ar);
997                         }
998                         rule_ar++;
999                     }
1000                 }
1001
1002                 /* Copy the structure to the state memory of if_matched_sid */
1003                 if (currently_rule->sid_prev_matched) {
1004                     if (!OSList_AddData(currently_rule->sid_prev_matched, lf)) {
1005                         merror("%s: Unable to add data to sig list.", ARGV0);
1006                     } else {
1007                         lf->sid_node_to_delete =
1008                             currently_rule->sid_prev_matched->last_node;
1009                     }
1010                 }
1011                 /* Group list */
1012                 else if (currently_rule->group_prev_matched) {
1013                     unsigned int j = 0;
1014
1015                     while (j < currently_rule->group_prev_matched_sz) {
1016                         if (!OSList_AddData(
1017                                     currently_rule->group_prev_matched[j],
1018                                     lf)) {
1019                             merror("%s: Unable to add data to grp list.", ARGV0);
1020                         }
1021                         j++;
1022                     }
1023                 }
1024
1025                 OS_AddEvent(lf);
1026
1027                 break;
1028
1029             } while ((rulenode_pt = rulenode_pt->next) != NULL);
1030
1031             /* If configured to log all, do it */
1032             if (Config.logall)
1033                 OS_Store(lf);
1034             if (Config.logall_json)
1035                 jsonout_output_archive(lf);
1036
1037 CLMEM:
1038             /** Cleaning the memory **/
1039
1040             /* Only clear the memory if the eventinfo was not
1041              * added to the stateful memory
1042              * -- message is free inside clean event --
1043              */
1044             if (lf->generated_rule == NULL) {
1045                 Free_Eventinfo(lf);
1046             }
1047         } else {
1048             free(lf);
1049         }
1050     }
1051 }
1052
1053 /* Checks if the current_rule matches the event information */
1054 RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node)
1055 {
1056     /* We check for:
1057      * decoded_as,
1058      * fts,
1059      * word match (fast regex),
1060      * regex,
1061      * url,
1062      * id,
1063      * user,
1064      * maxsize,
1065      * protocol,
1066      * srcip,
1067      * dstip,
1068      * srcport,
1069      * dstport,
1070      * time,
1071      * weekday,
1072      * status,
1073      */
1074     RuleInfo *rule = curr_node->ruleinfo;
1075     int i;
1076
1077     /* Can't be null */
1078     if (!rule) {
1079         merror("%s: Inconsistent state. currently rule NULL", ARGV0);
1080         return (NULL);
1081     }
1082
1083 #ifdef TESTRULE
1084     if (full_output && !alert_only)
1085         print_out("    Trying rule: %d - %s", rule->sigid,
1086                   rule->comment);
1087 #endif
1088
1089     /* Check if any decoder pre-matched here */
1090     if (rule->decoded_as &&
1091             rule->decoded_as != lf->decoder_info->id) {
1092         return (NULL);
1093     }
1094
1095     /* Check program name */
1096     if (rule->program_name) {
1097         if (!lf->program_name) {
1098             return (NULL);
1099         }
1100
1101         if (!OSMatch_Execute(lf->program_name,
1102                              lf->p_name_size,
1103                              rule->program_name)) {
1104             return (NULL);
1105         }
1106     }
1107     else if (rule->program_name_pcre2) {
1108         if (!lf->program_name) {
1109             return (NULL);
1110         }
1111
1112         if (!OSPcre2_Execute(lf->program_name,
1113                              rule->program_name_pcre2)) {
1114             return (NULL);
1115         }
1116     }
1117
1118     /* Check for the ID */
1119     if (rule->id) {
1120         if (!lf->id) {
1121             return (NULL);
1122         }
1123
1124         if (!OSMatch_Execute(lf->id,
1125                              strlen(lf->id),
1126                              rule->id)) {
1127             return (NULL);
1128         }
1129     }
1130     else if (rule->id_pcre2) {
1131         if (!lf->id) {
1132             return (NULL);
1133         }
1134
1135         if (!OSPcre2_Execute(lf->id,
1136                              rule->id_pcre2)) {
1137             return (NULL);
1138         }
1139     }
1140
1141     /* Check if any word to match exists */
1142     if (rule->match) {
1143         if (!OSMatch_Execute(lf->log, lf->size, rule->match)) {
1144             return (NULL);
1145         }
1146     }
1147     else if (rule->match_pcre2) {
1148         if (!OSPcre2_Execute(lf->log, rule->match_pcre2)) {
1149             return (NULL);
1150         }
1151     }
1152
1153     /* Check if exist any regex for this rule */
1154     if (rule->regex) {
1155         if (!OSRegex_Execute(lf->log, rule->regex)) {
1156             return (NULL);
1157         }
1158     }
1159     else if (rule->pcre2) {
1160         if (!OSPcre2_Execute(lf->log, rule->pcre2)) {
1161             return (NULL);
1162         }
1163     }
1164
1165     /* Check for actions */
1166     if (rule->action) {
1167         if (!lf->action) {
1168             return (NULL);
1169         }
1170
1171         if (strcmp(rule->action, lf->action) != 0) {
1172             return (NULL);
1173         }
1174     }
1175
1176     /* Checking for the URL */
1177     if (rule->url) {
1178         if (!lf->url) {
1179             return (NULL);
1180         }
1181
1182         if (!OSMatch_Execute(lf->url, strlen(lf->url), rule->url)) {
1183             return (NULL);
1184         }
1185     }
1186     if (rule->url_pcre2) {
1187         if (!lf->url) {
1188             return (NULL);
1189         }
1190
1191         if (!OSPcre2_Execute(lf->url, rule->url_pcre2)) {
1192             return (NULL);
1193         }
1194     }
1195
1196     /* Check for dynamic fields */
1197    
1198     for (i = 0; i < Config.decoder_order_size && rule->fields[i]; i++) {
1199         int j;
1200         
1201         for (j = 0; j < Config.decoder_order_size; j++)
1202             if (lf->decoder_info->fields[j])
1203                 if (strcasecmp(lf->decoder_info->fields[j], rule->fields[i]->name) == 0)
1204                     break;
1205
1206         if (j == Config.decoder_order_size)
1207
1208             return NULL;
1209         
1210         if (!OSRegex_Execute(lf->fields[j], rule->fields[i]->regex))
1211             return NULL;
1212     }
1213
1214
1215     /* Get TCP/IP packet information */
1216     if (rule->alert_opts & DO_PACKETINFO) {
1217         /* Check for the srcip */
1218         if (rule->srcip) {
1219             if (!lf->srcip) {
1220                 return (NULL);
1221             }
1222
1223             if (!OS_IPFoundList(lf->srcip, rule->srcip)) {
1224                 return (NULL);
1225             }
1226         }
1227
1228         /* Check for the dstip */
1229         if (rule->dstip) {
1230             if (!lf->dstip) {
1231                 return (NULL);
1232             }
1233
1234             if (!OS_IPFoundList(lf->dstip, rule->dstip)) {
1235                 return (NULL);
1236             }
1237         }
1238
1239         if (rule->srcport) {
1240             if (!lf->srcport) {
1241                 return (NULL);
1242             }
1243
1244             if (!OSMatch_Execute(lf->srcport,
1245                                  strlen(lf->srcport),
1246                                  rule->srcport)) {
1247                 return (NULL);
1248             }
1249         }
1250         else if (rule->srcport_pcre2) {
1251             if (!lf->srcport) {
1252                 return (NULL);
1253             }
1254
1255             if (!OSPcre2_Execute(lf->srcport,
1256                                  rule->srcport_pcre2)) {
1257                 return (NULL);
1258             }
1259         }
1260         if (rule->dstport) {
1261             if (!lf->dstport) {
1262                 return (NULL);
1263             }
1264
1265             if (!OSMatch_Execute(lf->dstport,
1266                                  strlen(lf->dstport),
1267                                  rule->dstport)) {
1268                 return (NULL);
1269             }
1270         }
1271         else if (rule->dstport_pcre2) {
1272             if (!lf->dstport) {
1273                 return (NULL);
1274             }
1275
1276             if (!OSPcre2_Execute(lf->dstport,
1277                                  rule->dstport_pcre2)) {
1278                 return (NULL);
1279             }
1280         }
1281     } /* END PACKET_INFO */
1282
1283     /* Extra information from event */
1284     if (rule->alert_opts & DO_EXTRAINFO) {
1285         /* Check compiled rule */
1286         if (rule->compiled_rule) {
1287             if (!rule->compiled_rule(lf)) {
1288                 return (NULL);
1289             }
1290         }
1291
1292         /* Checking if exist any user to match */
1293         if (rule->user) {
1294             if (lf->dstuser) {
1295                 if (!OSMatch_Execute(lf->dstuser,
1296                                      strlen(lf->dstuser),
1297                                      rule->user)) {
1298                     return (NULL);
1299                 }
1300             } else if (lf->srcuser) {
1301                 if (!OSMatch_Execute(lf->srcuser,
1302                                      strlen(lf->srcuser),
1303                                      rule->user)) {
1304                     return (NULL);
1305                 }
1306             } else {
1307                 /* no user set */
1308                 return (NULL);
1309             }
1310         }
1311         else if (rule->user_pcre2) {
1312             if (lf->dstuser) {
1313                 if (!OSPcre2_Execute(lf->dstuser,
1314                                      rule->user_pcre2)) {
1315                     return (NULL);
1316                 }
1317             } else if (lf->srcuser) {
1318                 if (!OSPcre2_Execute(lf->srcuser,
1319                                      rule->user_pcre2)) {
1320                     return (NULL);
1321                 }
1322             } else {
1323                 /* no user set */
1324                 return (NULL);
1325             }
1326         }
1327
1328         /* Adding checks for geoip. */
1329         if(rule->srcgeoip) {
1330             if(lf->srcgeoip) {
1331                 if(!OSMatch_Execute(lf->srcgeoip,
1332                             strlen(lf->srcgeoip),
1333                             rule->srcgeoip))
1334                     return(NULL);
1335             } else {
1336                 return(NULL);
1337             }
1338         }
1339         else if(rule->srcgeoip_pcre2) {
1340             if(lf->srcgeoip) {
1341                 if(!OSPcre2_Execute(lf->srcgeoip,
1342                             rule->srcgeoip_pcre2))
1343                     return(NULL);
1344             } else {
1345                 return(NULL);
1346             }
1347         }
1348
1349
1350         if(rule->dstgeoip) {
1351             if(lf->dstgeoip) {
1352                 if(!OSMatch_Execute(lf->dstgeoip,
1353                             strlen(lf->dstgeoip),
1354                             rule->dstgeoip))
1355                     return(NULL);
1356             } else {
1357                 return(NULL);
1358             }
1359         }
1360         else if(rule->dstgeoip_pcre2) {
1361             if(lf->dstgeoip) {
1362                 if(!OSPcre2_Execute(lf->dstgeoip,
1363                             rule->dstgeoip_pcre2))
1364                     return(NULL);
1365             } else {
1366                 return(NULL);
1367             }
1368         }
1369
1370
1371         /* Check if any rule related to the size exist */
1372         if (rule->maxsize) {
1373             if (lf->size < rule->maxsize) {
1374                 return (NULL);
1375             }
1376         }
1377
1378         /* Check if we are in the right time */
1379         if (rule->day_time) {
1380             if (!OS_IsonTime(lf->hour, rule->day_time)) {
1381                 return (NULL);
1382             }
1383         }
1384
1385         /* Check week day */
1386         if (rule->week_day) {
1387             if (!OS_IsonDay(__crt_wday, rule->week_day)) {
1388                 return (NULL);
1389             }
1390         }
1391
1392         /* Get extra data */
1393         if (rule->extra_data) {
1394             if (!lf->data) {
1395                 return (NULL);
1396             }
1397
1398             if (!OSMatch_Execute(lf->data,
1399                                  strlen(lf->data),
1400                                  rule->extra_data)) {
1401                 return (NULL);
1402             }
1403         }
1404         else if (rule->extra_data_pcre2) {
1405             if (!lf->data) {
1406                 return (NULL);
1407             }
1408
1409             if (!OSPcre2_Execute(lf->data,
1410                                  rule->extra_data_pcre2)) {
1411                 return (NULL);
1412             }
1413         }
1414
1415         /* Check hostname */
1416         if (rule->hostname) {
1417             if (!lf->hostname) {
1418                 return (NULL);
1419             }
1420
1421             if (!OSMatch_Execute(lf->hostname,
1422                                  strlen(lf->hostname),
1423                                  rule->hostname)) {
1424                 return (NULL);
1425             }
1426         }
1427         else if (rule->hostname_pcre2) {
1428             if (!lf->hostname) {
1429                 return (NULL);
1430             }
1431
1432             if (!OSPcre2_Execute(lf->hostname,
1433                                  rule->hostname_pcre2)) {
1434                 return (NULL);
1435             }
1436         }
1437
1438         /* Check for status */
1439         if (rule->status) {
1440             if (!lf->status) {
1441                 return (NULL);
1442             }
1443
1444             if (!OSMatch_Execute(lf->status,
1445                                  strlen(lf->status),
1446                                  rule->status)) {
1447                 return (NULL);
1448             }
1449         }
1450         else if (rule->status_pcre2) {
1451             if (!lf->status) {
1452                 return (NULL);
1453             }
1454
1455             if (!OSPcre2_Execute(lf->status,
1456                                  rule->status_pcre2)) {
1457                 return (NULL);
1458             }
1459         }
1460
1461
1462         /* Do diff check */
1463         if (rule->context_opts & SAME_DODIFF) {
1464             if (!doDiff(rule, lf)) {
1465                 return (NULL);
1466             }
1467         }
1468     }
1469
1470     /* Check for the FTS flag */
1471     if (rule->alert_opts & DO_FTS) {
1472         /** FTS CHECKS **/
1473         if (lf->decoder_info->fts) {
1474             if (lf->decoder_info->fts & FTS_DONE) {
1475                 /* We already did the fts in here */
1476             } else if (!FTS(lf)) {
1477                 return (NULL);
1478             }
1479         } else {
1480             return (NULL);
1481         }
1482     }
1483
1484     /* List lookups */
1485     if (rule->lists != NULL) {
1486         ListRule *list_holder = rule->lists;
1487         while (list_holder) {
1488             switch (list_holder->field) {
1489                 case RULE_SRCIP:
1490                     if (!lf->srcip) {
1491                         return (NULL);
1492                     }
1493                     if (!OS_DBSearch(list_holder, lf->srcip)) {
1494                         return (NULL);
1495                     }
1496                     break;
1497                 case RULE_SRCPORT:
1498                     if (!lf->srcport) {
1499                         return (NULL);
1500                     }
1501                     if (!OS_DBSearch(list_holder, lf->srcport)) {
1502                         return (NULL);
1503                     }
1504                     break;
1505                 case RULE_DSTIP:
1506                     if (!lf->dstip) {
1507                         return (NULL);
1508                     }
1509                     if (!OS_DBSearch(list_holder, lf->dstip)) {
1510                         return (NULL);
1511                     }
1512                     break;
1513                 case RULE_DSTPORT:
1514                     if (!lf->dstport) {
1515                         return (NULL);
1516                     }
1517                     if (!OS_DBSearch(list_holder, lf->dstport)) {
1518                         return (NULL);
1519                     }
1520                     break;
1521                 case RULE_USER:
1522                     if (lf->srcuser) {
1523                         if (!OS_DBSearch(list_holder, lf->srcuser)) {
1524                             return (NULL);
1525                         }
1526                     } else if (lf->dstuser) {
1527                         if (!OS_DBSearch(list_holder, lf->dstuser)) {
1528                             return (NULL);
1529                         }
1530                     } else {
1531                         return (NULL);
1532                     }
1533                     break;
1534                 case RULE_URL:
1535                     if (!lf->url) {
1536                         return (NULL);
1537                     }
1538                     if (!OS_DBSearch(list_holder, lf->url)) {
1539                         return (NULL);
1540                     }
1541                     break;
1542                 case RULE_ID:
1543                     if (!lf->id) {
1544                         return (NULL);
1545                     }
1546                     if (!OS_DBSearch(list_holder, lf->id)) {
1547                         return (NULL);
1548                     }
1549                     break;
1550                 case RULE_HOSTNAME:
1551                     if (!lf->hostname) {
1552                         return (NULL);
1553                     }
1554                     if (!OS_DBSearch(list_holder, lf->hostname)) {
1555                         return (NULL);
1556                     }
1557                     break;
1558                 case RULE_PROGRAM_NAME:
1559                     if (!lf->program_name) {
1560                         return (NULL);
1561                     }
1562                     if (!OS_DBSearch(list_holder, lf->program_name)) {
1563                         return (NULL);
1564                     }
1565                     break;
1566                 case RULE_STATUS:
1567                     if (!lf->status) {
1568                         return (NULL);
1569                     }
1570                     if (!OS_DBSearch(list_holder, lf->status)) {
1571                         return (NULL);
1572                     }
1573                     break;
1574                 case RULE_ACTION:
1575                     if (!lf->action) {
1576                         return (NULL);
1577                     }
1578                     if (!OS_DBSearch(list_holder, lf->action)) {
1579                         return (NULL);
1580                     }
1581                     break;
1582                 default:
1583                     return (NULL);
1584             }
1585
1586             list_holder = list_holder->next;
1587         }
1588     }
1589
1590     /* If it is a context rule, search for it */
1591     if (rule->context == 1) {
1592         if (!(rule->context_opts & SAME_DODIFF)) {
1593             if (rule->event_search) {
1594                 if (!rule->event_search(lf, rule)) {
1595                     return (NULL);
1596                 }
1597             }
1598         }
1599     }
1600
1601 #ifdef TESTRULE
1602     if (full_output && !alert_only) {
1603         print_out("       *Rule %d matched.", rule->sigid);
1604     }
1605 #endif
1606
1607     /* Search for dependent rules */
1608     if (curr_node->child) {
1609         RuleNode *child_node = curr_node->child;
1610         RuleInfo *child_rule = NULL;
1611
1612 #ifdef TESTRULE
1613         if (full_output && !alert_only) {
1614             print_out("       *Trying child rules.");
1615         }
1616 #endif
1617
1618         while (child_node) {
1619             child_rule = OS_CheckIfRuleMatch(lf, child_node);
1620             if (child_rule != NULL) {
1621                 return (child_rule);
1622             }
1623
1624             child_node = child_node->next;
1625         }
1626     }
1627
1628     /* If we are set to no alert, keep going */
1629     if (rule->alert_opts & NO_ALERT) {
1630         return (NULL);
1631     }
1632
1633     hourly_alerts++;
1634     rule->firedtimes++;
1635
1636     return (rule); /* Matched */
1637 }
1638
1639 /*  Update each rule and print it to the logs */
1640 static void LoopRule(RuleNode *curr_node, FILE *flog)
1641 {
1642     if (curr_node->ruleinfo->firedtimes) {
1643         fprintf(flog, "%d-%d-%d-%d\n",
1644                 thishour,
1645                 curr_node->ruleinfo->sigid,
1646                 curr_node->ruleinfo->level,
1647                 curr_node->ruleinfo->firedtimes);
1648         curr_node->ruleinfo->firedtimes = 0;
1649     }
1650
1651     if (curr_node->child) {
1652         RuleNode *child_node = curr_node->child;
1653
1654         while (child_node) {
1655             LoopRule(child_node, flog);
1656             child_node = child_node->next;
1657         }
1658     }
1659     return;
1660 }
1661
1662 /* Dump the hourly stats about each rule */
1663 static void DumpLogstats()
1664 {
1665     RuleNode *rulenode_pt;
1666     char logfile[OS_FLSIZE + 1];
1667     FILE *flog;
1668
1669     /* Open log file */
1670     snprintf(logfile, OS_FLSIZE, "%s/%d/", STATSAVED, prev_year);
1671     if (IsDir(logfile) == -1)
1672         if (mkdir(logfile, 0770) == -1) {
1673             merror(MKDIR_ERROR, ARGV0, logfile, errno, strerror(errno));
1674             return;
1675         }
1676
1677     snprintf(logfile, OS_FLSIZE, "%s/%d/%s", STATSAVED, prev_year, prev_month);
1678
1679     if (IsDir(logfile) == -1)
1680         if (mkdir(logfile, 0770) == -1) {
1681             merror(MKDIR_ERROR, ARGV0, logfile, errno, strerror(errno));
1682             return;
1683         }
1684
1685
1686     /* Creat the logfile name */
1687     snprintf(logfile, OS_FLSIZE, "%s/%d/%s/ossec-%s-%02d.log",
1688              STATSAVED,
1689              prev_year,
1690              prev_month,
1691              "totals",
1692              today);
1693
1694     flog = fopen(logfile, "a");
1695     if (!flog) {
1696         merror(FOPEN_ERROR, ARGV0, logfile, errno, strerror(errno));
1697         return;
1698     }
1699
1700     rulenode_pt = OS_GetFirstRule();
1701
1702     if (!rulenode_pt) {
1703         ErrorExit("%s: Rules in an inconsistent state. Exiting.",
1704                   ARGV0);
1705     }
1706
1707     /* Loop over all the rules and print their stats */
1708     do {
1709         LoopRule(rulenode_pt, flog);
1710     } while ((rulenode_pt = rulenode_pt->next) != NULL);
1711
1712
1713     /* Print total for the hour */
1714     fprintf(flog, "%d--%d--%d--%d--%d\n\n",
1715             thishour,
1716             hourly_alerts, hourly_events, hourly_syscheck, hourly_firewall);
1717     hourly_alerts = 0;
1718     hourly_events = 0;
1719     hourly_syscheck = 0;
1720     hourly_firewall = 0;
1721
1722     fclose(flog);
1723 }
1724