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