예제 #1
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));

        /* 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);
}
예제 #2
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;

    /* Initialize the logs */
    OS_InitLog();

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

    /* Initialize Rootcheck */
    RootcheckInit();

    /* Initialize host info */
    HostinfoInit();

    /* 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);
    }

    /* Start 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);

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

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

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

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

    /* Initialize the logs */
    {
        lf = (Eventinfo *)calloc(1, sizeof(Eventinfo));
        if (!lf) {
            ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
        }
        os_calloc(Config.decoder_order_size, sizeof(char*), lf->fields);
        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));
        os_calloc(Config.decoder_order_size, sizeof(char*), lf->fields);

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

        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;

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

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

            /* Check 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);

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

            /** Check 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;
                }
            }


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

            /***  Run decoders ***/

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

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

                /* Get 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 {
                /* Get 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) {
                /* Check 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) {
                    RuleInfo *saved_rule = lf->generated_rule;
                    char *saved_log;

                    /* Save 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 if (Config.alerts_log) {
                            OS_Log(lf);
                        }
                        /* Log to json file */
                        if (Config.jsonout_output) {
                            jsonout_output_event(lf);
                        }

                    }

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

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

            /* Loop over 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;
                    }

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

                /* 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;
                }

                /* 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,
                     * 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;

                /* Check if we should ignore it */
                if (currently_rule->ckignore && IGnore(lf)) {
                    /* Ignore rule */
                    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) {
                    __crt_ftell = ftell(_aflog);

                    if (Config.custom_alert_output) {
                        OS_CustomLog(lf, Config.custom_alert_output_format);
                    } else if (Config.alerts_log) {
                        OS_Log(lf);
                    }
                    /* Log to json file */
                    if (Config.jsonout_output) {
                        jsonout_output_event(lf);
                    }
                }

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

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


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

                /* 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) {
                    unsigned int j = 0;

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

                OS_AddEvent(lf);

                break;

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

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


CLMEM:
            /** Cleaning the memory **/

            /* 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);
        }
    }
}
예제 #3
0
/* Dump the hourly stats about each rule */
static void DumpLogstats()
{
    RuleNode *rulenode_pt;
    char logfile[OS_FLSIZE + 1];
    FILE *flog;

    /* Open log file */
    snprintf(logfile, OS_FLSIZE, "%s/%d/", STATSAVED, prev_year);
    if (IsDir(logfile) == -1)
        if (mkdir(logfile, 0770) == -1) {
            merror(MKDIR_ERROR, ARGV0, logfile, errno, strerror(errno));
            return;
        }

    snprintf(logfile, OS_FLSIZE, "%s/%d/%s", STATSAVED, prev_year, prev_month);

    if (IsDir(logfile) == -1)
        if (mkdir(logfile, 0770) == -1) {
            merror(MKDIR_ERROR, ARGV0, logfile, errno, strerror(errno));
            return;
        }


    /* Creat the logfile name */
    snprintf(logfile, OS_FLSIZE, "%s/%d/%s/ossec-%s-%02d.log",
             STATSAVED,
             prev_year,
             prev_month,
             "totals",
             today);

    flog = fopen(logfile, "a");
    if (!flog) {
        merror(FOPEN_ERROR, ARGV0, logfile, errno, strerror(errno));
        return;
    }

    rulenode_pt = OS_GetFirstRule();

    if (!rulenode_pt) {
        ErrorExit("%s: Rules in an inconsistent state. Exiting.",
                  ARGV0);
    }

    /* Loop over all the rules and print their stats */
    do {
        LoopRule(rulenode_pt, flog);
    } while ((rulenode_pt = rulenode_pt->next) != NULL);


    /* Print total for the hour */
    fprintf(flog, "%d--%d--%d--%d--%d\n\n",
            thishour,
            hourly_alerts, hourly_events, hourly_syscheck, hourly_firewall);
    hourly_alerts = 0;
    hourly_events = 0;
    hourly_syscheck = 0;
    hourly_firewall = 0;

    fclose(flog);
}
예제 #4
0
int main_analysisd(int argc, char **argv)
#endif
{
    int c = 0, m_queue = 0, test_config = 0, run_foreground = 0;
    int debug_level = 0;
    const char *dir = DEFAULTDIR;
    const char *user = USER;
    const char *group = GROUPGLOBAL;
    uid_t uid;
    gid_t gid;

    const char *cfg = DEFAULTCPATH;

    /* Set the name */
    OS_SetName(ARGV0);

    thishour = 0;
    today = 0;
    prev_year = 0;
    memset(prev_month, '\0', 4);
    hourly_alerts = 0;
    hourly_events = 0;
    hourly_syscheck = 0;
    hourly_firewall = 0;

#ifdef LIBGEOIP_ENABLED
    geoipdb = NULL;
#endif


    while ((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1) {
        switch (c) {
            case 'V':
                print_version();
                break;
            case 'h':
                help_analysisd();
                break;
            case 'd':
                nowDebug();
                debug_level = 1;
                break;
            case 'f':
                run_foreground = 1;
                break;
            case 'u':
                if (!optarg) {
                    ErrorExit("%s: -u needs an argument", ARGV0);
                }
                user = optarg;
                break;
            case 'g':
                if (!optarg) {
                    ErrorExit("%s: -g needs an argument", ARGV0);
                }
                group = optarg;
                break;
            case 'D':
                if (!optarg) {
                    ErrorExit("%s: -D needs an argument", ARGV0);
                }
                dir = optarg;
                break;
            case 'c':
                if (!optarg) {
                    ErrorExit("%s: -c needs an argument", ARGV0);
                }
                cfg = optarg;
                break;
            case 't':
                test_config = 1;
                break;
            default:
                help_analysisd();
                break;
        }

    }

    /* Check current debug_level
     * Command line setting takes precedence
     */
    if (debug_level == 0) {
        /* Get debug level */
        debug_level = getDefine_Int("analysisd", "debug", 0, 2);
        while (debug_level != 0) {
            nowDebug();
            debug_level--;
        }
    }

    /* Start daemon */
    debug1(STARTED_MSG, ARGV0);
    DEBUG_MSG("%s: DEBUG: Starting on debug mode - %d ", ARGV0, (int)time(0));

    /* Check if the user/group given are valid */
    uid = Privsep_GetUser(user);
    gid = Privsep_GetGroup(group);
    if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
        ErrorExit(USER_ERROR, ARGV0, user, group);
    }

    /* Found user */
    debug1(FOUND_USER, ARGV0);

    /* Initialize Active response */
    AR_Init();
    if (AR_ReadConfig(cfg) < 0) {
        ErrorExit(CONFIG_ERROR, ARGV0, cfg);
    }
    debug1(ASINIT, ARGV0);

    /* Read configuration file */
    if (GlobalConf(cfg) < 0) {
        ErrorExit(CONFIG_ERROR, ARGV0, cfg);
    }

    debug1(READ_CONFIG, ARGV0);


#ifdef LIBGEOIP_ENABLED
    Config.geoip_jsonout = getDefine_Int("analysisd", "geoip_jsonout", 0, 1);

    /* Opening GeoIP DB */
    if(Config.geoipdb_file) {
        geoipdb = GeoIP_open(Config.geoipdb_file, GEOIP_INDEX_CACHE);
        if (geoipdb == NULL)
        {
            merror("%s: ERROR: Unable to open GeoIP database from: %s (disabling GeoIP).", ARGV0, Config.geoipdb_file);
        }
    }
#endif



    /* Fix Config.ar */
    Config.ar = ar_flag;
    if (Config.ar == -1) {
        Config.ar = 0;
    }

    /* Get server's hostname */
    memset(__shost, '\0', 512);
    if (gethostname(__shost, 512 - 1) != 0) {
        strncpy(__shost, OSSEC_SERVER, 512 - 1);
    } else {
        char *_ltmp;

        /* Remove domain part if available */
        _ltmp = strchr(__shost, '.');
        if (_ltmp) {
            *_ltmp = '\0';
        }
    }

    /* Continuing in Daemon mode */
    if (!test_config && !run_foreground) {
        nowDaemon();
        goDaemon();
    }

#ifdef PRELUDE_OUTPUT_ENABLED
    /* Start prelude */
    if (Config.prelude) {
        prelude_start(Config.prelude_profile, argc, argv);
    }
#endif

#ifdef ZEROMQ_OUTPUT_ENABLED
    /* Start zeromq */
    if (Config.zeromq_output) {
#if CZMQ_VERSION_MAJOR == 2
        zeromq_output_start(Config.zeromq_output_uri);
#elif CZMQ_VERSION_MAJOR >= 3
        zeromq_output_start(Config.zeromq_output_uri, Config.zeromq_output_client_cert, Config.zeromq_output_server_cert);
#endif
    }
#endif

#ifdef PICVIZ_OUTPUT_ENABLED
    /* Open the Picviz socket */
    if (Config.picviz) {
        OS_PicvizOpen(Config.picviz_socket);

        if (chown(Config.picviz_socket, uid, gid) == -1) {
            ErrorExit(CHOWN_ERROR, ARGV0, Config.picviz_socket, errno, strerror(errno));
        }
    }
#endif

    /* Set the group */
    if (Privsep_SetGroup(gid) < 0) {
        ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
    }

    /* Chroot */
    if (Privsep_Chroot(dir) < 0) {
        ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
    }
    nowChroot();

    Config.decoder_order_size = (size_t)getDefine_Int("analysisd", "decoder_order_size", MIN_ORDER_SIZE, MAX_DECODER_ORDER_SIZE);

    /*
     * Anonymous Section: Load rules, decoders, and lists
     *
     * As lists require two-pass loading of rules that makes use of lists, lookups
     * are created with blank database structs, and need to be filled in after
     * completion of all rules and lists.
     */
    {
        {
            /* Initialize the decoders list */
            OS_CreateOSDecoderList();

            if (!Config.decoders) {
                /* Legacy loading */
                /* Read decoders */
                if (!ReadDecodeXML(XML_DECODER)) {
                    ErrorExit(CONFIG_ERROR, ARGV0,  XML_DECODER);
                }

                /* Read local ones */
                c = ReadDecodeXML(XML_LDECODER);
                if (!c) {
                    if ((c != -2)) {
                        ErrorExit(CONFIG_ERROR, ARGV0,  XML_LDECODER);
                    }
                } else {
                    if (!test_config) {
                        verbose("%s: INFO: Reading local decoder file.", ARGV0);
                    }
                }
            } else {
                /* New loaded based on file speified in ossec.conf */
                char **decodersfiles;
                decodersfiles = Config.decoders;
                while ( decodersfiles && *decodersfiles) {
                    if (!test_config) {
                        verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
                    }
                    if (!ReadDecodeXML(*decodersfiles)) {
                        ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles);
                    }

                    free(*decodersfiles);
                    decodersfiles++;
                }
            }

            /* Load decoders */
            SetDecodeXML();
        }
        {
            /* Load Lists */
            /* Initialize the lists of list struct */
            Lists_OP_CreateLists();
            /* Load each list into list struct */
            {
                char **listfiles;
                listfiles = Config.lists;
                while (listfiles && *listfiles) {
                    if (!test_config) {
                        verbose("%s: INFO: Reading loading the lists file: '%s'", ARGV0, *listfiles);
                    }
                    if (Lists_OP_LoadList(*listfiles) < 0) {
                        ErrorExit(LISTS_ERROR, ARGV0, *listfiles);
                    }
                    free(*listfiles);
                    listfiles++;
                }
                free(Config.lists);
                Config.lists = NULL;
            }
        }

        {
            /* Load Rules */
            /* Create the rules list */
            Rules_OP_CreateRules();

            /* Read the rules */
            {
                char **rulesfiles;
                rulesfiles = Config.includes;
                while (rulesfiles && *rulesfiles) {
                    if (!test_config) {
                        verbose("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles);
                    }
                    if (Rules_OP_ReadRules(*rulesfiles) < 0) {
                        ErrorExit(RULES_ERROR, ARGV0, *rulesfiles);
                    }

                    free(*rulesfiles);
                    rulesfiles++;
                }

                free(Config.includes);
                Config.includes = NULL;
            }

            /* Find all rules that require list lookups and attache the the
             * correct list struct to the rule. This keeps rules from having to
             * search thought the list of lists for the correct file during
             * rule evaluation.
             */
            OS_ListLoadRules();
        }
    }

    /* Fix the levels/accuracy */
    {
        int total_rules;
        RuleNode *tmp_node = OS_GetFirstRule();

        total_rules = _setlevels(tmp_node, 0);
        if (!test_config) {
            verbose("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules);
        }
    }

    /* Create a rules hash (for reading alerts from other servers) */
    {
        RuleNode *tmp_node = OS_GetFirstRule();
        Config.g_rules_hash = OSHash_Create();
        if (!Config.g_rules_hash) {
            ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
        }
        AddHash_Rule(tmp_node);
    }

    /* Ignored files on syscheck */
    {
        char **files;
        files = Config.syscheck_ignore;
        while (files && *files) {
            if (!test_config) {
                verbose("%s: INFO: Ignoring file: '%s'", ARGV0, *files);
            }
            files++;
        }
    }

    /* Check if log_fw is enabled */
    Config.logfw = (u_int8_t) getDefine_Int("analysisd",
                                 "log_fw",
                                 0, 1);

    /* Success on the configuration test */
    if (test_config) {
        exit(0);
    }

    /* Verbose message */
    debug1(PRIVSEP_MSG, ARGV0, dir, user);

    /* Signal manipulation */
    StartSIG(ARGV0);

    /* Set the user */
    if (Privsep_SetUser(uid) < 0) {
        ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
    }

    /* Create the PID file */
    if (CreatePID(ARGV0, getpid()) < 0) {
        ErrorExit(PID_ERROR, ARGV0);
    }

    /* Set the queue */
    if ((m_queue = StartMQ(DEFAULTQUEUE, READ)) < 0) {
        ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno));
    }

    /* Whitelist */
    if (Config.white_list == NULL) {
        if (Config.ar) {
            verbose("%s: INFO: No IP in the white list for active reponse.", ARGV0);
        }
    } else {
        if (Config.ar) {
            os_ip **wl;
            int wlc = 0;
            wl = Config.white_list;
            while (*wl) {
                verbose("%s: INFO: White listing IP: '%s'", ARGV0, (*wl)->ip);
                wl++;
                wlc++;
            }
            verbose("%s: INFO: %d IPs in the white list for active response.",
                    ARGV0, wlc);
        }
    }

    /* Hostname whitelist */
    if (Config.hostname_white_list == NULL) {
        if (Config.ar)
            verbose("%s: INFO: No Hostname in the white list for active reponse.",
                    ARGV0);
    } else {
        if (Config.ar) {
            int wlc = 0;
            OSMatch **wl;

            wl = Config.hostname_white_list;
            while (*wl) {
                char **tmp_pts = (*wl)->patterns;
                while (*tmp_pts) {
                    verbose("%s: INFO: White listing Hostname: '%s'", ARGV0, *tmp_pts);
                    wlc++;
                    tmp_pts++;
                }
                wl++;
            }
            verbose("%s: INFO: %d Hostname(s) in the white list for active response.",
                    ARGV0, wlc);
        }
    }

    /* Startup message */
    verbose(STARTUP_MSG, ARGV0, (int)getpid());

    /* Going to main loop */
    OS_ReadMSG(m_queue);

