diff --git a/.gitignore b/.gitignore index 8d287eaca..eca7d292d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ .DS_Store *.dll *.exe +*.core # Auto generated build files src/LOCATION diff --git a/.travis.yml b/.travis.yml index 8fdea12a5..9dd57aab8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,7 +48,10 @@ before_script: - if [[ "${PRELUDE}" == "yes" ]]; then ( sudo apt-get install libprelude-dev ); fi - if [[ "${ZEROMQ}" == "yes" ]]; then ( sudo apt-get install libzmq3-dev libtool autoconf libczmq-dev ); fi - if [[ "${OSSEC_TYPE}" == "winagent" ]]; then ( sudo apt-get install aptitude && sudo aptitude -y install mingw-w64 nsis ); fi -- if [[ "${OSSEC_TYPE}" == "server" ]]; then ( sudo apt-get install libsqlite3-dev sqlite3 ); fi +- if [[ "${USE_SQLITE}" == "yes" ]]; then ( sudo apt-get install libsqlite3-dev sqlite3 ); fi +- if [[ "${USE_LIBSODIUM}" == "yes" ]]; then ( sudo add-apt-repository -y ppa:chris-lea/libsodium && sudo apt-get update + && sudo apt-get install libsodium-dev libsodium13 + ); fi - if [[ "${OSSEC_TYPE}" == "test" ]]; then ( sudo apt-get update && sudo apt-get install check valgrind ); fi diff --git a/src/Makefile b/src/Makefile index 8014e9e3f..4eddf0ea2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -29,6 +29,8 @@ USE_PRELUDE?=no USE_ZEROMQ?=no USE_GEOIP?=no USE_INOTIFY=no +USE_SQLITE?=no +USE_LIBSODIUM?=no USE_PCRE2_JIT=yes ifneq (${TARGET},winagent) @@ -143,6 +145,8 @@ OSSEC_CFLAGS=${CFLAGS} ifdef DEBUG OSSEC_CFLAGS+=-g +else + OSSEC_CFLAGS+=-O2 endif #DEBUG ifneq (,$(filter ${CLEANFULL},yes y Y 1)) @@ -239,6 +243,11 @@ ifneq (,$(filter ${USE_GEOIP},auto yes y Y 1)) OSSEC_LDFLAGS+=-lGeoIP endif # USE_GEOIP +ifneq (,$(filter ${USE_LIBSODIUM},auto yes y Y 1)) + DEFINES+=-DLIBSODIUM_ENABLED + OSSEC_LDFLAGS+=-lsodium +endif # USE_LIBSODIUM + ifneq (,$(filter ${USE_SQLITE},auto yes y Y 1)) DEFINES+=-DSQLITE_ENABLED ANALYSISD_FLAGS="-lsqlite3" @@ -601,6 +610,7 @@ settings: @echo " USE_PRELUDE: ${USE_PRELUDE}" @echo " USE_OPENSSL: ${USE_OPENSSL}" @echo " USE_INOTIFY: ${USE_INOTIFY}" + @echo " USE_LIBSODIUM: ${USE_LIBSODIUM}" @echo " USE_SQLITE: ${USE_SQLITE}" @echo " USE_PCRE2_JIT: ${USE_PCRE2_JIT}" @echo "Mysql settings:" @@ -1103,7 +1113,7 @@ syscheck_o := $(syscheck_c:.c=.o) syscheckd/%.o: syscheckd/%.c ${OSSEC_CC} ${OSSEC_CFLAGS} -DARGV0=\"ossec-syscheckd\" -c $^ -o $@ -ossec-syscheckd: ${syscheck_o} rootcheck.a ${ossec_libs} ${ZLIB_LIB} +ossec-syscheckd: ${syscheck_o} rootcheck.a os_crypto.a ${ossec_libs} ${ZLIB_LIB} ${OSSEC_CCBIN} ${OSSEC_CFLAGS} ${ZLIB_INCLUDE} $^ ${OSSEC_LDFLAGS} -o $@ #### Monitor ####### diff --git a/src/analysisd/decoders/syscheck.c b/src/analysisd/decoders/syscheck.c index a6d675892..631a354a3 100644 --- a/src/analysisd/decoders/syscheck.c +++ b/src/analysisd/decoders/syscheck.c @@ -27,8 +27,13 @@ typedef struct __sdb { char perm[OS_FLSIZE + 1]; char owner[OS_FLSIZE + 1]; char gowner[OS_FLSIZE + 1]; +#ifdef LIBSODIUM_ENABLED + char md5[(OS_FLSIZE * 2) + 1]; + char sha1[(OS_FLSIZE * 2) + 1]; +#else //LIBSODIUM_ENABLED char md5[OS_FLSIZE + 1]; char sha1[OS_FLSIZE + 1]; +#endif char agent_cp[MAX_AGENTS + 1][1]; char *agent_ips[MAX_AGENTS + 1]; @@ -536,9 +541,26 @@ static int DB_Search(const char *f_name, const char *c_sum, Eventinfo *lf) if (!newmd5 || !oldmd5 || strcmp(newmd5, oldmd5) == 0) { sdb.md5[0] = '\0'; } else { +#ifdef LIBSODIUM_ENABLED + char *hash_type; + if (strncmp(newmd5, "GENERIC", 7) == 0) { + hash_type = "blake2b"; + } else if (strncmp(newmd5, "SHA256", 6) == 0) { + hash_type = "sha256"; + } else if (strncmp(newmd5, "MD5", 3) == 0) { + hash_type = "md5"; + } else if (strncmp(newmd5, "SHA1", 4) == 0) { + hash_type = "sha1"; + } else { + hash_type = "unknown"; + } + snprintf(sdb.md5, OS_FLSIZE * 2, "Old %s was: '%s'\n" + "New %s is: '%s'\n", hash_type, oldmd5, hash_type, newmd5); +#else //LIBSODIUM_ENABLED snprintf(sdb.md5, OS_FLSIZE, "Old md5sum was: '%s'\n" - "New md5sum is : '%s'\n", + "New md5sum is: '%s'\n", oldmd5, newmd5); +#endif //LIBSODIUM_ENABLED os_strdup(oldmd5, lf->md5_before); os_strdup(newmd5, lf->md5_after); } @@ -547,9 +569,22 @@ static int DB_Search(const char *f_name, const char *c_sum, Eventinfo *lf) if (!newsha1 || !oldsha1 || strcmp(newsha1, oldsha1) == 0) { sdb.sha1[0] = '\0'; } else { +#ifdef LIBSODIUM_ENABLED + char *hash_type; + if(strncmp(newsha1, "GENERIC", 7) == 0) { + hash_type = "blake2b"; + } else if(strncmp(newsha1, "SHA256", 6) == 0) { + hash_type = "sha256"; + } else { + hash_type = "unknown"; + } + snprintf(sdb.sha1, OS_FLSIZE * 2, "Old %s was: '%s'\n" + "New %s is : '%s'\n", hash_type, oldsha1, hash_type, newsha1); +#else //LIBSODIUM_ENABLED snprintf(sdb.sha1, OS_FLSIZE, "Old sha1sum was: '%s'\n" "New sha1sum is : '%s'\n", oldsha1, newsha1); +#endif //LIBSODIUM_ENABLED os_strdup(oldsha1, lf->sha1_before); os_strdup(newsha1, lf->sha1_after); } @@ -695,25 +730,30 @@ int DecodeSyscheck(Eventinfo *lf) if (Config.md5_allowlist) { extern sqlite3 *conn; if ((p = extract_token(c_sum, ":", 4))) { - if (!validate_md5(p)) { /* Never trust input from other origin */ - merror("%s: Not a valid MD5 hash: '%s'", ARGV0, p); - return(0); - } - debug1("%s: Checking MD5 '%s' in %s", ARGV0, p, Config.md5_allowlist); - sprintf(stmt, "select md5sum from files where md5sum = \"%s\"", p); - error = sqlite3_prepare_v2(conn, stmt, 1000, &res, &tail); - if (error == SQLITE_OK) { - while (sqlite3_step(res) == SQLITE_ROW) { - rec_count++; - } - if (rec_count) { - sqlite3_finalize(res); - //sqlite3_close(conn); - merror(MD5_NOT_CHECKED, ARGV0, p); + if((strncmp(p, "xxx", 3)) != 0) { + if (!validate_md5(p)) { /* Never trust input from other origin */ + merror("%s: Not a valid MD5 hash: '%s'", ARGV0, p); return(0); } + debug1("%s: Checking MD5 '%s' in %s", ARGV0, p, Config.md5_allowlist); + if((snprintf(stmt, OS_MAXSTR, "select md5sum from files where md5sum = \"%s\"", p)) < 0) { + merror("ERROR: snprintf failed for md5sum: %s", p); + } + stmt[OS_MAXSTR] = '\0'; + error = sqlite3_prepare_v2(conn, stmt, 1000, &res, &tail); + if (error == SQLITE_OK) { + while (sqlite3_step(res) == SQLITE_ROW) { + rec_count++; + } + if (rec_count) { + sqlite3_finalize(res); + //sqlite3_close(conn); + merror(MD5_NOT_CHECKED, ARGV0, p); + return(0); + } + } + sqlite3_finalize(res); } - sqlite3_finalize(res); } } #endif diff --git a/src/analysisd/rules.c b/src/analysisd/rules.c index ee1107090..17807acd7 100644 --- a/src/analysisd/rules.c +++ b/src/analysisd/rules.c @@ -199,6 +199,7 @@ int Rules_OP_ReadRules(const char *rulefile) merror("rules_op: Invalid root element \"%s\"." "Only \"group\" is allowed", node[i]->element); OS_ClearXML(&xml); + free(node); return (-1); } if ((!node[i]->attributes) || (!node[i]->values) || @@ -208,11 +209,13 @@ int Rules_OP_ReadRules(const char *rulefile) merror("rules_op: Invalid root element '%s'." "Only the group name is allowed", node[i]->element); OS_ClearXML(&xml); + free(node); return (-1); } } else { merror(XML_READ_ERROR, ARGV0); OS_ClearXML(&xml); + free(node); return (-1); } i++; diff --git a/src/config/syscheck-config.c b/src/config/syscheck-config.c index cc4946e3f..a58723de1 100644 --- a/src/config/syscheck-config.c +++ b/src/config/syscheck-config.c @@ -160,6 +160,8 @@ static int read_attr(syscheck_config *syscheck, const char *dirs, char **g_attrs 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_sha256sum = "check_sha256sum"; + const char *xml_check_genericsum = "check_genericsum"; const char *xml_check_size = "check_size"; const char *xml_check_owner = "check_owner"; const char *xml_check_group = "check_group"; @@ -220,19 +222,39 @@ static int read_attr(syscheck_config *syscheck, const char *dirs, char **g_attrs attrs = g_attrs; values = g_values; +#ifdef LIBSODIUM_ENABLED +#ifdef DEBUG + merror("DEBUG: libsodium enabled"); +#endif //DEBUG +#endif //LIBSODIUM_ENABLED + while (*attrs && *values) { /* Check all */ if (strcmp(*attrs, xml_check_all) == 0) { if (strcmp(*values, "yes") == 0) { +#ifdef LIBSODIUM_ENABLED + opts |= CHECK_PERM; + opts |= CHECK_SIZE; + opts |= CHECK_OWNER; + opts |= CHECK_GROUP; + opts |= CHECK_SHA256SUM; opts |= CHECK_MD5SUM; +#else //LIBSODIUM_ENABLED opts |= CHECK_SHA1SUM; + opts |= CHECK_MD5SUM; opts |= CHECK_PERM; opts |= CHECK_SIZE; opts |= CHECK_OWNER; opts |= CHECK_GROUP; +#endif //LIBSODIUM_ENABLED } else if (strcmp(*values, "no") == 0) { +#ifdef LIBSODIUM_ENABLED + opts &= ~ ( CHECK_MD5SUM | CHECK_SHA1SUM | CHECK_PERM + | CHECK_SIZE | CHECK_OWNER | CHECK_GROUP | CHECK_SHA256SUM | CHECK_GENERIC ); +#else //LIBSODIUM_ENABLED opts &= ~ ( CHECK_MD5SUM | CHECK_SHA1SUM | CHECK_PERM | CHECK_SIZE | CHECK_OWNER | CHECK_GROUP ); +#endif //LIBSODIUM_ENABLED } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; @@ -242,10 +264,20 @@ static int read_attr(syscheck_config *syscheck, const char *dirs, char **g_attrs /* Check sum */ else if (strcmp(*attrs, xml_check_sum) == 0) { if (strcmp(*values, "yes") == 0) { +#ifdef LIBSODIUM_ENABLED + opts |= CHECK_SHA256SUM; + opts |= CHECK_GENERIC; +#else //LIBSODIUM_ENABLED opts |= CHECK_MD5SUM; opts |= CHECK_SHA1SUM; +#endif //LIBSODIUM_ENABLED + } else if (strcmp(*values, "no") == 0) { +#ifdef LIBSODIUM_ENABLED + opts &= ~ ( CHECK_GENERIC | CHECK_SHA256SUM ); +#else //LIBSODIUM_ENALBED opts &= ~ ( CHECK_MD5SUM | CHECK_SHA1SUM ); +#endif } else { merror(SK_INV_OPT, __local_name, *values, *attrs); ret = 0; @@ -276,6 +308,30 @@ static int read_attr(syscheck_config *syscheck, const char *dirs, char **g_attrs goto out_free; } } +#ifdef LIBSODIUM_ENABLED + else if(strncmp(*attrs, xml_check_sha256sum, 15) == 0) { + if(strncmp(*values, "yes", 3) == 0) { + opts |= CHECK_SHA256SUM; + } else if(strncmp(*values, "no", 2) == 0) { + opts &= ~ CHECK_SHA256SUM; + } else { + merror(SK_INV_OPT, __local_name, *values, *attrs); + ret = 0; + goto out_free; + } + } + else if(strncmp(*attrs, xml_check_genericsum, 16) == 0) { + if(strncmp(*values, "yes", 3) == 0) { + opts |= CHECK_GENERIC; + } else if(strncmp(*values, "no", 2) == 0) { + opts &= ~ CHECK_GENERIC; + } else { + merror(SK_INV_OPT, __local_name, *values, *attrs); + ret = 0; + goto out_free; + } + } +#endif //LIBSODIUM_ENABLED /* Check permission */ else if (strcmp(*attrs, xml_check_perm) == 0) { if (strcmp(*values, "yes") == 0) { @@ -495,6 +551,7 @@ int Read_Syscheck(XML_NODE node, void *configp, __attribute__((unused)) void *ma ExpandEnvironmentStrings(node[i]->content, dirs, sizeof(dirs) - 1); #else strncpy(dirs, node[i]->content, sizeof(dirs) - 1); + dirs[sizeof(dirs) - 1] = '\0'; #endif if (!read_attr(syscheck, @@ -793,12 +850,14 @@ int Read_Syscheck(XML_NODE node, void *configp, __attribute__((unused)) void *ma ExpandEnvironmentStrings(node[i]->content, cmd, sizeof(cmd) - 1); #else strncpy(cmd, node[i]->content, sizeof(cmd) - 1); + cmd[sizeof(cmd) - 1] = '\0'; #endif if (strlen(cmd) > 0) { char statcmd[OS_MAXSTR]; char *ix; strncpy(statcmd, cmd, sizeof(statcmd) - 1); + statcmd[sizeof(statcmd) - 1] = '\0'; if (NULL != (ix = strchr(statcmd, ' '))) { *ix = '\0'; } @@ -806,6 +865,7 @@ int Read_Syscheck(XML_NODE node, void *configp, __attribute__((unused)) void *ma /* More checks needed (perms, owner, etc.) */ os_calloc(1, strlen(cmd) + 1, syscheck->prefilter_cmd); strncpy(syscheck->prefilter_cmd, cmd, strlen(cmd)); + syscheck->prefilter_cmd[sizeof(syscheck->prefilter_cmd) - 1] = '\0'; } else { merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content); return (OS_INVALID); @@ -833,24 +893,32 @@ char *syscheck_opts2str(char *buf, int buflen, int opts) { CHECK_SIZE, CHECK_OWNER, CHECK_GROUP, - CHECK_MD5SUM, + CHECK_MD5SUM, CHECK_SHA1SUM, CHECK_REALTIME, CHECK_SEECHANGES, +#ifdef LIBSODIUM_ENABLED + CHECK_SHA256SUM, + CHECK_GENERIC, +#endif //LIBSODIUM_ENABLED CHECK_NORECURSE, - 0 + 0 }; char *check_strings[] = { "perm", "size", "owner", "group", - "md5sum", + "md5sum", "sha1sum", "realtime", "report_changes", +#ifdef LIBSODIUM_ENABLED + "sha256sum", + "genericsum", +#endif //LIBSODIUM_ENABLED "no_recurse", - NULL + NULL }; buf[0] = '\0'; diff --git a/src/config/syscheck-config.h b/src/config/syscheck-config.h index 51ca01a05..aa0e1a7d9 100644 --- a/src/config/syscheck-config.h +++ b/src/config/syscheck-config.h @@ -27,7 +27,6 @@ #define CHECK_GENERIC 0001000 #define CHECK_NORECURSE 0002000 - #include #include "os_regex/os_regex.h" @@ -54,6 +53,10 @@ typedef struct _config { int *opts; /* attributes set in the tag element */ + char *algorithms; /* Algorithms to use for FIM */ + char *hash1_alg; + char *hash2_alg; + char *remote_db; char *db; diff --git a/src/headers/file_op.h b/src/headers/file_op.h index d1b095610..12fd26364 100644 --- a/src/headers/file_op.h +++ b/src/headers/file_op.h @@ -25,7 +25,7 @@ int IsDir(const char *file) __attribute__((nonnull)); int CreatePID(const char *name, int pid) __attribute__((nonnull)); -char *GetRandomNoise(); +char *GetRandomNoise(void); int DeletePID(const char *name) __attribute__((nonnull)); diff --git a/src/headers/randombytes.h b/src/headers/randombytes.h index 9c69de3f5..b14c5cfb8 100644 --- a/src/headers/randombytes.h +++ b/src/headers/randombytes.h @@ -1,7 +1,7 @@ #ifndef __RANDOMBYTES_H #define __RANDOMBYTES_H -void randombytes(void *ptr, size_t length); +void OS_randombytes(void *ptr, size_t length); void srandom_init(void); #endif diff --git a/src/monitord/sendcustomemail.c b/src/monitord/sendcustomemail.c index f25d5d3f1..ba8843632 100644 --- a/src/monitord/sendcustomemail.c +++ b/src/monitord/sendcustomemail.c @@ -50,7 +50,7 @@ int OS_SendCustomEmail2(char **to, char *subject, char *smtpserver, char *from, { FILE *sendmail = NULL; int socket = -1, i = 0; - char *msg; + char *msg = NULL; char snd_msg[128]; char buffer[2049]; diff --git a/src/os_crypto/md5_sha1/md5_sha1_op.c b/src/os_crypto/md5_sha1/md5_sha1_op.c index dd367c7a0..17fe67a87 100644 --- a/src/os_crypto/md5_sha1/md5_sha1_op.c +++ b/src/os_crypto/md5_sha1/md5_sha1_op.c @@ -9,6 +9,11 @@ #include #include +#include + +#ifdef LIBSODIUM_ENABLED +#include +#endif #include "md5_sha1_op.h" #include "../md5/md5.h" @@ -86,3 +91,142 @@ int OS_MD5_SHA1_File(const char *fname, const char *prefilter_cmd, os_md5 md5out return (0); } + +#ifdef LIBSODIUM_ENABLED +int OS_Hash_File(const char *fname, const char *prefilter_cmd, struct hash_output *file_output, int mode) +{ + + size_t n; + FILE *fp; + unsigned char buf[2048 + 2]; + unsigned char md5_digest[16]; + unsigned char sha1_digest[SHA_DIGEST_LENGTH]; + unsigned char generic_digest[crypto_generichash_BYTES_MAX]; + unsigned char sha256_digest[crypto_hash_sha256_BYTES]; + + /* Declare and init the hashes */ + MD5_CTX md5_ctx; + if(file_output->check_md5) { + MD5Init(&md5_ctx); + } + + SHA_CTX sha1_ctx; + if(file_output->check_sha1) { + SHA1_Init(&sha1_ctx); + } + + crypto_hash_sha256_state sha256_state; + crypto_generichash_state generic_state; + + /* Initialize libsodium */ + if((file_output->check_sha256 > 0) || (file_output->check_generic) > 0) { + if(sodium_init() < 0) { + exit(errno); // XXX - doesn't seem right + } + } + if(file_output->check_sha256) { + crypto_hash_sha256_init(&sha256_state); + } + + if(file_output->check_generic) { + crypto_generichash_init(&generic_state, NULL, 0, sizeof(generic_digest)); + } + + buf[2048 + 1] = '\0'; + + /* Use prefilter_cmd if set */ + if (prefilter_cmd == NULL) { + fp = fopen(fname, mode == OS_BINARY ? "rb" : "r"); + if (!fp) { + return (-1); + } + } else { + char cmd[OS_MAXSTR]; + size_t target_length = strlen(prefilter_cmd) + 1 + strlen(fname); + int res = snprintf(cmd, sizeof(cmd), "%s %s", prefilter_cmd, fname); + if (res < 0 || (unsigned int)res != target_length) { + return (-1); + } + fp = popen(cmd, "r"); + if (!fp) { + return (-1); + } + } + + /* Update for each hash */ + while ((n = fread(buf, 1, 2048, fp)) > 0) { + buf[n] = '\0'; + if(file_output->check_md5) { + MD5Update(&md5_ctx, buf, (unsigned)n); + } + if(file_output->check_sha256) { + crypto_hash_sha256_update(&sha256_state, buf, n); + } + if(file_output->check_sha1) { + SHA1_Update(&sha1_ctx, buf, n); + } + if(file_output->check_generic) { + crypto_generichash_update(&generic_state, buf, n); + } + } + + if(file_output->check_md5) { + MD5Final(md5_digest, &md5_ctx); + } + if(file_output->check_sha256) { + crypto_hash_sha256_final(&sha256_state, sha256_digest); + } + if(file_output->check_sha1) { + SHA1_Final(&(sha1_digest[0]), &sha1_ctx); + } + if(file_output->check_generic) { + crypto_generichash_final(&generic_state, generic_digest, crypto_generichash_BYTES_MAX); + } + + /* Set output for MD5 */ + char hashtmp[3]; + + if(file_output->check_md5) { + for (n = 0; n < 16; n++) { + hashtmp[0] = '\0'; + snprintf(hashtmp, 3, "%02x", md5_digest[n]); + strncat(file_output->md5output, hashtmp, 2); + } + } + if(file_output->check_sha1) { + for (n = 0; n < 16; n++) { + hashtmp[0] = '\0'; + snprintf(hashtmp, 3, "%02x", sha1_digest[n]); + strncat(file_output->sha1output, hashtmp, 2); + } + } + if(file_output->check_generic) { + for (n = 0; n < crypto_generichash_BYTES_MAX; ++n) { + hashtmp[0] = '\0'; + snprintf(hashtmp, 3, "%02x", generic_digest[n]); + strncat(file_output->genericoutput, hashtmp,2); + } + } + if(file_output->check_sha256) { + for (n = 0; n < crypto_hash_sha256_BYTES; ++n) { + hashtmp[0] = '\0'; + snprintf(hashtmp, 3, "%02x", sha256_digest[n]); + strncat(file_output->sha256output, hashtmp, 2); + } + } + + + + + + /* Close it */ + if (prefilter_cmd == NULL) { + fclose(fp); + } else { + pclose(fp); + } + + return (0); +} +#endif // LIBSODIUM_ENABLED + diff --git a/src/os_crypto/md5_sha1/md5_sha1_op.h b/src/os_crypto/md5_sha1/md5_sha1_op.h index 81c113224..759eaf384 100644 --- a/src/os_crypto/md5_sha1/md5_sha1_op.h +++ b/src/os_crypto/md5_sha1/md5_sha1_op.h @@ -10,6 +10,10 @@ #ifndef __MD5SHA1_OP_H #define __MD5SHA1_OP_H +#ifdef LIBSODIUM_ENABLED +#include +#endif //LIBSODIUM_ENABLED + #include "../md5/md5_op.h" #include "../sha1/sha1_op.h" @@ -17,3 +21,22 @@ int OS_MD5_SHA1_File(const char *fname, const char *prefilter_cmd, os_md5 md5out #endif +#ifdef LIBSODIUM_ENABLED + +struct hash_output { + // What are we looking for? + int check_md5; + int check_sha1; + int check_sha256; + int check_generic; + + // Here's where we put it. + char md5output[37]; + char sha1output[70]; + char genericoutput[256]; + char sha256output[96]; +}; + +int OS_Hash_File(const char *fname, const char *prefilter_cmd, struct hash_output *file_output, int mode); +#endif + diff --git a/src/shared/file_op.c b/src/shared/file_op.c index 325e2d25e..f6b9f4c9c 100644 --- a/src/shared/file_op.c +++ b/src/shared/file_op.c @@ -375,7 +375,6 @@ char *GetRandomNoise() return(NULL); } - buf[2048] = '\0'; frr = fread(buf, 1, 2048, fp); if(frr == 0) { merror("ERROR: GetRandomNoise() fread() returned 0."); diff --git a/src/shared/randombytes.c b/src/shared/randombytes.c index 2a72138cf..0f92ab965 100644 --- a/src/shared/randombytes.c +++ b/src/shared/randombytes.c @@ -9,7 +9,7 @@ #include "shared.h" -void randombytes(void *ptr, size_t length) +void OS_randombytes(void *ptr, size_t length) { char failed = 0; @@ -37,7 +37,7 @@ void randombytes(void *ptr, size_t length) #endif if (failed) { - ErrorExit("%s: ERROR: randombytes failed for all possible methods for accessing random data", __local_name); + ErrorExit("%s: ERROR: OS_randombytes failed for all possible methods for accessing random data", __local_name); } } @@ -48,7 +48,7 @@ void srandom_init(void) srandomdev(); #else unsigned int seed; - randombytes(&seed, sizeof seed); + OS_randombytes(&seed, sizeof seed); srandom(seed); #endif /* !__OpenBSD__ */ #endif /* !WIN32 */ diff --git a/src/shared/report_op.c b/src/shared/report_op.c index 813bc74c3..c5ae55282 100644 --- a/src/shared/report_op.c +++ b/src/shared/report_op.c @@ -539,6 +539,7 @@ void os_ReportdStart(report_filter *r_filter) al_data); } } + //free(mgroup); } /* Add to the location top filter */ diff --git a/src/syscheckd/create_db.c b/src/syscheckd/create_db.c index 3340fe5bf..fd88809f2 100644 --- a/src/syscheckd/create_db.c +++ b/src/syscheckd/create_db.c @@ -17,6 +17,9 @@ #include #endif +/* Make this big enough for most things. Might adjust later */ +#define ALERT_MSG_LEN 2048 + /* Prototypes */ static int read_file(const char *dir_name, int opts, OSMatch *restriction) __attribute__((nonnull(1))); @@ -63,16 +66,16 @@ static int read_file(const char *file_name, int opts, OSMatch *restriction) #endif { if(errno == ENOTDIR){ - /*Deletion message sending*/ - char alert_msg[PATH_MAX+4]; - alert_msg[PATH_MAX + 3] = '\0'; - snprintf(alert_msg, PATH_MAX + 4, "-1 %s", file_name); - send_syscheck_msg(alert_msg); - return (0); - }else{ - merror("%s: Error accessing '%s'.", ARGV0, file_name); - return (-1); - } + /*Deletion message sending*/ + char alert_msg[PATH_MAX+4]; + alert_msg[PATH_MAX + 3] = '\0'; + snprintf(alert_msg, PATH_MAX + 4, "-1 %s", file_name); + send_syscheck_msg(alert_msg); + return (0); + }else{ + merror("%s: Error accessing '%s'.", ARGV0, file_name); + return (-1); + } } if (S_ISDIR(statbuf.st_mode)) { @@ -101,9 +104,9 @@ static int read_file(const char *file_name, int opts, OSMatch *restriction) /* No S_ISLNK on Windows */ #ifdef WIN32 if (S_ISREG(statbuf.st_mode)) -#else +#else //WIN32 if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) -#endif +#endif //WIN32 { os_md5 mf_sum; os_sha1 sf_sum; @@ -117,20 +120,75 @@ static int read_file(const char *file_name, int opts, OSMatch *restriction) strncpy(sf_sum3, "xxx", 4); /* Generate checksums */ +#ifdef LIBSODIUM_ENABLED + /* Prep file_sums */ + struct hash_output *file_sums; + file_sums = malloc(sizeof(struct hash_output)); + if(file_sums == NULL) { + merror("file_sums malloc failed: %s", strerror(errno)); + } + strncpy(file_sums->md5output, "MD5=", 5); + strncpy(file_sums->sha256output, "SHA256=", 8); + strncpy(file_sums->sha1output, "SHA1=", 5); + strncpy(file_sums->genericoutput, "GENERIC=", 9); + + /* set the checks */ + if(opts & CHECK_MD5SUM) { + file_sums->check_md5 = 1; + } + if(opts & CHECK_SHA1SUM) { + file_sums->check_sha1 = 1; + } + if(opts & CHECK_SHA256SUM) { + file_sums->check_sha256 = 1; + } + if(opts & CHECK_GENERIC) { + file_sums->check_generic = 1; + } + + if ((opts & CHECK_MD5SUM) || (opts & CHECK_SHA1SUM) || (opts & CHECK_SHA256SUM) || (opts & CHECK_GENERIC)) { +#else if ((opts & CHECK_MD5SUM) || (opts & CHECK_SHA1SUM)) { +#endif //LIBSODIUM_ENABLED /* If it is a link, check if dest is valid */ #ifndef WIN32 + + /* XXX This is all weird */ if (S_ISLNK(statbuf.st_mode)) { + + /* Get the file the link points to */ + /* XXX not working? + char new_file_name[255]; + ssize_t rlret = readlink(file_name, new_file_name, 254); + if(rlret < 0) { + merror("Cannot find the file: %s", strerror(errno)); + } else { + new_file_name[sizeof(new_file_name) - 1] = '\0'; + } + */ + struct stat statbuf_lnk; + //if (stat(new_file_name, &statbuf_lnk) == 0) { if (stat(file_name, &statbuf_lnk) == 0) { if (S_ISREG(statbuf_lnk.st_mode)) { +#ifdef LIBSODIUM_ENABLED + if(OS_Hash_File(file_name, syscheck.prefilter_cmd, file_sums, OS_BINARY) < 0) { + merror("ossec-syscheckd: ERROR: OS_Hash_File() failed (0x00)"); + } + +#else //LIBSODIUM_ENABLED if (OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum, OS_BINARY) < 0) { strncpy(mf_sum, "xxx", 4); strncpy(sf_sum, "xxx", 4); } +#endif //LIBSODIUM_ENABLED } } +#ifdef LIBSODIUM_ENABLED + } else if(OS_Hash_File(file_name, syscheck.prefilter_cmd, file_sums, OS_BINARY) < 0) +#else //LIBSODIUM_ENABLED } else if (OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum, OS_BINARY) < 0) +#endif //LIBSODIUM_ENABLED #else if (OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum, OS_BINARY) < 0) #endif @@ -152,8 +210,8 @@ static int read_file(const char *file_name, int opts, OSMatch *restriction) buf = (char *) OSHash_Get(syscheck.fp, file_name); if (!buf) { - char alert_msg[916 + 1]; /* to accommodate a long */ - alert_msg[916] = '\0'; + char alert_msg[ALERT_MSG_LEN]; + alert_msg[ALERT_MSG_LEN - 1] = '\0'; #ifndef WIN32 if (opts & CHECK_SEECHANGES) { @@ -165,36 +223,106 @@ static int read_file(const char *file_name, int opts, OSMatch *restriction) } #endif - snprintf(alert_msg, 916, "%c%c%c%c%c%c%ld:%d:%d:%d:%s:%s", - opts & CHECK_SIZE ? '+' : '-', - opts & CHECK_PERM ? '+' : '-', - opts & CHECK_OWNER ? '+' : '-', - opts & CHECK_GROUP ? '+' : '-', - opts & CHECK_MD5SUM ? '+' : '-', +#ifdef LIBSODIUM_ENABLED + char new_hashes[512], new_hashes_tmp[512]; + int hashc = 0; + if(opts & CHECK_SHA256SUM) { + snprintf(new_hashes, 511, "%s", file_sums->sha256output); + hashc++; + } + if((opts & CHECK_SHA1SUM) && hashc < 2) { + if(hashc > 0) { + snprintf(new_hashes_tmp, 511, "%s:%s", new_hashes, file_sums->sha1output); + strncpy(new_hashes, new_hashes_tmp, 511); + hashc++; + } else if(hashc == 0) { + snprintf(new_hashes, 511, "%s", file_sums->sha1output); + hashc++; + } + } + if((opts & CHECK_MD5SUM) && hashc < 2) { + if(hashc > 0) { + snprintf(new_hashes_tmp, 511, "%s:%s", new_hashes, file_sums->md5output); + strncpy(new_hashes, new_hashes_tmp, 511); + hashc++; + } else if(hashc == 0) { + snprintf(new_hashes, 511, "%s", file_sums->md5output); + hashc++; + } + } + if((opts & CHECK_GENERIC) && hashc < 2) { + if(hashc > 0) { + snprintf(new_hashes_tmp, 511, "%s:%s", new_hashes, file_sums->genericoutput); + strncpy(new_hashes, new_hashes_tmp, 511); + hashc++; + } else if(hashc == 0) { + snprintf(new_hashes, 511, "%s", file_sums->genericoutput); + hashc++; + } + } + if(hashc < 2) { + if(hashc == 0) { + strncpy(new_hashes, "xxx:xxx", 8); + } else if (hashc == 1) { + snprintf(new_hashes_tmp, 511, "%s:xxx", new_hashes); + strncpy(new_hashes, new_hashes_tmp, 511); + } + } + + snprintf(alert_msg, (ALERT_MSG_LEN - 1), "%c%c%c%c%c%c%ld:%d:%d:%d:%s", + (opts & CHECK_SIZE) ? '+' : '-', + (opts & CHECK_PERM) ? '+' : '-', + (opts & CHECK_OWNER) ? '+' : '-', + (opts & CHECK_GROUP) ? '+' : '-', + (opts & CHECK_MD5SUM) ? '+' : '-', sha1s, - opts & CHECK_SIZE ? (long)statbuf.st_size : 0, - opts & CHECK_PERM ? (int)statbuf.st_mode : 0, - opts & CHECK_OWNER ? (int)statbuf.st_uid : 0, - opts & CHECK_GROUP ? (int)statbuf.st_gid : 0, - opts & CHECK_MD5SUM ? mf_sum : "xxx", - opts & CHECK_SHA1SUM ? sf_sum : "xxx"); + (opts & CHECK_SIZE) ? (long)statbuf.st_size : 0, + (opts & CHECK_PERM) ? (int)statbuf.st_mode : 0, + (opts & CHECK_OWNER) ? (int)statbuf.st_uid : 0, + (opts & CHECK_GROUP) ? (int)statbuf.st_gid : 0, + new_hashes); +#else // LIBSODIUM_ENABLED XXX - is this the source of my xxxes? + snprintf(alert_msg, (ALERT_MSG_LEN - 1), "%c%c%c%c%c%c%ld:%d:%d:%d:%s:%s", + (opts & CHECK_SIZE) ? '+' : '-', + (opts & CHECK_PERM) ? '+' : '-', + (opts & CHECK_OWNER) ? '+' : '-', + (opts & CHECK_GROUP) ? '+' : '-', + (opts & CHECK_MD5SUM) ? '+' : '-', + sha1s, + (opts & CHECK_SIZE) ? (long)statbuf.st_size : 0, + (opts & CHECK_PERM) ? (int)statbuf.st_mode : 0, + (opts & CHECK_OWNER) ? (int)statbuf.st_uid : 0, + (opts & CHECK_GROUP) ? (int)statbuf.st_gid : 0, + (opts & CHECK_MD5SUM) ? mf_sum : "xxx", + (opts & CHECK_SHA1SUM) ? sf_sum : "xxx"); +#endif // LIBSODIUM_ENABLED if (OSHash_Add(syscheck.fp, file_name, strdup(alert_msg)) <= 0) { merror("%s: ERROR: Unable to add file to db: %s", ARGV0, file_name); } /* Send the new checksum to the analysis server */ - alert_msg[916] = '\0'; + alert_msg[ALERT_MSG_LEN - 1] = '\0'; #ifndef WIN32 - snprintf(alert_msg, 916, "%ld:%d:%d:%d:%s:%s %s", - opts & CHECK_SIZE ? (long)statbuf.st_size : 0, - opts & CHECK_PERM ? (int)statbuf.st_mode : 0, - opts & CHECK_OWNER ? (int)statbuf.st_uid : 0, - opts & CHECK_GROUP ? (int)statbuf.st_gid : 0, - opts & CHECK_MD5SUM ? mf_sum : "xxx", - opts & CHECK_SHA1SUM ? sf_sum : "xxx", +#ifdef LIBSODIUM_ENABLED + snprintf(alert_msg, (ALERT_MSG_LEN - 1), "%ld:%d:%d:%d:%s %s", + (opts & CHECK_SIZE) ? (long)statbuf.st_size : 0, + (opts & CHECK_PERM) ? (int)statbuf.st_mode : 0, + (opts & CHECK_OWNER) ? (int)statbuf.st_uid : 0, + (opts & CHECK_GROUP) ? (int)statbuf.st_gid : 0, + new_hashes, file_name); +#else // LIBSODIUM_ENABLED + snprintf(alert_msg, (ALERT_MSG_LEN - 1), "%ld:%d:%d:%d:%s:%s %s", + (opts & CHECK_SIZE) ? (long)statbuf.st_size : 0, + (opts & CHECK_PERM) ? (int)statbuf.st_mode : 0, + (opts & CHECK_OWNER) ? (int)statbuf.st_uid : 0, + (opts & CHECK_GROUP) ? (int)statbuf.st_gid : 0, + (opts & CHECK_MD5SUM) ? mf_sum : "xxx", + (opts & CHECK_SHA1SUM) ? sf_sum : "xxx", + file_name); +#endif // LIBSODIUM_ENABLED #else HANDLE hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); @@ -230,7 +358,7 @@ static int read_file(const char *file_name, int opts, OSMatch *restriction) LocalFree(szSID); CloseHandle(hFile); - snprintf(alert_msg, 916, "%ld:%d:%s:%d:%s:%s %s", + snprintf(alert_msg, (ALERT_MSG_LEN - 1), "%ld:%d:%s:%d:%s:%s %s", opts & CHECK_SIZE ? (long)statbuf.st_size : 0, opts & CHECK_PERM ? (int)statbuf.st_mode : 0, (opts & CHECK_OWNER) ? st_uid : "0", @@ -239,7 +367,7 @@ static int read_file(const char *file_name, int opts, OSMatch *restriction) opts & CHECK_SHA1SUM ? sf_sum : "xxx", file_name); free(st_uid); -#endif +#endif // WIN32 send_syscheck_msg(alert_msg); } else { char alert_msg[OS_MAXSTR + 1]; @@ -251,7 +379,7 @@ static int read_file(const char *file_name, int opts, OSMatch *restriction) alert_msg[OS_MAXSTR] = '\0'; /* If it returns < 0, we have already alerted */ - if (c_read_file(file_name, buf, c_sum) < 0) { + if (c_read_file(file_name, buf, c_sum, opts) < 0) { return (0); } diff --git a/src/syscheckd/run_check.c b/src/syscheckd/run_check.c index 1bf45c6a2..8bfef8879 100644 --- a/src/syscheckd/run_check.c +++ b/src/syscheckd/run_check.c @@ -18,6 +18,10 @@ #include #endif +#ifdef LIBSODIUM_ENABLED +#include +#endif + #include "shared.h" #include "syscheck.h" #include "os_crypto/md5/md5_op.h" @@ -316,7 +320,7 @@ void start_daemon() } /* Read file information and return a pointer to the checksum */ -int c_read_file(const char *file_name, const char *oldsum, char *newsum) +int c_read_file(const char *file_name, const char *oldsum, char *newsum, int sysopts) { int size = 0, perm = 0, owner = 0, group = 0, md5sum = 0, sha1sum = 0; int return_error = 0; @@ -324,6 +328,40 @@ int c_read_file(const char *file_name, const char *oldsum, char *newsum) os_md5 mf_sum; os_sha1 sf_sum; +#ifdef LIBSODIUM_ENABLED + + struct hash_output *file_sums; + file_sums = malloc(sizeof(struct hash_output)); + if(file_sums == NULL) { + merror("run_check file_sums malloc failed: %s", strerror(errno)); + } + + /* Clean sums */ + strncpy(file_sums->md5output, "MD5=", 5); + strncpy(file_sums->sha256output, "SHA256=", 8); + strncpy(file_sums->sha1output, "SHA1=", 5); + strncpy(file_sums->genericoutput, "GENERIC=", 9); + /* set the checks */ + if(sysopts & CHECK_MD5SUM) { + file_sums->check_md5 = 1; + } + if(sysopts & CHECK_SHA1SUM) { + file_sums->check_sha1 = 1; + } + if(sysopts & CHECK_SHA256SUM) { + file_sums->check_sha256 = 1; + } + + if(sysopts & CHECK_GENERIC) { + file_sums->check_generic = 1; + } + + if(file_sums->check_md5 != 1 && file_sums->check_sha1 != 1 && file_sums->check_sha256 != 1 && file_sums->check_generic != 1) { + merror("XXX DOES NOT COMPUTER!"); // TODO replace with real message or something respectable + } + +#endif // LIBSODIUM_ENABLED + /* Clean sums */ strncpy(mf_sum, "xxx", 4); strncpy(sf_sum, "xxx", 4); @@ -341,12 +379,13 @@ int c_read_file(const char *file_name, const char *oldsum, char *newsum) alert_msg[PATH_MAX + 3] = '\0'; snprintf(alert_msg, PATH_MAX + 4, "-1 %s", file_name); send_syscheck_msg(alert_msg); - +#ifdef LIBSODIUM_ENABLED + free(file_sums); +#endif return (-1); } /* Get the old sum values */ - /* size */ if (oldsum[0] == '+') { size = 1; @@ -386,10 +425,16 @@ int c_read_file(const char *file_name, const char *oldsum, char *newsum) { if (sha1sum || md5sum) { /* Generate checksums of the file */ +#ifdef LIBSODIUM_ENABLED + if (OS_Hash_File(file_name, syscheck.prefilter_cmd, file_sums, OS_BINARY) < 0) { + merror("syscheckd: ERROR: OS_Hash_File() failed. (0x01)"); + } +#else if (OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum, OS_BINARY) < 0) { strncpy(sf_sum, "xxx", 4); strncpy(mf_sum, "xxx", 4); } +#endif } } #ifndef WIN32 @@ -400,10 +445,16 @@ int c_read_file(const char *file_name, const char *oldsum, char *newsum) if (S_ISREG(statbuf_lnk.st_mode)) { if (sha1sum || md5sum) { /* Generate checksums of the file */ +#ifdef LIBSODIUM_ENABLED + if (OS_Hash_File(file_name, syscheck.prefilter_cmd, file_sums, OS_BINARY) < 0) { + merror("syscheckd: ERROR: OS_Hash_File() failed. (0x02)"); + } +#else if (OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum, OS_BINARY) < 0) { strncpy(sf_sum, "xxx", 4); strncpy(mf_sum, "xxx", 4); } +#endif } } } @@ -412,6 +463,57 @@ int c_read_file(const char *file_name, const char *oldsum, char *newsum) newsum[0] = '\0'; newsum[255] = '\0'; + +#ifdef LIBSODIUM_ENABLED + char new_hashes[512], new_hashes_tmp[512]; + int hashc = 0; + if(file_sums->check_sha256 > 0) { + snprintf(new_hashes, 511, "%s", file_sums->sha256output); + hashc++; + } + if(file_sums->check_generic > 0) { + if(hashc > 0) { + snprintf(new_hashes_tmp, 511, "%s:%s", new_hashes, file_sums->genericoutput); + strncpy(new_hashes, new_hashes_tmp, 511); + hashc++; + } else if(hashc == 0) { + snprintf(new_hashes, 511, "%s", file_sums->genericoutput); + hashc++; + } + } + if(file_sums->check_sha1 > 0 && hashc < 2) { + if(hashc > 0) { + snprintf(new_hashes_tmp, 511, "%s:%s", new_hashes, file_sums->sha1output); + strncpy(new_hashes, new_hashes_tmp, 511); + hashc++; + } else if(hashc == 0) { snprintf(new_hashes, 511, "%s", file_sums->sha1output); + hashc++; + } + } + if(file_sums->check_md5 > 0 && hashc < 2) { + if(hashc > 0) { + snprintf(new_hashes_tmp, 511, "%s:%s", new_hashes, file_sums->md5output); + strncpy(new_hashes, new_hashes_tmp, 511); + hashc++; + } else if(hashc == 0) { + snprintf(new_hashes, 511, "%s", file_sums->md5output); hashc++; + } + } + if(hashc < 2) { + if(hashc == 0) { + strncpy(new_hashes, "xxx:xxx", 8); + } else if (hashc == 1) { snprintf(new_hashes_tmp, 511, "%s:xxx", new_hashes); + strncpy(new_hashes, new_hashes_tmp, 511); + } + } + + snprintf(newsum, 255, "%ld:%d:%d:%d:%s", + size == 0 ? 0 : (long)statbuf.st_size, + perm == 0 ? 0 : (int)statbuf.st_mode, + owner == 0 ? 0 : (int)statbuf.st_uid, + group == 0 ? 0 : (int)statbuf.st_gid, + new_hashes); +#else //LIBSODIUM_ENABLED #ifndef WIN32 snprintf(newsum, 255, "%ld:%d:%d:%d:%s:%s", size == 0 ? 0 : (long)statbuf.st_size, @@ -420,7 +522,7 @@ int c_read_file(const char *file_name, const char *oldsum, char *newsum) group == 0 ? 0 : (int)statbuf.st_gid, md5sum == 0 ? "xxx" : mf_sum, sha1sum == 0 ? "xxx" : sf_sum); -#else +#else //WIN32 HANDLE hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { DWORD dwErrorCode = GetLastError(); @@ -463,7 +565,13 @@ int c_read_file(const char *file_name, const char *oldsum, char *newsum) sha1sum == 0 ? "xxx" : sf_sum); free(st_uid); -#endif +#endif //WIN32 +#endif //LIBSODIUM_ENABLED +/* +#ifdef LIBSODIUM_ENABLED + free(file_sums); +#endif +*/ return (0); } diff --git a/src/syscheckd/run_realtime.c b/src/syscheckd/run_realtime.c index 575b97c39..6e4145fb2 100644 --- a/src/syscheckd/run_realtime.c +++ b/src/syscheckd/run_realtime.c @@ -50,7 +50,7 @@ int realtime_checksumfile(const char *file_name) c_sum[255] = '\0'; /* If it returns < 0, we have already alerted */ - if (c_read_file(file_name, buf, c_sum) < 0) { + if (c_read_file(file_name, buf, c_sum, syscheck.opts[0]) < 0) { return (0); } diff --git a/src/syscheckd/syscheck.h b/src/syscheckd/syscheck.h index 78cc1c356..6d907aace 100644 --- a/src/syscheckd/syscheck.h +++ b/src/syscheckd/syscheck.h @@ -56,7 +56,7 @@ int realtime_process(void); char *seechanges_addfile(const char *filename) __attribute__((nonnull)); /* Get checksum changes */ -int c_read_file(const char *file_name, const char *oldsum, char *newsum) __attribute__((nonnull)); +int c_read_file(const char *file_name, const char *oldsum, char *newsum, int sysopts) __attribute__((nonnull)); int send_syscheck_msg(const char *msg) __attribute__((nonnull)); int send_rootcheck_msg(const char *msg) __attribute__((nonnull));