/* SAMHAIN file system integrity testing */ /* Copyright (C) 2009 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 of the License, 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; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #ifdef HAVE_REGEX_H #include #endif #include "samhain.h" #include "sh_utils.h" #include "sh_mem.h" #include "sh_filter.h" #undef FIL__ #define FIL__ _("sh_filter.c") void sh_filter_free (sh_filter_type * filter) { int i; if (filter) { for (i = 0; i < filter->for_c; ++i) { #ifdef HAVE_REGEX_H if (filter->for_v[i]) regfree(filter->for_v[i]); #else if (filter->for_v[i]) SH_FREE(filter->for_v[i]); #endif filter->for_v[i] = NULL; } filter->for_c = 0; for (i = 0; i < filter->fand_c; ++i) { #ifdef HAVE_REGEX_H if (filter->fand_v[i]) regfree(filter->fand_v[i]); #else if (filter->fand_v[i]) SH_FREE(filter->fand_v[i]); #endif filter->fand_v[i] = NULL; } filter->fand_c = 0; for (i = 0; i < filter->fnot_c; ++i) { #ifdef HAVE_REGEX_H if (filter->fnot_v[i]) regfree(filter->fnot_v[i]); #else if (filter->fnot_v[i]) SH_FREE(filter->fnot_v[i]); #endif filter->fnot_v[i] = NULL; } filter->fnot_c = 0; } } int sh_filter_add (const char * str, sh_filter_type * filter, int type) { int i = 0; int flag = 0; size_t s; char * dupp; char * p; char * end; int * ntok; void ** stok; SL_ENTER(_("sh_filter_filteradd")); if (NULL == str || NULL == filter) { SL_RETURN((-1), _("sh_filter_filteradd")); } if (type == SH_FILT_OR) { ntok = &(filter->for_c); stok = filter->for_v; } else if (type == SH_FILT_AND) { ntok = &(filter->fand_c); stok = filter->fand_v; } else if (type == SH_FILT_NOT) { ntok = &(filter->fnot_c); stok = filter->fnot_v; } else { SL_RETURN((-1), _("sh_filter_filteradd")); } /* cppcheck-suppress uninitvar */ i = *ntok; if (i == SH_FILT_NUM) { SL_RETURN((-1), _("sh_filter_filteradd")); } dupp = sh_util_strdup(str); p = dupp; do { while (*p == ',' || *p == ' ' || *p == '\t') ++p; if (*p == '\0') break; end = p; ++end; if (*end == '\0') break; if (*p == '\'') { ++p; end = p; if (*end != '\'') ++end; if (*p == '\0' || *end == '\0') break; while (*end != '\0' && *end != '\'') ++end; } else if (*p == '"') { ++p; end = p; if (*end != '"') ++end; if (*p == '\0' || *end == '\0') break; while (*end != '\0' && *end != '"') ++end; } else { while (*end != '\0' && *end != ',' && *end != ' ' && *end != '\t') ++end; } if (*end == '\0') flag = 1; else *end = '\0'; s = strlen(p); if (s > 0) { ++s; #ifdef HAVE_REGEX_H if (stok[i] != NULL) regfree((regex_t *) stok[i]); { int status; stok[i] = SH_ALLOC(sizeof(regex_t)); status = regcomp((regex_t *) stok[i], p, REG_NOSUB|REG_EXTENDED); if (status != 0) { char * errbuf = SH_ALLOC(BUFSIZ); (void) regerror(status, (regex_t *) stok[i], errbuf, BUFSIZ); errbuf[BUFSIZ-1] = '\0'; sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_REGEX, errbuf, p); SH_FREE(errbuf); } } #else if (stok[i] != NULL) SH_FREE(stok[i]); stok[i] = SH_ALLOC(s); (void) sl_strlcpy((char *) stok[i], p, s); #endif ++i; } p = end; ++p; if (i == SH_FILT_NUM) break; } while (p != NULL && *p != '\0' && flag == 0); *ntok = i; SH_FREE(dupp); SL_RETURN (0, _("sh_filter_filteradd")); } #ifdef HAVE_REGEX_H static int sh_filter_cmp(const char * message, void * pattern) { int result; result = regexec((regex_t *)pattern, message, 0, NULL, 0); if (result != 0) return -1; /* Successful match. */ return 0; } #else static int sh_filter_cmp(const char * message, void * pattern) { if (NULL == sl_strstr(message, (char *)pattern)) return -1; /* Successful match. */ return 0; } #endif /* * -- Check filters. Returns 0 if message passes. */ int sh_filter_filter (const char * message, sh_filter_type * filter) { int i; SL_ENTER(_("sh_filter_filter")); if (filter) { /* Presence of any of these keywords prevents execution. */ if (filter->fnot_c > 0) { for (i = 0; i < filter->fnot_c; ++i) { if (0 == sh_filter_cmp(message, filter->fnot_v[i])) { SL_RETURN ((-1), _("sh_filter_filter")); } } } /* Presence of all of these keywords is required for execution. */ if (filter->fand_c > 0) { for (i = 0; i < filter->fand_c; ++i) { if (0 != sh_filter_cmp(message, filter->fand_v[i])) { SL_RETURN ((-1), _("sh_filter_filter")); } } } /* Presence of at least one of these keywords is required for execution. */ if (filter->for_c > 0) { for (i = 0; i < filter->for_c; ++i) { if (0 == sh_filter_cmp(message, filter->for_v[i])) { goto isok; } } SL_RETURN ((-1), _("sh_filter_filter")); } } isok: SL_RETURN ((0), _("sh_filter_filter")); } sh_filter_type * sh_filter_alloc(void) { sh_filter_type * filter = SH_ALLOC(sizeof(sh_filter_type)); memset(filter, 0, sizeof(sh_filter_type)); filter->for_c = 0; filter->fand_c = 0; filter->fnot_c = 0; return filter; }