.14.1.tar.gz) = c63484af8fd157f61b6bf0297b4233c3e2a3eee481f35c7d15fcb5b90d711489 SIZE (wazuh-4.14.1/wazuh-cache-fbsd15-aarch64-4.14.1.tar.gz) = 24690859 SHA256 (wazuh-4.14.1/wazuh-cache-fbsd15-amd64-4.14.1.tar.gz) = 8b70abd8e3b408cd69dc2a5434ddaaa7afa9e59c9173c8a3242cef5c657327db SIZE (wazuh-4.14.1/wazuh-cache-fbsd15-amd64-4.14.1.tar.gz) = 26650226 -SHA256 (wazuh-4.14.1/wazuh-cache-fbsd16-aarch64-4.14.1.tar.gz) = 1510ef710bcae78e22db88f443504d006e9e4b45d27c66bb84984211409f7e65 -SIZE (wazuh-4.14.1/wazuh-cache-fbsd16-aarch64-4.14.1.tar.gz) = 24863114 -SHA256 (wazuh-4.14.1/wazuh-cache-fbsd16-amd64-4.14.1.tar.gz) = 03e92ad3b8cc1d06f9e31d07aa13d1ba3dca85b302d869ec5ec3a2b517d3dbf0 -SIZE (wazuh-4.14.1/wazuh-cache-fbsd16-amd64-4.14.1.tar.gz) = 26653557 +SHA256 (wazuh-4.14.1/wazuh-cache-fbsd16-aarch64-4.14.1.tar.gz) = 29ca4f074475bc29a852850193da0da421133f62f38ccd0a990edd17743845bb +SIZE (wazuh-4.14.1/wazuh-cache-fbsd16-aarch64-4.14.1.tar.gz) = 24862885 +SHA256 (wazuh-4.14.1/wazuh-cache-fbsd16-amd64-4.14.1.tar.gz) = f706a10b1e31dc959e1751a015b3ec2e74ddbda0362ab192ba3918852731635c +SIZE (wazuh-4.14.1/wazuh-cache-fbsd16-amd64-4.14.1.tar.gz) = 26653845 SHA256 (wazuh-4.14.1/wazuh-wazuh-v4.14.1_GH0.tar.gz) = aa59cb2baa7e7d38d8bb4ff6a22afbf2945de4fb555f9b8bb2657b6f89a773ed SIZE (wazuh-4.14.1/wazuh-wazuh-v4.14.1_GH0.tar.gz) = 19810038 SHA256 (wazuh-4.14.1/alonsobsd-wazuh-freebsd-2f1307c_GH0.tar.gz) = a955c569217122779ab5b6b58bdfabbfa1cd452b4719cc35c791f7047b1f364f diff --git a/security/wazuh-manager/files/check_pid.c b/security/wazuh-manager/files/check_pid.c new file mode 100644 index 000000000000..a5697601c41b --- /dev/null +++ b/security/wazuh-manager/files/check_pid.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define PID_MAX_FALLBACK 99999 +#define PROC_PATH "/proc" +/* + * /proc = 5, / = 1, = 5, \0 = 1 + */ +#define PID_PATH_LEN 12 + +static void usage(void); +static void raise_invalid_number(int); +static void raise_atoi_exception(const char *); +static int safe_atoi(const char *, int *); + +int +main(int argc, char **argv) +{ + const char *pid_str; + if ((pid_str = argv[1]) == NULL) + usage(); + + int pid; + if (safe_atoi(pid_str, &pid) != 0) + raise_atoi_exception(pid_str); + + pid_t pid_max; + + size_t pid_max_len; + + pid_max_len = sizeof(pid_max); + if (sysctlbyname("kern.pid_max", &pid_max, &pid_max_len, NULL, 0) == -1) { + warnx("error getting sysctl"); + pid_max = PID_MAX_FALLBACK; + } + + if (pid <= 0 || pid > pid_max) + raise_invalid_number(pid); + + char pid_path[PID_PATH_LEN]; + + snprintf(pid_path, sizeof(pid_path), "/proc/%d", pid); + + struct stat sbuf; + + if (lstat(pid_path, &sbuf) == -1) { + if (errno == ENOENT) + return EX_NOINPUT; + else + warnx("error getting file status"); + return EX_SOFTWARE; + } + + return EX_OK; +} + +static void +raise_invalid_number(int n) +{ + errx(EX_DATAERR, "%d: invalid number", n); +} + +static void +raise_atoi_exception(const char *s) +{ + if (errno != 0) + err(EX_SOFTWARE, "atol()"); + else + errx(EX_SOFTWARE, "could not convert %s to an integer", s); +} + +static int +safe_atoi(const char *s, int *ret_i) +{ + char *x = NULL; + long l; + + errno = 0; + l = strtol(s, &x, 0); + + if (!x || x == s || *x || errno) + return errno > 0 ? -errno : -EINVAL; + + if ((long)(int)l != l) + return -ERANGE; + + *ret_i = (int)l; + + return 0; +} + +static void +usage(void) +{ + errx(EX_USAGE, "%s", + "usage: check_pid "); +} diff --git a/security/wazuh-manager/files/patch-framework-wazuh-core-cluster_utils.py b/security/wazuh-manager/files/patch-framework-wazuh-core-cluster_utils.py new file mode 100644 index 000000000000..8dc0d329d5dc --- /dev/null +++ b/security/wazuh-manager/files/patch-framework-wazuh-core-cluster_utils.py @@ -0,0 +1,33 @@ +--- framework/wazuh/core/cluster/utils.py 2025-12-30 23:32:30.875588000 -0800 ++++ framework/wazuh/core/cluster/utils.py 2025-12-30 23:33:42.825809000 -0800 +@@ -11,6 +11,7 @@ + import socket + import time + import typing ++import subprocess + from contextvars import ContextVar + from functools import lru_cache + from glob import glob +@@ -282,7 +283,7 @@ + # it means each process crashed and was not able to remove its own pidfile. + data[process] = 'failed' + for pid in pidfile: +- if os.path.exists(os.path.join(proc_path, pidfile_regex.match(pid).group(1))): ++ if _check_pid_as_superman(pidfile_regex.match(pid).group(1)): + data[process] = 'running' + break + +@@ -291,6 +292,13 @@ + + return data + ++def _check_pid_as_superman(pid): ++ try: ++ subprocess.check_call(["/var/ossec/libexec/check_pid", pid]) ++ except subprocess.CalledProcessError as e: ++ return False ++ ++ return True + + def get_cluster_status() -> typing.Dict: + """Get cluster status. diff --git a/security/wazuh-manager/files/patch-src-data_provider-src_sysInfoFreeBSD.cpp b/security/wazuh-manager/files/patch-src-data_provider-src_sysInfoFreeBSD.cpp index 929fef4ec8c1..7765db26eb93 100644 --- a/security/wazuh-manager/files/patch-src-data_provider-src_sysInfoFreeBSD.cpp +++ b/security/wazuh-manager/files/patch-src-data_provider-src_sysInfoFreeBSD.cpp @@ -1,17 +1,22 @@ ---- src/data_provider/src/sysInfoFreeBSD.cpp 2025-09-23 06:59:40.000000000 -0700 -+++ src/data_provider/src/sysInfoFreeBSD.cpp 2025-10-16 15:42:56.638994000 -0700 -@@ -11,20 +11,23 @@ +--- src/data_provider/src/sysInfoFreeBSD.cpp.orig 2025-12-29 18:29:38.128837000 -0400 ++++ src/data_provider/src/sysInfoFreeBSD.cpp 2025-12-30 01:04:57.828191000 -0400 +@@ -11,20 +11,28 @@ #include "sysInfo.hpp" #include "cmdHelper.h" #include "stringHelper.h" +#include "timeHelper.h" #include "osinfo/sysOsParsers.h" ++#include "sqliteWrapperTemp.h" ++#include "filesystemHelper.h" #include #include #include #include "sharedDefs.h" +#include ++const std::string PKG_DB_PATHNAME {"/var/db/pkg/local.sqlite"}; ++const std::string PKG_QUERY {"SELECT p.name, p.maintainer, p.version, p.arch, p.comment, p.flatsize, p.time, v.annotation AS repository,p.origin FROM packages p LEFT JOIN (SELECT pa.package_id, pa.value_id FROM pkg_annotation pa JOIN annotation t ON t.annotation_id = pa.tag_id AND t.annotation = 'repository') pr ON pr.package_id = p.id LEFT JOIN annotation v ON v.annotation_id = pr.value_id;"}; ++ static void getMemory(nlohmann::json& info) { + constexpr auto vmFree{"vm.stats.vm.v_free_count"}; @@ -27,7 +32,7 @@ if (ret) { -@@ -52,11 +55,23 @@ +@@ -52,11 +60,23 @@ }; } @@ -54,7 +59,7 @@ if (ret) { -@@ -64,11 +79,11 @@ +@@ -64,11 +84,11 @@ { ret, std::system_category(), @@ -68,7 +73,7 @@ info["ram_free"] = ramFree; info["ram_usage"] = 100 - (100 * ramFree / ramTotal); } -@@ -184,8 +199,12 @@ +@@ -184,8 +204,12 @@ nlohmann::json SysInfo::getProcessesInfo() const { @@ -83,7 +88,7 @@ } nlohmann::json SysInfo::getOsInfo() const -@@ -196,11 +215,12 @@ +@@ -196,11 +220,12 @@ if (!spParser->parseUname(Utils::exec("uname -r"), ret)) { @@ -97,32 +102,40 @@ if (uname(&uts) >= 0) { ret["sysname"] = uts.sysname; -@@ -215,18 +235,200 @@ +@@ -215,44 +240,257 @@ nlohmann::json SysInfo::getPorts() const { - // Currently not supported for this OS. - return nlohmann::json {}; +-} + nlohmann::json ports {}; + + /* USER COMMAND PID FD PROTO LOCAL_ADDRESS FOREIGN_ADDRESS PATH_STATE CONN_STATE */ + +#if __FreeBSD_version > 1500045 + const auto query{exec(R"(sockstat -46qs --libxo json)")}; -+ + +-void SysInfo::getProcessesInfo(std::function /*callback*/) const +-{ +- // Currently not supported for this OS. +-} + if (!query.empty()) + { + nlohmann::json portsjson; + portsjson = nlohmann::json::parse(query); + auto &portsResult = portsjson["sockstat"]["socket"]; -+ + +-void SysInfo::getPackages(std::function callback) const +-{ +- const auto query{Utils::exec(R"(pkg query -a "%n|%m|%v|%q|%c")")}; + for(auto &port : portsResult) { + std::string localip = ""; + std::string localport = ""; + std::string remoteip = ""; + std::string remoteport = ""; + std::string statedata = ""; -+ + + if (port["pid"] != nullptr) { + + localip = port["local"]["address"]; @@ -170,16 +183,32 @@ +#else + const auto query{Utils::exec(R"(sockstat -46qs)")}; + -+ if (!query.empty()) -+ { + if (!query.empty()) + { +- const auto lines{Utils::split(query, '\n')}; + const auto lines{Utils::split(Utils::trimToOneSpace(query), '\n')}; -+ + + std::regex expression(R"(^(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s*(\S+)\s+(\S+)\s+(\S+)(?:\s+(\S+))?\s*$)"); + -+ for (const auto& line : lines) -+ { + for (const auto& line : lines) + { +- const auto data{Utils::split(line, '|')}; +- nlohmann::json package; + std::smatch data; -+ + +- package["name"] = data[0]; +- package["vendor"] = data[1]; +- package["version"] = data[2]; +- package["install_time"] = UNKNOWN_VALUE; +- package["location"] = UNKNOWN_VALUE; +- package["architecture"] = data[3]; +- package["groups"] = UNKNOWN_VALUE; +- package["description"] = data[4]; +- package["size"] = 0; +- package["priority"] = UNKNOWN_VALUE; +- package["source"] = UNKNOWN_VALUE; +- package["format"] = "pkg"; +- // The multiarch field won't have a default value + if (std::regex_search(line, data, expression)) + { + std::string localip = ""; @@ -187,7 +216,8 @@ + std::string remoteip = ""; + std::string remoteport = ""; + std::string statedata = ""; -+ + +- callback(package); + auto localdata{Utils::split(data[6], ':')}; + auto remotedata{Utils::split(data[7], ':')}; + @@ -240,12 +270,10 @@ + } +#endif + return ports; - } - --void SysInfo::getProcessesInfo(std::function /*callback*/) const ++} ++ +void SysInfo::getProcessesInfo(std::function callback) const - { -- // Currently not supported for this OS. ++{ + const auto query{Utils::exec(R"(ps -ax -w -o pid,comm,state,ppid,usertime,systime,user,ruser,svuid,group,rgroup,svgid,pri,nice,ssiz,vsz,rss,pmem,etimes,sid,pgid,tpgid,tty,cpu,nlwp,args --libxo json)")}; + + if (!query.empty()) @@ -294,42 +322,68 @@ + callback(jsProcessInfo); + } + } ++} ++ ++void SysInfo::getPackages(std::function callback) const ++{ ++ if (Utils::existsRegular(PKG_DB_PATHNAME)) ++ { ++ try ++ { ++ std::shared_ptr sqliteConnection = std::make_shared(PKG_DB_PATHNAME); ++ ++ SQLite::Statement stmt ++ { ++ sqliteConnection, ++ PKG_QUERY ++ }; ++ ++ while (SQLITE_ROW == stmt.step()) ++ { ++ try ++ { ++ auto pkg_name{ stmt.column(0) }; ++ auto pkg_maintainer{ stmt.column(1) }; ++ auto pkg_version{ stmt.column(2) }; ++ auto pkg_arch{ stmt.column(3) }; ++ auto pkg_comment{ stmt.column(4) }; ++ auto pkg_flatsize{ stmt.column(5) }; ++ auto pkg_time{ stmt.column(6) }; ++ auto pkg_repository{ stmt.column(7) }; ++ auto pkg_origin{ stmt.column(8) }; ++ ++ const auto archdata{Utils::split(pkg_arch->value(std::string{}), ':')}; ++ const auto sectiondata{Utils::split(pkg_origin->value(std::string{}), '/')}; ++ ++ nlohmann::json package; ++ ++ package["name"] = pkg_name->value(std::string{}); ++ package["vendor"] = pkg_maintainer->value(std::string{}); ++ package["version"] = pkg_version->value(std::string{}); ++ package["install_time"] = pkg_time->value(std::string{}); ++ package["location"] = UNKNOWN_VALUE; ++ package["architecture"] = archdata[2]; ++ package["groups"] = UNKNOWN_VALUE; ++ package["description"] = pkg_comment->value(std::string{}); ++ package["size"] = pkg_flatsize->value(uint64_t{}); ++ package["priority"] = UNKNOWN_VALUE; ++ package["source"] = pkg_repository->value(std::string{}); ++ package["section"] = sectiondata[0]; ++ package["format"] = "pkg"; ++ // The multiarch field won't have a default value ++ ++ callback(package); ++ } ++ catch (const std::exception& e) ++ { ++ std::cerr << e.what() << std::endl; ++ } ++ } + } ++ catch (const std::exception& e) ++ { ++ std::cerr << e.what() << std::endl; ++ } + } } - void SysInfo::getPackages(std::function callback) const - { -- const auto query{Utils::exec(R"(pkg query -a "%n|%m|%v|%q|%c")")}; -+ const auto query{Utils::exec(R"(pkg query -a "%n|%m|%v|%q|%c|%sb|%t|%R|%o")")}; - - if (!query.empty()) - { -@@ -235,6 +437,9 @@ - for (const auto& line : lines) - { - const auto data{Utils::split(line, '|')}; -+ const auto archdata{Utils::split(data[3], ':')}; -+ const auto sectiondata{Utils::split(data[8], '/')}; -+ - nlohmann::json package; - std::string vendor { UNKNOWN_VALUE }; - std::string email { UNKNOWN_VALUE }; -@@ -244,14 +449,15 @@ - package["name"] = data[0]; - package["vendor"] = vendor; - package["version"] = data[2]; -- package["install_time"] = UNKNOWN_VALUE; -+ package["install_time"] = data[6]; - package["location"] = UNKNOWN_VALUE; -- package["architecture"] = data[3]; -+ package["architecture"] = archdata[2]; - package["groups"] = UNKNOWN_VALUE; - package["description"] = data[4]; -- package["size"] = 0; -+ package["size"] = data[5]; - package["priority"] = UNKNOWN_VALUE; -- package["source"] = UNKNOWN_VALUE; -+ package["source"] = data[7]; -+ package["section"] = sectiondata[0]; - package["format"] = "pkg"; - // The multiarch field won't have a default value - diff --git a/security/wazuh-manager/pkg-plist b/security/wazuh-manager/pkg-plist index cc555ee1a4da..221932188520 100644 --- a/security/wazuh-manager/pkg-plist +++ b/security/wazuh-manager/pkg-plist @@ -29886,6 +29886,7 @@ /var/ossec/lib/libvulnerability_scanner.so /var/ossec/lib/libwazuhext.so /var/ossec/lib/libwazuhshared.so +@(root,wheel,4755) /var/ossec/libexec/check_pid @mode 660 @owner wazuh @group wazuh @@ -33161,6 +33162,7 @@ @dir /var/ossec/framework @dir /var/ossec/integrations @dir /var/ossec/lib +@dir(root,wazuh,750) /var/ossec/libexec @dir /var/ossec/logs/alerts @dir /var/ossec/logs/api @dir /var/ossec/logs/archives