Skip to content
API Documentation
BastionGuard™
SaneSecurityUpdater.cpp
Go to the documentation of this file.
1/*
2 * BastionGuard™
3 * Copyright (C) 2025–2026 Calogero Scarnà
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 *
17 * BastionGuard™ is a trademark of Calogero Scarnà.
18 * The BastionGuard™ name and branding are not licensed under the GPL.
19 */
20
22#include <iostream>
23#include <cstdlib>
24#include <vector>
25#include <filesystem>
26#include <algorithm>
27#include <system_error>
28#include <glibmm/i18n.h>
29#include "SafeProcess.hpp"
30
31static bool reload_clamav_service() {
32 const std::vector<std::string> services = {
33 "clamav-daemon.service",
34 "clamd@scan.service",
35 "clamd.service"
36 };
37
38 for (const auto& svc : services) {
39 if (bg_process::run({"/usr/libexec/bastionguard/bastionguard-service",
40 "--system", "is-active", svc}).ok() &&
41 bg_process::run({"/usr/libexec/bastionguard/bastionguard-service",
42 "--system", "try-reload-or-restart", svc}).ok())
43 return true;
44 }
45
46 return false;
47}
49
50 const std::string tmpDir = "/var/lib/clamav/sanesecurity.tmp";
51
52
53 // Fixed working directory and argument-vector execution: no root shell.
54 // Keep deletion confined to this directory, never to /var/lib/clamav.
55 namespace fs = std::filesystem;
56 std::error_code ec;
57 fs::remove_all(tmpDir, ec);
58 if (ec || !fs::create_directories(tmpDir, ec) || ec) {
59 std::cerr << _("Errore: impossibile creare la cartella temporanea") << std::endl;
60 return false;
61 }
62
63 const auto sync = bg_process::run({"rsync", "-av", "--delete", "--",
64 "rsync://rsync.sanesecurity.net/sanesecurity", tmpDir + "/"}, true);
65 if (!sync.ok()) {
66 std::cerr << _("Errore durante rsync") << std::endl;
67 fs::remove_all(tmpDir, ec);
68 return false;
69 }
70
71 // Never evaluate downloaded filenames as shell metacharacters.
72 // Copy only extensions that ClamAV/SaneSecurity expects.
73 const std::vector<std::string> extensions = {
74 ".ndb", ".hdb", ".ldb", ".yar", ".yara", ".ign2", ".txt"
75 };
76 bool copies_ok = true;
77 for (const auto& entry : fs::directory_iterator(tmpDir, ec)) {
78 if (ec) { copies_ok = false; break; }
79 // Never follow symlinks provided by an external rsync mirror.
80 if (entry.is_symlink(ec) || ec) {
81 copies_ok = false;
82 ec.clear();
83 continue;
84 }
85 if (!entry.is_regular_file(ec) || ec) {
86 ec.clear();
87 continue;
88 }
89 const auto extension = entry.path().extension().string();
90 if (std::find(extensions.begin(), extensions.end(), extension) == extensions.end()) continue;
91 const fs::path destination = fs::path("/var/lib/clamav") / entry.path().filename();
92 fs::copy_file(entry.path(), destination, fs::copy_options::overwrite_existing, ec);
93 if (ec) {
94 copies_ok = false;
95 ec.clear();
96 }
97 }
98 fs::remove_all(tmpDir, ec);
99 if (!copies_ok) std::cerr << _("Errore copiando i file SaneSecurity") << std::endl;
100
101 if (!reload_clamav_service()) {
102 std::cerr << _("⚠ Impossibile ricaricare il servizio ClamAV: servizio non trovato") << "\n";
103}
104
105 return copies_ok;
106}
#define _(s)
static bool reload_clamav_service()
Result run(const std::vector< std::string > &args, bool merge_stderr=false, std::size_t limit=8U *1024U *1024U, const std::map< std::string, std::string > &environment={}, const std::function< bool(const std::string &)> &on_line={})