#ifdef PICVIZ_OUTPUT_ENABLED
    if (Config.picviz) {
        OS_PicvizClose();
    }
#endif

    exit(0);
}
예제 #5
0
/** int main(int argc, char **argv)
 */
int main(int argc, char **argv)
{
    int t_config = 0;
    int c = 0, m_queue = 0;
    char *ut_str = NULL;

    char *dir = DEFAULTDIR;
    // TODO: delete or implement
    char *user __attribute__((unused)) = USER;
    // TODO: delete or implement
    char *group __attribute__((unused)) = GROUPGLOBAL;

    char *cfg = DEFAULTCPATH;

    /* Setting the name */
    OS_SetName(ARGV0);

    thishour = 0;
    today = 0;
    prev_year = 0;
    full_output = 0;
    alert_only = 0;

    active_responses = NULL;
    memset(prev_month, '\0', 4);

    while((c = getopt(argc, argv, "VatvdhU:u:g:D:c:")) != -1){
        switch(c){
	    case 'V':
		print_version();
		break;
            case 't':
                t_config = 1;
                break;
            case 'h':
                logtest_help(ARGV0);
                break;
            case 'd':
                nowDebug();
                break;
            case 'U':
                if(!optarg)
                    ErrorExit("%s: -U needs an argument",ARGV0);
                ut_str = optarg;
                break;
            case 'u':
                if(!optarg)
                    ErrorExit("%s: -u needs an argument",ARGV0);
                user = optarg;
                break;
            case 'g':
                if(!optarg)
                    ErrorExit("%s: -g needs an argument",ARGV0);
                group = optarg;
                break;
            case 'D':
                if(!optarg)
                    ErrorExit("%s: -D needs an argument",ARGV0);
                dir = optarg;
                break;
            case 'c':
                if(!optarg)
                    ErrorExit("%s: -c needs an argument",ARGV0);
                cfg = optarg;
                break;
            case 'a':
                alert_only = 1;
                break;
            case 'v':
                full_output = 1;
                break;
            default:
                logtest_help(ARGV0);
                break;
        }

    }




    /* Reading configuration file */
    if(GlobalConf(cfg) < 0)
    {
        ErrorExit(CONFIG_ERROR,ARGV0, cfg);
    }

    debug1(READ_CONFIG, ARGV0);



    /* Getting servers hostname */
    memset(__shost, '\0', 512);
    if(gethostname(__shost, 512 -1) != 0)
    {
        strncpy(__shost, OSSEC_SERVER, 512 -1);
    }
    else
    {
        char *_ltmp;

        /* Remove domain part if available */
        _ltmp = strchr(__shost, '.');
        if(_ltmp)
            *_ltmp = '\0';
    }



    if(chdir(dir) != 0)
        ErrorExit(CHROOT_ERROR,ARGV0,dir);


    /*
     * Anonymous Section: Load rules, decoders, and lists
     *
     * As lists require two pass loading of rules that make use of list lookups
     * are created with blank database structs, and need to be filled in after
     * completion of all rules and lists.
     */
    {
        { /* Lad decders */
            /* Initializing the decoders list */
            OS_CreateOSDecoderList();

            if(!Config.decoders)
            { /* Legacy loading */
                /* Reading decoders */
                if(!ReadDecodeXML("etc/decoder.xml"))
                {
                    ErrorExit(CONFIG_ERROR, ARGV0,  XML_DECODER);
                }

                /* Reading local ones. */
                c = ReadDecodeXML("etc/local_decoder.xml");
                if(!c)
                {
                    if((c != -2))
                        ErrorExit(CONFIG_ERROR, ARGV0,  XML_LDECODER);
                }
                else
                {
                    verbose("%s: INFO: Reading local decoder file.", ARGV0);
                }
            }
            else
            { /* New loaded based on file speified in ossec.conf */
                char **decodersfiles;
                decodersfiles = Config.decoders;
                while( decodersfiles && *decodersfiles)
                {

                    verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
                    if(!ReadDecodeXML(*decodersfiles))
                        ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles);

                    free(*decodersfiles);
                    decodersfiles++;
                }
            }

            /* Load decoders */
            SetDecodeXML();
        }
        { /* Load Lists */
            /* Initializing the lists of list struct */
            Lists_OP_CreateLists();
            /* Load each list into list struct */
            {
                char **listfiles;
                listfiles = Config.lists;
                while(listfiles && *listfiles)
                {
                    verbose("%s: INFO: Reading the lists file: '%s'", ARGV0, *listfiles);
                    if(Lists_OP_LoadList(*listfiles) < 0)
                        ErrorExit(LISTS_ERROR, ARGV0, *listfiles);
                    free(*listfiles);
                    listfiles++;
                }
                free(Config.lists);
                Config.lists = NULL;
            }
        }
        { /* Load Rules */
            /* Creating the rules list */
            Rules_OP_CreateRules();

            /* Reading the rules */
            {
                char **rulesfiles;
                rulesfiles = Config.includes;
                while(rulesfiles && *rulesfiles)
                {
                    debug1("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles);
                    if(Rules_OP_ReadRules(*rulesfiles) < 0)
                        ErrorExit(RULES_ERROR, ARGV0, *rulesfiles);

                    free(*rulesfiles);
                    rulesfiles++;
                }

                free(Config.includes);
                Config.includes = NULL;
            }

            /* Find all rules with that require list lookups and attache the
             * the correct list struct to the rule.  This keeps rules from having to
             * search thought the list of lists for the correct file during rule evaluation.
             */
            OS_ListLoadRules();
        }
    }


    /* Fixing the levels/accuracy */
    {
        int total_rules;
        RuleNode *tmp_node = OS_GetFirstRule();

        total_rules = _setlevels(tmp_node, 0);
        debug1("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules);
    }


    /* Creating a rules hash (for reading alerts from other servers). */
    {
        RuleNode *tmp_node = OS_GetFirstRule();
        Config.g_rules_hash = OSHash_Create();
        if(!Config.g_rules_hash)
        {
            ErrorExit(MEM_ERROR, ARGV0);
        }
        AddHash_Rule(tmp_node);
    }


    if(t_config == 1)
    {
        exit(0);
    }


    /* Start up message */
    verbose(STARTUP_MSG, ARGV0, getpid());


    /* Going to main loop */
    OS_ReadMSG(m_queue, ut_str);


    exit(0);

}
예제 #6
0
int main(int argc, char **argv)
{
    int test_config = 0;
    int c = 0;
    char *ut_str = NULL;
    const char *dir = DEFAULTDIR;
    const char *cfg = DEFAULTCPATH;
    const char *user = USER;
    const char *group = GROUPGLOBAL;
    uid_t uid;
    gid_t gid;
    int quiet = 0;

    /* Set the name */
    OS_SetName(ARGV0);

    thishour = 0;
    today = 0;
    prev_year = 0;
    full_output = 0;
    alert_only = 0;

    active_responses = NULL;
    memset(prev_month, '\0', 4);

#ifdef LIBGEOIP_ENABLED
    geoipdb = NULL;
#endif

    while ((c = getopt(argc, argv, "VatvdhU:D:c:q")) != -1) {
        switch (c) {
            case 'V':
                print_version();
                break;
            case 't':
                test_config = 1;
                break;
            case 'h':
                help_logtest();
                break;
            case 'd':
                nowDebug();
                break;
            case 'U':
                if (!optarg) {
                    ErrorExit("%s: -U needs an argument", ARGV0);
                }
                ut_str = optarg;
                break;
            case 'D':
                if (!optarg) {
                    ErrorExit("%s: -D needs an argument", ARGV0);
                }
                dir = optarg;
                break;
            case 'c':
                if (!optarg) {
                    ErrorExit("%s: -c needs an argument", ARGV0);
                }
                cfg = optarg;
                break;
            case 'a':
                alert_only = 1;
                break;
            case 'q':
                quiet = 1;
                break;
            case 'v':
                full_output = 1;
                break;
            default:
                help_logtest();
                break;
        }
    }

    /* Read configuration file */
    if (GlobalConf(cfg) < 0) {
        ErrorExit(CONFIG_ERROR, ARGV0, cfg);
    }

    debug1(READ_CONFIG, ARGV0);

#ifdef LIBGEOIP_ENABLED
    Config.geoip_jsonout = getDefine_Int("analysisd", "geoip_jsonout", 0, 1);

    /* Opening GeoIP DB */
    if(Config.geoipdb_file) {
        geoipdb = GeoIP_open(Config.geoipdb_file, GEOIP_INDEX_CACHE);
        if (geoipdb == NULL)
        {
            merror("%s: Unable to open GeoIP database from: %s (disabling GeoIP).", ARGV0, Config.geoipdb_file);
        }
    }
#endif

    /* Get server hostname */
    memset(__shost, '\0', 512);
    if (gethostname(__shost, 512 - 1) != 0) {
        strncpy(__shost, OSSEC_SERVER, 512 - 1);
    } else {
        char *_ltmp;

        /* Remove domain part if available */
        _ltmp = strchr(__shost, '.');
        if (_ltmp) {
            *_ltmp = '\0';
        }
    }

    /* Check if the user/group given are valid */
    uid = Privsep_GetUser(user);
    gid = Privsep_GetGroup(group);
    if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
        ErrorExit(USER_ERROR, ARGV0, user, group);
    }

    /* Set the group */
    if (Privsep_SetGroup(gid) < 0) {
        ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
    }

    /* Chroot */
    if (Privsep_Chroot(dir) < 0) {
        ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
    }
    nowChroot();

    Config.decoder_order_size = (size_t)getDefine_Int("analysisd", "decoder_order_size", 8, MAX_DECODER_ORDER_SIZE);


    /*
     * Anonymous Section: Load rules, decoders, and lists
     *
     * As lists require two pass loading of rules that make use of list lookups
     * are created with blank database structs, and need to be filled in after
     * completion of all rules and lists.
     */
    {
        {
            /* Load decoders */
            /* Initialize the decoders list */
            OS_CreateOSDecoderList();

            if (!Config.decoders) {
                /* Legacy loading */
                /* Read decoders */
                if (!ReadDecodeXML("etc/decoder.xml")) {
                    ErrorExit(CONFIG_ERROR, ARGV0,  XML_DECODER);
                }

                /* Read local ones */
                c = ReadDecodeXML("etc/local_decoder.xml");
                if (!c) {
                    if ((c != -2)) {
                        ErrorExit(CONFIG_ERROR, ARGV0,  XML_LDECODER);
                    }
                } else {
                    verbose("%s: INFO: Reading local decoder file.", ARGV0);
                }
            } else {
                /* New loaded based on file specified in ossec.conf */
                char **decodersfiles;
                decodersfiles = Config.decoders;
                while ( decodersfiles && *decodersfiles) {

                    if(!quiet) {
                        verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
                    }
                    if (!ReadDecodeXML(*decodersfiles)) {
                        ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles);
                    }

                    free(*decodersfiles);
                    decodersfiles++;
                }
            }

            /* Load decoders */
            SetDecodeXML();
        }
        {
            /* Load Lists */
            /* Initialize the lists of list struct */
            Lists_OP_CreateLists();
            /* Load each list into list struct */
            {
                char **listfiles;
                listfiles = Config.lists;
                while (listfiles && *listfiles) {
                    verbose("%s: INFO: Reading the lists file: '%s'", ARGV0, *listfiles);
                    if (Lists_OP_LoadList(*listfiles) < 0) {
                        ErrorExit(LISTS_ERROR, ARGV0, *listfiles);
                    }
                    free(*listfiles);
                    listfiles++;
                }
                free(Config.lists);
                Config.lists = NULL;
            }
        }
        {
            /* Load Rules */
            /* Create the rules list */
            Rules_OP_CreateRules();

            /* Read the rules */
            {
                char **rulesfiles;
                rulesfiles = Config.includes;
                while (rulesfiles && *rulesfiles) {
                    debug1("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles);
                    if (Rules_OP_ReadRules(*rulesfiles) < 0) {
                        ErrorExit(RULES_ERROR, ARGV0, *rulesfiles);
                    }

                    free(*rulesfiles);
                    rulesfiles++;
                }

                free(Config.includes);
                Config.includes = NULL;
            }

            /* Find all rules with that require list lookups and attache the
             * the correct list struct to the rule.  This keeps rules from
             * having to search thought the list of lists for the correct file
             * during rule evaluation.
             */
            OS_ListLoadRules();
        }
    }

    /* Fix the levels/accuracy */
    {
        int total_rules;
        RuleNode *tmp_node = OS_GetFirstRule();

        total_rules = _setlevels(tmp_node, 0);
        debug1("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules);
    }

    /* Creating a rules hash (for reading alerts from other servers) */
    {
        RuleNode *tmp_node = OS_GetFirstRule();
        Config.g_rules_hash = OSHash_Create();
        if (!Config.g_rules_hash) {
            ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
        }
        AddHash_Rule(tmp_node);
    }

    if (test_config == 1) {
        exit(0);
    }

    /* Set the user */
    if (Privsep_SetUser(uid) < 0) {
        ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
    }

    /* Start up message */
    verbose(STARTUP_MSG, ARGV0, getpid());

    /* Going to main loop */
    OS_ReadMSG(ut_str);

    exit(0);
}