Example #1
0
void OS_ReadMSG_analysisd(int m_queue)
#endif
{
    int i;
    char msg[OS_MAXSTR +1];
    Eventinfo *lf;

    RuleInfo *stats_rule = NULL;


    /* Null to global currently pointers */
    currently_rule = NULL;

    /* Initiating the logs */
    OS_InitLog();


    /* Initiating the integrity database */
    SyscheckInit();


    /* Initializing Rootcheck */
    RootcheckInit();


    /* Initializing host info */
    HostinfoInit();


    /* Creating the event list */
    OS_CreateEventList(Config.memorysize);


    /* Initiating the FTS list */
    if(!FTS_Init())
    {
        ErrorExit(FTS_LIST_ERROR, ARGV0);
    }

    /* Initialize the Accumulator */
    if(!Accumulate_Init()) {
        merror("accumulator: ERROR: Initialization failed");
        exit(1);
    }

    /* Starting the active response queues */
    if(Config.ar)
    {
        /* Waiting the ARQ to settle .. */
        sleep(3);


        #ifndef LOCAL
        if(Config.ar & REMOTE_AR)
        {
            if((arq = StartMQ(ARQUEUE, WRITE)) < 0)
            {
                merror(ARQ_ERROR, ARGV0);

                /* If LOCAL_AR is set, keep it there */
                if(Config.ar & LOCAL_AR)
                {
                    Config.ar = 0;
                    Config.ar|=LOCAL_AR;
                }
                else
                {
                    Config.ar = 0;
                }
            }
            else
            {
                verbose(CONN_TO, ARGV0, ARQUEUE, "active-response");
            }
        }

        #else
        /* Only for LOCAL_ONLY installs */
        if(Config.ar & REMOTE_AR)
        {
            if(Config.ar & LOCAL_AR)
            {
                Config.ar = 0;
                Config.ar|=LOCAL_AR;
            }
            else
            {
                Config.ar = 0;
            }
        }
        #endif

        if(Config.ar & LOCAL_AR)
        {
            if((execdq = StartMQ(EXECQUEUE, WRITE)) < 0)
            {
                merror(ARQ_ERROR, ARGV0);

                /* If REMOTE_AR is set, keep it there */
                if(Config.ar & REMOTE_AR)
                {
                    Config.ar = 0;
                    Config.ar|=REMOTE_AR;
                }
                else
                {
                    Config.ar = 0;
                }
            }
            else
            {
                verbose(CONN_TO, ARGV0, EXECQUEUE, "exec");
            }
        }
    }
    debug1("%s: DEBUG: Active response Init completed.", ARGV0);


    /* Getting currently time before starting */
    c_time = time(NULL);


    /* Starting the hourly/weekly stats */
    if(Start_Hour() < 0)
        Config.stats = 0;
    else
    {
        /* Initializing stats rules */
        stats_rule = zerorulemember(
                STATS_MODULE,
                Config.stats,
                0,0,0,0,0,0);

        if(!stats_rule)
        {
            ErrorExit(MEM_ERROR, ARGV0);
        }
        stats_rule->group = "stats,";
        stats_rule->comment = "Excessive number of events (above normal).";
    }


    /* Doing some cleanup */
    memset(msg, '\0', OS_MAXSTR +1);


    /* Initializing the logs */
    {
        lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
        if(!lf)
            ErrorExit(MEM_ERROR, ARGV0);
        lf->year = prev_year;
        strncpy(lf->mon, prev_month, 3);
        lf->day = today;

        if(OS_GetLogLocation(lf) < 0)
        {
            ErrorExit("%s: Error allocating log files", ARGV0);
        }

        Free_Eventinfo(lf);
    }


    debug1("%s: DEBUG: Startup completed. Waiting for new messages..",ARGV0);

    if(Config.custom_alert_output)
      debug1("%s: INFO: Custom output found.!",ARGV0);

    /* Daemon loop */
    while(1)
    {
        lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));

        /* This shouldn't happen .. */
        if(lf == NULL)
        {
            ErrorExit(MEM_ERROR,ARGV0);
        }

        DEBUG_MSG("%s: DEBUG: Waiting for msgs - %d ", ARGV0, (int)time(0));


        /* Receive message from queue */
        if((i = OS_RecvUnix(m_queue, OS_MAXSTR, msg)))
        {
            RuleNode *rulenode_pt;

            /* Getting the time we received the event */
            c_time = time(NULL);


            /* Default values for the log info */
            Zero_Eventinfo(lf);


            /* Checking for a valid message. */
            if(i < 4)
            {
                merror(IMSG_ERROR, ARGV0, msg);
                Free_Eventinfo(lf);
                continue;
            }


            /* Message before extracting header */
            DEBUG_MSG("%s: DEBUG: Received msg: %s ", ARGV0, msg);


            /* Clean the msg appropriately */
            if(OS_CleanMSG(msg, lf) < 0)
            {
                merror(IMSG_ERROR,ARGV0, msg);
                Free_Eventinfo(lf);
                continue;
            }


            /* Msg cleaned */
            DEBUG_MSG("%s: DEBUG: Msg cleanup: %s ", ARGV0, lf->log);


            /* Currently rule must be null in here */
            currently_rule = NULL;


            /** Checking the date/hour changes **/

            /* Update the hour */
            if(thishour != __crt_hour)
            {
                /* Search all the rules and print the number
                 * of alerts that each one fired.
                 */
                DumpLogstats();
                thishour = __crt_hour;

                /* Check if the date has changed */
                if(today != lf->day)
                {
                    if(Config.stats)
                    {
                        /* Update the hourly stats (done daily) */
                        Update_Hour();
                    }

                    if(OS_GetLogLocation(lf) < 0)
                    {
                        ErrorExit("%s: Error allocating log files", ARGV0);
                    }

                    today = lf->day;
                    strncpy(prev_month, lf->mon, 3);
                    prev_year = lf->year;
                }
            }


            /* Incrementing number of events received */
            hourly_events++;


            /***  Running decoders ***/

            /* Integrity check from syscheck */
            if(msg[0] == SYSCHECK_MQ)
            {
                hourly_syscheck++;

                if(!DecodeSyscheck(lf))
                {
                    /* We don't process syscheck events further */
                    goto CLMEM;
                }

                /* Getting log size */
                lf->size = strlen(lf->log);
            }

            /* Rootcheck decoding */
            else if(msg[0] == ROOTCHECK_MQ)
            {
                if(!DecodeRootcheck(lf))
                {
                    /* We don't process rootcheck events further */
                    goto CLMEM;
                }
                lf->size = strlen(lf->log);
            }

            /* Host information special decoder */
            else if(msg[0] == HOSTINFO_MQ)
            {
                if(!DecodeHostinfo(lf))
                {
                    /* We don't process hostinfo events further */
                    goto CLMEM;
                }
                lf->size = strlen(lf->log);
            }

            /* Run the general Decoders  */
            else
            {
                /* Getting log size */
                lf->size = strlen(lf->log);

                DecodeEvent(lf);
            }

            /* Run accumulator */
            if( lf->decoder_info->accumulate == 1 ) {
                lf = Accumulate(lf);
            }

            /* Firewall event */
            if(lf->decoder_info->type == FIREWALL)
            {
                /* If we could not get any information from
                 * the log, just ignore it
                 */
                hourly_firewall++;
                if(Config.logfw)
                {
                    if(!FW_Log(lf))
                    {
                        goto CLMEM;
                    }
                }
            }


            /* We only check if the last message is
             * duplicated on syslog.
             */
            else if(lf->decoder_info->type == SYSLOG)
            {
                /* Checking if the message is duplicated */
                if(LastMsg_Stats(lf->full_log) == 1)
                    goto CLMEM;
                else
                    LastMsg_Change(lf->full_log);
            }


            /* Stats checking */
            if(Config.stats)
            {
                if(Check_Hour() == 1)
                {
                    void *saved_rule = lf->generated_rule;
                    char *saved_log;

                    /* Saving previous log */
                    saved_log = lf->full_log;

                    lf->generated_rule = stats_rule;
                    lf->full_log = __stats_comment;


                    /* alert for statistical analysis */
                    if(stats_rule->alert_opts & DO_LOGALERT)
                    {
                        __crt_ftell = ftell(_aflog);
                        if(Config.custom_alert_output)
                        {
                          OS_CustomLog(lf,Config.custom_alert_output_format);
                        }
                        else
                        {
                          OS_Log(lf);
                        }

                    }


                    /* Set lf to the old values */
                    lf->generated_rule = saved_rule;
                    lf->full_log = saved_log;
                }
            }


            /* Checking the rules */
            DEBUG_MSG("%s: DEBUG: Checking the rules - %d ",
                           ARGV0, lf->decoder_info->type);


            /* Looping all the rules */
            rulenode_pt = OS_GetFirstRule();
            if(!rulenode_pt)
            {
                ErrorExit("%s: Rules in an inconsistent state. Exiting.",
                        ARGV0);
            }


            do
            {
                if(lf->decoder_info->type == OSSEC_ALERT)
                {
                    if(!lf->generated_rule)
                    {
                        goto CLMEM;
                    }

                    /* We go ahead in here and process the alert. */
                    currently_rule = lf->generated_rule;
                }

                /* The categories must match */
                else if(rulenode_pt->ruleinfo->category !=
                        lf->decoder_info->type)
                {
                    continue;
                }

                /* Checking each rule. */
                else if((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt))
                        == NULL)
                {
                    continue;
                }


                /* Ignore level 0 */
                if(currently_rule->level == 0)
                {
                    break;
                }


                /* Checking ignore time */
                if(currently_rule->ignore_time)
                {
                    if(currently_rule->time_ignored == 0)
                    {
                        currently_rule->time_ignored = lf->time;
                    }
                    /* If the currently time - the time the rule was ignored
                     * is less than the time it should be ignored,
                     * leave (do not alert again).
                     */
                    else if((lf->time - currently_rule->time_ignored)
                            < currently_rule->ignore_time)
                    {
                        break;
                    }
                    else
                    {
                        currently_rule->time_ignored = lf->time;
                    }
                }


                /* Pointer to the rule that generated it */
                lf->generated_rule = currently_rule;


                /* Checking if we should ignore it */
                if(currently_rule->ckignore && IGnore(lf))
                {
                    /* Ignoring rule */
                    lf->generated_rule = NULL;
                    break;
                }


                /* Checking if we need to add to ignore list */
                if(currently_rule->ignore)
                {
                    AddtoIGnore(lf);
                }


                /* Log the alert if configured to ... */
                if(currently_rule->alert_opts & DO_LOGALERT)
                {
                    __crt_ftell = ftell(_aflog);

                    if(Config.custom_alert_output)
                    {
                      OS_CustomLog(lf,Config.custom_alert_output_format);
                    }
                    else
                    {
                      OS_Log(lf);
                    }
                }


                /* Log to prelude */
                #ifdef PRELUDE
                if(Config.prelude)
                {
                    if(Config.prelude_log_level <= currently_rule->level)
                    {
                        OS_PreludeLog(lf);
                    }
                }
                #endif

                /* Log to zeromq */
                #ifdef ZEROMQ_OUTPUT
                if(Config.zeromq_output)
                {
                    zeromq_output_event(lf);
                }
                #endif


                /* Log to Picviz */
                if (Config.picviz)
                {
                    OS_PicvizLog(lf);
                }


                /* Execute an active response */
                if(currently_rule->ar)
                {
                    int do_ar;
                    active_response **rule_ar;

                    rule_ar = currently_rule->ar;

                    while(*rule_ar)
                    {
                        do_ar = 1;
                        if((*rule_ar)->ar_cmd->expect & USERNAME)
                        {
                            if(!lf->dstuser ||
                                !OS_PRegex(lf->dstuser,"^[a-zA-Z._0-9@?-]*$"))
                            {
                                if(lf->dstuser)
                                    merror(CRAFTED_USER, ARGV0, lf->dstuser);
                                do_ar = 0;
                            }
                        }
                        if((*rule_ar)->ar_cmd->expect & SRCIP)
                        {
                            if(!lf->srcip ||
                                !OS_PRegex(lf->srcip, "^[a-zA-Z.:_0-9-]*$"))
                            {
                                if(lf->srcip)
                                    merror(CRAFTED_IP, ARGV0, lf->srcip);
                                do_ar = 0;
                            }
                        }
                        if((*rule_ar)->ar_cmd->expect & FILENAME)
                        {
                            if(!lf->filename)
                            {
                                do_ar = 0;
                            }
                        }

                        if(do_ar)
                        {
                            OS_Exec(&execdq, &arq, lf, *rule_ar);
                        }
                        rule_ar++;
                    }
                }


                /* Copy the structure to the state memory of if_matched_sid */
                if(currently_rule->sid_prev_matched)
                {
                    if(!OSList_AddData(currently_rule->sid_prev_matched, lf))
                    {
                        merror("%s: Unable to add data to sig list.", ARGV0);
                    }
                    else
                    {
                        lf->sid_node_to_delete =
                            currently_rule->sid_prev_matched->last_node;
                    }
                }
                /* Group list */
                else if(currently_rule->group_prev_matched)
                {
                    i = 0;

                    while(i < currently_rule->group_prev_matched_sz)
                    {
                        if(!OSList_AddData(
                                currently_rule->group_prev_matched[i],
                                lf))
                        {
                           merror("%s: Unable to add data to grp list.",ARGV0);
                        }
                        i++;
                    }
                }

                OS_AddEvent(lf);

                break;

            }while((rulenode_pt = rulenode_pt->next) != NULL);


            /* If configured to log all, do it */
            if(Config.logall)
                OS_Store(lf);


            /* Cleaning the memory */
            CLMEM:


            /* Only clear the memory if the eventinfo was not
             * added to the stateful memory
             * -- message is free inside clean event --
             */
            if(lf->generated_rule == NULL)
                Free_Eventinfo(lf);

        }
        else
        {
            free(lf);
        }
    }
    return;
}
Example #2
0
void OS_ReadMSG(char *ut_str)
{
    char msg[OS_MAXSTR + 1];
    int exit_code = 0;
    char *ut_alertlevel = NULL;
    char *ut_rulelevel = NULL;
    char *ut_decoder_name = NULL;

    if (ut_str) {
        /* XXX Break apart string */
        ut_rulelevel = ut_str;
        ut_alertlevel =  strchr(ut_rulelevel, ':');
        if (!ut_alertlevel) {
            ErrorExit("%s: -U requires the matching format to be "
                      "\"<rule_id>:<alert_level>:<decoder_name>\"", ARGV0);
        } else {
            *ut_alertlevel = '\0';
            ut_alertlevel++;
        }
        ut_decoder_name = strchr(ut_alertlevel, ':');
        if (!ut_decoder_name) {
            ErrorExit("%s: -U requires the matching format to be "
                      "\"<rule_id>:<alert_level>:<decoder_name>\"", ARGV0);
        } else {
            *ut_decoder_name = '\0';
            ut_decoder_name++;
        }
    }

    RuleInfoDetail *last_info_detail;
    Eventinfo *lf;

    /* Null global pointer to current rule */
    currently_rule = NULL;

    /* Create the event list */
    OS_CreateEventList(Config.memorysize);

    /* Initiate the FTS list */
    if (!FTS_Init()) {
        ErrorExit(FTS_LIST_ERROR, ARGV0);
    }

    /* Initialize the Accumulator */
    if (!Accumulate_Init()) {
        merror("accumulator: ERROR: Initialization failed");
        exit(1);
    }

    __crt_ftell = 1;

    /* Get current time before starting */
    c_time = time(NULL);

    /* Do some cleanup */
    memset(msg, '\0', OS_MAXSTR + 1);

    if (!alert_only) {
        print_out("%s: Type one log per line.\n", ARGV0);
    }

    /* Daemon loop */
    while (1) {
        lf = (Eventinfo *)calloc(1, sizeof(Eventinfo));
        os_calloc(Config.decoder_order_size, sizeof(char*), lf->fields);

        /* This shouldn't happen */
        if (lf == NULL) {
            ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
        }

        /* Fix the msg */
        snprintf(msg, 15, "1:stdin:");

        /* Receive message from queue */
        if (fgets(msg + 8, OS_MAXSTR - 8, stdin)) {
            RuleNode *rulenode_pt;

            /* Get the time we received the event */
            c_time = time(NULL);

            /* Remov newline */
            if (msg[strlen(msg) - 1] == '\n') {
                msg[strlen(msg) - 1] = '\0';
            }

            /* Make sure we ignore blank lines */
            if (strlen(msg) < 10) {
                continue;
            }

            if (!alert_only) {
                print_out("\n");
            }

            /* Default values for the log info */
            Zero_Eventinfo(lf);

            /* Clean the msg appropriately */
            if (OS_CleanMSG(msg, lf) < 0) {
                merror(IMSG_ERROR, ARGV0, msg);

                Free_Eventinfo(lf);

                continue;
            }

            /* Current rule must be null in here */
            currently_rule = NULL;

            /***  Run decoders ***/
            /* Get log size */
            lf->size = strlen(lf->log);

            /* Decode event */
            DecodeEvent(lf);

            /* Run accumulator */
            if ( lf->decoder_info->accumulate == 1 ) {
                print_out("\n**ACCUMULATOR: LEVEL UP!!**\n");
                lf = Accumulate(lf);
            }

            /* Loop over all the rules */
            rulenode_pt = OS_GetFirstRule();
            if (!rulenode_pt) {
                ErrorExit("%s: Rules in an inconsistent state. Exiting.",
                          ARGV0);
            }

#ifdef TESTRULE
            if (full_output && !alert_only) {
                print_out("\n**Rule debugging:");
            }
#endif

            do {
                if (lf->decoder_info->type == OSSEC_ALERT) {
                    if (!lf->generated_rule) {
                        break;
                    }

                    /* Process the alert */
                    currently_rule = lf->generated_rule;
                }

                /* The categories must match */
                else if (rulenode_pt->ruleinfo->category !=
                         lf->decoder_info->type) {
                    continue;
                }

                /* Check each rule */
                else if ((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt))
                         == NULL) {
                    continue;
                }

#ifdef TESTRULE
                if (!alert_only) {
                    const char *(ruleinfodetail_text[]) = {"Text", "Link", "CVE", "OSVDB", "BUGTRACKID"};
                    print_out("\n**Phase 3: Completed filtering (rules).");
                    print_out("       Rule id: '%d'", currently_rule->sigid);
                    print_out("       Level: '%d'", currently_rule->level);
                    print_out("       Description: '%s'", currently_rule->comment);
                    for (last_info_detail = currently_rule->info_details; last_info_detail != NULL; last_info_detail = last_info_detail->next) {
                        print_out("       Info - %s: '%s'", ruleinfodetail_text[last_info_detail->type], last_info_detail->data);
                    }
                }
#endif

                /* Ignore level 0 */
                if (currently_rule->level == 0) {
                    break;
                }

                /* Check ignore time */
                if (currently_rule->ignore_time) {
                    if (currently_rule->time_ignored == 0) {
                        currently_rule->time_ignored = lf->time;
                    }
                    /* If the current time - the time the rule was ignored
                     * is less than the time it should be ignored,
                     * do not alert again
                     */
                    else if ((lf->time - currently_rule->time_ignored)
                             < currently_rule->ignore_time) {
                        break;
                    } else {
                        currently_rule->time_ignored = 0;
                    }
                }

                /* Pointer to the rule that generated it */
                lf->generated_rule = currently_rule;


                /* Check if we should ignore it */
                if (currently_rule->ckignore && IGnore(lf)) {
                    lf->generated_rule = NULL;
                    break;
                }

                /* Check if we need to add to ignore list */
                if (currently_rule->ignore) {
                    AddtoIGnore(lf);
                }

                /* Log the alert if configured to */
                if (currently_rule->alert_opts & DO_LOGALERT) {
                    if (alert_only) {
                        OS_LogOutput(lf);
                        __crt_ftell++;
                    } else {
                        print_out("**Alert to be generated.\n\n");
                    }
                }

                /* Copy the structure to the state memory of if_matched_sid */
                if (currently_rule->sid_prev_matched) {
                    if (!OSList_AddData(currently_rule->sid_prev_matched, lf)) {
                        merror("%s: Unable to add data to sig list.", ARGV0);
                    } else {
                        lf->sid_node_to_delete =
                            currently_rule->sid_prev_matched->last_node;
                    }
                }

                /* Group list */
                else if (currently_rule->group_prev_matched) {
                    unsigned int i = 0;

                    while (i < currently_rule->group_prev_matched_sz) {
                        if (!OSList_AddData(
                                    currently_rule->group_prev_matched[i],
                                    lf)) {
                            merror("%s: Unable to add data to grp list.", ARGV0);
                        }
                        i++;
                    }
                }

                OS_AddEvent(lf);
                break;

            } while ((rulenode_pt = rulenode_pt->next) != NULL);

            if (ut_str) {
                /* Set up exit code if we are doing unit testing */
                char holder[1024];
                holder[1] = '\0';
                exit_code = 3;
                print_out("lf->decoder_info->name: '%s'", lf->decoder_info->name);
                print_out("ut_decoder_name       : '%s'", ut_decoder_name);
                if (lf->decoder_info->name != NULL && strcasecmp(ut_decoder_name, lf->decoder_info->name) == 0) {
                    exit_code--;

                    if (!currently_rule) {
                        merror("%s: currently_rule not set!", ARGV0);
                        exit(-1);
                    }
                    snprintf(holder, 1023, "%d", currently_rule->sigid);
                    if (strcasecmp(ut_rulelevel, holder) == 0) {
                        exit_code--;
                        snprintf(holder, 1023, "%d", currently_rule->level);
                        if (strcasecmp(ut_alertlevel, holder) == 0) {
                            exit_code--;
                            printf("%d\n", exit_code);
                        }
                    }
                } else if (lf->decoder_info->name != NULL) {
                    print_out("decoder matched : '%s'", lf->decoder_info->name);
                    print_out("decoder expected: '%s'", ut_decoder_name);
                } else {
                    print_out("decoder matched : 'NULL'");
                }
            }

            /* Only clear the memory if the eventinfo was not
             * added to the stateful memory
             * -- message is free inside clean event --
             */
            if (lf->generated_rule == NULL) {
                Free_Eventinfo(lf);
            }

        } else {
            exit(exit_code);
        }
    }
    exit(exit_code);
}