END_TEST START_TEST(test_strbreak) { int i; /* * Please note that all strings are \ escaped */ const char *tests[][15] = { { "X", "testX1234", "4", "test", "1234", NULL}, { "X", "XtestX1234X", "4", "", "test", "1234", "", NULL}, { "Y", "testX1234", "4", "testX1234", NULL}, { "X", "testXX1234", "4", "test", "", "1234", NULL}, { "X", "testX1234", "1", "testX1234", NULL}, { "X", "testX1234X5678", "2", "test", "1234X5678", NULL}, { "X", "testX1234", "0", NULL}, {NULL}, }; for(i=0; tests[i][0] != NULL; i++) { char **result = OS_StrBreak(tests[i][0][0], tests[i][1], (unsigned) atoi(tests[i][2])); int j = 3; if(tests[i][j] == NULL) { ck_assert_ptr_eq(result, NULL); continue; } int k; for(k = 0; tests[i][j] != NULL; j++, k++) { ck_assert_ptr_ne(result[k], NULL); ck_assert_str_eq(result[k], tests[i][j]); } ck_assert_ptr_eq(result[k], NULL); k=0; while(result[k]) free(result[k++]); free(result); } }
/* Read directories attributes */ static int read_attr(syscheck_config *syscheck, const char *dirs, char **g_attrs, char **g_values) { const char *xml_check_all = "check_all"; const char *xml_check_sum = "check_sum"; const char *xml_check_sha1sum = "check_sha1sum"; const char *xml_check_md5sum = "check_md5sum"; const char *xml_check_size = "check_size"; const char *xml_check_owner = "check_owner"; const char *xml_check_group = "check_group"; const char *xml_check_perm = "check_perm"; const char *xml_check_mtime = "check_mtime"; const char *xml_check_inode = "check_inode"; const char *xml_real_time = "realtime"; const char *xml_report_changes = "report_changes"; const char *xml_restrict = "restrict"; char *restrictfile = NULL; char **dir; char *tmp_str; dir = OS_StrBreak(',', dirs, MAX_DIR_SIZE); /* Max number */ char **dir_org = dir; int ret = 0, i; /* Dir can not be null */ if (dir == NULL) { return (0); } while (*dir) { int j = 0; int opts = 0; char *tmp_dir; char **attrs = NULL; char **values = NULL; tmp_dir = *dir; restrictfile = NULL; /* Remove spaces at the beginning */ while (*tmp_dir == ' ') { tmp_dir++; } /* Remove spaces at the end */ tmp_str = strchr(tmp_dir, ' '); if (tmp_str) { tmp_str++; /* Check if it is really at the end */ if ((*tmp_str == '\0') || (*tmp_str == ' ')) { tmp_str--; *tmp_str = '\0'; } } /* Get the options */ if (!g_attrs || !g_values) { merror(SYSCHECK_NO_OPT, __local_name, dirs); ret = 0; goto out_free; } attrs = g_attrs; values = g_values; while (*attrs && *values) { /* Check all */ if (strcmp(*attrs, xml_check_all) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_MD5SUM; opts |= CHECK_SHA1SUM; opts |= CHECK_PERM; opts |= CHECK_SIZE; opts |= CHECK_OWNER; opts |= CHECK_GROUP; opts |= CHECK_MTIME; opts |= CHECK_INODE; } else if (strcmp(*values, "no") == 0) { opts &= ~ ( CHECK_MD5SUM | CHECK_SHA1SUM | CHECK_PERM | CHECK_SIZE | CHECK_OWNER | CHECK_GROUP | CHECK_MTIME | CHECK_INODE ); } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } /* Check sum */ else if (strcmp(*attrs, xml_check_sum) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_MD5SUM; opts |= CHECK_SHA1SUM; } else if (strcmp(*values, "no") == 0) { opts &= ~ ( CHECK_MD5SUM | CHECK_SHA1SUM ); } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } /* Check md5sum */ else if (strcmp(*attrs, xml_check_md5sum) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_MD5SUM; } else if (strcmp(*values, "no") == 0) { opts &= ~ CHECK_MD5SUM; } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } /* Check sha1sum */ else if (strcmp(*attrs, xml_check_sha1sum) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_SHA1SUM; } else if (strcmp(*values, "no") == 0) { opts &= ~ CHECK_SHA1SUM; } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } /* Check permission */ else if (strcmp(*attrs, xml_check_perm) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_PERM; } else if (strcmp(*values, "no") == 0) { opts &= ~ CHECK_PERM; } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } /* Check size */ else if (strcmp(*attrs, xml_check_size) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_SIZE; } else if (strcmp(*values, "no") == 0) { opts &= ~ CHECK_SIZE; } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } /* Check owner */ else if (strcmp(*attrs, xml_check_owner) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_OWNER; } else if (strcmp(*values, "no") == 0) { opts &= ~ CHECK_OWNER; } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } /* Check group */ else if (strcmp(*attrs, xml_check_group) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_GROUP; } else if (strcmp(*values, "no") == 0) { opts &= ~ CHECK_GROUP; } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } /* Check modification time */ else if (strcmp(*attrs, xml_check_mtime) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_MTIME; } else if (strcmp(*values, "no") == 0) { opts &= ~ CHECK_MTIME; } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } /* Check inode */ else if (strcmp(*attrs, xml_check_inode) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_INODE; } else if (strcmp(*values, "no") == 0) { opts &= ~ CHECK_INODE; } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } else if (strcmp(*attrs, xml_real_time) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_REALTIME; } else if (strcmp(*values, "no") == 0) { opts &= ~ CHECK_REALTIME; } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } else if (strcmp(*attrs, xml_report_changes) == 0) { if (strcmp(*values, "yes") == 0) { opts |= CHECK_SEECHANGES; } else if (strcmp(*values, "no") == 0) { opts &= ~ CHECK_SEECHANGES; } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; goto out_free; } } else if (strcmp(*attrs, xml_restrict) == 0) { if (restrictfile) { free(restrictfile); restrictfile = NULL; } os_strdup(*values, restrictfile); } else { merror(SK_INV_ATTR, __local_name, *attrs); ret = 0; goto out_free; } attrs++; values++; } /* You must have something set */ if (opts == 0) { merror(SYSCHECK_NO_OPT, __local_name, dirs); ret = 0; goto out_free; } /* Add directory - look for the last available */ j = 0; while (syscheck->dir && syscheck->dir[j]) { /* Duplicate entry */ if (strcmp(syscheck->dir[j], tmp_dir) == 0) { merror(SK_DUP, __local_name, tmp_dir); ret = 1; goto out_free; } j++; } /* Check for glob */ /* The mingw32 builder used by travis.ci can't find glob.h * Yet glob must work on actual win32. */ #ifndef __MINGW32__ if (strchr(tmp_dir, '*') || strchr(tmp_dir, '?') || strchr(tmp_dir, '[')) { int gindex = 0; glob_t g; if (glob(tmp_dir, 0, NULL, &g) != 0) { merror(GLOB_ERROR, __local_name, tmp_dir); ret = 1; goto out_free; } if (g.gl_pathv[0] == NULL) { merror(GLOB_NFOUND, __local_name, tmp_dir); ret = 1; goto out_free; } while (g.gl_pathv[gindex]) { dump_syscheck_entry(syscheck, g.gl_pathv[gindex], opts, 0, restrictfile); gindex++; } globfree(&g); } else { dump_syscheck_entry(syscheck, tmp_dir, opts, 0, restrictfile); } #else dump_syscheck_entry(syscheck, tmp_dir, opts, 0, restrictfile); #endif if (restrictfile) { free(restrictfile); restrictfile = NULL; } /* Next entry */ dir++; } ret = 1; out_free: i = 0; while (dir_org[i]) { free(dir_org[i++]); } free(dir_org); free(restrictfile); return ret; }
/* Read Windows registry configuration */ int read_reg(syscheck_config *syscheck, char *entries, int arch) { int i; char **entry; char *tmp_str; /* Get each entry separately */ entry = OS_StrBreak(',', entries, MAX_DIR_SIZE); /* Max number */ if (entry == NULL) { return (0); } while (*entry) { char *tmp_entry; tmp_entry = *entry; /* Remove spaces at the beginning */ while (*tmp_entry == ' ') { tmp_entry++; } /* Remove spaces at the end */ tmp_str = strchr(tmp_entry, ' '); if (tmp_str) { tmp_str++; /* Check if it is really at the end */ if ((*tmp_str == '\0') || (*tmp_str == ' ')) { tmp_str--; *tmp_str = '\0'; } } /* Add entries - look for the last available */ i = 0; while (syscheck->registry && syscheck->registry[i].entry) { int str_len_i; int str_len_dir; str_len_dir = strlen(tmp_entry); str_len_i = strlen(syscheck->registry[i].entry); if (str_len_dir > str_len_i) { str_len_dir = str_len_i; } /* Duplicated entry */ if (syscheck->registry[i].arch == arch && strcmp(syscheck->registry[i].entry, tmp_entry) == 0) { merror(SK_DUP, __local_name, tmp_entry); return (1); } i++; } /* Add new entry */ dump_syscheck_entry(syscheck, tmp_entry, arch, 1, NULL); /* Next entry */ entry++; } return (1); }
/* Read directories attributes */ int read_attr(config *syscheck, char *dirs, char **g_attrs, char **g_values) { char *xml_check_all = "check_all"; char *xml_check_sum = "check_sum"; char *xml_check_sha1sum = "check_sha1sum"; char *xml_check_md5sum = "check_md5sum"; char *xml_check_size = "check_size"; char *xml_check_owner = "check_owner"; char *xml_check_group = "check_group"; char *xml_check_perm = "check_perm"; char *xml_real_time = "realtime"; char *xml_report_changes = "report_changes"; char *xml_restrict = "restrict"; char *restrictfile = NULL; char **dir; char *tmp_str; dir = OS_StrBreak(',', dirs, MAX_DIR_SIZE); /* Max number */ char **dir_org = dir; int ret = 0, i; /* Dir can not be null */ if(dir == NULL) { return(0); } /* Doing it for each directory */ while(*dir) { int i = 0; int opts = 0; char *tmp_dir; char **attrs = NULL; char **values = NULL; tmp_dir = *dir; restrictfile = NULL; /* Removing spaces at the beginning */ while(*tmp_dir == ' ') { tmp_dir++; } /* Removing spaces at the end */ tmp_str = strchr(tmp_dir, ' '); if(tmp_str) { tmp_str++; /* Checking if it is really at the end */ if((*tmp_str == '\0') || (*tmp_str == ' ')) { tmp_str--; *tmp_str = '\0'; } } /* Getting the options */ if(!g_attrs || !g_values) { merror(SYSCHECK_NO_OPT, ARGV0, dirs); ret = 0; goto out_free; } attrs = g_attrs; values = g_values; while(*attrs && *values) { /* Checking all */ if(strcmp(*attrs, xml_check_all) == 0) { if(strcmp(*values, "yes") == 0) { opts|=CHECK_MD5SUM; opts|=CHECK_SHA1SUM; opts|=CHECK_PERM; opts|=CHECK_SIZE; opts|=CHECK_OWNER; opts|=CHECK_GROUP; } else if(strcmp(*values, "no") == 0) { } else { merror(SK_INV_OPT, ARGV0, *values, *attrs); ret = 0; goto out_free; } } /* Checking sum */ else if(strcmp(*attrs, xml_check_sum) == 0) { if(strcmp(*values, "yes") == 0) { opts|=CHECK_MD5SUM; opts|=CHECK_SHA1SUM; } else if(strcmp(*values, "no") == 0) { } else { merror(SK_INV_OPT, ARGV0, *values, *attrs); ret = 0; goto out_free; } } /* Checking md5sum */ else if(strcmp(*attrs, xml_check_md5sum) == 0) { if(strcmp(*values, "yes") == 0) { opts|=CHECK_MD5SUM; } else if(strcmp(*values, "no") == 0) { } else { merror(SK_INV_OPT, ARGV0, *values, *attrs); ret = 0; goto out_free; } } /* Checking sha1sum */ else if(strcmp(*attrs, xml_check_sha1sum) == 0) { if(strcmp(*values, "yes") == 0) { opts|=CHECK_SHA1SUM; } else if(strcmp(*values, "no") == 0) { } else { merror(SK_INV_OPT, ARGV0, *values, *attrs); ret = 0; goto out_free; } } /* Checking permission */ else if(strcmp(*attrs, xml_check_perm) == 0) { if(strcmp(*values, "yes") == 0) { opts|=CHECK_PERM; } else if(strcmp(*values, "no") == 0) { } else { merror(SK_INV_OPT, ARGV0, *values, *attrs); ret = 0; goto out_free; } } /* Checking size */ else if(strcmp(*attrs, xml_check_size) == 0) { if(strcmp(*values, "yes") == 0) { opts|=CHECK_SIZE; } else if(strcmp(*values, "no") == 0) { } else { merror(SK_INV_OPT, ARGV0, *values, *attrs); ret = 0; goto out_free; } } /* Checking owner */ else if(strcmp(*attrs, xml_check_owner) == 0) { if(strcmp(*values, "yes") == 0) { opts|=CHECK_OWNER; } else if(strcmp(*values, "no") == 0) { } else { merror(SK_INV_OPT, ARGV0, *values, *attrs); ret = 0; goto out_free; } } /* Checking group */ else if(strcmp(*attrs, xml_check_group) == 0) { if(strcmp(*values, "yes") == 0) { opts|=CHECK_GROUP; } else if(strcmp(*values, "no") == 0) { } else { merror(SK_INV_OPT, ARGV0, *values, *attrs); ret = 0; goto out_free; } } else if(strcmp(*attrs, xml_real_time) == 0) { if(strcmp(*values, "yes") == 0) { opts|=CHECK_REALTIME; } else if(strcmp(*values, "no") == 0) { } else { merror(SK_INV_OPT, ARGV0, *values, *attrs); ret = 0; goto out_free; } } else if(strcmp(*attrs, xml_report_changes) == 0) { if(strcmp(*values, "yes") == 0) { opts|=CHECK_SEECHANGES; } else if(strcmp(*values, "no") == 0) { } else { merror(SK_INV_OPT, ARGV0, *values, *attrs); ret = 0; goto out_free; } } else if(strcmp(*attrs, xml_restrict) == 0) { os_strdup(*values, restrictfile); } else { merror(SK_INV_ATTR, ARGV0, *attrs); ret = 0; goto out_free; } attrs++; values++; } /* You must have something set */ if(opts == 0) { merror(SYSCHECK_NO_OPT, ARGV0, dirs); if(restrictfile) free(restrictfile); ret = 0; goto out_free; } /* Adding directory - looking for the last available */ i = 0; while(syscheck->dir && syscheck->dir[i]) { int str_len_i; int str_len_dir; str_len_dir = strlen(tmp_dir); str_len_i = strlen(syscheck->dir[i]); if(str_len_dir > str_len_i) { str_len_dir = str_len_i; } /* Duplicate entry */ if(strcmp(syscheck->dir[i], tmp_dir) == 0) { merror(SK_DUP, ARGV0, tmp_dir); ret = 1; goto out_free; } i++; } /* Checking for glob. */ #ifndef WIN32 if(strchr(tmp_dir, '*') || strchr(tmp_dir, '?') || strchr(tmp_dir, '[')) { int gindex = 0; glob_t g; if(glob(tmp_dir, 0, NULL, &g) != 0) { merror(GLOB_ERROR, ARGV0, tmp_dir); ret = 1; goto out_free; } if(g.gl_pathv[0] == NULL) { merror(GLOB_NFOUND, ARGV0, tmp_dir); ret = 1; goto out_free; } while(g.gl_pathv[gindex]) { dump_syscheck_entry(syscheck, g.gl_pathv[gindex], opts, 0, restrictfile); gindex++; } globfree(&g); } else { dump_syscheck_entry(syscheck, tmp_dir, opts, 0, restrictfile); } #else dump_syscheck_entry(syscheck, tmp_dir, opts, 0, restrictfile); #endif if(restrictfile) { free(restrictfile); restrictfile = NULL; } /* Next entry */ dir++; } ret = 1; out_free: i = 0; while(dir_org[i]) free(dir_org[i++]); free(dir_org); return ret; }
int read_reg(config *syscheck, char *entries) { int i; char **entry; char *tmp_str; /* Getting each entry separately */ entry = OS_StrBreak(',', entries, MAX_DIR_SIZE); /* Max number */ /* entry can not be null */ if(entry == NULL) { return(0); } /* Doing it for each Entry */ while(*entry) { char *tmp_entry; tmp_entry = *entry; /* Removing spaces at the beginning */ while(*tmp_entry == ' ') { tmp_entry++; } /* Removing spaces at the end */ tmp_str = strchr(tmp_entry, ' '); if(tmp_str) { tmp_str++; /* Checking if it is really at the end */ if((*tmp_str == '\0') || (*tmp_str == ' ')) { tmp_str--; *tmp_str = '\0'; } } /* Adding entries - looking for the last available */ i = 0; while(syscheck->registry && syscheck->registry[i]) { int str_len_i; int str_len_dir; str_len_dir = strlen(tmp_entry); str_len_i = strlen(syscheck->registry[i]); if(str_len_dir > str_len_i) { str_len_dir = str_len_i; } /* Duplicated entry */ if(strcmp(syscheck->registry[i], tmp_entry) == 0) { merror(SK_DUP, ARGV0, tmp_entry); return(1); } i++; } /* Adding new entry */ dump_syscheck_entry(syscheck, tmp_entry, 0, 1, NULL); /* Next entry */ entry++; } return(1); }
void os_ReportdStart(report_filter *r_filter) { int alerts_processed = 0; int alerts_filtered = 0; char *first_alert = NULL; char *last_alert = NULL; void **data_to_clean = NULL; time_t tm; struct tm *p; file_queue *fileq; alert_data *al_data; /* Getting current time before starting */ tm = time(NULL); p = localtime(&tm); /* Initating file queue - to read the alerts */ os_calloc(1, sizeof(file_queue), fileq); if(r_filter->report_type == REPORT_TYPE_DAILY && r_filter->filename) { fileq->fp = fopen(r_filter->filename, "r"); if(!fileq->fp) { merror("%s: ERROR: Unable to open alerts file to generate report.", __local_name); return; } if(r_filter->fp) { __g_rtype = r_filter->fp; } } else { fileq->fp = stdin; } /* Creating top hashes. */ r_filter->top_user = OSStore_Create(); r_filter->top_srcip = OSStore_Create(); r_filter->top_level = OSStore_Create(); r_filter->top_rule = OSStore_Create(); r_filter->top_group = OSStore_Create(); r_filter->top_location = OSStore_Create(); r_filter->top_files = OSStore_Create(); Init_FileQueue(fileq, p, CRALERT_READ_ALL|CRALERT_FP_SET); /* Reading the alerts. */ while(1) { /* Get message if available */ al_data = Read_FileMon(fileq, p, 1); if(!al_data) { break; } alerts_processed++; /* Checking the filters. */ if(!_os_report_check_filters(al_data, r_filter)) { FreeAlertData(al_data); continue; } alerts_filtered++; data_to_clean = os_AddPtArray(al_data, data_to_clean); /* Setting first and last alert for summary. */ if(!first_alert) first_alert = al_data->date; last_alert = al_data->date; /* Adding source ip if it is set properly. */ if(al_data->srcip != NULL && strcmp(al_data->srcip, "(none)") != 0) _os_report_add_tostore(al_data->srcip, r_filter->top_srcip, al_data); /* Adding user if it is set properly. */ if(al_data->user != NULL && strcmp(al_data->user, "(none)") != 0) _os_report_add_tostore(al_data->user, r_filter->top_user, al_data); /* Adding level and severity. */ { char mlevel[16]; char mrule[76 +1]; mrule[76] = '\0'; snprintf(mlevel, 16, "Severity %d" , al_data->level); snprintf(mrule, 76, "%d - %s" , al_data->rule, al_data->comment); _os_report_add_tostore(strdup(mlevel), r_filter->top_level, al_data); _os_report_add_tostore(strdup(mrule), r_filter->top_rule, al_data); } /* Dealing with the group. */ { char *tmp_str; char **mgroup; mgroup = OS_StrBreak(',', al_data->group, 32); if(mgroup) { while(*mgroup) { tmp_str = *mgroup; while(*tmp_str == ' ') tmp_str++; if(*tmp_str == '\0') { mgroup++; continue; } _os_report_add_tostore(tmp_str, r_filter->top_group, al_data); mgroup++; } } else { tmp_str = al_data->group; while(*tmp_str == ' ') tmp_str++; if(*tmp_str != '\0') { _os_report_add_tostore(tmp_str, r_filter->top_group, al_data); } } } /* Adding to the location top filter. */ _os_report_add_tostore(al_data->location, r_filter->top_location, al_data); if(al_data->filename != NULL) { _os_report_add_tostore(al_data->filename, r_filter->top_files, al_data); } } /* No report available */ if(alerts_filtered == 0) { if(!r_filter->report_name) merror("%s: INFO: Report completed and zero alerts post-filter.", __local_name); else merror("%s: INFO: Report '%s' completed and zero alerts post-filter.", __local_name, r_filter->report_name); return; } if(r_filter->report_name) verbose("%s: INFO: Report '%s' completed. Creating output...", __local_name, r_filter->report_name); else verbose("%s: INFO: Report completed. Creating output...", __local_name); l_print_out(" "); if(r_filter->report_name) l_print_out("Report '%s' completed.", r_filter->report_name); else l_print_out("Report completed. =="); l_print_out("------------------------------------------------"); l_print_out("->Processed alerts: %d", alerts_processed); l_print_out("->Post-filtering alerts: %d", alerts_filtered); l_print_out("->First alert: %s", first_alert); l_print_out("->Last alert: %s", last_alert); l_print_out(" "); l_print_out(" "); OSStore_Sort(r_filter->top_srcip, _os_report_sort_compare); OSStore_Sort(r_filter->top_user, _os_report_sort_compare); OSStore_Sort(r_filter->top_level, _os_report_sort_compare); OSStore_Sort(r_filter->top_group, _os_report_sort_compare); OSStore_Sort(r_filter->top_location, _os_report_sort_compare); OSStore_Sort(r_filter->top_rule, _os_report_sort_compare); OSStore_Sort(r_filter->top_files, _os_report_sort_compare); if(r_filter->top_srcip) os_report_printtop(r_filter->top_srcip, "Source ip", 0); if(r_filter->top_user) os_report_printtop(r_filter->top_user, "Username", 0); if(r_filter->top_level) os_report_printtop(r_filter->top_level, "Level", 0); if(r_filter->top_group) os_report_printtop(r_filter->top_group, "Group", 0); if(r_filter->top_location) os_report_printtop(r_filter->top_location, "Location", 0); if(r_filter->top_rule) os_report_printtop(r_filter->top_rule, "Rule", 0); if(r_filter->top_files) os_report_printtop(r_filter->top_files, "Filenames", 0); /* Print related events. */ if(r_filter->related_srcip) os_report_printtop(r_filter->top_srcip, "Source ip", r_filter->related_srcip); if(r_filter->related_user) os_report_printtop(r_filter->top_user, "Username", r_filter->related_user); if(r_filter->related_level) os_report_printtop(r_filter->top_level, "Level", r_filter->related_level); if(r_filter->related_group) os_report_printtop(r_filter->top_group, "Group", r_filter->related_group); if(r_filter->related_location) os_report_printtop(r_filter->top_location, "Location", r_filter->related_location); if(r_filter->related_rule) os_report_printtop(r_filter->top_rule, "Rule", r_filter->related_rule); if(r_filter->related_file) os_report_printtop(r_filter->top_files, "Filename", r_filter->related_file); /* If we have to dump the alerts. */ if(data_to_clean) { int i = 0; if(r_filter->show_alerts) { l_print_out("Log dump:"); l_print_out("------------------------------------------------"); } while(data_to_clean[i]) { alert_data *md = data_to_clean[i]; if(r_filter->show_alerts) l_print_out("%s %s\nRule: %d (level %d) -> '%s'\n%s\n\n", md->date, md->location, md->rule, md->level, md->comment, md->log[0]); FreeAlertData(md); i++; } free(data_to_clean); data_to_clean = NULL; } }
/* ExecdConfig v0.1, 2006/03/24 * Read the config file */ int ExecdConfig(char * cfgfile) { extern int repeated_offenders_timeout[]; #ifdef WIN32 int is_disabled = 1; #else int is_disabled = 0; #endif const char *(xmlf[]) = {"ossec_config", "active-response", "disabled", NULL}; const char *(blocks[]) = {"ossec_config", "active-response", "repeated_offenders", NULL}; char *disable_entry; char *repeated_t; char **repeated_a; OS_XML xml; /* Reading XML file */ if(OS_ReadXML(cfgfile,&xml) < 0) { ErrorExit(XML_ERROR, ARGV0, cfgfile, xml.err, xml.err_line); } /* We do not validate the xml in here. It is done by other processes */ disable_entry = OS_GetOneContentforElement(&xml, xmlf); if(disable_entry) { if(strcmp(disable_entry, "yes") == 0) { is_disabled = 1; } else if(strcmp(disable_entry, "no") == 0) { is_disabled = 0; } else { merror(XML_VALUEERR, ARGV0, "disabled", disable_entry); return(-1); } } repeated_t = OS_GetOneContentforElement(&xml, blocks); if(repeated_t) { int i = 0; int j = 0; repeated_a = OS_StrBreak(',', repeated_t, 5); if(!repeated_a) { merror(XML_VALUEERR, ARGV0, "repeated_offenders", disable_entry); return(-1); } while(repeated_a[i] != NULL) { char *tmpt = repeated_a[i]; while(*tmpt != '\0') { if(*tmpt == ' ' || *tmpt == '\t') tmpt++; else break; } if(*tmpt == '\0') { i++; continue; } repeated_offenders_timeout[j] = atoi(tmpt); verbose("%s: INFO: Adding offenders timeout: %d (for #%d)", ARGV0, repeated_offenders_timeout[j], j+1); j++; repeated_offenders_timeout[j] = 0; if(j >= 6) break; i++; } } OS_ClearXML(&xml); return(is_disabled); }
int ReadDecodeXML(const char *file) { OS_XML xml; XML_NODE node = NULL; /* XML variables */ /* These are the available options for the rule configuration */ const char *xml_plugindecoder = "plugin_decoder"; const char *xml_decoder = "decoder"; const char *xml_decoder_name = "name"; const char *xml_decoder_status = "status"; const char *xml_usename = "use_own_name"; const char *xml_parent = "parent"; const char *xml_program_name = "program_name"; const char *xml_prematch = "prematch"; const char *xml_regex = "regex"; const char *xml_order = "order"; const char *xml_type = "type"; const char *xml_fts = "fts"; const char *xml_ftscomment = "ftscomment"; const char *xml_accumulate = "accumulate"; int i = 0; OSDecoderInfo *NULL_Decoder_tmp = NULL; /* Read the XML */ if ((i = OS_ReadXML(file, &xml)) < 0) { if ((i == -2) && (strcmp(file, XML_LDECODER) == 0)) { return (-2); } merror(XML_ERROR, ARGV0, file, xml.err, xml.err_line); return (0); } /* Apply any variables found */ if (OS_ApplyVariables(&xml) != 0) { merror(XML_ERROR_VAR, ARGV0, file, xml.err); return (0); } /* Get the root elements */ node = OS_GetElementsbyNode(&xml, NULL); if (!node) { if (strcmp(file, XML_LDECODER) != 0) { merror(XML_ELEMNULL, ARGV0); return (0); } return (-2); } /* Zero NULL_decoder */ if (!NULL_Decoder) { os_calloc(1, sizeof(OSDecoderInfo), NULL_Decoder_tmp); NULL_Decoder_tmp->id = 0; NULL_Decoder_tmp->type = SYSLOG; NULL_Decoder_tmp->name = NULL; NULL_Decoder_tmp->fts = 0; NULL_Decoder = NULL_Decoder_tmp; } i = 0; while (node[i]) { XML_NODE elements = NULL; OSDecoderInfo *pi; int j = 0; char *regex; char *prematch; char *p_name; if (!node[i]->element || strcasecmp(node[i]->element, xml_decoder) != 0) { merror(XML_INVELEM, ARGV0, node[i]->element); return (0); } /* Get name */ if ((!node[i]->attributes) || (!node[i]->values) || (!node[i]->values[0]) || (!node[i]->attributes[0]) || (strcasecmp(node[i]->attributes[0], xml_decoder_name) != 0)) { merror(XML_INVELEM, ARGV0, node[i]->element); return (0); } /* Check for additional entries */ if (node[i]->attributes[1] && node[i]->values[1]) { if (strcasecmp(node[i]->attributes[0], xml_decoder_status) != 0) { merror(XML_INVELEM, ARGV0, node[i]->element); return (0); } if (node[i]->attributes[2]) { merror(XML_INVELEM, ARGV0, node[i]->element); return (0); } } /* Get decoder options */ elements = OS_GetElementsbyNode(&xml, node[i]); if (elements == NULL) { merror(XML_ELEMNULL, ARGV0); return (0); } /* Create the OSDecoderInfo */ pi = (OSDecoderInfo *)calloc(1, sizeof(OSDecoderInfo)); if (pi == NULL) { merror(MEM_ERROR, ARGV0, errno, strerror(errno)); return (0); } /* Default values to the list */ pi->parent = NULL; pi->id = 0; pi->name = strdup(node[i]->values[0]); pi->order = NULL; pi->plugindecoder = NULL; pi->fts = 0; pi->accumulate = 0; pi->type = SYSLOG; pi->prematch = NULL; pi->program_name = NULL; pi->regex = NULL; pi->use_own_name = 0; pi->get_next = 0; pi->regex_offset = 0; pi->prematch_offset = 0; regex = NULL; prematch = NULL; p_name = NULL; /* Check if strdup worked */ if (!pi->name) { merror(MEM_ERROR, ARGV0, errno, strerror(errno)); return (0); } /* Add decoder */ if (!addDecoder2list(pi->name)) { merror(MEM_ERROR, ARGV0, errno, strerror(errno)); free(pi); return (0); } /* Loop over all the elements */ while (elements[j]) { if (!elements[j]->element) { merror(XML_ELEMNULL, ARGV0); return (0); } else if (!elements[j]->content) { merror(XML_VALUENULL, ARGV0, elements[j]->element); return (0); } /* Check if it is a child of a rule */ else if (strcasecmp(elements[j]->element, xml_parent) == 0) { pi->parent = _loadmemory(pi->parent, elements[j]->content); } /* Get the regex */ else if (strcasecmp(elements[j]->element, xml_regex) == 0) { int r_offset; r_offset = ReadDecodeAttrs(elements[j]->attributes, elements[j]->values); if (r_offset & AFTER_ERROR) { merror(DEC_REGEX_ERROR, ARGV0, pi->name); return (0); } /* Only the first regex entry may have an offset */ if (regex && r_offset) { merror(DUP_REGEX, ARGV0, pi->name); merror(DEC_REGEX_ERROR, ARGV0, pi->name); return (0); } /* regex offset */ if (r_offset) { pi->regex_offset = r_offset; } /* Assign regex */ regex = _loadmemory(regex, elements[j]->content); } /* Get the pre match */ else if (strcasecmp(elements[j]->element, xml_prematch) == 0) { int r_offset; r_offset = ReadDecodeAttrs( elements[j]->attributes, elements[j]->values); if (r_offset & AFTER_ERROR) { ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name); } /* Only the first prematch entry may have an offset */ if (prematch && r_offset) { merror(DUP_REGEX, ARGV0, pi->name); ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name); } if (r_offset) { pi->prematch_offset = r_offset; } prematch = _loadmemory(prematch, elements[j]->content); } /* Get program name */ else if (strcasecmp(elements[j]->element, xml_program_name) == 0) { p_name = _loadmemory(p_name, elements[j]->content); } /* Get the FTS comment */ else if (strcasecmp(elements[j]->element, xml_ftscomment) == 0) { } else if (strcasecmp(elements[j]->element, xml_usename) == 0) { if (strcmp(elements[j]->content, "true") == 0) { pi->use_own_name = 1; } } else if (strcasecmp(elements[j]->element, xml_plugindecoder) == 0) { int ed_c = 0; for (ed_c = 0; plugin_decoders[ed_c] != NULL; ed_c++) { if (strcmp(plugin_decoders[ed_c], elements[j]->content) == 0) { /* Initialize plugin */ void (*dec_init)(void) = (void (*)(void)) plugin_decoders_init[ed_c]; dec_init(); pi->plugindecoder = (void (*)(void *)) plugin_decoders_exec[ed_c]; break; } } /* Decoder not found */ if (pi->plugindecoder == NULL) { merror(INV_DECOPTION, ARGV0, elements[j]->element, elements[j]->content); return (0); } } /* Get the type */ else if (strcmp(elements[j]->element, xml_type) == 0) { if (strcmp(elements[j]->content, "firewall") == 0) { pi->type = FIREWALL; } else if (strcmp(elements[j]->content, "ids") == 0) { pi->type = IDS; } else if (strcmp(elements[j]->content, "web-log") == 0) { pi->type = WEBLOG; } else if (strcmp(elements[j]->content, "syslog") == 0) { pi->type = SYSLOG; } else if (strcmp(elements[j]->content, "squid") == 0) { pi->type = SQUID; } else if (strcmp(elements[j]->content, "windows") == 0) { pi->type = DECODER_WINDOWS; } else if (strcmp(elements[j]->content, "host-information") == 0) { pi->type = HOST_INFO; } else if (strcmp(elements[j]->content, "ossec") == 0) { pi->type = OSSEC_RL; } else { merror("%s: Invalid decoder type '%s'.", ARGV0, elements[j]->content); return (0); } } /* Get the order */ else if (strcasecmp(elements[j]->element, xml_order) == 0) { char **norder, **s_norder; int order_int = 0; /* Maximum number is 8 for the order */ norder = OS_StrBreak(',', elements[j]->content, 8); s_norder = norder; os_calloc(8, sizeof(void *), pi->order); /* Initialize the function pointers */ while (order_int < 8) { pi->order[order_int] = NULL; order_int++; } order_int = 0; /* Check the values from the order */ while (*norder) { if (strstr(*norder, "dstuser") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) DstUser_FP; } else if (strstr(*norder, "srcuser") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) SrcUser_FP; } /* User is an alias to dstuser */ else if (strstr(*norder, "user") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) DstUser_FP; } else if (strstr(*norder, "srcip") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) SrcIP_FP; } else if (strstr(*norder, "dstip") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) DstIP_FP; } else if (strstr(*norder, "srcport") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) SrcPort_FP; } else if (strstr(*norder, "dstport") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) DstPort_FP; } else if (strstr(*norder, "protocol") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) Protocol_FP; } else if (strstr(*norder, "action") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) Action_FP; } else if (strstr(*norder, "id") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) ID_FP; } else if (strstr(*norder, "url") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) Url_FP; } else if (strstr(*norder, "data") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) Data_FP; } else if (strstr(*norder, "extra_data") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) Data_FP; } else if (strstr(*norder, "status") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) Status_FP; } else if (strstr(*norder, "system_name") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) SystemName_FP; } else if (strstr(*norder, "filename") != NULL) { pi->order[order_int] = (void (*)(void *, char *)) FileName_FP; } else { ErrorExit("decode-xml: Wrong field '%s' in the order" " of decoder '%s'", *norder, pi->name); } free(*norder); norder++; order_int++; } free(s_norder); } else if (strcasecmp(elements[j]->element, xml_accumulate) == 0) { /* Enable Accumulator */ pi->accumulate = 1; } /* Get the FTS order */ else if (strcasecmp(elements[j]->element, xml_fts) == 0) { char **norder; char **s_norder; /* Maximum number is 8 for the FTS */ norder = OS_StrBreak(',', elements[j]->content, 8); if (norder == NULL) { ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno)); } /* Save the initial point to free later */ s_norder = norder; /* Check the values from the FTS */ while (*norder) { if (strstr(*norder, "dstuser") != NULL) { pi->fts |= FTS_DSTUSER; } if (strstr(*norder, "user") != NULL) { pi->fts |= FTS_DSTUSER; } else if (strstr(*norder, "srcuser") != NULL) { pi->fts |= FTS_SRCUSER; } else if (strstr(*norder, "srcip") != NULL) { pi->fts |= FTS_SRCIP; } else if (strstr(*norder, "dstip") != NULL) { pi->fts |= FTS_DSTIP; } else if (strstr(*norder, "id") != NULL) { pi->fts |= FTS_ID; } else if (strstr(*norder, "location") != NULL) { pi->fts |= FTS_LOCATION; } else if (strstr(*norder, "data") != NULL) { pi->fts |= FTS_DATA; } else if (strstr(*norder, "extra_data") != NULL) { pi->fts |= FTS_DATA; } else if (strstr(*norder, "system_name") != NULL) { pi->fts |= FTS_SYSTEMNAME; } else if (strstr(*norder, "name") != NULL) { pi->fts |= FTS_NAME; } else { ErrorExit("decode-xml: Wrong field '%s' in the fts" " decoder '%s'", *norder, pi->name); } free(*norder); norder++; } /* Clear memory here */ free(s_norder); } else { merror("%s: Invalid element '%s' for " "decoder '%s'", ARGV0, elements[j]->element, node[i]->element); return (0); } /* NEXT */ j++; } /* while(elements[j]) */ OS_ClearNode(elements); /* Prematch must be set */ if (!prematch && !pi->parent && !p_name) { merror(DECODE_NOPRE, ARGV0, pi->name); merror(DEC_REGEX_ERROR, ARGV0, pi->name); return (0); } /* If pi->regex is not set, fts must not be set too */ if ((!regex && (pi->fts || pi->order)) || (regex && !pi->order)) { merror(DEC_REGEX_ERROR, ARGV0, pi->name); return (0); } /* For the offsets */ if ((pi->regex_offset & AFTER_PARENT) && !pi->parent) { merror(INV_OFFSET, ARGV0, "after_parent"); merror(DEC_REGEX_ERROR, ARGV0, pi->name); return (0); } if (pi->regex_offset & AFTER_PREMATCH) { /* If after_prematch is set, but rule have * no parent, set AFTER_PARENT and unset * pre_match. */ if (!pi->parent) { pi->regex_offset = 0; pi->regex_offset |= AFTER_PARENT; } else if (!prematch) { merror(INV_OFFSET, ARGV0, "after_prematch"); merror(DEC_REGEX_ERROR, ARGV0, pi->name); return (0); } } /* For the after_regex offset */ if (pi->regex_offset & AFTER_PREVREGEX) { if (!pi->parent || !regex) { merror(INV_OFFSET, ARGV0, "after_regex"); merror(DEC_REGEX_ERROR, ARGV0, pi->name); return (0); } } /* Check the prematch offset */ if (pi->prematch_offset) { /* Only the after parent is allowed */ if (pi->prematch_offset & AFTER_PARENT) { if (!pi->parent) { merror(INV_OFFSET, ARGV0, "after_parent"); merror(DEC_REGEX_ERROR, ARGV0, pi->name); return (0); } } else { merror(DEC_REGEX_ERROR, ARGV0, pi->name); return (0); } } /* Compile the regex/prematch */ if (prematch) { os_calloc(1, sizeof(OSRegex), pi->prematch); if (!OSRegex_Compile(prematch, pi->prematch, 0)) { merror(REGEX_COMPILE, ARGV0, prematch, pi->prematch->error); return (0); } free(prematch); } /* Compile the p_name */ if (p_name) { os_calloc(1, sizeof(OSMatch), pi->program_name); if (!OSMatch_Compile(p_name, pi->program_name, 0)) { merror(REGEX_COMPILE, ARGV0, p_name, pi->program_name->error); return (0); } free(p_name); } /* We may not have the pi->regex */ if (regex) { os_calloc(1, sizeof(OSRegex), pi->regex); if (!OSRegex_Compile(regex, pi->regex, OS_RETURN_SUBSTRING)) { merror(REGEX_COMPILE, ARGV0, regex, pi->regex->error); return (0); } /* We must have the sub_strings to retrieve the nodes */ if (!pi->regex->sub_strings) { merror(REGEX_SUBS, ARGV0, regex); return (0); } free(regex); } /* Validate arguments */ if (pi->plugindecoder && (pi->regex || pi->order)) { merror(DECODE_ADD, ARGV0, pi->name); return (0); } /* Add osdecoder to the list */ if (!OS_AddOSDecoder(pi)) { merror(DECODER_ERROR, ARGV0); return (0); } i++; } /* while (node[i]) */ /* Clean node and XML structures */ OS_ClearNode(node); OS_ClearXML(&xml); return (1); }
int main(int argc, char **argv) { int key_added = 0; int c; int test_config = 0; int auto_method = 0; #ifndef WIN32 gid_t gid = 0; #endif int sock = 0, port = DEFAULT_PORT, ret = 0; const char *dir = DEFAULTDIR; const char *group = GROUPGLOBAL; char *authpass = NULL; const char *manager = NULL; const char *ipaddress = NULL; const char *agentname = NULL; const char *agent_cert = NULL; const char *agent_key = NULL; const char *ca_cert = NULL; char lhostname[512 + 1]; char buf[4096 + 1]; SSL_CTX *ctx; SSL *ssl; BIO *sbio; bio_err = 0; buf[4096] = '\0'; #ifdef WIN32 WSADATA wsaData; #endif /* Set the name */ OS_SetName(ARGV0); while ((c = getopt(argc, argv, "Vdhtg:m:p:A:v:x:k:D:P:a")) != -1) { switch (c) { case 'V': print_version(); break; case 'h': help_agent_auth(); break; case 'd': nowDebug(); break; case 'g': if (!optarg) { ErrorExit("%s: -g needs an argument", ARGV0); } group = optarg; break; case 'D': if (!optarg) { ErrorExit("%s: -g needs an argument", ARGV0); } dir = optarg; break; case 't': test_config = 1; break; case 'm': if (!optarg) { ErrorExit("%s: -%c needs an argument", ARGV0, c); } manager = optarg; break; case 'A': if (!optarg) { ErrorExit("%s: -%c needs an argument", ARGV0, c); } agentname = optarg; break; case 'p': if (!optarg) { ErrorExit("%s: -%c needs an argument", ARGV0, c); } port = atoi(optarg); if (port <= 0 || port >= 65536) { ErrorExit("%s: Invalid port: %s", ARGV0, optarg); } break; case 'v': if (!optarg) { ErrorExit("%s: -%c needs an argument", ARGV0, c); } ca_cert = optarg; break; case 'x': if (!optarg) { ErrorExit("%s: -%c needs an argument", ARGV0, c); } agent_cert = optarg; break; case 'k': if (!optarg) { ErrorExit("%s: -%c needs an argument", ARGV0, c); } agent_key = optarg; break; case 'P': if (!optarg) ErrorExit("%s: -%c needs an argument", ARGV0, c); authpass = optarg; break; case 'a': auto_method = 1; break; default: help_agent_auth(); break; } } /* Start daemon */ debug1(STARTED_MSG, ARGV0); #ifndef WIN32 /* Check if the user/group given are valid */ gid = Privsep_GetGroup(group); if (gid == (gid_t) - 1) { ErrorExit(USER_ERROR, ARGV0, "", group); } /* Exit here if test config is set */ if (test_config) { exit(0); } /* Privilege separation */ if (Privsep_SetGroup(gid) < 0) { ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno)); } /* Signal manipulation */ StartSIG(ARGV0); /* Create PID files */ if (CreatePID(ARGV0, getpid()) < 0) { ErrorExit(PID_ERROR, ARGV0); } #else /* Initialize Windows socket stuff */ if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { ErrorExit("%s: WSAStartup() failed", ARGV0); } #endif /* WIN32 */ /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); if (agentname == NULL) { lhostname[512] = '\0'; if (gethostname(lhostname, 512 - 1) != 0) { merror("%s: ERROR: Unable to extract hostname. Custom agent name not set.", ARGV0); exit(1); } agentname = lhostname; } #ifdef LEGACY_SSL auto_method = 1; merror("WARN: TLS v1.2 method-forcing disabled. This program was compiled to use SSL/TLS auto-negotiation."); #endif /* Start SSL */ ctx = os_ssl_keys(0, dir, agent_cert, agent_key, ca_cert, auto_method); if (!ctx) { merror("%s: ERROR: SSL error. Exiting.", ARGV0); exit(1); } if (!manager) { merror("%s: ERROR: Manager IP not set.", ARGV0); exit(1); } /* Check to see if the manager to connect to was specified as an IP address * or hostname on the command line. If it was given as a hostname then ensure * the hostname is preserved so that certificate verification can be done. */ if (!(ipaddress = OS_GetHost(manager, 3))) { merror("%s: Could not resolve hostname: %s\n", ARGV0, manager); exit(1); } /* Checking if there is a custom password file */ if (authpass == NULL) { FILE *fp; fp = fopen(AUTHDPASS_PATH, "r"); buf[0] = '\0'; if (fp) { buf[4096] = '\0'; char *ret = fgets(buf, 4095, fp); if (ret && strlen(buf) > 2) { authpass = buf; } fclose(fp); printf("INFO: Using password specified on file: %s\n", AUTHDPASS_PATH); } } if (!authpass) { printf("WARN: No authentication password provided.\n"); } /* Connect via TCP */ sock = OS_ConnectTCP(port, ipaddress, 0); if (sock <= 0) { merror("%s: Unable to connect to %s:%d", ARGV0, ipaddress, port); exit(1); } /* Connect the SSL socket */ ssl = SSL_new(ctx); sbio = BIO_new_socket(sock, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio); ret = SSL_connect(ssl); if (ret <= 0) { ERR_print_errors_fp(stderr); merror("%s: ERROR: SSL error (%d). Exiting.", ARGV0, ret); exit(1); } printf("INFO: Connected to %s:%d\n", ipaddress, port); /* Additional verification of the manager's certificate if a hostname * rather than an IP address is given on the command line. Could change * this to do the additional validation on IP addresses as well if needed. */ if (ca_cert) { printf("INFO: Verifing manager's certificate\n"); if (check_x509_cert(ssl, manager) != VERIFY_TRUE) { debug1("%s: DEBUG: Unable to verify server certificate.", ARGV0); exit(1); } } printf("INFO: Using agent name as: %s\n", agentname); if (authpass) { snprintf(buf, 2048, "OSSEC PASS: %s OSSEC A:'%s'\n", authpass, agentname); } else { snprintf(buf, 2048, "OSSEC A:'%s'\n", agentname); } ret = SSL_write(ssl, buf, strlen(buf)); if (ret < 0) { printf("SSL write error (unable to send message.)\n"); ERR_print_errors_fp(stderr); exit(1); } printf("INFO: Send request to manager. Waiting for reply.\n"); while (1) { ret = SSL_read(ssl, buf, sizeof(buf) - 1); switch (SSL_get_error(ssl, ret)) { case SSL_ERROR_NONE: buf[ret] = '\0'; if (strncmp(buf, "ERROR", 5) == 0) { char *tmpstr; tmpstr = strchr(buf, '\n'); if (tmpstr) { *tmpstr = '\0'; } printf("%s (from manager)\n", buf); } else if (strncmp(buf, "OSSEC K:'", 9) == 0) { char *key; char *tmpstr; char **entry; printf("INFO: Received response with agent key\n"); key = buf; key += 9; tmpstr = strchr(key, '\''); if (!tmpstr) { printf("ERROR: Invalid key received. Closing connection.\n"); exit(1); } *tmpstr = '\0'; entry = OS_StrBreak(' ', key, 4); if (!OS_IsValidID(entry[0]) || !OS_IsValidName(entry[1]) || !OS_IsValidName(entry[2]) || !OS_IsValidName(entry[3])) { printf("ERROR: Invalid key received (2). Closing connection.\n"); exit(1); } { FILE *fp; fp = fopen(KEYSFILE_PATH, "w"); if (!fp) { printf("ERROR: Unable to open key file: %s", KEYSFILE_PATH); exit(1); } fprintf(fp, "%s\n", key); fclose(fp); } key_added = 1; printf("INFO: Valid key created. Finished.\n"); } break; case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_SYSCALL: if (key_added == 0) { printf("ERROR: Unable to create key. Either wrong password or connection not accepted by the manager.\n"); } printf("INFO: Connection closed.\n"); exit(0); break; default: printf("ERROR: SSL read (unable to receive message)\n"); exit(1); break; } } /* Shut down the socket */ if (key_added == 0) { printf("ERROR: Unable to create key. Either wrong password or connection not accepted by the manager.\n"); } SSL_CTX_free(ctx); close(sock); exit(0); }
int main(int argc, char **argv) { int c, test_config = 0; #ifndef WIN32 int gid = 0; #endif int sock = 0, port = 1515, ret = 0; char *dir = DEFAULTDIR; char *user = USER; char *group = GROUPGLOBAL; char *cfg = DEFAULTCPATH; char *manager = NULL; char *agentname = NULL; char lhostname[512 + 1]; char buf[2048 +1]; SSL_CTX *ctx; SSL *ssl; BIO *sbio; bio_err = 0; buf[2048] = '\0'; /* Setting the name */ OS_SetName(ARGV0); while((c = getopt(argc, argv, "Vdhu:g:D:c:m:p:A:")) != -1) { switch(c) { case 'V': print_version(); break; case 'h': report_help(); break; case 'd': nowDebug(); 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; case 'm': if(!optarg) ErrorExit("%s: -%c needs an argument",ARGV0, c); manager = optarg; break; case 'A': if(!optarg) ErrorExit("%s: -%c needs an argument",ARGV0, c); agentname = optarg; break; case 'p': if(!optarg) ErrorExit("%s: -%c needs an argument",ARGV0, c); port = atoi(optarg); if(port <= 0 || port >= 65536) { ErrorExit("%s: Invalid port: %s", ARGV0, optarg); } break; default: report_help(); break; } } /* Starting daemon */ debug1(STARTED_MSG,ARGV0); #ifndef WIN32 /* Check if the user/group given are valid */ gid = Privsep_GetGroup(group); if(gid < 0) ErrorExit(USER_ERROR,ARGV0,user,group); /* Privilege separation */ if(Privsep_SetGroup(gid) < 0) ErrorExit(SETGID_ERROR,ARGV0,group); /* Signal manipulation */ StartSIG(ARGV0); /* Creating PID files */ if(CreatePID(ARGV0, getpid()) < 0) ErrorExit(PID_ERROR,ARGV0); #endif /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); if(agentname == NULL) { lhostname[512] = '\0'; if(gethostname(lhostname, 512 -1) != 0) { merror("%s: ERROR: Unable to extract hostname. Custom agent name not set.", ARGV0); exit(1); } agentname = lhostname; } /* Starting SSL */ ctx = os_ssl_keys(1, NULL); if(!ctx) { merror("%s: ERROR: SSL error. Exiting.", ARGV0); exit(1); } if(!manager) { merror("%s: ERROR: Manager IP not set.", ARGV0); exit(1); } /* Check to see if manager is an IP */ int is_ip = 1; struct sockaddr_in iptest; memset(&iptest, 0, sizeof(iptest)); if(inet_pton(AF_INET, manager, &iptest.sin_addr) != 1) is_ip = 0; /* This is not an IPv4 address */ /* Not IPv4, IPv6 maybe? */ if(is_ip == 0) { struct sockaddr_in6 iptest6; memset(&iptest6, 0, sizeof(iptest6)); if(inet_pton(AF_INET6, manager, &iptest6.sin6_addr) != 1) is_ip = 0; else is_ip = 1; /* This is an IPv6 address */ } /* If it isn't an ip, try to resolve the IP */ if(is_ip == 0) { char *ipaddress; ipaddress = OS_GetHost(manager, 3); if(ipaddress != NULL) strncpy(manager, ipaddress, 16); else { printf("Could not resolve hostname: %s\n", manager); return(1); } } /* Connecting via TCP */ sock = OS_ConnectTCP(port, manager, 0); if(sock <= 0) { merror("%s: Unable to connect to %s:%d", ARGV0, manager, port); exit(1); } /* Connecting the SSL socket */ ssl = SSL_new(ctx); sbio = BIO_new_socket(sock, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio); ret = SSL_connect(ssl); if(ret <= 0) { ERR_print_errors_fp(stderr); merror("%s: ERROR: SSL error (%d). Exiting.", ARGV0, ret); exit(1); } printf("INFO: Connected to %s:%d\n", manager, port); printf("INFO: Using agent name as: %s\n", agentname); snprintf(buf, 2048, "OSSEC A:'%s'\n", agentname); ret = SSL_write(ssl, buf, strlen(buf)); if(ret < 0) { printf("SSL write error (unable to send message.)\n"); ERR_print_errors_fp(stderr); exit(1); } printf("INFO: Send request to manager. Waiting for reply.\n"); while(1) { ret = SSL_read(ssl,buf,sizeof(buf) -1); switch(SSL_get_error(ssl,ret)) { case SSL_ERROR_NONE: buf[ret] = '\0'; if(strncmp(buf, "ERROR", 5) == 0) { char *tmpstr; tmpstr = strchr(buf, '\n'); if(tmpstr) *tmpstr = '\0'; printf("%s (from manager)\n", buf); } else if(strncmp(buf, "OSSEC K:'",9) == 0) { char *key; char *tmpstr; char **entry; printf("INFO: Received response with agent key\n"); key = buf; key += 9; tmpstr = strchr(key, '\''); if(!tmpstr) { printf("ERROR: Invalid key received. Closing connection.\n"); exit(1); } *tmpstr = '\0'; entry = OS_StrBreak(' ', key, 4); if(!OS_IsValidID(entry[0]) || !OS_IsValidName(entry[1]) || !OS_IsValidName(entry[2]) || !OS_IsValidName(entry[3])) { printf("ERROR: Invalid key received (2). Closing connection.\n"); exit(1); } { FILE *fp; fp = fopen(KEYSFILE_PATH,"w"); if(!fp) { printf("ERROR: Unable to open key file: %s", KEYSFILE_PATH); exit(1); } fprintf(fp, "%s\n", key); fclose(fp); } printf("INFO: Valid key created. Finished.\n"); } break; case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_SYSCALL: printf("INFO: Connection closed.\n"); exit(0); break; default: printf("ERROR: SSL read (unable to receive message)\n"); exit(1); break; } } /* Shutdown the socket */ SSL_CTX_free(ctx); close(sock); exit(0); }