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