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