入口函数、规则ruleset/rule xml格式各种规则
#ifndef TESTRULE
#ifdef WAZUH_UNIT_TESTING
__attribute((weak))
#endif
int main(int argc, char **argv)
#else
__attribute__((noreturn))
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 *user = USER;
const char *group = GROUPGLOBAL;
uid_t uid;
gid_t gid;
const char *cfg = OSSECCONF;
/* Set the name */
OS_SetName(ARGV0);
// Define current working directory
char * home_path = w_homedir(argv[0]);
...
/* Change working directory */
if (chdir(home_path) == -1) {
merror_exit(CHDIR_ERROR, home_path, errno, strerror(errno));
}
sys_debug_level = getDefine_Int("analysisd", "debug", 0, 2);
/* Check current debug_level
* Command line setting takes precedence
*/
if (debug_level == 0) {
/* Get debug level */
debug_level = sys_debug_level;
while (debug_level != 0) {
nowDebug();
debug_level--;
}
}
mdebug1(WAZUH_HOMEDIR, home_path);
/* Start daemon */
DEBUG_MSG("%s: DEBUG: Starting on debug mode - %d ", ARGV0, (int)time(0));
srandom_init();
/* 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) {
merror_exit(USER_ERROR, user, group, strerror(errno), errno);
}
/* Found user */
mdebug1(FOUND_USER);
/* Initialize Active response */
AR_Init();
if (AR_ReadConfig(cfg) < 0) {
merror_exit(CONFIG_ERROR, cfg);
}
mdebug1(ASINIT);
/* Read configuration file */
if (GlobalConf(cfg) < 0) {
merror_exit(CONFIG_ERROR, cfg);
}
mdebug1(READ_CONFIG);
if (!(Config.alerts_log || Config.jsonout_output)) {
mwarn("All alert formats are disabled. Mail reporting, Syslog client and Integrator won't work properly.");
}
#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("Unable to open GeoIP database from: %s (disabling GeoIP).", 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, WAZUH_SERVER, 512 - 1);
} else {
char *_ltmp;
/* Remove domain part if available */
_ltmp = strchr(__shost, '.');
if (_ltmp) {
*_ltmp = '\0';
}
}
// Set resource limit for file descriptors
{
nofile = getDefine_Int("analysisd", "rlimit_nofile", 1024, 1048576);
struct rlimit rlimit = { nofile, nofile };
if (setrlimit(RLIMIT_NOFILE, &rlimit) < 0) {
merror("Could not set resource limit for file descriptors to %d: %s (%d)", (int)nofile, strerror(errno), errno);
}
}
/* Check the CPU INFO */
/* If we have the threads set to 0 on internal_options.conf, then */
/* we assign them automatically based on the number of cores */
cpu_cores = get_nproc();
num_rule_matching_threads = getDefine_Int("analysisd", "rule_matching_threads", 0, 32);
if(num_rule_matching_threads == 0){
num_rule_matching_threads = cpu_cores;
}
/* 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
/* Set the group */
if (Privsep_SetGroup(gid) < 0) {
merror_exit(SETGID_ERROR, group, errno, strerror(errno));
}
/* Chroot */
if (Privsep_Chroot(home_path) < 0) {
merror_exit(CHROOT_ERROR, home_path, errno, strerror(errno));
}
nowChroot();
/* Set the user */
if (Privsep_SetUser(uid) < 0) {
merror_exit(SETUID_ERROR, user, errno, strerror(errno));
}
/* Verbose message */
mdebug1(PRIVSEP_MSG, home_path, user);
os_free(home_path);
if (!test_config) {
/* Signal manipulation */
StartSIG(ARGV0);
/* Create the PID file */
if (CreatePID(ARGV0, getpid()) < 0) {
merror_exit(PID_ERROR);
}
/* Set the queue */
if ((m_queue = StartMQ(DEFAULTQUEUE, READ, 0)) < 0) {
merror_exit(QUEUE_ERROR, DEFAULTQUEUE, strerror(errno));
}
}
Config.decoder_order_size = (size_t)getDefine_Int("analysisd", "decoder_order_size", MIN_ORDER_SIZE, MAX_DECODER_ORDER_SIZE);
if (!os_analysisd_last_events) {
os_calloc(1, sizeof(EventList), os_analysisd_last_events);
OS_CreateEventList(Config.memorysize, os_analysisd_last_events);
}
/*
* 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.
*/
{
{
/* Error and warning messages */
char * msg;
OSList * list_msg = OSList_Create();
OSList_SetMaxSize(list_msg, ERRORLIST_MAXSIZE);
OSListNode * node_log_msg;
int error_exit = 0;
/* Initialize the decoders list */
OS_CreateOSDecoderList();
/* If we haven't specified a decoders directory, load default */
if (!Config.decoders) {
/* Legacy loading */
/* Read default decoders */
Read_Rules(NULL, &Config, NULL);
}
/* New loaded based on file loaded (in ossec.conf or default) */
{
char **decodersfiles;
decodersfiles = Config.decoders;
while ( decodersfiles && *decodersfiles) {
if (!test_config) {
mdebug1("Reading decoder file %s.", *decodersfiles);
}
if (!ReadDecodeXML(*decodersfiles, &os_analysisd_decoderlist_pn,
&os_analysisd_decoderlist_nopn, &os_analysisd_decoder_store, list_msg)) {
error_exit = 1;
}
node_log_msg = OSList_GetFirstNode(list_msg);
while (node_log_msg) {
os_analysisd_log_msg_t * data_msg = node_log_msg->data;
msg = os_analysisd_string_log_msg(data_msg);
if (data_msg->level == LOGLEVEL_WARNING) {
mwarn("%s", msg);
} else if (data_msg->level == LOGLEVEL_ERROR) {
merror("%s", msg);
}
os_free(msg);
os_analysisd_free_log_msg(&data_msg);
OSList_DeleteCurrentlyNode(list_msg);
node_log_msg = OSList_GetFirstNode(list_msg);
}
if (error_exit) {
merror_exit(CONFIG_ERROR, *decodersfiles);
}
decodersfiles++;
}
}
/* Load decoders */
SetDecodeXML(list_msg, &os_analysisd_decoder_store, &os_analysisd_decoderlist_nopn, &os_analysisd_decoderlist_pn);
node_log_msg = OSList_GetFirstNode(list_msg);
while (node_log_msg) {
os_analysisd_log_msg_t * data_msg = node_log_msg->data;
msg = os_analysisd_string_log_msg(data_msg);
if (data_msg->level == LOGLEVEL_WARNING) {
mwarn("%s", msg);
} else if (data_msg->level == LOGLEVEL_ERROR) {
merror("%s", msg);
error_exit = 1;
}
os_free(msg);
os_analysisd_free_log_msg(&data_msg);
OSList_DeleteCurrentlyNode(list_msg);
node_log_msg = OSList_GetFirstNode(list_msg);
}
if (error_exit) {
merror_exit(DEC_PLUGIN_ERR);
}
os_free(list_msg);
}
{
/* Load Lists */
/* Initialize the lists of list struct */
Lists_OP_CreateLists();
/* Load each list into list struct */
{
/* Error and warning messages */
OSList * list_msg = OSList_Create();
OSList_SetMaxSize(list_msg, ERRORLIST_MAXSIZE);
char **listfiles;
listfiles = Config.lists;
int error_exit = 0;
while (listfiles && *listfiles) {
if (!test_config) {
mdebug1("Reading the lists file: '%s'", *listfiles);
}
if (Lists_OP_LoadList(*listfiles, &os_analysisd_cdblists, list_msg) < 0) {
error_exit = 1;
}
char * msg;
OSListNode * node_log_msg;
node_log_msg = OSList_GetFirstNode(list_msg);
while (node_log_msg) {
os_analysisd_log_msg_t * data_msg = node_log_msg->data;
msg = os_analysisd_string_log_msg(data_msg);
if (data_msg->level == LOGLEVEL_WARNING) {
mwarn("%s", msg);
} else if (data_msg->level == LOGLEVEL_ERROR) {
merror("%s", msg);
}
os_free(msg);
os_analysisd_free_log_msg(&data_msg);
OSList_DeleteCurrentlyNode(list_msg);
node_log_msg = OSList_GetFirstNode(list_msg);
}
if (error_exit) {
merror_exit(LISTS_ERROR, *listfiles);
}
listfiles++;
}
os_free(list_msg);
}
mdebug1("Building CDB lists.");
Lists_OP_MakeAll(0, 0, &os_analysisd_cdblists);
}
{
/* Load Rules */
/* Create the rules list */
Rules_OP_CreateRules();
/* If we haven't specified a rules directory, load default */
if (!Config.includes) {
Read_Rules(NULL, &Config, NULL);
}
/* Read the rules */
{
/* Error and warning msg */
char * msg;
OSList * list_msg = OSList_Create();
OSList_SetMaxSize(list_msg, ERRORLIST_MAXSIZE);
OSListNode * node_log_msg;
int error_exit = 0;
char **rulesfiles;
rulesfiles = Config.includes;
while (rulesfiles && *rulesfiles) {
if (!test_config) {
mdebug1("Reading rules file: '%s'", *rulesfiles);
}
if (Rules_OP_ReadRules(*rulesfiles, &os_analysisd_rulelist,
&os_analysisd_cdblists, &os_analysisd_last_events,
&os_analysisd_decoder_store, list_msg) < 0) {
error_exit = 1;
}
node_log_msg = OSList_GetFirstNode(list_msg);
while (node_log_msg) {
os_analysisd_log_msg_t * data_msg = node_log_msg->data;
msg = os_analysisd_string_log_msg(data_msg);
if (data_msg->level == LOGLEVEL_WARNING) {
mwarn("%s", msg);
} else if (data_msg->level == LOGLEVEL_ERROR) {
merror("%s", msg);
}
os_free(msg);
os_analysisd_free_log_msg(&data_msg);
OSList_DeleteCurrentlyNode(list_msg);
node_log_msg = OSList_GetFirstNode(list_msg);
}
if (error_exit) {
merror_exit(RULES_ERROR, *rulesfiles);
}
rulesfiles++;
}
os_free(list_msg);
}
/* 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(&os_analysisd_cdblists, &os_analysisd_cdbrules);
}
}
/* Fix the levels/accuracy */
{
int total_rules;
RuleNode *tmp_node = OS_GetFirstRule();
total_rules = _setlevels(tmp_node, 0);
if (!test_config) {
minfo("Total rules enabled: '%d'", 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) {
merror_exit(MEM_ERROR, errno, strerror(errno));
}
AddHash_Rule(tmp_node);
}
/* 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);
}
if (Config.queue_size != 0) {
minfo("The option <queue_size> is deprecated and won't apply. Set up each queue size in the internal_options file.");
}
/* Whitelist */
if (Config.white_list == NULL) {
if (Config.ar) {
minfo("No IP in the white list for active response.");
}
} else {
if (Config.ar) {
os_ip **wl;
int wlc = 0;
wl = Config.white_list;
while (*wl) {
minfo("White listing IP: '%s'", (*wl)->ip);
wl++;
wlc++;
}
minfo("%d IPs in the white list for active response.", wlc);
}
}
/* Hostname whitelist */
if (Config.hostname_white_list == NULL) {
if (Config.ar)
minfo("No Hostname in the white list for active response.");
} else {
if (Config.ar) {
int wlc = 0;
OSMatch **wl;
wl = Config.hostname_white_list;
while (*wl) {
char **tmp_pts = (*wl)->patterns;
while (*tmp_pts) {
minfo("White listing Hostname: '%s'", *tmp_pts);
wlc++;
tmp_pts++;
}
wl++;
}
minfo("%d Hostname(s) in the white list for active response.", wlc);
}
}
/* Startup message */
minfo(STARTUP_MSG, (int)getpid());
// Start com request thread
w_create_thread(asyscom_main, NULL);
/* Load Mitre JSON File and Mitre hash table */
mitre_load();
/* Initialize Logtest */
w_create_thread(w_logtest_init, NULL);
/* Going to main loop */
OS_ReadMSG(m_queue);
exit(0);
}
描述一个事件,事件双向链表
typedef struct _EventNode EventNode;
/* Event Information structure */
typedef struct _Eventinfo {
/* Extracted from the event */
char *log;
char *full_log;
const char * log_after_parent;
const char * log_after_prematch;
char *agent_id;
char *location;
char *hostname;
char *program_name;
char *comment;
char *dec_timestamp;
/* Extracted from the decoders */
char *srcip;
char *srcgeoip;
char *dstip;
char *dstgeoip;
char *srcport;
char *dstport;
char *protocol;
char *action;
char *srcuser;
char *dstuser;
char *id;
char *status;
char *url;
char *data;
char *extra_data;
char *systemname;
DynamicField *fields;
int nfields;
/* Pointer to the rule that generated it */
RuleInfo *generated_rule;
/* Pointer to the decoder that matched */
OSDecoderInfo *decoder_info;
/* Sid node to delete */
OSListNode *sid_node_to_delete;
/* Group node to delete */
OSListNode **group_node_to_delete;
/* Extract when the event fires a rule */
size_t size;
size_t p_name_size;
/* Other internal variables */
int matched;
time_t generate_time;
struct timespec time;
int day;
int year;
char hour[10];
char mon[4];
char *previous;
wlabel_t *labels;
u_int16_t decoder_syscheck_id;
int rootcheck_fts;
int is_a_copy;
char **last_events;
int r_firedtimes;
int queue_added;
// Node reference
EventNode *node;
// Process thread id
int tid;
} Eventinfo;
/* Events List structure */
struct _EventNode {
Eventinfo *event;
pthread_mutex_t mutex;
volatile int count;
EventNode *next;
EventNode *prev;
};
struct EventList {
EventNode *first_node;
EventNode *last_node;
EventNode *last_added_node;
int _memoryused;
int _memorymaxsize;
int _max_freq;
pthread_mutex_t event_mutex;
};
读消息并处理主函数
/* Main function. Receives the messages(events) and analyze them all */
#ifndef TESTRULE
__attribute__((noreturn))
void OS_ReadMSG(int m_queue)
#else
__attribute__((noreturn))
void OS_ReadMSG_analysisd(int m_queue)
#endif
{
Eventinfo *lf = NULL;
int i;
/* Initialize the logs */
OS_InitLog();
/* Initialize the integrity database */
if (!fim_init()) merror_exit("fim: Initialization failed");
/* Initialize Rootcheck */
RootcheckInit();
/* Initialize Syscollector */
SyscollectorInit();
/* Initialize CIS-CAT */
CiscatInit();
/* Initialize host info */
HostinfoInit();
/* Initialize windows event */
WinevtInit();
/* Initialize Security Configuration Assessment event */
SecurityConfigurationAssessmentInit();
/* Initialize the Accumulator */
if (!Accumulate_Init(&os_analysisd_acm_store, &os_analysisd_acm_lookups, &os_analysisd_acm_purge_ts)) {
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, 1)) < 0) {
merror(ARQ_ERROR);
} else {
minfo(CONN_TO, ARQUEUE, "active-response");
}
}
#endif
if (Config.ar & LOCAL_AR) {
if ((execdq = StartMQ(EXECQUEUE, WRITE, 1)) < 0) {
merror(ARQ_ERROR);
} else {
minfo(CONN_TO, EXECQUEUE, "exec");
}
}
}
mdebug1("Active response Init completed.");
/* Get current time before starting */
gettime(&c_timespec);
Start_Time();
/* Start the hourly/weekly stats directories*/
if(Init_Stats_Directories() < 0) {
Config.stats = 0;
}
/* Initialize the logs */
{
os_calloc(1, sizeof(Eventinfo), lf);
os_calloc(Config.decoder_order_size, sizeof(DynamicField), lf->fields);
lf->year = prev_year;
strncpy(lf->mon, prev_month, 3);
lf->day = today;
if (OS_GetLogLocation(today, prev_year, prev_month) < 0) {
merror_exit("Error allocating log files");
}
Free_Eventinfo(lf);
}
/* Initialize label cache */
if (!labels_init()) merror_exit("Error allocating labels");
Config.label_cache_maxage = getDefine_Int("analysisd", "label_cache_maxage", 0, 60);
Config.show_hidden_labels = getDefine_Int("analysisd", "show_hidden_labels", 0, 1);
if (Config.custom_alert_output) {
mdebug1("Custom output found.!");
}
w_init_queues();
/* Queue stats */
w_get_initial_queues_size();
int num_decode_event_threads = getDefine_Int("analysisd", "event_threads", 0, 32);
int num_decode_syscheck_threads = getDefine_Int("analysisd", "syscheck_threads", 0, 32);
int num_decode_syscollector_threads = getDefine_Int("analysisd", "syscollector_threads", 0, 32);
int num_decode_rootcheck_threads = getDefine_Int("analysisd", "rootcheck_threads", 0, 32);
int num_decode_sca_threads = getDefine_Int("analysisd", "sca_threads", 0, 32);
int num_decode_hostinfo_threads = getDefine_Int("analysisd", "hostinfo_threads", 0, 32);
int num_decode_winevt_threads = getDefine_Int("analysisd", "winevt_threads", 0, 32);
int num_dispatch_dbsync_threads = getDefine_Int("analysisd", "dbsync_threads", 0, 32);
if(num_decode_event_threads == 0){
num_decode_event_threads = cpu_cores;
}
if(num_decode_syscheck_threads == 0){
num_decode_syscheck_threads = cpu_cores;
}
if(num_decode_syscollector_threads == 0){
num_decode_syscollector_threads = cpu_cores;
}
if(num_decode_rootcheck_threads == 0){
num_decode_rootcheck_threads = cpu_cores;
}
if(num_decode_sca_threads == 0){
num_decode_sca_threads = cpu_cores;
}
if(num_decode_hostinfo_threads == 0){
num_decode_hostinfo_threads = cpu_cores;
}
if(num_decode_winevt_threads == 0){
num_decode_winevt_threads = cpu_cores;
}
num_dispatch_dbsync_threads = (num_dispatch_dbsync_threads > 0) ? num_dispatch_dbsync_threads : cpu_cores;
/* Initiate the FTS list */
if (!FTS_Init(num_rule_matching_threads, &os_analysisd_fts_list, &os_analysisd_fts_store)) {
merror_exit(FTS_LIST_ERROR);
}
mdebug1("FTS_Init completed.");
/* Create message handler thread */
w_create_thread(ad_input_main, &m_queue);
/* Create archives writer thread */
w_create_thread(w_writer_thread, NULL);
/* Create alerts log writer thread */
w_create_thread(w_writer_log_thread, NULL);
/* Create statistical log writer thread */
w_create_thread(w_writer_log_statistical_thread, NULL);
/* Create firewall log writer thread */
w_create_thread(w_writer_log_firewall_thread, NULL);
/* Create FTS log writer thread */
w_create_thread(w_writer_log_fts_thread, NULL);
/* Create log rotation thread */
w_create_thread(w_log_rotate_thread, NULL);
/* Create decode syscheck threads */
for(i = 0; i < num_decode_syscheck_threads;i++){
w_create_thread(w_decode_syscheck_thread, NULL);
}
/* Create decode syscollector threads */
for(i = 0; i < num_decode_syscollector_threads;i++){
w_create_thread(w_decode_syscollector_thread, NULL);
}
/* Create decode hostinfo threads */
for(i = 0; i < num_decode_hostinfo_threads;i++){
w_create_thread(w_decode_hostinfo_thread, NULL);
}
/* Create decode rootcheck threads */
for(i = 0; i < num_decode_rootcheck_threads;i++){
w_create_thread(w_decode_rootcheck_thread, NULL);
}
/* Create decode Security Configuration Assessment threads */
for(i = 0; i < num_decode_sca_threads;i++){
w_create_thread(w_decode_sca_thread, NULL);
}
/* Create decode event threads */
for(i = 0; i < num_decode_event_threads;i++){
w_create_thread(w_decode_event_thread, NULL);
}
/* Create the process event threads */
for(i = 0; i < num_rule_matching_threads;i++){
w_create_thread(w_process_event_thread,(void *) (intptr_t)i);
}
/* Create decode winevt threads */
for(i = 0; i < num_decode_winevt_threads;i++){
w_create_thread(w_decode_winevt_thread, NULL);
}
/* Create database synchronization dispatcher threads */
for (i = 0; i < num_dispatch_dbsync_threads; i++){
w_create_thread(w_dispatch_dbsync_thread, NULL);
}
/* Create upgrade module dispatcher thread */
w_create_thread(w_dispatch_upgrade_module_thread, NULL);
/* Create State thread */
w_create_thread(w_analysisd_state_main, NULL);
mdebug1("Startup completed. Waiting for new messages..");
while (1) {
sleep(1);
}
}
原始消息处理线程
/* Create message handler thread */
w_create_thread(ad_input_main, &m_queue);
版权声明:本文为CSDN博主「x-ghost」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/MEIYOUDAO_J…