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