/* * * Copyright (C) 2005 Yoann Vandoorselaere, Prelude IDS Technologies * Rainer Wichmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * 28/04/2005 : R.W.: * move libprelude 0.8 code to seperate file * * 23/04/2005 : R.W.: * include libprelude 0.9 code from Yoann Vandoorselaere */ /* * for strptime() */ #define _GNU_SOURCE 1 #include "config_xor.h" #include #include #include #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include #include int sh_argc_store; char ** sh_argv_store; #if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9) /* * _() macros are samhain specific; they are used to replace string * constants at runtime. This is part of the samhain stealth mode * (fill string constants with encoded strings, decode at runtime). */ #define FIL__ _("sh_prelude.c") #include #include /* * includes for samhain-specific functions (sl_strstr, sh_error_handle) */ #include "slib.h" #include "sh_cat.h" #include "sh_error_min.h" #include "sh_prelude.h" /* * When SH_USE_XML is set, value are formated using name="value". * Otherwise, value is formatted using the format name=. */ #ifdef SH_USE_XML # define VALUE_DELIM_START '"' # define VALUE_DELIM_END '"' #else # define VALUE_DELIM_START '<' # define VALUE_DELIM_END '>' #endif #define IDMEF_ANALYZER_MODEL _("Samhain") #define IDMEF_ANALYZER_CLASS _("Integrity Checker") #define IDMEF_ANALYZER_VERSION VERSION #define IDMEF_ANALYZER_MANUFACTURER _("http://www.la-samhna.de/samhain/") /* * 0 = not initialized; -1 = failed; 1 = initialized */ static int initialized = 0; static int ready_for_init = 0; static char *profile = NULL; static prelude_client_t *client = NULL; static int severity_map[1 + (unsigned int) IDMEF_IMPACT_SEVERITY_HIGH] = { /* 0: unused (?) */ 0, /* 1: INFO */ 0, /* 2: LOW */ SH_ERR_ALL|SH_ERR_INFO, /* 3: MEDIUM */ SH_ERR_NOTICE|SH_ERR_WARN|SH_ERR_STAMP|SH_ERR_ERR, /* 4: HIGH */ SH_ERR_SEVERE|SH_ERR_FATAL }; /* returns 0/tiger, 1/sha1, or 2/md5 */ extern int sh_tiger_get_hashtype(void); static void clear_and_set (int setpos, int flag) { unsigned int i; /* clear everywhere, and set at correct position */ for (i = 1; i < (1 + (unsigned int) IDMEF_IMPACT_SEVERITY_HIGH); ++i) severity_map[i] &= ~flag; severity_map[setpos] |= flag; return; } static int set_prelude_severity_int (const char * str, int prelude_sev) { char * p; char * dup = strdup (str); if (!dup) return -1; p = strtok (dup, ", \t"); if (p) { do { if (0 == strcmp (p, _("alert"))) clear_and_set (prelude_sev, SH_ERR_FATAL); else if (0 == strcmp (p, _("crit"))) clear_and_set (prelude_sev, SH_ERR_SEVERE); else if (0 == strcmp (p, _("err"))) clear_and_set (prelude_sev, SH_ERR_ERR); else if (0 == strcmp (p, _("mark"))) clear_and_set (prelude_sev, SH_ERR_STAMP); else if (0 == strcmp (p, _("warn"))) clear_and_set (prelude_sev, SH_ERR_WARN); else if (0 == strcmp (p, _("notice"))) clear_and_set (prelude_sev, SH_ERR_NOTICE); else if (0 == strcmp (p, _("debug"))) clear_and_set (prelude_sev, SH_ERR_ALL); else if (0 == strcmp (p, _("info"))) clear_and_set (prelude_sev, SH_ERR_INFO); else { free (dup); return -1; } p = strtok (NULL, ", \t"); } while (p); } free(dup); return 0; } int sh_prelude_map_info (const char * str) { return (set_prelude_severity_int(str,(int)IDMEF_IMPACT_SEVERITY_INFO)); } int sh_prelude_map_low (const char * str) { return (set_prelude_severity_int(str,(int)IDMEF_IMPACT_SEVERITY_LOW)); } int sh_prelude_map_medium (const char * str) { return (set_prelude_severity_int(str,(int)IDMEF_IMPACT_SEVERITY_MEDIUM)); } int sh_prelude_map_high (const char * str) { return (set_prelude_severity_int(str,(int)IDMEF_IMPACT_SEVERITY_HIGH)); } static idmef_impact_severity_t map_severity (int sam_sev) { int i; int max = 1 + (unsigned int) IDMEF_IMPACT_SEVERITY_HIGH; idmef_impact_severity_t retval = IDMEF_IMPACT_SEVERITY_MEDIUM; for (i = 0; i < max; ++i) { if (severity_map[i] & sam_sev) { retval = (idmef_impact_severity_t) i; } } return retval; } static char *do_get_value(char *ptr, char delim_start, char delim_end) { char *ret = NULL; ptr = strchr(ptr, delim_start); if ( ! ptr ) return NULL; ret = ++ptr; ptr = strchr(ptr, delim_end); if ( ! ptr ) return NULL; *ptr = '\0'; ret = strdup(ret); *ptr = delim_end; return ret; } static char *get_value(char *msg, const char *toktmp, const char *toksuffix) { char *ptr, tok[128]; snprintf(tok, sizeof(tok), "%s%s=", toktmp, (toksuffix) ? toksuffix : ""); ptr = strstr(msg, tok); if ( ! ptr ) return NULL; return do_get_value(ptr, VALUE_DELIM_START, VALUE_DELIM_END); } static char *get_time_value(char *msg, const char *toktmp, const char *toksuffix) { char *ret, *ptr, tok[128]; snprintf(tok, sizeof(tok), "%s%s=", toktmp, (toksuffix) ? toksuffix : ""); ptr = strstr(msg, tok); if ( ! ptr ) return NULL; #ifndef SH_USE_XML ret = do_get_value(ptr, '[', ']'); #else ret = do_get_value(ptr, VALUE_DELIM_START, VALUE_DELIM_END); #endif return ret; } #if 0 void debug_print_message(idmef_message_t *msg) { int ret; prelude_io_t *fd; ret = prelude_io_new(&fd); if ( ret < 0 ) return; prelude_io_set_file_io(fd, stderr); idmef_message_print(idmef, fd); prelude_io_destroy(fd); } #endif static int idmef_time_from_samhain(idmef_time_t **time, const char *str) { int ret; char *ptr; time_t utc; struct tm lt; /* * Samhain stamp are encoded in UTC. */ ptr = strptime(str, _("%Y-%m-%dT%H:%M:%S"), <); if ( ! ptr ) { sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, _("could not format Samhain time"), _("idmef_time_from_samhain")); return -1; } utc = prelude_timegm(<); ret = idmef_time_new_from_time(time, &utc); if ( ret < 0 ) return ret; return 0; } /* flawfinder: ignore *//* is part of name, not access() */ static void get_access_info(idmef_file_access_t *access, char * mode, int pos, int mpos) { int got = 0; int ret; prelude_string_t *str; do { if ( mode[pos] == 'r' ) { /* flawfinder: ignore *//* is part of name, not access() */ ret = idmef_file_access_new_permission(access, &str, IDMEF_LIST_APPEND); if ( ret < 0 ) return; prelude_string_set_dup(str, _("read")); ++got; } else if ( mode[pos] == 'w' ) { /* flawfinder: ignore *//* is part of name, not access() */ ret = idmef_file_access_new_permission(access, &str, IDMEF_LIST_APPEND); if ( ret < 0 ) return; prelude_string_set_dup(str, _("write")); ++got; } else if ( mode[pos] == 'x' || mode[pos] == 's' || mode[pos] == 't') { /* flawfinder: ignore *//* is part of name, not access() */ ret = idmef_file_access_new_permission(access, &str, IDMEF_LIST_APPEND); if ( ret < 0 ) return; if ( mode[pos] == 'x' && mode[0] == 'd' ) prelude_string_set_dup(str, _("search")); else if ( mode[pos] == 'x' || mode[pos] == 't' ) prelude_string_set_dup(str, _("execute")); else /* 's' */ prelude_string_set_dup(str, _("executeAs")); ++got; } ++pos; } while (pos <= mpos); if ( got == 0 ) { /* flawfinder: ignore *//* is part of name, not access() */ ret = idmef_file_access_new_permission(access, &str, IDMEF_LIST_APPEND); if ( ret < 0 ) return; prelude_string_set_dup(str, _("noAccess")); } return; } static void get_file_infos(idmef_target_t *target, char *msg, idmef_file_category_t category) { int ret; int hashtype = 0; char *ptr; idmef_time_t *time; idmef_file_t *file; idmef_inode_t *inode; prelude_string_t *str; idmef_checksum_t *checksum; idmef_file_access_t *access; /* flawfinder: ignore */ idmef_user_id_t *userid; const char *suffix = (category == IDMEF_FILE_CATEGORY_CURRENT) ? "_new" : "_old"; char *mode = NULL; ret = idmef_target_new_file(target, &file, IDMEF_LIST_APPEND); if ( ret < 0 ) return; idmef_file_set_category(file, category); ptr = get_value(msg, _("path"), NULL); if ( ptr ) { /* * In term of IDMEF, this is the full path, * including the name. */ ret = idmef_file_new_path(file, &str); if ( ret < 0 ) { free(ptr); return; } prelude_string_set_nodup(str, ptr); ptr = strrchr(ptr, '/'); if ( ptr ) { ret = idmef_file_new_name(file, &str); if ( ret == 0 ) { prelude_string_set_dup(str, ptr + 1); } } } ptr = get_value(msg, _("size"), suffix); if ( ptr ) { idmef_file_set_data_size(file, strtoul(ptr, NULL, 10)); free(ptr); } ptr = get_time_value(msg, _("mtime"), suffix); if ( ptr ) { ret = idmef_time_from_samhain(&time, ptr); if ( ret == 0 ) { idmef_file_set_modify_time(file, time); } free(ptr); } ptr = get_time_value(msg, _("ctime"), suffix); if ( ptr ) { ret = idmef_time_from_samhain(&time, ptr); if ( ret == 0 ) { idmef_file_set_create_time(file, time); } free(ptr); } ptr = get_value(msg, _("inode"), suffix); if ( ptr ) { ret = idmef_file_new_inode(file, &inode); if ( ret == 0 ) { char * dev = get_value(msg, _("dev"), suffix); if (dev) { char * q = strchr(dev, ','); if (*q) { *q = '\0'; ++q; idmef_inode_set_major_device(inode, strtoul(dev, NULL, 0)); idmef_inode_set_minor_device(inode, strtoul( q, NULL, 0)); } free(dev); } idmef_inode_set_number(inode, strtoul(ptr, NULL, 10)); } free(ptr); } ptr = get_value(msg, _("chksum"), suffix); if ( ptr ) { ret = idmef_file_new_checksum(file, &checksum, IDMEF_LIST_APPEND); if ( ret < 0 ) { free(ptr); goto get_mode; } hashtype = sh_tiger_get_hashtype(); if (hashtype == 0) idmef_checksum_set_algorithm(checksum, IDMEF_CHECKSUM_ALGORITHM_TIGER); else if (hashtype == 1) idmef_checksum_set_algorithm(checksum, IDMEF_CHECKSUM_ALGORITHM_SHA1); else if (hashtype == 2) idmef_checksum_set_algorithm(checksum, IDMEF_CHECKSUM_ALGORITHM_MD5); else idmef_checksum_set_algorithm(checksum, IDMEF_CHECKSUM_ALGORITHM_TIGER); ret = idmef_checksum_new_value(checksum, &str); if ( ret < 0 ) { free(ptr); goto get_mode; } /* will be freed on destroy() */ prelude_string_set_nodup(str, ptr); } get_mode: mode = get_value(msg, _("mode"), suffix); if ( mode ) { /* flawfinder: ignore *//* is part of name, not access() */ ret = idmef_file_new_file_access(file, &access, IDMEF_LIST_APPEND); if ( ret < 0 ) goto get_owner; /* flawfinder: ignore *//* is part of name, not access() */ ret = idmef_file_access_new_user_id(access, &userid); if ( ret < 0 ) goto get_owner; idmef_user_id_set_type(userid, IDMEF_USER_ID_TYPE_OTHER_PRIVS); /* flawfinder: ignore *//* is part of name, not access() */ get_access_info ( access, mode, 7, 9 ); } get_owner: ptr = get_value(msg, _("owner"), suffix); if ( ptr ) { char * uid; /* flawfinder: ignore *//* is part of name, not access() */ ret = idmef_file_new_file_access(file, &access, IDMEF_LIST_APPEND); if ( ret < 0 ) { free(ptr); goto get_group; } /* flawfinder: ignore *//* is part of name, not access() */ ret = idmef_file_access_new_user_id(access, &userid); if ( ret < 0 ) { free(ptr); goto get_group; } idmef_user_id_set_type(userid, IDMEF_USER_ID_TYPE_USER_PRIVS); ret = idmef_user_id_new_name(userid, &str); if ( ret < 0 ) { free(ptr); goto get_group; } prelude_string_set_nodup(str, ptr); uid = get_value(msg, _("iowner"), suffix); if ( ! uid ) goto get_group; idmef_user_id_set_number(userid, strtoul(uid, NULL, 0)); if ( mode ) { /* flawfinder: ignore *//* is part of name, not access() */ get_access_info ( access, mode, 1, 3 ); } free(uid); } get_group: ptr = get_value(msg, _("group"), suffix); if ( ptr ) { char *gid; /* flawfinder: ignore *//* is part of name, not access() */ ret = idmef_file_new_file_access(file, &access, IDMEF_LIST_APPEND); if ( ret < 0 ) { free(ptr); goto mode_free; } ret = idmef_file_access_new_user_id(access, &userid);/* flawfinder: ignore *//* is part of name, not access() */ if ( ret < 0 ) { free(ptr); goto mode_free; } idmef_user_id_set_type(userid, IDMEF_USER_ID_TYPE_GROUP_PRIVS); ret = idmef_user_id_new_name(userid, &str); if ( ret < 0 ) { free(ptr); goto mode_free; } prelude_string_set_nodup(str, ptr); gid = get_value(msg, _("igroup"), suffix); if ( ! gid ) goto mode_free; idmef_user_id_set_number(userid, strtoul(gid, NULL, 0)); if ( mode ) { get_access_info ( access, mode, 4, 6 ); /* flawfinder: ignore */ } free(gid); } mode_free: if ( mode ) { free ( mode ); } return; } static int map_policy_to_class(char *msg, unsigned long msgid, idmef_impact_t *impact, prelude_string_t *out) { char *ptr; int ret, i; struct tbl { unsigned int msgid; const char *name; idmef_impact_type_t type; } tbl[] = { #ifdef SH_USE_UTMP { MSG_UT_LG1X, N_("User Login"), IDMEF_IMPACT_TYPE_USER }, { MSG_UT_LG1A, N_("User Login"), IDMEF_IMPACT_TYPE_USER }, { MSG_UT_LG1B, N_("User Login"), IDMEF_IMPACT_TYPE_USER }, { MSG_UT_LG2X, N_("Multiple User Login"), IDMEF_IMPACT_TYPE_USER }, { MSG_UT_LG2A, N_("Multiple User Login"), IDMEF_IMPACT_TYPE_USER }, { MSG_UT_LG2B, N_("Multiple User Login"), IDMEF_IMPACT_TYPE_USER }, { MSG_UT_LG3X, N_("User Logout"), IDMEF_IMPACT_TYPE_USER }, { MSG_UT_LG3A, N_("User Logout"), IDMEF_IMPACT_TYPE_USER }, { MSG_UT_LG3B, N_("User Logout"), IDMEF_IMPACT_TYPE_USER }, { MSG_UT_LG3C, N_("User Logout"), IDMEF_IMPACT_TYPE_USER }, #endif #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) { MSG_FI_MISS, N_("File Missing"), IDMEF_IMPACT_TYPE_FILE }, { MSG_FI_MISS2, N_("File Missing"), IDMEF_IMPACT_TYPE_FILE }, { MSG_FI_ADD, N_("File Added"), IDMEF_IMPACT_TYPE_FILE }, { MSG_FI_ADD2, N_("File Added"), IDMEF_IMPACT_TYPE_FILE }, { MSG_FI_CHAN, N_("File Modified"), IDMEF_IMPACT_TYPE_FILE }, { MSG_FI_NODIR, N_("File found where directory was expected"), IDMEF_IMPACT_TYPE_FILE }, #endif #ifdef SH_USE_KERN { MSG_KERN_POLICY, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER }, { MSG_KERN_POL_CO, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER }, { MSG_KERN_PROC, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER }, { MSG_KERN_GATE, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER }, { MSG_KERN_IDT, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER }, { MSG_KERN_SYSCALL, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER }, #endif #ifdef SH_USE_SUIDCHK { MSG_SUID_POLICY, N_("SUID/SGID File Detected"), IDMEF_IMPACT_TYPE_FILE }, #endif /* * This must be the last table entry */ { 0, NULL, IDMEF_IMPACT_TYPE_OTHER }, }; for ( i = 0; tbl[i].name != NULL; i++ ) { if ( tbl[i].msgid != msgid ) continue; idmef_impact_set_type(impact, tbl[i].type); return prelude_string_cat(out, _(tbl[i].name)); } /* some other message */ ptr = get_value(msg, _("msg"), NULL); if ( ! ptr ) { sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, _("could not format Samhain message"), _("map_policy_to_class")); return -1; } ret = prelude_string_cat(out, ptr); free(ptr); return ret; } static int get_login_info(char *msg, idmef_alert_t *alert) { int ret; char *ptr, *ip; idmef_user_t *user; idmef_node_t *node; struct passwd *pw; prelude_string_t *str; idmef_user_id_t *user_id; idmef_address_t *address; idmef_target_t *target = idmef_alert_get_next_target(alert, NULL); idmef_source_t *source = idmef_alert_get_next_source(alert, NULL); ip = ptr = get_value(msg, _("ip"), NULL); if ( ptr ) { if ( ! source ) { ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND); if ( ret < 0 ) { free(ptr); return ret; } } ret = idmef_source_new_node(source, &node); if ( ret < 0 ) { free(ptr); return ret; } ret = idmef_node_new_address(node, &address, IDMEF_LIST_APPEND); if ( ret < 0 ) { free(ptr); return ret; } ret = idmef_address_new_address(address, &str); if ( ret < 0 ) { free(ptr); return ret; } prelude_string_set_nodup(str, ptr); } ptr = get_value(msg, _("host"), NULL); if ( ptr ) { if ( ip && strcmp(ptr, ip) == 0 ) free(ptr); else { if ( ! source ) { ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND); if ( ret < 0 ) { free(ptr); return ret; } } ret = idmef_source_new_node(source, &node); if ( ret < 0 ) { free(ptr); return ret; } ret = idmef_node_new_name(node, &str); if ( ret < 0 ) { free(ptr); return ret; } prelude_string_set_nodup(str, ptr); } } ptr = get_value(msg, _("name"), NULL); if ( ptr ) { ret = idmef_target_new_user(target, &user); if ( ret < 0 ) { free(ptr); return ret; } idmef_user_set_category(user, IDMEF_USER_CATEGORY_OS_DEVICE); ret = idmef_user_new_user_id(user, &user_id, IDMEF_LIST_APPEND); if ( ret < 0 ) { free(ptr); return ret; } idmef_user_id_set_type(user_id, IDMEF_USER_ID_TYPE_TARGET_USER); pw = getpwnam(ptr); if ( pw ) idmef_user_id_set_number(user_id, pw->pw_uid); ret = idmef_user_id_new_name(user_id, &str); if ( ret < 0 ) { free(ptr); return ret; } prelude_string_set_nodup(str, ptr); ptr = get_value(msg, _("tty"), NULL); if ( ptr ) { ret = idmef_user_id_new_tty(user_id, &str); if ( ret < 0 ) { free(ptr); return ret; } prelude_string_set_nodup(str, ptr); } } ptr = get_time_value(msg, _("time"), NULL); if ( ptr ) { idmef_time_t *time; ret = idmef_time_from_samhain(&time, ptr); free(ptr); if ( ret < 0 ) return ret; idmef_alert_set_detect_time(alert, time); } return 0; } static int samhain_alert_prelude(int priority, int sh_class, char *message, unsigned long msgid) { int ret; idmef_time_t *time; idmef_alert_t *alert; idmef_message_t *idmef; idmef_classification_t *classification; idmef_assessment_t *assessment; idmef_additional_data_t *data; idmef_impact_t *impact; idmef_target_t *target; idmef_confidence_t *confidence; prelude_string_t *str; if ( !client || sh_class == STAMP) return 0; ret = idmef_message_new(&idmef); if ( ret < 0 ) goto err; ret = idmef_message_new_alert(idmef, &alert); if ( ret < 0 ) goto err; idmef_alert_set_analyzer(alert, idmef_analyzer_ref(prelude_client_get_analyzer(client)), IDMEF_LIST_PREPEND); ret = idmef_time_new_from_gettimeofday(&time); if ( ret < 0 ) goto err; idmef_alert_set_detect_time(alert, time); ret = idmef_time_new_from_gettimeofday(&time); if ( ret < 0 ) goto err; idmef_alert_set_create_time(alert, time); ret = idmef_alert_new_classification(alert, &classification); if ( ret < 0 ) goto err; ret = idmef_alert_new_target(alert, &target, IDMEF_LIST_APPEND); if ( ret < 0 ) goto err; idmef_target_set_decoy(target, IDMEF_TARGET_DECOY_NO); if ( idmef_analyzer_get_node(prelude_client_get_analyzer(client)) ) { idmef_node_ref(idmef_analyzer_get_node(prelude_client_get_analyzer(client))); idmef_target_set_node(target, idmef_analyzer_get_node(prelude_client_get_analyzer(client))); } if ( strstr(message, _("path=")) ) { #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) if ( msgid != MSG_FI_ADD && msgid != MSG_FI_ADD2 ) get_file_infos(target, message, IDMEF_FILE_CATEGORY_ORIGINAL); #endif get_file_infos(target, message, IDMEF_FILE_CATEGORY_CURRENT); } ret = idmef_alert_new_assessment(alert, &assessment); if ( ret < 0 ) goto err; ret = idmef_assessment_new_impact(assessment, &impact); if ( ret < 0 ) goto err; ret = idmef_classification_new_text(classification, &str); if ( ret < 0 ) goto err; ret = get_login_info(message, alert); if ( ret < 0 ) goto err; map_policy_to_class(message, msgid, impact, str); #if 0 if ( priority == SH_ERR_SEVERE || priority == SH_ERR_FATAL ) idmef_impact_set_severity(impact, IDMEF_IMPACT_SEVERITY_HIGH); else if ( priority == SH_ERR_ALL || priority == SH_ERR_INFO || priority == SH_ERR_NOTICE ) idmef_impact_set_severity(impact, IDMEF_IMPACT_SEVERITY_LOW); else idmef_impact_set_severity(impact, IDMEF_IMPACT_SEVERITY_MEDIUM); #endif idmef_impact_set_severity(impact, map_severity(priority)); idmef_impact_set_completion(impact, IDMEF_IMPACT_COMPLETION_SUCCEEDED); ret = idmef_assessment_new_confidence(assessment, &confidence); if ( ret < 0 ) goto err; idmef_confidence_set_rating(confidence, IDMEF_CONFIDENCE_RATING_HIGH); ret = idmef_alert_new_additional_data(alert, &data, IDMEF_LIST_APPEND); if ( ret < 0 ) goto err; ret = idmef_additional_data_new_meaning(data, &str); if ( ret < 0 ) goto err; prelude_string_set_dup(str, _("Message generated by Samhain")); idmef_additional_data_set_type(data, IDMEF_ADDITIONAL_DATA_TYPE_STRING); idmef_additional_data_set_string_ref(data, message); /* debug_print_message(idmef); */ prelude_client_send_idmef(client, idmef); idmef_message_destroy(idmef); return 0; err: idmef_message_destroy(idmef); return -1; } int sh_prelude_alert(int priority, int sh_class, char *message, long msgflags, unsigned long msgid) { int ret; (void) msgflags; /* fix compiler warning */ if ( initialized < 1 ) return -1; ret = samhain_alert_prelude(priority, sh_class, message, msgid); if ( ret < 0 ) { sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, _("Problem with IDMEF for prelude-ids support: alert lost"), _("sh_prelude_alert")); } return ret; } int sh_prelude_set_profile(const char *arg) { if ( profile ) { free(profile); profile = NULL; } if ( arg ) { profile = strdup(arg); if ( ! profile ) return -1; } return 0; } /* Allow initialization of prelude; to be called * after forking the daemon. Delays heartbeat * start after config read until it is safe. */ void sh_prelude_reset(void) { extern void sh_error_init_prelude(); ready_for_init = 1; sh_error_init_prelude(); return; } void sh_prelude_stop(void) { if (initialized < 1) return; prelude_client_destroy(client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS); client = NULL; initialized = 0; return; } int sh_prelude_init(void) { int ret; prelude_string_t *str; idmef_analyzer_t *analyzer; prelude_client_flags_t flags; #ifdef SH_NOFAILOVER prelude_connection_pool_t *pool; prelude_connection_pool_flags_t conn_flags; #endif if (ready_for_init == 0) return initialized; if (initialized > 0) return initialized; prelude_thread_init(NULL); prelude_init(&sh_argc_store, sh_argv_store); ret = prelude_client_new(&client, profile ? profile : _("samhain")); if ( ret < 0 ) { sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, _("Failed to initialize Prelude"), _("sh_prelude_init")); initialized = -1; return -1; } /* * Enable automatic heartbeat sending. */ flags = prelude_client_get_flags(client); ret = prelude_client_set_flags(client, flags | PRELUDE_CLIENT_FLAGS_ASYNC_TIMER); analyzer = prelude_client_get_analyzer(client); ret = idmef_analyzer_new_model(analyzer, &str); prelude_string_set_dup(str, IDMEF_ANALYZER_MODEL); ret = idmef_analyzer_new_class(analyzer, &str); prelude_string_set_dup(str, IDMEF_ANALYZER_CLASS); ret = idmef_analyzer_new_version(analyzer, &str); prelude_string_set_dup(str, IDMEF_ANALYZER_VERSION); #ifdef SH_NOFAILOVER pool = prelude_client_get_connection_pool(client); conn_flags = prelude_connection_pool_get_flags(pool); conn_flags &= ~PRELUDE_CONNECTION_POOL_FLAGS_FAILOVER; prelude_connection_pool_set_flags(pool, conn_flags); #endif ret = prelude_client_start(client); if ( ret < 0 ) { prelude_perror(ret, _("error starting prelude client")); if ( prelude_client_is_setup_needed(ret) ) prelude_client_print_setup_error(client); sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN, _("Failed to start Prelude"), _("sh_prelude_init")); initialized = -1; return -1; } initialized = 1; return 1; } /* HAVE_LIBPRELUDE_9 */ #endif